using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using System.Text.Json.Serialization;
using AK;
using Agents;
using AssetShards;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using ExtraSyringeCustomization.Converters;
using ExtraSyringeCustomization.Packets;
using ExtraSyringeCustomization.Properties;
using ExtraSyringeCustomization.Properties.BuiltIn;
using ExtraSyringeCustomization.Registries;
using ExtraSyringeCustomization.Utils;
using FX_EffectSystem;
using Flaff.Collections.Registries;
using GTFO.API;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MTFO.Managers;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ExtraSyringeCustomization")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ExtraSyringeCustomization")]
[assembly: AssemblyTitle("ExtraSyringeCustomization")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ExtraSyringeCustomization
{
public class CustomSyringeDefinition : IRegisterable
{
public uint SyringeID { get; set; }
public string? DebugName { get; set; }
public SyringePropertyList Properties { get; set; }
public CustomSyringeDefinition()
{
Properties = new SyringePropertyList();
}
internal IEnumerator ActivateSequence(PlayerAgent player, SyringeFirstPerson syringe, Random random)
{
SyringePropertyBase[] properties = Properties.GetProperties();
int index = 0;
int propertyCount = properties.Length;
List<SyringePropertyBase> batch = new List<SyringePropertyBase>(propertyCount);
while (index < propertyCount)
{
SyringePropertyBase item = properties[index];
batch.Add(item);
if (index + 1 < propertyCount && !properties[index].Timing.IsRelativeToPreviousProperties)
{
index++;
continue;
}
List<(IEnumerator, SyringePropertyBase)> batchSequences = new List<(IEnumerator, SyringePropertyBase)>();
foreach (SyringePropertyBase item2 in batch)
{
batchSequences.Add((CreatePropertySequence(player, syringe, item2, random), item2));
}
while (batchSequences.Count > 0)
{
int num = 0;
while (num < batchSequences.Count)
{
var (enumerator2, syringePropertyBase) = batchSequences[num];
try
{
if (!enumerator2.MoveNext())
{
batchSequences.RemoveAt(num);
}
else
{
num++;
}
}
catch (Exception value)
{
L.Error($"Error whilst processing property '{syringePropertyBase.Name}' on player {player.PlayerName} with syringe ID {SyringeID}: {value}");
batchSequences.RemoveAt(num);
}
}
yield return null;
}
batch.Clear();
index++;
}
}
private IEnumerator CreatePropertySequence(PlayerAgent player, SyringeFirstPerson syringe, SyringePropertyBase property, Random random)
{
SyringePropertySequenceInfo info = new SyringePropertySequenceInfo();
if ((int)GameStateManager.CurrentStateName != 10)
{
info.ForceCompletion();
}
IEnumerator enumerator = CreatePropertyInnerSequence(player, syringe, property, random, info);
while (enumerator.MoveNext() && !info.ForceComplete)
{
if ((int)GameStateManager.CurrentStateName != 10)
{
info.ForceCompletion();
}
yield return enumerator.Current;
}
}
private IEnumerator CreatePropertyInnerSequence(PlayerAgent player, SyringeFirstPerson syringe, SyringePropertyBase property, Random random, SyringePropertySequenceInfo info)
{
double delay = property.Timing.Delay.GetValue(random);
for (double t = 0.0; t < delay; t += info.DeltaTime)
{
if (info.ForceComplete)
{
break;
}
yield return null;
}
if (!info.ForceComplete)
{
IEnumerator sequence = property.Apply(player, syringe, random, info);
while (sequence.MoveNext())
{
yield return sequence.Current;
}
}
}
string IRegisterable.GetID()
{
return CustomSyringeRegistry.SyringeIDToRegistryID(SyringeID);
}
}
public sealed class ExtraSyringeHandler : MonoBehaviour
{
private class SyringeWrapper
{
private enum SyringeState
{
NONE,
SETUP,
INJECT,
CLEANUP
}
private readonly Random m_random;
private readonly _ApplySyringe_d__18 m_enumerator;
private readonly CustomSyringeDefinition? m_syringe;
private SyringeState m_state;
public SyringeWrapper(_ApplySyringe_d__18 enumerator)
{
m_random = new Random();
m_enumerator = enumerator;
SyringeRegistryHandler.Syringes.TryGetEntry(((GameDataBlockBase<ItemDataBlock>)(object)((Item)enumerator.__4__this).ItemDataBlock).persistentID, out m_syringe);
m_state = SyringeState.NONE;
}
public bool Equals(SyringeWrapper other)
{
return ((Il2CppObjectBase)m_enumerator).Pointer == ((Il2CppObjectBase)other.m_enumerator).Pointer;
}
public bool Equals(_ApplySyringe_d__18 other)
{
return ((Il2CppObjectBase)m_enumerator).Pointer == ((Il2CppObjectBase)other).Pointer;
}
public bool OnMoveNext(ref bool result)
{
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Expected O, but got Unknown
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
m_state++;
SyringeFirstPerson _4__this = m_enumerator.__4__this;
L.Debug("MoveNext Syringe (" + ((GameDataBlockBase<ItemDataBlock>)(object)((Item)_4__this).ItemDataBlock).persistentID + ") " + m_state);
if (m_syringe != null)
{
if (m_state == SyringeState.SETUP)
{
return true;
}
if (m_state == SyringeState.INJECT)
{
((Item)_4__this).Owner.FPItemHolder.ItemHiddenTrigger = true;
Current.StartCoroutine(m_syringe.ActivateSequence(((Item)_4__this).Owner, _4__this, m_random));
m_enumerator.__2__current = (Object)new WaitForSeconds(0.7f);
result = true;
return false;
}
if (m_state == SyringeState.CLEANUP)
{
for (int i = 0; i < s_syringeWrappers.Count; i++)
{
if (s_syringeWrappers[i].Equals(this))
{
s_syringeWrappers.RemoveAt(i);
break;
}
}
FirstPersonItemHolder fPItemHolder = ((ItemEquippable)_4__this).FPItemHolder;
if (fPItemHolder != null)
{
fPItemHolder.AnimationSequenceEnd();
}
pItemData_Custom customData = ((Item)_4__this).GetCustomData();
if ((customData.ammo -= 1f) <= 0.01f)
{
ItemDataBlock itemDataBlock = ((Item)_4__this).ItemDataBlock;
PlayerBackpackManager.ClearLocalSlot((InventorySlot)((itemDataBlock == null) ? 5 : ((int)itemDataBlock.inventorySlot)), true, true);
}
else
{
((Item)_4__this).SetCustomData(customData, true);
}
_4__this.m_applyTriggered = false;
result = false;
return false;
}
}
else
{
L.Debug("Custom Syringe was null!");
}
return true;
}
}
private static ExtraSyringeHandler? s_current;
private static readonly List<SyringeWrapper> s_syringeWrappers;
public static string ConfigPath { get; internal set; }
public static ExtraSyringeHandler Current
{
get
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
if ((Object)(object)s_current == (Object)null)
{
GameObject val = new GameObject();
s_current = val.AddComponent<ExtraSyringeHandler>();
Object.DontDestroyOnLoad((Object)val);
}
return s_current;
}
}
static ExtraSyringeHandler()
{
s_syringeWrappers = new List<SyringeWrapper>();
ConfigPath = "";
ClassInjector.RegisterTypeInIl2Cpp<ExtraSyringeHandler>();
}
[HideFromIl2Cpp]
public Coroutine StartCoroutine(CustomRoutine routine)
{
return ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp((IEnumerator)routine));
}
[HideFromIl2Cpp]
public Coroutine StartCoroutine(IEnumerator routine)
{
return ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(routine));
}
internal static void ClearSyringeList()
{
s_syringeWrappers.Clear();
}
internal static bool InvokeMoveNextOnApplySyringe(_ApplySyringe_d__18 instance, ref bool result)
{
SyringeWrapper syringeWrapper = null;
for (int i = 0; i < s_syringeWrappers.Count; i++)
{
SyringeWrapper syringeWrapper2 = s_syringeWrappers[i];
if (syringeWrapper2.Equals(instance))
{
syringeWrapper = syringeWrapper2;
break;
}
}
if (syringeWrapper == null)
{
syringeWrapper = new SyringeWrapper(instance);
s_syringeWrappers.Add(syringeWrapper);
}
return syringeWrapper.OnMoveNext(ref result);
}
}
[BepInPlugin("dev.flaff.gtfo.ExtraSyringeCustomization", "ExtraSyringeCustomization", "0.3.3")]
internal class MainPlugin : BasePlugin
{
internal static ManualLogSource? LogSource;
public override void Load()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
LogSource = ((BasePlugin)this).Log;
new Harmony("dev.flaff.gtfo.ExtraSyringeCustomization").PatchAll();
SyringeRegistryHandler.Properties.Register<SyringeMeleeBuffTimeProperty>();
SyringeRegistryHandler.Properties.Register<SyringeMovementMultiplierProperty>();
SyringeRegistryHandler.Properties.Register<SyringeHealthValueProperty>();
SyringeRegistryHandler.Properties.Register<SyringeAmmoValueProperty>();
SyringeRegistryHandler.Properties.Register<SyringeToolValueProperty>();
SyringeRegistryHandler.Properties.Register<SyringeDisinfectionValueProperty>();
SyringeRegistryHandler.Properties.Register<SyringeInfectionValueProperty>();
SyringeRegistryHandler.Properties.Register<SyringeSelfDestructProperty>();
SyringeRegistryHandler.Properties.Register<SyringeDOTProperty>();
SyringeRegistryHandler.Properties.Register<SyringeROTProperty>();
NetworkAPI.RegisterEvent<SelfDestruct>("Syringe-Self-Destruct", (Action<ulong, SelfDestruct>)delegate(ulong _, SelfDestruct packet)
{
SNet_Player val = default(SNet_Player);
if (SNet.Core.TryGetPlayer(packet.playerID, ref val, false))
{
SyringeSelfDestructProperty.DoExplodeEffect(((Il2CppObjectBase)val.PlayerAgent).Cast<PlayerAgent>());
}
});
}
}
internal static class PLUGIN_CONSTANTS
{
public const string PLUGIN_NAME = "ExtraSyringeCustomization";
public const string PLUGIN_VERSION = "0.3.3";
public const string PLUGIN_GUID = "dev.flaff.gtfo.ExtraSyringeCustomization";
}
internal sealed class SyringePropertyInfo : IRegisterable
{
public string PropertyName { get; }
public Type PropertyType { get; }
public SyringePropertyInfo(string name, Type type)
{
PropertyName = name;
PropertyType = type;
}
public static SyringePropertyInfo Create<T>() where T : SyringePropertyBase, new()
{
return new SyringePropertyInfo(new T().Name, typeof(T));
}
string IRegisterable.GetID()
{
return PropertyName;
}
}
}
namespace ExtraSyringeCustomization.Utils
{
internal abstract class AppliedRoutine : DelayedRoutineBase
{
public double Time { get; }
protected AppliedRoutine(double delay, double time)
: base(delay)
{
Time = time;
}
public abstract void Apply();
public abstract void Remove();
protected override IEnumerator CreateRoutine()
{
float t = 0f;
IEnumerator routine = CreateDelayRoutine(delegate(float newT)
{
t = newT;
});
while (routine.MoveNext())
{
yield return routine.Current;
}
Apply();
for (; (double)t < Time; t += Time.deltaTime)
{
yield return null;
}
Remove();
}
}
public abstract class CustomRoutine : IEnumerator
{
private readonly IEnumerator m_routine;
object IEnumerator.Current => m_routine.Current;
protected CustomRoutine()
{
m_routine = CreateRoutine();
}
protected abstract IEnumerator CreateRoutine();
bool IEnumerator.MoveNext()
{
return m_routine.MoveNext();
}
void IEnumerator.Reset()
{
m_routine.Reset();
}
}
public abstract class DelayedRoutine : DelayedRoutineBase
{
protected DelayedRoutine(double delay)
: base(delay)
{
}
public abstract void Activate();
protected override IEnumerator CreateRoutine()
{
IEnumerator routine = CreateDelayRoutine();
while (routine.MoveNext())
{
yield return routine.Current;
}
Activate();
}
}
public abstract class DelayedRoutineBase : CustomRoutine
{
public double Delay { get; }
protected DelayedRoutineBase(double delay)
{
Delay = delay;
}
protected IEnumerator CreateDelayRoutine()
{
return CreateDelayRoutine(null);
}
protected IEnumerator CreateDelayRoutine(Action<float>? timeRemainderCallback)
{
float t2;
for (t2 = 0f; (double)t2 < Delay; t2 += Time.deltaTime)
{
yield return null;
}
t2 -= (float)Delay;
timeRemainderCallback?.Invoke(t2);
}
}
public class DelayValue : MinMaxValue
{
public bool HasDelay { get; set; }
public override double GetValue(Random random)
{
if (!HasDelay)
{
return double.NaN;
}
return base.GetValue(random);
}
}
public interface IMovementModifier
{
double WalkSpeedMultiplier { get; set; }
double RunSpeedMultiplier { get; set; }
double CrouchSpeedMultiplier { get; set; }
double AirSpeedMultiplier { get; set; }
void Remove();
void SetAll(double value)
{
WalkSpeedMultiplier = value;
RunSpeedMultiplier = value;
CrouchSpeedMultiplier = value;
AirSpeedMultiplier = value;
}
}
internal static class L
{
private static ManualLogSource Source => MainPlugin.LogSource;
public static void Msg(object data)
{
Source.LogMessage(data);
}
public static void Info(object data)
{
Source.LogInfo(data);
}
public static void Debug(object data)
{
Source.LogDebug(data);
}
public static void Warn(object data)
{
Source.LogWarning(data);
}
public static void Error(object data)
{
Source.LogError(data);
}
}
public class MinMaxValue
{
public double Min { get; set; }
public double Max { get; set; }
public virtual double GetValue(double t)
{
if (t < 0.0)
{
t = 0.0;
}
else if (t > 1.0)
{
t = 1.0;
}
return GetValueUnclamped(t);
}
public virtual double GetValueUnclamped(double t)
{
double num = Min;
if (num != Max)
{
num += (Max - Min) * t;
}
return num;
}
public virtual double GetValue(Random random)
{
double num = Min;
if (num != Max)
{
num += random.NextDouble() * (Max - Min);
}
return num;
}
}
public static class MovementMultiplierManager
{
private sealed class MovementModifier : IMovementModifier, IEquatable<MovementModifier>
{
private static ulong s_lastID;
private double m_walkSpeed;
private double m_runSpeed;
private double m_crouchSpeed;
private double m_airSpeed;
private bool m_removed;
public ulong ID { get; }
public double WalkSpeedMultiplier
{
get
{
return m_walkSpeed;
}
set
{
if (!m_removed)
{
m_walkSpeed = value;
OnModifierChange();
}
}
}
public double RunSpeedMultiplier
{
get
{
return m_runSpeed;
}
set
{
if (!m_removed)
{
m_runSpeed = value;
OnModifierChange();
}
}
}
public double CrouchSpeedMultiplier
{
get
{
return m_crouchSpeed;
}
set
{
if (!m_removed)
{
m_crouchSpeed = value;
OnModifierChange();
}
}
}
public double AirSpeedMultiplier
{
get
{
return m_airSpeed;
}
set
{
if (!m_removed)
{
m_airSpeed = value;
OnModifierChange();
}
}
}
public MovementModifier()
{
m_walkSpeed = 1.0;
m_runSpeed = 1.0;
m_crouchSpeed = 1.0;
m_airSpeed = 1.0;
m_removed = false;
ID = s_lastID;
s_lastID++;
}
public void SetAll(double value)
{
m_walkSpeed = value;
m_runSpeed = value;
m_crouchSpeed = value;
m_airSpeed = value;
OnModifierChange();
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
public override bool Equals(object? obj)
{
if (obj is MovementModifier other)
{
return Equals(other);
}
return false;
}
public bool Equals(MovementModifier? other)
{
if (other == null)
{
return false;
}
return other.ID == ID;
}
public void Remove()
{
if (!m_removed && s_modifiers.Remove(this))
{
OnModifierChange();
m_removed = true;
}
}
}
public static List<Func<float>> s_onRefresh = new List<Func<float>>();
private static readonly List<MovementModifier> s_modifiers = new List<MovementModifier>();
private static float BaseWalkSpeed { get; set; } = 0f;
private static float BaseRunSpeed { get; set; }
private static float BaseCrouchSpeed { get; set; }
private static float BaseAirSpeed { get; set; }
private static void OnModifierChange()
{
PlayerDataBlock block = GameDataBlockBase<PlayerDataBlock>.GetBlock(1u);
GetDefaultMovementSpeed();
float num = 1f;
foreach (Func<float> item in s_onRefresh)
{
num *= item();
}
double num2 = (double)BaseWalkSpeed * (double)num;
double num3 = (double)BaseRunSpeed * (double)num;
double num4 = (double)BaseCrouchSpeed * (double)num;
double num5 = (double)BaseAirSpeed * (double)num;
if (s_modifiers.Count > 0)
{
foreach (MovementModifier s_modifier in s_modifiers)
{
num2 *= s_modifier.WalkSpeedMultiplier;
num3 *= s_modifier.RunSpeedMultiplier;
num4 *= s_modifier.CrouchSpeedMultiplier;
num5 *= s_modifier.AirSpeedMultiplier;
}
}
block.walkMoveSpeed = (float)num2;
block.runMoveSpeed = (float)num3;
block.crouchMoveSpeed = (float)num4;
block.airMoveSpeed = (float)num5;
}
public static (float walk, float run, float crouch, float air) GetDefaultMovementSpeed()
{
if (BaseWalkSpeed != 0f)
{
return (BaseWalkSpeed, BaseRunSpeed, BaseCrouchSpeed, BaseAirSpeed);
}
PlayerDataBlock block = GameDataBlockBase<PlayerDataBlock>.GetBlock(1u);
BaseWalkSpeed = block.walkMoveSpeed;
BaseRunSpeed = block.runMoveSpeed;
BaseCrouchSpeed = block.crouchMoveSpeed;
BaseAirSpeed = block.airMoveSpeed;
return (BaseWalkSpeed, BaseRunSpeed, BaseCrouchSpeed, BaseAirSpeed);
}
public static IMovementModifier CreateModifier()
{
MovementModifier movementModifier = new MovementModifier();
s_modifiers.Add(movementModifier);
return movementModifier;
}
public static void AddRefreshCallback(Func<float> onRefresh)
{
s_onRefresh.Add(onRefresh);
}
public static void Refresh()
{
OnModifierChange();
}
}
public class OverTimeIntervalValue : MinMaxValue
{
public bool RandomizeEveryInterval { get; set; }
}
public class OverTimeValue : MinMaxValue
{
public bool IsTimeBased { get; set; }
}
public static class PathUtil
{
public static string NiceRelativePath(string relativeTo, string path)
{
path = path.Replace(Path.DirectorySeparatorChar, '/');
string text = Path.GetRelativePath(relativeTo.Replace('/', Path.DirectorySeparatorChar), path.EndsWith('/') ? path : (path + "/")).Replace(Path.DirectorySeparatorChar, '/');
if (text == ".")
{
text = "";
}
text = "/" + text;
if (text.EndsWith("/"))
{
text = text.Substring(0, text.Length - 1);
}
return text;
}
}
}
namespace ExtraSyringeCustomization.Registries
{
public sealed class CustomSyringePropertyRegistry
{
internal sealed class RegistryImpl : Registry<SyringePropertyInfo>
{
protected override void OnRegisterFailed(SyringePropertyInfo entry, string failReason)
{
L.Warn("Failed to add syringe property with name '" + entry.PropertyName + "': " + failReason);
}
protected override void OnRegistered(SyringePropertyInfo entry)
{
L.Info("Added syringe property with name '" + entry.PropertyName + "'");
}
}
private readonly RegistryImpl m_registry;
internal RegistryImpl Registry => m_registry;
public CustomSyringePropertyRegistry()
{
m_registry = new RegistryImpl();
}
public void Register<T>() where T : SyringePropertyBase, new()
{
((RegistryBase<SyringePropertyInfo>)(object)Registry).Register(SyringePropertyInfo.Create<T>());
}
public void UnRegister<T>() where T : SyringePropertyBase, new()
{
((RegistryBase<SyringePropertyInfo>)(object)Registry).UnRegister(SyringePropertyInfo.Create<T>());
}
}
public sealed class CustomSyringeRegistry : Registry<CustomSyringeDefinition>
{
private const string SYRINGE_PREFIX = "SYRINGE_";
public bool TryGetEntry(uint syringeID, [NotNullWhen(true)] out CustomSyringeDefinition? syringe)
{
return ((RegistryBase<CustomSyringeDefinition>)(object)this).TryGetEntry(SyringeIDToRegistryID(syringeID), ref syringe);
}
protected override void OnRegistered(CustomSyringeDefinition entry)
{
uint syringeID = entry.SyringeID;
Dictionary<uint, ItemDataBlock> s_blockByID = GameDataBlockBase<ItemDataBlock>.s_blockByID;
if (s_blockByID == null || !s_blockByID.ContainsKey(syringeID))
{
L.Debug($"Added syringe with id '{syringeID}'");
L.Warn($"Custom Syringe Definition with ID '{syringeID}' does not currently have an item datablock entry");
}
else
{
L.Debug($"Added syringe with id '{syringeID}' (ItemDataBlock - {((GameDataBlockBase<ItemDataBlock>)(object)GameDataBlockBase<ItemDataBlock>.GetBlock(syringeID)).name})");
}
}
public static string SyringeIDToRegistryID(uint id)
{
return "SYRINGE_" + id;
}
public static uint RegistryIDToSyringeID(string id)
{
if (id.StartsWith("SYRINGE_"))
{
return uint.Parse(id.Substring("SYRINGE_".Length));
}
throw new ArgumentException("Invalid Registry ID given", "id");
}
}
public static class SyringeRegistryHandler
{
public static CustomSyringeRegistry Syringes { get; } = new CustomSyringeRegistry();
public static CustomSyringePropertyRegistry Properties { get; } = new CustomSyringePropertyRegistry();
}
}
namespace ExtraSyringeCustomization.Properties
{
public class PropertySequenceTiming
{
public bool IsRelativeToPreviousProperties { get; set; }
public DelayValue Delay { get; set; } = new DelayValue();
}
public abstract class SyringePropertyBase : IRegisterable
{
public bool Enabled { get; set; }
public PropertySequenceTiming Timing { get; set; } = new PropertySequenceTiming();
public abstract string Name { get; }
public abstract IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo sequenceInfo);
string IRegisterable.GetID()
{
return Name;
}
public virtual Type? GetDataType()
{
return null;
}
public virtual SyringePropertyData? GetData()
{
return null;
}
public virtual void SetData(SyringePropertyData? data)
{
}
}
public abstract class SyringePropertyBase<T> : SyringePropertyBase where T : SyringePropertyData, new()
{
public T Data { get; set; } = new T();
public override Type? GetDataType()
{
return typeof(T);
}
public sealed override SyringePropertyData? GetData()
{
return Data;
}
public sealed override void SetData(SyringePropertyData? data)
{
if (data is T data2)
{
Data = data2;
}
else
{
Data = new T();
}
}
}
public class SyringePropertyData
{
}
[JsonConverter(typeof(SyringePropertyListConverter))]
public sealed class SyringePropertyList
{
private readonly Dictionary<string, SyringePropertyBase> m_properties = new Dictionary<string, SyringePropertyBase>();
public void AddProperty(SyringePropertyBase property)
{
if (property == null)
{
throw new ArgumentNullException("property");
}
string name = property.Name;
if (m_properties.ContainsKey(name))
{
throw new ArgumentException("Syringe Property with name '" + name + "' already exists!", "property");
}
m_properties.Add(name, property);
}
public IEnumerator<SyringePropertyBase> GetAllProperties()
{
return m_properties.Values.GetEnumerator();
}
public SyringePropertyBase[] GetProperties()
{
return m_properties.Values.Where((SyringePropertyBase property) => property.Enabled).ToArray();
}
public IEnumerable<KeyValuePair<string, SyringePropertyBase>> GetEntries()
{
foreach (string key in m_properties.Keys)
{
yield return new KeyValuePair<string, SyringePropertyBase>(key, m_properties[key]);
}
}
}
public sealed class SyringePropertySequenceInfo
{
private bool m_forceComplete;
public bool ForceComplete => m_forceComplete;
public double DeltaTime
{
get
{
if (m_forceComplete)
{
return double.MaxValue;
}
return Time.deltaTime;
}
}
public void ForceCompletion()
{
m_forceComplete = true;
}
}
}
namespace ExtraSyringeCustomization.Properties.BuiltIn
{
public sealed class SyringeAmmoValueProperty : SyringePropertyMinMaxBase
{
public override string Name => "Ammo";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
float num = (float)base.Data.GetValue(random);
PlayerBackpackManager.GiveAmmoToPlayer(player.Owner, num, num, 0f);
yield break;
}
}
public sealed class SyringeDisinfectionValueProperty : SyringePropertyMinMaxBase
{
public override string Name => "Disinfection";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
player.Damage.ModifyInfection(new pInfection
{
amount = 0f - (float)base.Data.GetValue(random),
effect = (pInfectionEffect)1,
mode = (pInfectionMode)1
}, true, true);
yield break;
}
}
public sealed class SyringeDOTProperty : SyringePropertyBase<SyringeDOTProperty.JsonData>
{
public sealed class JsonData : SyringePropertyData
{
public MinMaxValue TotalTime { get; set; } = new MinMaxValue();
public OverTimeIntervalValue DamageInterval { get; set; } = new OverTimeIntervalValue();
public OverTimeValue Damage { get; set; } = new OverTimeValue();
public bool ClearWhenDown { get; set; } = true;
}
public override string Name => "DamageOverTime";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
double value = base.Data.TotalTime.GetValue(random);
L.Debug($"Apply DOT! (Total Time: {value})");
IEnumerator routine = InnerRoutine(player, random, value, info);
while (!info.ForceComplete && routine.MoveNext())
{
yield return routine.Current;
}
}
private IEnumerator InnerRoutine(PlayerAgent player, Random random, double totalTime, SyringePropertySequenceInfo info)
{
double t = 0.0;
double interval = 0.0;
double damageInterval = base.Data.DamageInterval.GetValue(random);
while (t < totalTime)
{
while (interval < damageInterval && t < totalTime)
{
yield return null;
interval += info.DeltaTime;
t += info.DeltaTime;
}
interval -= damageInterval;
if ((int)player.Locomotion.m_currentStateEnum == 7)
{
if (base.Data.ClearWhenDown)
{
break;
}
yield return null;
continue;
}
double num = ((!base.Data.Damage.IsTimeBased) ? base.Data.Damage.GetValue(random) : base.Data.Damage.GetValue(t / totalTime));
((Dam_SyncedDamageBase)player.Damage).NoAirDamage((float)num);
if (base.Data.DamageInterval.RandomizeEveryInterval)
{
damageInterval = base.Data.DamageInterval.GetValue(random);
}
}
}
}
public sealed class SyringeHealthValueProperty : SyringePropertyMinMaxBase
{
public override string Name => "Health";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
PlayerBackpackManager.PickupHealthRel((float)base.Data.GetValue(random), player);
yield break;
}
}
public sealed class SyringeInfectionValueProperty : SyringePropertyMinMaxBase
{
public override string Name => "Infection";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
player.Damage.ModifyInfection(new pInfection
{
amount = (float)base.Data.GetValue(random),
effect = (pInfectionEffect)0,
mode = (pInfectionMode)1
}, true, true);
yield break;
}
}
public sealed class SyringeMeleeBuffTimeProperty : SyringePropertyMinMaxBase
{
public override string Name => "MeleeBuffTime";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
double value = base.Data.GetValue(random);
float num = (float)(Clock.TimeDouble + value);
L.Debug($"Apply MeleeBuffTime! (Time: {value}, Game End Time: {num})");
player.MeleeBuffTimer = num;
yield break;
}
}
public sealed class SyringeMovementMultiplierProperty : SyringePropertyMinMaxBase<SyringeMovementMultiplierProperty.JsonData>
{
public sealed class JsonData : BasicMinMaxData
{
public MinMaxValue Time { get; set; } = new MinMaxValue();
public bool ClearWhenDown { get; set; } = true;
}
public override string Name => "MovementMultiplier";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
double value = base.Data.Time.GetValue(random);
double value2 = base.Data.GetValue(random);
L.Debug($"Apply Movement Multiplier! (time: {value}, value: {value2})");
IMovementModifier modifier = MovementMultiplierManager.CreateModifier();
modifier.SetAll(value2);
IEnumerator routine = InnerRoutine(value, info);
while (!info.ForceComplete && routine.MoveNext() && (!base.Data.ClearWhenDown || (int)player.Locomotion.m_currentStateEnum != 7))
{
yield return routine.Current;
}
modifier.Remove();
}
private static IEnumerator InnerRoutine(double time, SyringePropertySequenceInfo info)
{
for (double t = 0.0; t < time; t += info.DeltaTime)
{
yield return null;
}
}
}
public class BasicMinMaxData : SyringePropertyData
{
public double Min { get; set; }
public double Max { get; set; }
public double GetValue(Random random)
{
double num = Min;
if (num != Max)
{
num += random.NextDouble() * (Max - Min);
}
return num;
}
}
public abstract class SyringePropertyMinMaxBase<TData> : SyringePropertyBase<TData> where TData : BasicMinMaxData, new()
{
}
public abstract class SyringePropertyMinMaxBase : SyringePropertyMinMaxBase<BasicMinMaxData>
{
}
public sealed class SyringeROTProperty : SyringePropertyBase<SyringeROTProperty.JsonData>
{
public sealed class JsonData : SyringePropertyData
{
public MinMaxValue TotalTime { get; set; } = new MinMaxValue();
public OverTimeIntervalValue RegenInterval { get; set; } = new OverTimeIntervalValue();
public OverTimeValue Health { get; set; } = new OverTimeValue();
public bool ClearWhenDown { get; set; } = true;
}
public override string Name => "RegenOverTime";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
double value = base.Data.TotalTime.GetValue(random);
L.Debug($"Apply ROT! (Total Time: {value})");
IEnumerator routine = InnerRoutine(player, random, value, info);
while (!info.ForceComplete && routine.MoveNext())
{
yield return routine.Current;
}
}
private IEnumerator InnerRoutine(PlayerAgent player, Random random, double totalTime, SyringePropertySequenceInfo info)
{
double t = 0.0;
double interval = 0.0;
double regenInterval = base.Data.RegenInterval.GetValue(random);
while (t < totalTime)
{
while (interval < regenInterval && t < totalTime)
{
yield return null;
interval += info.DeltaTime;
t += info.DeltaTime;
}
interval -= regenInterval;
if ((int)player.Locomotion.m_currentStateEnum == 7)
{
if (base.Data.ClearWhenDown)
{
break;
}
yield return null;
continue;
}
double num = ((!base.Data.Health.IsTimeBased) ? base.Data.Health.GetValue(random) : base.Data.Health.GetValue(t / totalTime));
double num2 = num / (double)player.PlayerData.health;
player.GiveHealth(player, (float)num2);
if (base.Data.RegenInterval.RandomizeEveryInterval)
{
regenInterval = base.Data.RegenInterval.GetValue(random);
}
}
}
}
public sealed class SyringeSelfDestructProperty : SyringePropertyBase<SyringeSelfDestructProperty.JsonData>
{
public sealed class JsonData : SyringePropertyData
{
public double Damage { get; set; }
public double Radius { get; set; }
}
private static FX_Pool s_detonateFX;
public override string Name => "SelfDestruct";
private static FX_Pool DetonateFX
{
get
{
if ((Object)(object)s_detonateFX == (Object)null)
{
s_detonateFX = FX_Manager.GetEffectPool(AssetShardManager.GetLoadedAsset<GameObject>("Assets/AssetPrefabs/FX_Effects/FX_Tripmine.prefab", false));
}
return s_detonateFX;
}
}
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
L.Debug("Self Destruct : Activate!");
DamageUtil.DoExplosionDamage(player.FPSCamera.Position, (float)base.Data.Radius, (float)base.Data.Damage, LayerManager.MASK_EXPLOSION_TARGETS, LayerManager.MASK_EXPLOSION_BLOCKERS, false, 0f);
DoExplodeEffect(player);
((Dam_SyncedDamageBase)player.Damage).ExplosionDamage((float)base.Data.Damage, ((Agent)player).Position, Vector3.up, 0u);
NetworkAPI.InvokeEvent<SelfDestruct>("Syringe-Self-Destruct", new SelfDestruct
{
playerID = player.Owner.Lookup
}, (SNet_ChannelType)2);
yield break;
}
public static void DoExplodeEffect(PlayerAgent player)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
player.Sound.Post(EVENTS.STICKYMINEEXPLODE, true);
((FX_EffectBase)DetonateFX.AquireEffect()).Play((FX_Trigger)null, ((Component)player).transform.position, Quaternion.LookRotation(Vector3.up));
}
}
public sealed class SyringeToolValueProperty : SyringePropertyMinMaxBase
{
public override string Name => "Tool";
public override IEnumerator Apply(PlayerAgent player, SyringeFirstPerson syringe, Random random, SyringePropertySequenceInfo info)
{
float num = (float)base.Data.GetValue(random);
PlayerBackpackManager.GiveAmmoToPlayer(player.Owner, 0f, 0f, num);
yield break;
}
}
}
namespace ExtraSyringeCustomization.Patches
{
[HarmonyPatch]
internal sealed class GameDataInitPatch
{
private class RawJSONFile
{
public List<CustomSyringeDefinition> Syringes { get; set; }
public RawJSONFile()
{
Syringes = new List<CustomSyringeDefinition>();
}
}
[HarmonyPatch(typeof(GameDataInit), "Initialize")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void InitializePatch()
{
string text = ConfigManager.CustomPath;
if (text == null)
{
text = Path.Combine(ConfigManager.GameDataPath, "Custom");
}
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
}
string text2 = Path.Combine(ConfigManager.CustomPath, "ExtraSyringeCustomization");
if (!Directory.Exists(text2))
{
Directory.CreateDirectory(text2);
}
string text3 = Path.Combine(text2, "syringes.json");
string path = Path.Combine(text2, "GENERATED_syringe-properties.json");
string path2 = Path.Combine(text2, "GENERATED_example-syringes.json");
ExtraSyringeHandler.ConfigPath = text2;
IEnumerable<SyringePropertyInfo> entries = ((RegistryBase<SyringePropertyInfo>)(object)SyringeRegistryHandler.Properties.Registry).GetEntries();
if (!File.Exists(path))
{
SyringePropertyList syringePropertyList = new SyringePropertyList();
foreach (SyringePropertyInfo item in entries)
{
syringePropertyList.AddProperty((SyringePropertyBase)Activator.CreateInstance(item.PropertyType));
}
L.Info("Generating List of all Syringe Properties at '" + PathUtil.NiceRelativePath(ConfigManager.GameDataPath, path) + "'");
File.WriteAllText(path, JsonSerializer.Serialize(syringePropertyList, new JsonSerializerOptions
{
WriteIndented = true
}));
}
else
{
L.Debug("Skipping Syringe Property List file generation. (Delete '" + PathUtil.NiceRelativePath(ConfigManager.GameDataPath, path) + "' to regenerate it)");
}
if (!File.Exists(path2))
{
RawJSONFile rawJSONFile = new RawJSONFile();
CustomSyringeDefinition customSyringeDefinition = new CustomSyringeDefinition();
customSyringeDefinition.SyringeID = 999u;
rawJSONFile.Syringes.Add(customSyringeDefinition);
foreach (SyringePropertyInfo item2 in entries)
{
customSyringeDefinition.Properties.AddProperty((SyringePropertyBase)Activator.CreateInstance(item2.PropertyType));
}
L.Info("Generating Syringe Example File at '" + PathUtil.NiceRelativePath(ConfigManager.GameDataPath, path2) + "'");
File.WriteAllText(path2, JsonSerializer.Serialize(rawJSONFile, new JsonSerializerOptions
{
WriteIndented = true
}));
}
else
{
L.Debug("Skipping Syringe Example file generation. (Delete '" + PathUtil.NiceRelativePath(ConfigManager.GameDataPath, path2) + "' to regenerate it)");
}
L.Debug("Custom Syringes Path: " + text3);
if (!File.Exists(text3))
{
L.Warn("No syringe definition file found. (Create one at '" + PathUtil.NiceRelativePath(ConfigManager.GameDataPath, text3) + "')");
return;
}
try
{
RawJSONFile rawJSONFile2 = JsonSerializer.Deserialize<RawJSONFile>(File.ReadAllText(text3), new JsonSerializerOptions
{
AllowTrailingCommas = true
});
if (rawJSONFile2 == null)
{
L.Warn("Syringe File was empty! Rewriting to basic blank json!");
rawJSONFile2 = new RawJSONFile();
File.WriteAllText(text3, JsonSerializer.Serialize(rawJSONFile2, new JsonSerializerOptions
{
WriteIndented = true
}));
return;
}
if (rawJSONFile2.Syringes == null)
{
L.Warn("No 'Syringes' property was defined in JSON! Rewriting json to include it!");
rawJSONFile2.Syringes = new List<CustomSyringeDefinition>();
File.WriteAllText(text3, JsonSerializer.Serialize(rawJSONFile2, new JsonSerializerOptions
{
WriteIndented = true
}));
return;
}
foreach (CustomSyringeDefinition syringe in rawJSONFile2.Syringes)
{
if (syringe != null)
{
try
{
((RegistryBase<CustomSyringeDefinition>)(object)SyringeRegistryHandler.Syringes).Register(syringe);
}
catch (Exception value)
{
L.Error($"Error whilst adding syringe with id {syringe.SyringeID}: {value}");
}
}
}
}
catch (Exception value2)
{
L.Error($"Error whilst reading syringes file: {value2}");
}
}
}
[HarmonyPatch]
internal static class SyringePatches
{
[HarmonyPatch(typeof(_ApplySyringe_d__18), "MoveNext")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool MoveNextPatch(_ApplySyringe_d__18 __instance, ref bool __result)
{
return ExtraSyringeHandler.InvokeMoveNextOnApplySyringe(__instance, ref __result);
}
[HarmonyPatch(typeof(GS_Lobby), "Enter")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void EnterLobbyPatch()
{
ExtraSyringeHandler.ClearSyringeList();
}
}
}
namespace ExtraSyringeCustomization.Packets
{
public struct SelfDestruct
{
public ulong playerID;
}
public struct Vec3
{
public float x;
public float y;
public float z;
public Vec3(Vector3 vec)
: this(vec.x, vec.y, vec.z)
{
}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
public Vec3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public static implicit operator Vec3(Vector3 vec)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
return new Vec3(vec);
}
public static implicit operator Vector3(Vec3 vec)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(vec.x, vec.y, vec.z);
}
}
}
namespace ExtraSyringeCustomization.Converters
{
public sealed class SyringePropertyConverter : JsonConverter<SyringePropertyBase>
{
private sealed class V1DataFormat
{
public DelayValue? Delay { get; set; }
public bool Enabled { get; set; }
}
private readonly string? m_fixedID;
private readonly bool m_asMap;
public SyringePropertyConverter()
{
m_fixedID = null;
m_asMap = false;
}
public SyringePropertyConverter(string id)
{
m_fixedID = id;
m_asMap = true;
}
public override bool CanConvert(Type typeToConvert)
{
return typeof(SyringePropertyBase).IsAssignableFrom(typeToConvert);
}
private static string ReadPropertyName(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
string text = reader.GetString();
if (options.PropertyNameCaseInsensitive)
{
text = text.ToLower();
}
return text;
}
private static string GetPropertyName(string baseName, JsonSerializerOptions options)
{
string text = options.PropertyNamingPolicy?.ConvertName(baseName) ?? baseName;
if (options.PropertyNameCaseInsensitive)
{
text = text.ToLower();
}
return text;
}
private void ParseAsV1MapData(ref Utf8JsonReader reader, SyringePropertyBase result, JsonSerializerOptions options)
{
Utf8JsonReader reader2 = reader;
V1DataFormat v1DataFormat = JsonSerializer.Deserialize<V1DataFormat>(ref reader2, options);
result.Enabled = v1DataFormat?.Enabled ?? true;
if (v1DataFormat?.Delay != null)
{
result.Timing.Delay = v1DataFormat.Delay;
}
Type dataType = result.GetDataType();
if (dataType != null)
{
SyringePropertyData syringePropertyData = (SyringePropertyData)JsonSerializer.Deserialize(ref reader, dataType, options);
if (syringePropertyData == null)
{
syringePropertyData = (SyringePropertyData)Activator.CreateInstance(dataType);
}
result.SetData(syringePropertyData);
}
else
{
reader = reader2;
}
}
public override SyringePropertyBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Utf8JsonReader reader2 = reader;
SyringePropertyBase syringePropertyBase = null;
if (reader.TokenType == JsonTokenType.Null)
{
return syringePropertyBase;
}
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException($"Unexpected token '{reader.TokenType}' (expected {1})");
}
string text = m_fixedID;
if (!string.IsNullOrEmpty(text))
{
SyringePropertyInfo syringePropertyInfo = default(SyringePropertyInfo);
if (!((RegistryBase<SyringePropertyInfo>)(object)SyringeRegistryHandler.Properties.Registry).TryGetEntry(text, ref syringePropertyInfo))
{
throw new JsonException("Failed to resolve custom syringe property with id '" + text + "'");
}
syringePropertyBase = (SyringePropertyBase)Activator.CreateInstance(syringePropertyInfo.PropertyType);
}
string propertyName = GetPropertyName("ID", options);
bool? flag = null;
string propertyName2 = GetPropertyName("Enabled", options);
PropertySequenceTiming propertySequenceTiming = null;
string propertyName3 = GetPropertyName("Timing", options);
SyringePropertyData syringePropertyData = null;
string propertyName4 = GetPropertyName("Data", options);
bool flag2 = false;
SyringePropertyInfo syringePropertyInfo2 = default(SyringePropertyInfo);
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
if (text == null || syringePropertyBase == null)
{
throw new JsonException("An ID field is required!");
}
if (!flag.HasValue)
{
flag = true;
}
if (flag2 && syringePropertyData == null)
{
throw new JsonException("A Data field is required!");
}
syringePropertyBase.Enabled = flag.Value;
if (flag2)
{
syringePropertyBase.SetData(syringePropertyData);
}
return syringePropertyBase;
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException($"Unexpected token '{reader.TokenType}' (expected {5} or {2})");
}
string text2 = ReadPropertyName(ref reader, options);
if (!reader.Read())
{
break;
}
if (!m_asMap && text2 == propertyName)
{
if (text != null)
{
throw new JsonException("An ID field is already specified!");
}
text = reader.GetString();
if (text == null)
{
throw new JsonException("Syringe Property ID cannot be null");
}
if (!((RegistryBase<SyringePropertyInfo>)(object)SyringeRegistryHandler.Properties.Registry).TryGetEntry(text, ref syringePropertyInfo2))
{
throw new JsonException("Failed to resolve custom syringe property with id '" + text + "'");
}
syringePropertyBase = (SyringePropertyBase)Activator.CreateInstance(syringePropertyInfo2.PropertyType);
flag2 = syringePropertyBase.GetDataType() != null;
}
else if (text2 == propertyName2)
{
if (flag.HasValue)
{
throw new JsonException("An Enabled field is already specified!");
}
flag = reader.GetBoolean();
}
else if (text2 == propertyName3)
{
if (propertySequenceTiming != null)
{
throw new JsonException("A Timing field is already specified!");
}
propertySequenceTiming = JsonSerializer.Deserialize<PropertySequenceTiming>(ref reader, options);
if (propertySequenceTiming == null)
{
propertySequenceTiming = new PropertySequenceTiming();
}
}
else if (text2 == propertyName4)
{
if (syringePropertyData != null)
{
throw new JsonException("A Data field is already specified!");
}
if (text == null)
{
throw new JsonException("An ID field must come before a Data field!");
}
if (!flag2)
{
throw new JsonException("A Data field is not allowed for syringe property '" + text + "'");
}
Type dataType = syringePropertyBase.GetDataType();
syringePropertyData = (SyringePropertyData)JsonSerializer.Deserialize(ref reader, dataType, options);
if (syringePropertyData == null)
{
syringePropertyData = (SyringePropertyData)Activator.CreateInstance(dataType);
}
}
else
{
if (m_asMap)
{
ParseAsV1MapData(ref reader2, syringePropertyBase, options);
reader = reader2;
return syringePropertyBase;
}
L.Warn("Unsupport field for json syringe property '" + text2 + "'");
reader.Skip();
}
}
throw new JsonException("Unexpected end of input.");
}
public override void Write(Utf8JsonWriter writer, SyringePropertyBase value, JsonSerializerOptions options)
{
writer.WriteStartObject();
if (!m_asMap)
{
writer.WriteString("ID", m_fixedID);
}
writer.WritePropertyName("Timing");
JsonSerializer.Serialize(writer, value.Timing ?? new PropertySequenceTiming(), options);
writer.WriteBoolean("Enabled", value.Enabled);
Type dataType = value.GetDataType();
if (dataType != null)
{
writer.WritePropertyName("Data");
JsonSerializer.Serialize(writer, value.GetData(), dataType, options);
}
writer.WriteEndObject();
}
}
public class SyringePropertyListConverter : JsonConverter<SyringePropertyList>
{
private readonly bool m_writeAsMap;
public SyringePropertyListConverter()
: this(writeAsMap: false)
{
}
public SyringePropertyListConverter(bool writeAsMap)
{
m_writeAsMap = writeAsMap;
}
private static SyringePropertyList ReadAsArray(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
SyringePropertyList syringePropertyList = new SyringePropertyList();
new JsonSerializerOptions(options).Converters.Add(new SyringePropertyConverter());
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
return syringePropertyList;
}
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException($"Unexpected token '{reader.TokenType}' (expected {1} or {4})");
}
SyringePropertyBase syringePropertyBase = JsonSerializer.Deserialize<SyringePropertyBase>(ref reader, options);
if (syringePropertyBase != null)
{
syringePropertyList.AddProperty(syringePropertyBase);
}
}
throw new JsonException("Unexpected end of input.");
}
private static SyringePropertyList ReadAsMap(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
SyringePropertyList syringePropertyList = new SyringePropertyList();
SyringePropertyInfo syringePropertyInfo = default(SyringePropertyInfo);
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return syringePropertyList;
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException($"Unexpected token '{reader.TokenType}' (expected {5})");
}
string @string = reader.GetString();
if (@string == null || !((RegistryBase<SyringePropertyInfo>)(object)SyringeRegistryHandler.Properties.Registry).TryGetEntry(@string, ref syringePropertyInfo))
{
throw new JsonException("Failed to resolve custom syringe property with id '" + @string + "'");
}
JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(options);
jsonSerializerOptions.Converters.Add(new SyringePropertyConverter(@string));
SyringePropertyBase syringePropertyBase = (SyringePropertyBase)JsonSerializer.Deserialize(ref reader, syringePropertyInfo.PropertyType, jsonSerializerOptions);
if (syringePropertyBase == null)
{
syringePropertyBase = (SyringePropertyBase)Activator.CreateInstance(syringePropertyInfo.PropertyType);
syringePropertyBase.Enabled = false;
}
syringePropertyList.AddProperty(syringePropertyBase);
}
throw new JsonException("Unexpected end of input.");
}
public override SyringePropertyList Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return new SyringePropertyList();
}
if (reader.TokenType == JsonTokenType.StartObject)
{
return ReadAsMap(ref reader, options);
}
if (reader.TokenType == JsonTokenType.StartArray)
{
return ReadAsArray(ref reader, options);
}
throw new JsonException($"Unexpected token '{reader.TokenType}' (expected {1} or {3})");
}
public override void Write(Utf8JsonWriter writer, SyringePropertyList value, JsonSerializerOptions options)
{
if (m_writeAsMap)
{
WriteAsMap(writer, value, options);
}
else
{
WriteAsArray(writer, value, options);
}
}
private static void WriteAsArray(Utf8JsonWriter writer, SyringePropertyList value, JsonSerializerOptions options)
{
writer.WriteStartArray();
JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(options);
jsonSerializerOptions.Converters.Add(new SyringePropertyConverter());
SyringePropertyBase[] properties = value.GetProperties();
foreach (SyringePropertyBase value2 in properties)
{
JsonSerializer.Serialize(writer, value2, jsonSerializerOptions);
}
writer.WriteEndArray();
}
private static void WriteAsMap(Utf8JsonWriter writer, SyringePropertyList value, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (KeyValuePair<string, SyringePropertyBase> entry in value.GetEntries())
{
writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(entry.Key) ?? entry.Key);
JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(options);
jsonSerializerOptions.Converters.Add(new SyringePropertyConverter(entry.Key));
JsonSerializer.Serialize(writer, entry.Value, entry.Value.GetType(), jsonSerializerOptions);
}
writer.WriteEndObject();
}
}
}