using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RpgStatusEffects")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RpgStatusEffects")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f0207a1b-c30c-4443-9d71-04c8e6c57b88")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace RPGStatusEffects
{
[BepInPlugin("com.Fire.rpgstatuseffects", "RPGStatusEffects", "1.0.1")]
public class RPGStatusEffects : BaseUnityPlugin
{
[HarmonyPatch(typeof(ObjectDB), "Awake")]
public static class ObjectDB_Awake_Path
{
public static void Postfix()
{
if (IsObjectDBValid())
{
AddItems(itemPrefabs);
Instance.SetupStatusEffects();
RecipeManager.SetupRecipe();
}
}
}
[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
public static class Object_CopyOtherDB_Path
{
public static void Postfix()
{
if (!IsObjectDBValid())
{
if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: ObjectDB not valid in CopyOtherDB, skipping item addition.");
}
}
else
{
AddItems(itemPrefabs);
Instance.SetupStatusEffects();
}
}
}
[HarmonyPatch(typeof(ZNetScene), "Awake")]
public static class ZNetScene_Awake_Path
{
public static void Prefix(ZNetScene __instance)
{
if ((Object)(object)__instance == (Object)null)
{
if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: No ZNetScene found");
}
}
else
{
AddPrefabsToZNetScene(__instance);
}
}
}
[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
public static class TauntAIUpdatePatch
{
private static readonly MethodInfo setAlertedMethod = typeof(MonsterAI).GetMethod("SetAlerted", BindingFlags.Instance | BindingFlags.NonPublic);
public static void Postfix(MonsterAI __instance, float dt)
{
if ((Object)(object)__instance == (Object)null)
{
return;
}
Character component = ((Component)__instance).GetComponent<Character>();
if ((Object)(object)component == (Object)null || component.IsPlayer())
{
return;
}
SEMan sEMan = component.GetSEMan();
if (sEMan == null)
{
return;
}
int stableHashCode = StringExtensionMethods.GetStableHashCode("Taunted");
TauntEffect tauntEffect = sEMan.GetStatusEffect(stableHashCode) as TauntEffect;
if ((Object)(object)tauntEffect != (Object)null && (Object)(object)tauntEffect.Taunter != (Object)null && ((StatusEffect)tauntEffect).m_ttl > 0f)
{
typeof(MonsterAI).GetField("m_targetCreature", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(__instance, tauntEffect.Taunter);
FieldInfo field = typeof(MonsterAI).GetField("m_fleeIfHurtWhenTargetCantBeReached", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = typeof(MonsterAI).GetField("m_fleeIfLowHealth", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field3 = typeof(MonsterAI).GetField("m_enableHuntPlayer", BindingFlags.Instance | BindingFlags.NonPublic);
if (!originalHuntStates.ContainsKey(component))
{
bool flag = field != null && (bool)field.GetValue(__instance);
float num = ((field2 != null) ? ((float)field2.GetValue(__instance)) : 0f);
bool flag2 = field3 != null && (bool)field3.GetValue(__instance);
originalHuntStates[component] = (flag, num > 0f, flag2);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Stored original states for {1}: fleeIfHurt={2}, fleeIfLowHealth={3}, enableHuntPlayer={4}.", "RPGStatusEffects", ((Object)component).name, flag, num > 0f, flag2));
if (field != null)
{
Debug.Log((object)("RPGStatusEffects: Set fleeIfHurtWhenTargetCantBeReached=false for " + ((Object)component).name + " during taunt."));
}
if (field2 != null)
{
Debug.Log((object)("RPGStatusEffects: Set fleeIfLowHealth=0 for " + ((Object)component).name + " during taunt."));
}
if (field3 != null)
{
Debug.Log((object)("RPGStatusEffects: Set enableHuntPlayer=true for " + ((Object)component).name + " during taunt."));
}
if (setAlertedMethod != null)
{
Debug.Log((object)("RPGStatusEffects: Called SetAlerted(true) for " + ((Object)component).name + " during taunt."));
}
Debug.Log((object)string.Format("{0}: Taunt locked enemy {1} to player (remaining: {2:F1}s).", "RPGStatusEffects", ((Object)component).name, ((StatusEffect)tauntEffect).m_ttl));
}
lastTauntLogTimes[component] = ((StatusEffect)tauntEffect).m_ttl;
}
if (field != null)
{
field.SetValue(__instance, false);
}
if (field2 != null)
{
field2.SetValue(__instance, 0f);
}
if (field3 != null)
{
field3.SetValue(__instance, true);
}
if (setAlertedMethod != null)
{
setAlertedMethod.Invoke(__instance, new object[1] { true });
}
}
else
{
if (!lastTauntLogTimes.Remove(component))
{
return;
}
if (originalHuntStates.TryGetValue(component, out (bool, bool, bool) value))
{
FieldInfo field4 = typeof(MonsterAI).GetField("m_fleeIfHurtWhenTargetCantBeReached", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field5 = typeof(MonsterAI).GetField("m_fleeIfLowHealth", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field6 = typeof(MonsterAI).GetField("m_enableHuntPlayer", BindingFlags.Instance | BindingFlags.NonPublic);
if (field4 != null)
{
field4.SetValue(__instance, value.Item1);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Restored fleeIfHurtWhenTargetCantBeReached={1} for {2}.", "RPGStatusEffects", value.Item1, ((Object)component).name));
}
}
if (field5 != null)
{
field5.SetValue(__instance, value.Item2 ? 0.2f : 0f);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Restored fleeIfLowHealth={1} for {2}.", "RPGStatusEffects", value.Item2 ? 0.2f : 0f, ((Object)component).name));
}
}
if (field6 != null)
{
field6.SetValue(__instance, value.Item3);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Restored enableHuntPlayer={1} for {2}.", "RPGStatusEffects", value.Item3, ((Object)component).name));
}
}
originalHuntStates.Remove(component);
}
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Taunt ended on " + ((Object)component).name + "."));
}
}
}
}
[HarmonyPatch(typeof(Character), "Damage")]
public static class SetTauntOnDamagePatch
{
public static void Prefix(Character __instance, ref HitData hit)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if (hit == null || ((ZDOID)(ref hit.m_attacker)).IsNone() || __instance.IsPlayer() || hit.m_statusEffectHash != StringExtensionMethods.GetStableHashCode("Taunted"))
{
return;
}
GameObject obj = ZNetScene.instance.FindInstance(hit.m_attacker);
Character val = ((obj != null) ? obj.GetComponent<Character>() : null);
if ((Object)(object)val == (Object)null)
{
return;
}
SEMan sEMan = __instance.GetSEMan();
if (sEMan == null)
{
return;
}
TauntEffect tauntEffect = sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Taunted")) as TauntEffect;
if ((Object)(object)tauntEffect == (Object)null)
{
tauntEffect = sEMan.AddStatusEffect(StringExtensionMethods.GetStableHashCode("Taunted"), true, 0, 0f) as TauntEffect;
}
if (!((Object)(object)tauntEffect != (Object)null))
{
return;
}
tauntEffect.Taunter = val;
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Applied taunt from player to " + ((Object)__instance).name + "."));
}
if (!val.IsPlayer())
{
return;
}
SEMan sEMan2 = val.GetSEMan();
TauntingEffect tauntingEffect = StatusEffectManager.GetEffect("Taunting") as TauntingEffect;
if ((Object)(object)tauntingEffect != (Object)null)
{
tauntingEffect.Duration = tauntEffect.Duration;
sEMan2.AddStatusEffect((StatusEffect)(object)tauntingEffect, true, 0, 0f);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Applied Taunting effect to player {1} for {2}s.", "RPGStatusEffects", ((Object)val).name, tauntingEffect.Duration));
}
}
}
}
[CompilerGenerated]
private sealed class <InitializeStatusEffects>d__24 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public RPGStatusEffects <>4__this;
private int <maxAttempts>5__2;
private int <attempts>5__3;
private float <approximateTimeSpent>5__4;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <InitializeStatusEffects>d__24(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Expected O, but got Unknown
int num = <>1__state;
RPGStatusEffects rPGStatusEffects = <>4__this;
switch (num)
{
default:
return false;
case 0:
{
<>1__state = -1;
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name == "start")
{
if (rPGStatusEffects.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Main menu detected, skipping initialization.");
}
return false;
}
<maxAttempts>5__2 = 100;
<attempts>5__3 = 0;
<approximateTimeSpent>5__4 = 0f;
break;
}
case 1:
<>1__state = -1;
<approximateTimeSpent>5__4 += 0.1f;
break;
}
if (!IsObjectDBValid() || (Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null || ZNetScene.instance.m_prefabs.Count == 0)
{
if (rPGStatusEffects.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Waiting for ObjectDB and ZNetScene (attempt {1}/{2})...", "RPGStatusEffects", <attempts>5__3 + 1, <maxAttempts>5__2));
}
<attempts>5__3++;
if (<approximateTimeSpent>5__4 >= 10f)
{
Debug.LogError((object)string.Format("{0}: ObjectDB and ZNetScene failed to initialize after {1} attempts.", "RPGStatusEffects", <maxAttempts>5__2));
return false;
}
<>2__current = (object)new WaitForSeconds(0.1f);
<>1__state = 1;
return true;
}
rPGStatusEffects.ValidateConfigs();
rPGStatusEffects.SetupStatusEffects();
RecipeManager.SetupRecipe();
rPGStatusEffects.isInitialized = true;
if (rPGStatusEffects.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Status effects and recipe initialized.");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public static RPGStatusEffects Instance;
private readonly Harmony harmony = new Harmony("com.Fire.rpgstatuseffects");
public const string PluginGUID = "com.Fire.rpgstatuseffects";
public const string PluginName = "RPGStatusEffects";
public const string PluginVersion = "1.0.1";
public ConfigSync configSync;
public SyncedConfigEntry<bool> configVerboseLogging;
public SyncedConfigEntry<float> configPurityDuration;
public SyncedConfigEntry<float> configTauntDuration;
public SyncedConfigEntry<string> configTauntHammerRecipe;
private bool isInitialized;
private bool isShuttingDown;
public static AssetBundle assetBundle;
public static readonly List<GameObject> itemPrefabs = new List<GameObject>();
public static readonly FieldInfo knownRecipesField = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly Dictionary<Character, float> lastTauntLogTimes = new Dictionary<Character, float>();
private static readonly Dictionary<Character, (bool fleeIfHurt, bool fleeIfLowHealth, bool enableHuntPlayer)> originalHuntStates = new Dictionary<Character, (bool, bool, bool)>();
private void Awake()
{
Instance = this;
configSync = new ConfigSync("com.Fire.rpgstatuseffects")
{
DisplayName = "RPGStatusEffects",
CurrentVersion = "1.0.1",
MinimumRequiredVersion = "1.0.1"
};
configSync.lockedConfigChanged += delegate
{
if (!isShuttingDown && isInitialized && IsObjectDBValid())
{
ValidateConfigs();
SetupStatusEffects();
RecipeManager.SetupRecipe();
if (configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Config sync triggered status effect and recipe update.");
}
}
};
configVerboseLogging = configSync.AddConfigEntry<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Enable detailed debug logs."));
configPurityDuration = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("StatusEffects", "PurityDuration", 10f, "Duration of the Purity status effect in seconds."));
configTauntDuration = configSync.AddConfigEntry<float>(((BaseUnityPlugin)this).Config.Bind<float>("StatusEffects", "TauntDuration", 15f, "Duration of the Taunt effect in seconds."));
configTauntHammerRecipe = configSync.AddConfigEntry<string>(((BaseUnityPlugin)this).Config.Bind<string>("Item_Recipe_TauntHammer", "Recipe", "Wood,10,5,LeatherScraps,5,2,SwordCheat,1,0", "Recipe for TauntHammer_vad (format: ItemName,Amount,AmountPerLevel,...)"));
ValidateConfigs();
loadAssets();
harmony.PatchAll();
RegisterConsoleCommands();
((MonoBehaviour)this).StartCoroutine(InitializeStatusEffects());
if (configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Initialized version 1.0.1.");
}
}
private void loadAssets()
{
try
{
assetBundle = GetAssetBundleFromResources("verdantsascent");
if ((Object)(object)assetBundle == (Object)null)
{
Debug.LogError((object)"RPGStatusEffects: Failed to load asset bundle!");
return;
}
if (configVerboseLogging.Value)
{
string[] allAssetNames = assetBundle.GetAllAssetNames();
Debug.Log((object)("RPGStatusEffects: Available assets in bundle: " + string.Join(", ", allAssetNames)));
}
LoadItems("Assets/Custom/VAitems/");
}
catch (Exception ex)
{
Debug.LogError((object)("RPGStatusEffects: Error loading assets: " + ex.Message + "\n" + ex.StackTrace));
}
}
private AssetBundle GetAssetBundleFromResources(string filename)
{
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string text = executingAssembly.GetManifestResourceNames().SingleOrDefault((string str) => str.EndsWith(filename, StringComparison.OrdinalIgnoreCase));
if (text == null)
{
Debug.LogError((object)("RPGStatusEffects: No resource found ending with " + filename + "."));
return null;
}
if (configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Loading asset bundle from resource: " + text));
}
using Stream stream = executingAssembly.GetManifestResourceStream(text);
if (stream == null)
{
Debug.LogError((object)("RPGStatusEffects: Failed to open stream for resource " + text + "."));
return null;
}
return AssetBundle.LoadFromStream(stream);
}
private void LoadItems(string mainPath)
{
string[] obj = new string[1] { "TauntHammer_vad" };
itemPrefabs.Clear();
string[] array = obj;
foreach (string text in array)
{
string text2 = mainPath + "items/" + text + ".prefab";
AssetBundle obj2 = assetBundle;
GameObject val = ((obj2 != null) ? obj2.LoadAsset<GameObject>(text2) : null);
if ((Object)(object)val == (Object)null)
{
if (configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: Could not find prefab: " + text2));
}
continue;
}
ItemDrop component = val.GetComponent<ItemDrop>();
if ((Object)(object)component == (Object)null)
{
if (configVerboseLogging.Value)
{
Debug.LogError((object)("RPGStatusEffects: " + text + " - ItemDrop component missing!"));
}
continue;
}
val.SetActive(true);
itemPrefabs.Add(val);
if (configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Loaded prefab: " + text + ", m_dropPrefab: " + (((Object)(object)component.m_itemData.m_dropPrefab != (Object)null) ? ((Object)component.m_itemData.m_dropPrefab).name : "null")));
}
}
}
public static void AddItems(List<GameObject> items)
{
try
{
foreach (GameObject item in items)
{
if ((Object)(object)item == (Object)null)
{
if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Null item in list, skipping.");
}
}
else if ((Object)(object)item.GetComponent<ItemDrop>() != (Object)null)
{
if ((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)item).name) == (Object)null)
{
ObjectDB.instance.m_items.Add(item);
((Dictionary<int, GameObject>)typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ObjectDB.instance))[((Object)item).name.GetHashCode()] = item;
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Added " + ((Object)item).name + " to ObjectDB.m_items"));
}
}
else if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: " + ((Object)item).name + " already exists in ObjectDB, skipping."));
}
}
else if (Instance.configVerboseLogging.Value)
{
Debug.LogError((object)("RPGStatusEffects: " + ((Object)item).name + " - ItemDrop not found on prefab"));
}
}
}
catch (Exception ex)
{
Debug.LogError((object)("RPGStatusEffects: Error adding items to ObjectDB: " + ex.Message));
}
}
public static void AddPrefabsToZNetScene(ZNetScene zNetScene)
{
try
{
foreach (GameObject gm in itemPrefabs)
{
if ((Object)(object)gm == (Object)null)
{
if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Null prefab in itemPrefabs list, skipping.");
}
}
else if ((Object)(object)zNetScene.m_prefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == ((Object)gm).name) == (Object)null)
{
zNetScene.m_prefabs.Add(gm);
if (Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Added " + ((Object)gm).name + " to ZNetScene.m_prefabs"));
}
}
else if (Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: Object exists in ZNetScene, skipping: " + ((Object)gm).name));
}
}
}
catch (Exception ex)
{
Debug.LogError((object)("RPGStatusEffects: Error adding prefabs to ZNetScene: " + ex.Message));
}
zNetScene.m_prefabs.RemoveAll((GameObject x) => (Object)(object)x == (Object)null);
}
private void ValidateConfigs()
{
List<string> list = configTauntHammerRecipe.Value.Split(new char[1] { ',' }).ToList();
if (list.Count % 3 != 0)
{
if (configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Invalid recipe config for TauntHammer_vad - resetting to default.");
}
configTauntHammerRecipe.Value = configTauntHammerRecipe.DefaultValue.ToString();
}
for (int i = 1; i < list.Count; i += 3)
{
if (!int.TryParse(list[i], out var result) || !int.TryParse(list[i + 1], out result))
{
if (configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Invalid amounts in recipe config for TauntHammer_vad - resetting to default.");
}
configTauntHammerRecipe.Value = configTauntHammerRecipe.DefaultValue.ToString();
break;
}
}
}
[IteratorStateMachine(typeof(<InitializeStatusEffects>d__24))]
private IEnumerator InitializeStatusEffects()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <InitializeStatusEffects>d__24(0)
{
<>4__this = this
};
}
public void SetupStatusEffects()
{
if (!IsObjectDBValid())
{
if (configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Skipping SetupStatusEffects - ObjectDB not valid.");
}
}
else
{
StatusEffectManager.Initialize();
}
}
private void RegisterConsoleCommands()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
new ConsoleCommand("va_status_reload", "Reload RPGStatusEffects configs", (ConsoleEvent)delegate
{
if (!isShuttingDown)
{
((BaseUnityPlugin)this).Config.Reload();
RecipeManager.ClearCache();
ValidateConfigs();
if (IsObjectDBValid())
{
SetupStatusEffects();
RecipeManager.SetupRecipe();
if (configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Configs reloaded and status effects/recipe updated.");
}
}
else if (configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Cannot reload configs, ObjectDB not valid.");
}
}
}, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
}
private void OnDestroy()
{
isShuttingDown = true;
harmony.UnpatchSelf();
if ((Object)(object)assetBundle != (Object)null)
{
assetBundle.Unload(true);
if (configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Unloaded asset bundle.");
}
}
if (configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Unloaded.");
}
}
public static bool IsObjectDBValid()
{
return (Object)(object)ObjectDB.instance != (Object)null;
}
}
public static class AdminSyncing
{
[HarmonyPatch(typeof(ZNet), "Awake")]
private static class AdminStatusSyncPatch
{
[CompilerGenerated]
private sealed class <>c__DisplayClass1_0
{
public SyncedList adminList;
public Func<ZNetPeer, bool> <>9__0;
internal bool <WatchAdminListChanges>b__0(ZNetPeer p)
{
return adminList.Contains(p.m_rpc.GetSocket().GetHostName());
}
}
[CompilerGenerated]
private sealed class <WatchAdminListChanges>d__1 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
private <>c__DisplayClass1_0 <>8__1;
private List<string> <currentList>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WatchAdminListChanges>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<currentList>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
List<string> list = <>8__1.adminList.GetList();
if (!list.SequenceEqual(<currentList>5__2))
{
<currentList>5__2 = new List<string>(list);
List<ZNetPeer> peers = ZNet.instance.GetPeers();
List<ZNetPeer> list2 = peers.Where((ZNetPeer p) => <>8__1.adminList.Contains(p.m_rpc.GetSocket().GetHostName())).ToList();
SendAdmin(peers.Except(list2).ToList(), isAdmin: false);
SendAdmin(list2, isAdmin: true);
}
}
else
{
<>1__state = -1;
<>8__1 = new <>c__DisplayClass1_0();
<>8__1.adminList = (SyncedList)AccessTools.Field(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
<currentList>5__2 = new List<string>(<>8__1.adminList.GetList());
}
<>2__current = (object)new WaitForSeconds(30f);
<>1__state = 1;
return true;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[HarmonyPostfix]
[HarmonyPriority(700)]
private static void Postfix(ZNet __instance)
{
isServer = __instance.IsServer();
if (!((Object)(object)RPGStatusEffects.Instance == (Object)null))
{
if (isServer)
{
ZRoutedRpc.instance.Register<ZPackage>("RPGStatusEffects AdminStatusSync", (Action<long, ZPackage>)RPC_AdminStatusSync);
}
else if (!registeredOnClient)
{
ZRoutedRpc.instance.Register<ZPackage>("RPGStatusEffects AdminStatusSync", (Action<long, ZPackage>)RPC_AdminStatusSync);
registeredOnClient = true;
}
if (isServer)
{
((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges());
}
}
}
[IteratorStateMachine(typeof(<WatchAdminListChanges>d__1))]
private static IEnumerator WatchAdminListChanges()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WatchAdminListChanges>d__1(0);
}
private static void SendAdmin(List<ZNetPeer> peers, bool isAdmin)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
ZPackage val = new ZPackage();
val.Write(isAdmin);
((MonoBehaviour)ZNet.instance).StartCoroutine(SendZPackage(peers, val));
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass4_0
{
public ZPackage package;
internal IEnumerator<bool> <SendZPackage>b__1(ZNetPeer p)
{
return TellPeerAdminStatus(p, package);
}
}
[CompilerGenerated]
private sealed class <SendZPackage>d__4 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ZPackage package;
public List<ZNetPeer> peers;
private List<IEnumerator<bool>> <writers>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <SendZPackage>d__4(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<writers>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
<>c__DisplayClass4_0 CS$<>8__locals0 = new <>c__DisplayClass4_0
{
package = package
};
if (!Object.op_Implicit((Object)(object)ZNet.instance))
{
return false;
}
byte[] array = CS$<>8__locals0.package.GetArray();
if (array.Length > 10000)
{
ZPackage val = new ZPackage();
val.Write(4);
using MemoryStream memoryStream = new MemoryStream();
using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Optimal))
{
deflateStream.Write(array, 0, array.Length);
}
val.Write(memoryStream.ToArray());
CS$<>8__locals0.package = val;
}
<writers>5__2 = (from p in peers
where p.IsReady()
select TellPeerAdminStatus(p, CS$<>8__locals0.package)).ToList();
<writers>5__2.RemoveAll((IEnumerator<bool> w) => !w.MoveNext());
break;
}
case 1:
<>1__state = -1;
<writers>5__2.RemoveAll((IEnumerator<bool> w) => !w.MoveNext());
break;
}
if (<writers>5__2.Count > 0)
{
<>2__current = null;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <TellPeerAdminStatus>d__5 : IEnumerator<bool>, IDisposable, IEnumerator
{
private int <>1__state;
private bool <>2__current;
public ZPackage package;
public ZNetPeer peer;
bool IEnumerator<bool>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TellPeerAdminStatus>d__5(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (ZRoutedRpc.instance != null)
{
ZPackage val = new ZPackage(package.GetArray());
if (isServer)
{
peer.m_rpc.Invoke("RPGStatusEffects AdminStatusSync", new object[1] { val });
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_server ? 0 : peer.m_uid, "RPGStatusEffects AdminStatusSync", new object[1] { val });
}
}
<>2__current = false;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static bool isServer;
internal static bool registeredOnClient;
private static void RPC_AdminStatusSync(long sender, ZPackage package)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
bool lockExempt = false;
try
{
lockExempt = package.ReadBool();
}
catch
{
}
if (isServer)
{
ZNetPeer peer = ZNet.instance.GetPeer(sender);
SyncedList val = (SyncedList)AccessTools.Field(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
if (peer != null && val.Contains(peer.m_rpc.GetSocket().GetHostName()))
{
ZPackage val2 = new ZPackage();
val2.Write(true);
peer.m_rpc.Invoke("RPGStatusEffects AdminStatusSync", new object[1] { val2 });
}
}
else
{
ConfigSync.lockExempt = lockExempt;
RPGStatusEffects.Instance?.SetupStatusEffects();
RecipeManager.SetupRecipe();
}
}
[IteratorStateMachine(typeof(<SendZPackage>d__4))]
internal static IEnumerator SendZPackage(List<ZNetPeer> peers, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SendZPackage>d__4(0)
{
peers = peers,
package = package
};
}
[IteratorStateMachine(typeof(<TellPeerAdminStatus>d__5))]
private static IEnumerator<bool> TellPeerAdminStatus(ZNetPeer peer, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TellPeerAdminStatus>d__5(0)
{
peer = peer,
package = package
};
}
}
public class ConfigSync
{
[CompilerGenerated]
private sealed class <>c__DisplayClass57_0
{
public long target;
internal bool <SendZPackage>b__0(ZNetPeer p)
{
if (target != ZRoutedRpc.Everybody)
{
return p.m_uid == target;
}
return true;
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass58_0
{
public ConfigSync <>4__this;
public ZPackage package;
internal IEnumerator <SendZPackage>b__1(ZNetPeer p)
{
return <>4__this.distributeConfigToPeers(p, package);
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass59_0
{
public ZNetPeer peer;
public ConfigSync <>4__this;
}
[CompilerGenerated]
private sealed class <SendZPackage>d__57 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public long target;
public ConfigSync <>4__this;
public ZPackage package;
private IEnumerator <enumerator>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <SendZPackage>d__57(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<enumerator>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
ConfigSync configSync = <>4__this;
switch (num)
{
default:
return false;
case 0:
{
<>1__state = -1;
<>c__DisplayClass57_0 CS$<>8__locals0 = new <>c__DisplayClass57_0
{
target = target
};
if (!Object.op_Implicit((Object)(object)ZNet.instance))
{
return false;
}
List<ZNetPeer> peers = ((List<ZNetPeer>)AccessTools.Field(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance)).Where((ZNetPeer p) => CS$<>8__locals0.target == ZRoutedRpc.Everybody || p.m_uid == CS$<>8__locals0.target).ToList();
<enumerator>5__2 = configSync.SendZPackage(peers, package);
break;
}
case 1:
<>1__state = -1;
break;
}
if (<enumerator>5__2.MoveNext())
{
<>2__current = <enumerator>5__2.Current;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <SendZPackage>d__58 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ConfigSync <>4__this;
public ZPackage package;
public List<ZNetPeer> peers;
private List<IEnumerator> <writers>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <SendZPackage>d__58(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<writers>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
<>c__DisplayClass58_0 CS$<>8__locals0 = new <>c__DisplayClass58_0
{
<>4__this = <>4__this,
package = package
};
if (!Object.op_Implicit((Object)(object)ZNet.instance))
{
return false;
}
byte[] array = CS$<>8__locals0.package.GetArray();
if (array.Length > 10000)
{
ZPackage val = new ZPackage();
val.Write((byte)4);
using MemoryStream memoryStream = new MemoryStream();
using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Optimal))
{
deflateStream.Write(array, 0, array.Length);
}
val.Write(memoryStream.ToArray());
CS$<>8__locals0.package = val;
}
<writers>5__2 = (from p in peers
where p.IsReady()
select CS$<>8__locals0.<>4__this.distributeConfigToPeers(p, CS$<>8__locals0.package)).ToList();
<writers>5__2.RemoveAll((IEnumerator w) => !w.MoveNext());
break;
}
case 1:
<>1__state = -1;
<writers>5__2.RemoveAll((IEnumerator w) => !w.MoveNext());
break;
}
if (<writers>5__2.Any())
{
<>2__current = null;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <distributeConfigToPeers>d__59 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ZNetPeer peer;
public ConfigSync <>4__this;
public ZPackage package;
private <>c__DisplayClass59_0 <>8__1;
private byte[] <data>5__2;
private int <fragments>5__3;
private long <packageId>5__4;
private int <i>5__5;
private IEnumerator<bool> <>7__wrap5;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <distributeConfigToPeers>d__59(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
switch (<>1__state)
{
case -3:
case 1:
try
{
}
finally
{
<>m__Finally1();
}
break;
case -4:
case 3:
try
{
}
finally
{
<>m__Finally2();
}
break;
}
<>8__1 = null;
<data>5__2 = null;
<>7__wrap5 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Expected O, but got Unknown
try
{
ZPackage val;
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>8__1 = new <>c__DisplayClass59_0();
<>8__1.peer = peer;
<>8__1.<>4__this = <>4__this;
<data>5__2 = package.GetArray();
if (<data>5__2.Length > 250000)
{
<fragments>5__3 = (<data>5__2.Length + 249999) / 250000;
<packageId>5__4 = ++packageCounter;
<i>5__5 = 0;
goto IL_01e3;
}
<>7__wrap5 = waitForQueue().GetEnumerator();
<>1__state = -4;
goto IL_0243;
case 1:
<>1__state = -3;
goto IL_0103;
case 2:
<>1__state = -1;
goto IL_01d1;
case 3:
{
<>1__state = -4;
goto IL_0243;
}
IL_0243:
if (<>7__wrap5.MoveNext())
{
bool current = <>7__wrap5.Current;
<>2__current = current;
<>1__state = 3;
return true;
}
<>m__Finally2();
<>7__wrap5 = null;
SendPackage(package);
break;
IL_01e3:
if (<i>5__5 < <fragments>5__3)
{
<>7__wrap5 = waitForQueue().GetEnumerator();
<>1__state = -3;
goto IL_0103;
}
break;
IL_01d1:
<i>5__5++;
goto IL_01e3;
IL_0103:
if (<>7__wrap5.MoveNext())
{
bool current2 = <>7__wrap5.Current;
<>2__current = current2;
<>1__state = 1;
return true;
}
<>m__Finally1();
<>7__wrap5 = null;
if (!<>8__1.peer.m_socket.IsConnected())
{
break;
}
val = new ZPackage();
val.Write((byte)2);
val.Write(<packageId>5__4);
val.Write(<i>5__5);
val.Write(<fragments>5__3);
val.Write(<data>5__2.Skip(250000 * <i>5__5).Take(250000).ToArray());
SendPackage(val);
if (<i>5__5 < <fragments>5__3 - 1)
{
<>2__current = true;
<>1__state = 2;
return true;
}
goto IL_01d1;
}
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
void SendPackage(ZPackage pkg)
{
if (isServer)
{
((<>c__DisplayClass59_0)this).peer.m_rpc.Invoke(((<>c__DisplayClass59_0)this).<>4__this.Name + " ConfigSync", new object[1] { pkg });
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(((<>c__DisplayClass59_0)this).peer.m_server ? 0 : ((<>c__DisplayClass59_0)this).peer.m_uid, ((<>c__DisplayClass59_0)this).<>4__this.Name + " ConfigSync", new object[1] { pkg });
}
}
[IteratorStateMachine(typeof(<>c__DisplayClass59_0.<<distributeConfigToPeers>g__waitForQueue|0>d))]
IEnumerable<bool> waitForQueue()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <>c__DisplayClass59_0.<<distributeConfigToPeers>g__waitForQueue|0>d(-2)
{
<>4__this = this
};
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap5 != null)
{
<>7__wrap5.Dispose();
}
}
private void <>m__Finally2()
{
<>1__state = -1;
if (<>7__wrap5 != null)
{
<>7__wrap5.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public static bool ProcessingServerUpdate = false;
public readonly string Name;
public string DisplayName;
public string CurrentVersion;
public string MinimumRequiredVersion;
public bool ModRequired;
private bool? forceConfigLocking;
private bool isSourceOfTruth = true;
public static HashSet<ConfigSync> configSyncs = new HashSet<ConfigSync>();
public HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>();
public HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>();
public static bool isServer;
public static bool lockExempt = false;
private OwnConfigEntryBase lockedConfig;
private const byte PARTIAL_CONFIGS = 1;
private const byte FRAGMENTED_CONFIG = 2;
private const byte COMPRESSED_CONFIG = 4;
private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>();
private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>();
private static long packageCounter = 0L;
private bool initialSyncDone;
public bool IsLocked
{
get
{
bool? flag = forceConfigLocking;
bool num;
if (!flag.HasValue)
{
OwnConfigEntryBase ownConfigEntryBase = lockedConfig;
if (!(((ownConfigEntryBase != null) ? ownConfigEntryBase.BaseConfig.BoxedValue : null) is IConvertible convertible))
{
goto IL_0055;
}
num = convertible.ToInt32(CultureInfo.InvariantCulture) != 0;
}
else
{
num = flag.GetValueOrDefault();
}
if (num)
{
return !lockExempt;
}
goto IL_0055;
IL_0055:
return false;
}
set
{
forceConfigLocking = value;
}
}
public bool IsAdmin
{
get
{
if (!lockExempt)
{
return isSourceOfTruth;
}
return true;
}
}
public bool IsSourceOfTruth
{
get
{
return isSourceOfTruth;
}
internal set
{
if (value != isSourceOfTruth)
{
isSourceOfTruth = value;
this.SourceOfTruthChanged?.Invoke(value);
}
}
}
public bool InitialSyncDone
{
get
{
return initialSyncDone;
}
internal set
{
initialSyncDone = value;
}
}
public event Action<bool> SourceOfTruthChanged;
public event Action lockedConfigChanged;
public ConfigSync(string name)
{
Name = name;
DisplayName = name;
configSyncs.Add(this);
}
public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
{
SyncedConfigEntry<T> syncedEntry = (configData((ConfigEntryBase)(object)configEntry) as SyncedConfigEntry<T>) ?? new SyncedConfigEntry<T>(configEntry);
object[] first = ((ConfigEntryBase)configEntry).Description.Tags?.ToArray() ?? new object[1]
{
new ConfigurationManagerAttributes()
};
first = first.Concat(new object[1] { syncedEntry }).ToArray();
AccessTools.Field(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry).Description, first);
configEntry.SettingChanged += delegate
{
if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig)
{
Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)(object)configEntry);
}
};
allConfigs.Add(syncedEntry);
return syncedEntry;
}
public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible
{
if (lockedConfig != null)
{
throw new Exception("Cannot initialize locking ConfigEntry twice");
}
lockedConfig = AddConfigEntry<T>(lockingConfig);
lockingConfig.SettingChanged += delegate
{
this.lockedConfigChanged?.Invoke();
};
return (SyncedConfigEntry<T>)lockedConfig;
}
internal void AddCustomValue(CustomSyncedValueBase customValue)
{
if (allCustomValues.Any((CustomSyncedValueBase v) => v.Identifier == customValue.Identifier) || customValue.Identifier == "serverversion")
{
throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)");
}
allCustomValues.Add(customValue);
allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority));
customValue.ValueChanged += delegate
{
if (!ProcessingServerUpdate)
{
Broadcast(ZRoutedRpc.Everybody, customValue);
}
};
}
private void Broadcast(long target, ConfigEntryBase config)
{
if (!IsLocked || IsAdmin)
{
ZPackage package = ConfigsToPackage((IEnumerable<ConfigEntryBase>)(object)new ConfigEntryBase[1] { config });
ZNet instance = ZNet.instance;
if (instance != null)
{
((MonoBehaviour)instance).StartCoroutine(SendZPackage(target, package));
}
}
}
private void Broadcast(long target, CustomSyncedValueBase customValue)
{
if (!IsLocked || IsAdmin)
{
ZPackage package = ConfigsToPackage(null, new CustomSyncedValueBase[1] { customValue });
ZNet instance = ZNet.instance;
if (instance != null)
{
((MonoBehaviour)instance).StartCoroutine(SendZPackage(target, package));
}
}
}
internal void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package)
{
lockedConfigChanged += serverLockedSettingChanged;
IsSourceOfTruth = false;
if (HandleConfigSyncRPC(0L, package, clientUpdate: false))
{
InitialSyncDone = true;
}
}
internal void RPC_FromOtherClientConfigSync(long sender, ZPackage package)
{
HandleConfigSyncRPC(sender, package, clientUpdate: true);
}
private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Expected O, but got Unknown
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Expected O, but got Unknown
try
{
if (isServer && IsLocked)
{
ZRpc currentRpc = SnatchCurrentlyHandlingRPC.currentRpc;
object obj;
if (currentRpc == null)
{
obj = null;
}
else
{
ISocket socket = currentRpc.GetSocket();
obj = ((socket != null) ? socket.GetHostName() : null);
}
string text = (string)obj;
SyncedList val = (SyncedList)AccessTools.Field(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
if (text != null && !val.Contains(text))
{
return false;
}
}
cacheExpirations.RemoveAll((KeyValuePair<long, string> kv) => kv.Key < DateTimeOffset.Now.Ticks && configValueCache.Remove(kv.Value));
byte b = package.ReadByte();
if ((b & 2u) != 0)
{
long num = package.ReadLong();
string text2 = sender.ToString() + num;
if (!configValueCache.TryGetValue(text2, out var value))
{
value = new SortedDictionary<int, byte[]>();
configValueCache[text2] = value;
cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.Ticks + 600000000, text2));
}
int key = package.ReadInt();
int num2 = package.ReadInt();
value[key] = package.ReadByteArray();
if (value.Count < num2)
{
return false;
}
configValueCache.Remove(text2);
package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray());
b = package.ReadByte();
}
ProcessingServerUpdate = true;
if ((b & 4u) != 0)
{
using MemoryStream stream = new MemoryStream(package.ReadByteArray());
using MemoryStream memoryStream = new MemoryStream();
using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress))
{
deflateStream.CopyTo(memoryStream);
}
package = new ZPackage(memoryStream.ToArray());
b = package.ReadByte();
}
if ((b & 1) == 0)
{
resetConfigsFromServer();
}
ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package);
ConfigFile val2 = null;
bool saveOnConfigSet = false;
foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues)
{
if (!isServer && configValue.Key.LocalBaseValue == null)
{
configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue;
}
if (val2 == null)
{
val2 = configValue.Key.BaseConfig.ConfigFile;
saveOnConfigSet = val2.SaveOnConfigSet;
val2.SaveOnConfigSet = false;
}
configValue.Key.BaseConfig.BoxedValue = configValue.Value;
}
if (val2 != null)
{
val2.SaveOnConfigSet = saveOnConfigSet;
val2.Save();
}
foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues)
{
if (!isServer && customValue.Key.LocalBaseValue == null)
{
customValue.Key.LocalBaseValue = customValue.Key.BoxedValue;
}
customValue.Key.BoxedValue = customValue.Value;
}
Debug.Log((object)string.Format("[RPGStatusEffects] Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "server", DisplayName ?? Name));
if (!isServer)
{
serverLockedSettingChanged();
}
return true;
}
finally
{
ProcessingServerUpdate = false;
}
}
private void serverLockedSettingChanged()
{
foreach (OwnConfigEntryBase allConfig in allConfigs)
{
configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig);
}
}
internal static bool isWritableConfig(OwnConfigEntryBase config)
{
ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config));
if (configSync == null || configSync.IsSourceOfTruth || !config.SynchronizedConfig || config.LocalBaseValue == null)
{
return true;
}
if (configSync.IsLocked && config == configSync.lockedConfig)
{
return lockExempt;
}
return true;
}
internal void resetConfigsFromServer()
{
ConfigFile val = null;
bool saveOnConfigSet = false;
foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase c) => c.LocalBaseValue != null))
{
if (val == null)
{
val = item.BaseConfig.ConfigFile;
saveOnConfigSet = val.SaveOnConfigSet;
val.SaveOnConfigSet = false;
}
item.BaseConfig.BoxedValue = item.LocalBaseValue;
item.LocalBaseValue = null;
}
if (val != null)
{
val.SaveOnConfigSet = saveOnConfigSet;
val.Save();
}
foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase c) => c.LocalBaseValue != null))
{
item2.BoxedValue = item2.LocalBaseValue;
item2.LocalBaseValue = null;
}
lockedConfigChanged -= serverLockedSettingChanged;
serverLockedSettingChanged();
}
private ParsedConfigs ReadConfigsFromPackage(ZPackage package)
{
ParsedConfigs parsedConfigs = new ParsedConfigs();
Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "*" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c);
int num = package.ReadInt();
for (int i = 0; i < num; i++)
{
string text = package.ReadString();
string key = package.ReadString();
string text2 = package.ReadString();
Type type = Type.GetType(text2);
if (text2 == "" || type != null)
{
object obj;
try
{
obj = ((text2 == "") ? null : ReadValueWithTypeFromZPackage(package, type));
}
catch (InvalidDeserializationTypeException ex)
{
Debug.LogWarning((object)("[RPGStatusEffects] Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text2 + " for " + key + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected));
continue;
}
OwnConfigEntryBase value;
if (text == "Internal")
{
if (key == "lockexempt" && obj is bool flag)
{
lockExempt = flag;
continue;
}
CustomSyncedValueBase customSyncedValueBase = allCustomValues.FirstOrDefault((CustomSyncedValueBase v) => v.Identifier == key);
if (customSyncedValueBase != null)
{
if ((text2 == "" && (!customSyncedValueBase.Type.IsValueType || Nullable.GetUnderlyingType(customSyncedValueBase.Type) != null)) || GetZPackageTypeString(customSyncedValueBase.Type) == text2)
{
parsedConfigs.customValues[customSyncedValueBase] = obj;
continue;
}
Debug.LogWarning((object)("[RPGStatusEffects] Got unexpected type " + text2 + " for internal value " + key + " for mod " + (DisplayName ?? Name) + ", expecting " + customSyncedValueBase.Type.AssemblyQualifiedName));
}
}
else if (dictionary.TryGetValue(text + "*" + key, out value))
{
Type type2 = configType(value.BaseConfig);
if ((text2 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text2)
{
parsedConfigs.configValues[value] = obj;
continue;
}
Debug.LogWarning((object)("[RPGStatusEffects] Got unexpected type " + text2 + " for " + key + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName));
}
else
{
Debug.LogWarning((object)("[RPGStatusEffects] Received unknown config entry " + key + " in section " + text + " for mod " + (DisplayName ?? Name) + "."));
}
continue;
}
Debug.LogWarning((object)("[RPGStatusEffects] Got invalid type " + text2 + ", abort reading of received configs"));
return new ParsedConfigs();
}
return parsedConfigs;
}
private static string GetZPackageTypeString(Type type)
{
return type.AssemblyQualifiedName;
}
private static void AddValueToZPackage(ZPackage package, object value)
{
Type type = value?.GetType();
if (value is Enum)
{
value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(type), CultureInfo.InvariantCulture);
}
else
{
if (value is ICollection collection)
{
package.Write(collection.Count);
{
IEnumerator enumerator = collection.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
AddValueToZPackage(package, enumerator.Current);
}
return;
}
finally
{
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
}
if (type != null && type.IsValueType && !type.IsPrimitive)
{
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
package.Write(fields.Length);
FieldInfo[] array = fields;
foreach (FieldInfo fieldInfo in array)
{
package.Write(GetZPackageTypeString(fieldInfo.FieldType));
AddValueToZPackage(package, fieldInfo.GetValue(value));
}
return;
}
}
ZRpc.Serialize(new object[1] { value }, ref package);
}
private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type)
{
if (type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum)
{
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
int num = package.ReadInt();
if (num != fields.Length)
{
throw new InvalidDeserializationTypeException
{
received = $"(field count: {num})",
expected = $"(field count: {fields.Length})"
};
}
object uninitializedObject = FormatterServices.GetUninitializedObject(type);
FieldInfo[] array = fields;
foreach (FieldInfo fieldInfo in array)
{
string text = package.ReadString();
if (text != GetZPackageTypeString(fieldInfo.FieldType))
{
throw new InvalidDeserializationTypeException
{
received = text,
expected = GetZPackageTypeString(fieldInfo.FieldType),
field = fieldInfo.Name
};
}
fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType));
}
return uninitializedObject;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
{
int num2 = package.ReadInt();
Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);
for (int j = 0; j < num2; j++)
{
object obj = ReadValueWithTypeFromZPackage(package, type2);
dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
}
return dictionary;
}
if (type.IsGenericType)
{
Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
if (type3.IsAssignableFrom(type))
{
int num3 = package.ReadInt();
object obj2 = Activator.CreateInstance(type);
MethodInfo method = type3.GetMethod("Add");
for (int k = 0; k < num3; k++)
{
method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) });
}
return obj2;
}
}
ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
AccessTools.Field(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
List<object> source = new List<object>();
ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
return source.First();
}
internal ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase> configs = null, IEnumerable<CustomSyncedValueBase> customValues = null, IEnumerable<PackageEntry> packageEntries = null, bool partial = true)
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Expected O, but got Unknown
List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase c) => configData(c).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>();
List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>();
List<PackageEntry> list3 = packageEntries?.ToList() ?? new List<PackageEntry>();
ZPackage val = new ZPackage();
val.Write(partial ? ((byte)1) : ((byte)0));
val.Write(list.Count + list2.Count + list3.Count);
foreach (PackageEntry item in list3)
{
val.Write(item.section);
val.Write(item.key);
val.Write((item.value == null) ? "" : GetZPackageTypeString(item.type));
AddValueToZPackage(val, item.value);
}
foreach (CustomSyncedValueBase item2 in list2)
{
val.Write("Internal");
val.Write(item2.Identifier);
val.Write(GetZPackageTypeString(item2.Type));
AddValueToZPackage(val, item2.BoxedValue);
}
foreach (ConfigEntryBase item3 in list)
{
val.Write(item3.Definition.Section);
val.Write(item3.Definition.Key);
val.Write(GetZPackageTypeString(configType(item3)));
AddValueToZPackage(val, item3.BoxedValue);
}
return val;
}
private static Type configType(ConfigEntryBase config)
{
return configType(config.SettingType);
}
private static Type configType(Type type)
{
if (!type.IsEnum)
{
return type;
}
return Enum.GetUnderlyingType(type);
}
[IteratorStateMachine(typeof(<SendZPackage>d__57))]
internal IEnumerator SendZPackage(long target, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SendZPackage>d__57(0)
{
<>4__this = this,
target = target,
package = package
};
}
[IteratorStateMachine(typeof(<SendZPackage>d__58))]
internal IEnumerator SendZPackage(List<ZNetPeer> peers, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SendZPackage>d__58(0)
{
<>4__this = this,
peers = peers,
package = package
};
}
[IteratorStateMachine(typeof(<distributeConfigToPeers>d__59))]
private IEnumerator distributeConfigToPeers(ZNetPeer peer, ZPackage package)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <distributeConfigToPeers>d__59(0)
{
<>4__this = this,
peer = peer,
package = package
};
}
internal static OwnConfigEntryBase configData(ConfigEntryBase config)
{
return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault();
}
private static T configAttribute<T>(ConfigEntryBase config) where T : class
{
object[] tags = config.Description.Tags;
if (tags == null)
{
return null;
}
return tags.OfType<T>().FirstOrDefault();
}
}
public abstract class OwnConfigEntryBase
{
public readonly ConfigEntryBase BaseConfig;
public object LocalBaseValue;
public bool SynchronizedConfig = true;
protected OwnConfigEntryBase(ConfigEntryBase config)
{
BaseConfig = config;
}
}
public class SyncedConfigEntry<T> : OwnConfigEntryBase
{
public T Value
{
get
{
if (BaseConfig is ConfigEntry<T> val)
{
return val.Value;
}
throw new InvalidOperationException("Cannot cast BaseConfig to ConfigEntry<" + typeof(T).Name + ">");
}
set
{
((ConfigEntry<T>)(object)BaseConfig).Value = value;
}
}
public T DefaultValue
{
get
{
if (BaseConfig is ConfigEntry<T> val)
{
return (T)((ConfigEntryBase)val).BoxedValue;
}
throw new InvalidOperationException("Cannot cast BaseConfig to ConfigEntry<" + typeof(T).Name + ">");
}
}
public SyncedConfigEntry(ConfigEntry<T> config)
: base((ConfigEntryBase)(object)config)
{
}
}
public class CustomSyncedValueBase
{
public string Identifier { get; }
public Type Type { get; }
public object BoxedValue { get; set; }
public object LocalBaseValue { get; set; }
public int Priority { get; }
public event Action ValueChanged;
public CustomSyncedValueBase(string identifier, Type type, int priority = 0)
{
Identifier = identifier;
Type = type;
Priority = priority;
}
}
public class ConfigurationManagerAttributes
{
public bool? ReadOnly;
}
public class ParsedConfigs
{
public readonly Dictionary<OwnConfigEntryBase, object> configValues = new Dictionary<OwnConfigEntryBase, object>();
public readonly Dictionary<CustomSyncedValueBase, object> customValues = new Dictionary<CustomSyncedValueBase, object>();
}
public class PackageEntry
{
public string section;
public string key;
public Type type;
public object value;
}
public class InvalidDeserializationTypeException : Exception
{
public string expected;
public string received;
public string field = "";
}
[HarmonyPatch(typeof(ZRpc), "HandlePackage")]
public class SnatchCurrentlyHandlingRPC
{
public static ZRpc currentRpc;
[HarmonyPrefix]
private static void Prefix(ZRpc __instance)
{
currentRpc = __instance;
}
}
[HarmonyPatch(typeof(ZNet), "Awake")]
public class RegisterRPCPatch
{
[HarmonyPostfix]
private static void Postfix(ZNet __instance)
{
ConfigSync.isServer = __instance.IsServer();
foreach (ConfigSync configSync in ConfigSync.configSyncs)
{
ZRoutedRpc.instance.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<long, ZPackage>)configSync.RPC_FromOtherClientConfigSync);
if (ConfigSync.isServer)
{
Debug.Log((object)("[RPGStatusEffects] Registered '" + configSync.Name + " ConfigSync' RPC"));
}
}
}
}
[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
public class RegisterClientRPCPatch
{
[HarmonyPostfix]
private static void Postfix(ZNet __instance, ZNetPeer peer)
{
if (__instance.IsServer())
{
return;
}
foreach (ConfigSync configSync in ConfigSync.configSyncs)
{
peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync);
}
}
}
[HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")]
public class PreventSavingServerInfo
{
[HarmonyPrefix]
private static bool Prefix(ConfigEntryBase __instance, ref string __result)
{
OwnConfigEntryBase ownConfigEntryBase = ConfigSync.configData(__instance);
if (ownConfigEntryBase == null || ConfigSync.isWritableConfig(ownConfigEntryBase))
{
return true;
}
__result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType);
return false;
}
}
[HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")]
public class PreventConfigRereadChangingValues
{
[HarmonyPrefix]
private static bool Prefix(ConfigEntryBase __instance, string value)
{
OwnConfigEntryBase ownConfigEntryBase = ConfigSync.configData(__instance);
if (ownConfigEntryBase != null && ownConfigEntryBase.LocalBaseValue != null)
{
try
{
ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType);
}
catch (Exception ex)
{
Debug.LogWarning((object)($"[RPGStatusEffects] Config value of setting \"{__instance.Definition}\"" + " could not be parsed and will be ignored. Reason: " + ex.Message + "; Value: " + value));
}
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
public class SendConfigsAfterLogin
{
public class BufferingSocket : ZPlayFabSocket, ISocket
{
public volatile bool finished;
public volatile int versionMatchQueued;
public readonly List<ZPackage> Package = new List<ZPackage>();
public readonly ISocket Original;
public BufferingSocket(ISocket original)
{
Original = original;
object obj = AccessTools.Field(typeof(ZPlayFabSocket), "m_remotePlayerId")?.GetValue(original);
if (obj != null)
{
AccessTools.Field(typeof(BufferingSocket), "m_remotePlayerId")?.SetValue(this, obj);
}
}
public bool IsConnected()
{
return Original.IsConnected();
}
public ZPackage Recv()
{
return Original.Recv();
}
public int GetSendQueueSize()
{
return Original.GetSendQueueSize();
}
public int GetCurrentSendRate()
{
return Original.GetCurrentSendRate();
}
public bool IsHost()
{
return Original.IsHost();
}
public void Dispose()
{
Original.Dispose();
}
public bool GotNewData()
{
return Original.GotNewData();
}
public void Close()
{
Original.Close();
}
public string GetEndPointString()
{
return Original.GetEndPointString();
}
public void GetAndResetStats(out int totalSent, out int totalRecv)
{
Original.GetAndResetStats(ref totalSent, ref totalRecv);
}
public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec)
{
Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec);
}
public ISocket Accept()
{
return Original.Accept();
}
public int GetHostPort()
{
return Original.GetHostPort();
}
public bool Flush()
{
return Original.Flush();
}
public string GetHostName()
{
return Original.GetHostName();
}
public void VersionMatch()
{
if (finished)
{
Original.VersionMatch();
}
else
{
versionMatchQueued = Package.Count;
}
}
public void Send(ZPackage pkg)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
int pos = pkg.GetPos();
pkg.SetPos(0);
int num = pkg.ReadInt();
if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished)
{
ZPackage val = new ZPackage(pkg.GetArray());
val.SetPos(pos);
Package.Add(val);
}
else
{
pkg.SetPos(pos);
Original.Send(pkg);
}
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1_0
{
public ZRpc rpc;
public ZNet __instance;
public Dictionary<Assembly, BufferingSocket> __state;
public ZNetPeer peer;
}
[HarmonyPrefix]
[HarmonyPriority(800)]
private static void Prefix(ref Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
if (!__instance.IsServer())
{
return;
}
BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket());
AccessTools.Field(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket);
ZNetPeer val = (ZNetPeer)AccessTools.Method(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
if (val != null && (int)ZNet.m_onlineBackend != 0)
{
FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetPeer), "m_socket");
object? value = fieldInfo.GetValue(val);
ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null);
if (val2 != null)
{
AccessTools.Field(typeof(BufferingSocket), "m_remotePlayerId")?.SetValue(bufferingSocket, val2.m_remotePlayerId);
}
fieldInfo.SetValue(val, bufferingSocket);
}
if (__state == null)
{
__state = new Dictionary<Assembly, BufferingSocket>();
}
__state[Assembly.GetExecutingAssembly()] = bufferingSocket;
}
[HarmonyPostfix]
private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
<>c__DisplayClass1_0 CS$<>8__locals0 = new <>c__DisplayClass1_0();
CS$<>8__locals0.rpc = rpc;
CS$<>8__locals0.__instance = __instance;
CS$<>8__locals0.__state = __state;
if (CS$<>8__locals0.__instance.IsServer())
{
CS$<>8__locals0.peer = (ZNetPeer)AccessTools.Method(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(CS$<>8__locals0.__instance, new object[1] { CS$<>8__locals0.rpc });
if (CS$<>8__locals0.peer == null)
{
SendBufferedData();
}
else
{
((MonoBehaviour)CS$<>8__locals0.__instance).StartCoroutine(SendAsync());
}
}
[IteratorStateMachine(typeof(<>c__DisplayClass1_0.<<Postfix>g__SendAsync|1>d))]
IEnumerator SendAsync()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <>c__DisplayClass1_0.<<Postfix>g__SendAsync|1>d(0)
{
<>4__this = CS$<>8__locals0
};
}
void SendBufferedData()
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
if (CS$<>8__locals0.rpc.GetSocket() is BufferingSocket bufferingSocket)
{
AccessTools.Field(typeof(ZRpc), "m_socket").SetValue(CS$<>8__locals0.rpc, bufferingSocket.Original);
ZNetPeer val = (ZNetPeer)AccessTools.Method(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(CS$<>8__locals0.__instance, new object[1] { CS$<>8__locals0.rpc });
if (val != null)
{
AccessTools.Field(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original);
}
}
BufferingSocket bufferingSocket2 = CS$<>8__locals0.__state[Assembly.GetExecutingAssembly()];
bufferingSocket2.finished = true;
for (int i = 0; i < bufferingSocket2.Package.Count; i++)
{
if (i == bufferingSocket2.versionMatchQueued)
{
bufferingSocket2.Original.VersionMatch();
}
bufferingSocket2.Original.Send(bufferingSocket2.Package[i]);
}
if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued)
{
bufferingSocket2.Original.VersionMatch();
}
}
}
}
public static class RecipeManager
{
private static readonly Dictionary<string, Recipe> _existingRecipes = new Dictionary<string, Recipe>();
private static readonly Dictionary<string, Requirement[]> itemRecipeCache = new Dictionary<string, Requirement[]>();
public static void SetupRecipe()
{
if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null || (Object)(object)ZNetScene.instance == (Object)null)
{
return;
}
_existingRecipes.Clear();
string itemName = "TauntHammer_vad";
GameObject val = ((IEnumerable<GameObject>)RPGStatusEffects.itemPrefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => (Object)(object)p != (Object)null && string.Equals(((Object)p).name, itemName, StringComparison.OrdinalIgnoreCase)));
if ((Object)(object)val == (Object)null)
{
return;
}
ItemDrop component = val.GetComponent<ItemDrop>();
if ((Object)(object)component == (Object)null)
{
return;
}
TauntEffect tauntEffect = StatusEffectManager.GetEffect("Taunted") as TauntEffect;
if ((Object)(object)tauntEffect != (Object)null)
{
component.m_itemData.m_shared.m_attackStatusEffect = (StatusEffect)(object)tauntEffect;
component.m_itemData.m_shared.m_attackStatusEffectChance = 1f;
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Assigned Taunt effect to TauntHammer_vad (effect: {1}, duration: {2}s).", "RPGStatusEffects", ((Object)tauntEffect).name, tauntEffect.Duration));
}
}
GameObject prefab = ZNetScene.instance.GetPrefab("piece_workbench");
CraftingStation val2 = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
if ((Object)(object)val2 == (Object)null)
{
return;
}
Requirement[] array = ParseRequirements(RPGStatusEffects.Instance.configTauntHammerRecipe.Value, itemName);
if (array.Length == 0)
{
return;
}
Recipe recipe = ScriptableObject.CreateInstance<Recipe>();
((Object)recipe).name = "Recipe_" + itemName;
recipe.m_item = component;
recipe.m_craftingStation = val2;
recipe.m_minStationLevel = 1;
recipe.m_amount = 1;
recipe.m_resources = array;
if (!ObjectDB.instance.m_recipes.Any((Recipe r) => ((Object)r).name == ((Object)recipe).name))
{
ObjectDB.instance.m_recipes.Add(recipe);
_existingRecipes[itemName] = recipe;
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Added Recipe_TauntHammer_vad to ObjectDB.m_recipes");
}
}
if (!((Object)(object)Player.m_localPlayer != (Object)null))
{
return;
}
HashSet<string> hashSet = (HashSet<string>)(RPGStatusEffects.knownRecipesField?.GetValue(Player.m_localPlayer));
if (hashSet != null && !hashSet.Contains(((Object)recipe).name))
{
hashSet.Add(((Object)recipe).name);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Added Recipe_TauntHammer_vad to player's known recipes.");
}
}
}
public static void ClearCache()
{
itemRecipeCache.Clear();
}
private static Requirement[] ParseRequirements(string configValue, string key)
{
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Expected O, but got Unknown
if (itemRecipeCache.TryGetValue(key, out var value))
{
return value;
}
List<Requirement> list = new List<Requirement>();
string[] array = (from s in configValue.Split(new char[1] { ',' })
select s.Trim()).ToArray();
for (int i = 0; i < array.Length && i + 2 < array.Length; i += 3)
{
string text = array[i];
if (!int.TryParse(array[i + 1], out var result))
{
result = 1;
}
if (!int.TryParse(array[i + 2], out var result2))
{
result2 = 0;
}
ZNetScene instance = ZNetScene.instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
GameObject prefab = instance.GetPrefab(text);
obj = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
}
if (obj == null)
{
ObjectDB instance2 = ObjectDB.instance;
if (instance2 == null)
{
obj = null;
}
else
{
GameObject itemPrefab = instance2.GetItemPrefab(text);
obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
}
}
ItemDrop val = (ItemDrop)obj;
if ((Object)(object)val == (Object)null)
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: Invalid material '" + text + "' in recipe for " + key + " - skipping."));
}
}
else
{
list.Add(new Requirement
{
m_resItem = val,
m_amount = result,
m_amountPerLevel = result2,
m_recover = true
});
}
}
Requirement[] array2 = list.ToArray();
itemRecipeCache[key] = array2;
if (array2.Length == 0 && RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: No valid requirements parsed for " + key + " - recipe may fail."));
}
return array2;
}
}
public static class StatusEffectManager
{
private static readonly Dictionary<string, StatusEffect> CustomEffects = new Dictionary<string, StatusEffect>();
public static void Initialize()
{
if (!RPGStatusEffects.IsObjectDBValid())
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)"RPGStatusEffects: Skipping StatusEffectManager init - ObjectDB not valid.");
}
return;
}
CustomEffects.Clear();
ObjectDB instance = ObjectDB.instance;
RegisterPurityEffect(instance);
RegisterTauntEffect(instance);
RegisterTauntingEffect(instance);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: StatusEffectManager initialized {1} custom effects.", "RPGStatusEffects", CustomEffects.Count));
}
}
private static void RegisterPurityEffect(ObjectDB objectDB)
{
StatusEffect val = ((IEnumerable<StatusEffect>)objectDB.m_StatusEffects).FirstOrDefault((Func<StatusEffect, bool>)((StatusEffect se) => ((Object)se).name == "Purify"));
if ((Object)(object)val != (Object)null)
{
objectDB.m_StatusEffects.Remove(val);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Removed existing Purify effect to update duration.");
}
}
PurityEffect purityEffect = ScriptableObject.CreateInstance<PurityEffect>();
((Object)purityEffect).name = "Purify";
purityEffect.Icon = LoadOrCreateIcon();
purityEffect.Duration = RPGStatusEffects.Instance.configPurityDuration.Value;
objectDB.m_StatusEffects.Add((StatusEffect)(object)purityEffect);
CustomEffects["Purify"] = (StatusEffect)(object)purityEffect;
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Registered PurityEffect with duration {1}s, Icon: {2}.", "RPGStatusEffects", purityEffect.Duration, ((Object)(object)purityEffect.Icon != (Object)null) ? "Assigned" : "Null"));
}
}
private static void RegisterTauntEffect(ObjectDB objectDB)
{
StatusEffect val = ((IEnumerable<StatusEffect>)objectDB.m_StatusEffects).FirstOrDefault((Func<StatusEffect, bool>)((StatusEffect se) => ((Object)se).name == "Taunted"));
if ((Object)(object)val != (Object)null)
{
objectDB.m_StatusEffects.Remove(val);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Removed existing Taunted effect to update duration.");
}
}
TauntEffect tauntEffect = ScriptableObject.CreateInstance<TauntEffect>();
((Object)tauntEffect).name = "Taunted";
tauntEffect.Duration = RPGStatusEffects.Instance.configTauntDuration.Value;
tauntEffect.Icon = null;
objectDB.m_StatusEffects.Add((StatusEffect)(object)tauntEffect);
CustomEffects["Taunted"] = (StatusEffect)(object)tauntEffect;
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Registered TauntEffect with duration {1}s, Icon: {2}.", "RPGStatusEffects", tauntEffect.Duration, ((Object)(object)tauntEffect.Icon != (Object)null) ? "Assigned" : "Null"));
}
}
private static void RegisterTauntingEffect(ObjectDB objectDB)
{
StatusEffect val = ((IEnumerable<StatusEffect>)objectDB.m_StatusEffects).FirstOrDefault((Func<StatusEffect, bool>)((StatusEffect se) => ((Object)se).name == "Taunting"));
if ((Object)(object)val != (Object)null)
{
objectDB.m_StatusEffects.Remove(val);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)"RPGStatusEffects: Removed existing Taunting effect to update duration.");
}
}
TauntingEffect tauntingEffect = ScriptableObject.CreateInstance<TauntingEffect>();
((Object)tauntingEffect).name = "Taunting";
tauntingEffect.Duration = RPGStatusEffects.Instance.configTauntDuration.Value;
tauntingEffect.Icon = LoadTauntingIcon();
objectDB.m_StatusEffects.Add((StatusEffect)(object)tauntingEffect);
CustomEffects["Taunting"] = (StatusEffect)(object)tauntingEffect;
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Registered TauntingEffect with duration {1}s, Icon: {2}.", "RPGStatusEffects", tauntingEffect.Duration, ((Object)(object)tauntingEffect.Icon != (Object)null) ? "Assigned" : "Null"));
}
}
private static Sprite LoadOrCreateIcon()
{
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Expected O, but got Unknown
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
string[] array = new string[5] { "assets/custom/vaitems/icons/purity_icon", "Assets/Custom/VAItems/Icons/purity_icon", "assets/custom/VAitems/icons/purity_icon", "Assets/Custom/VAItems/Icons/Purity_Icon", "assets/custom/vaitems/icons/purity_icon.png" };
Sprite val = null;
string[] array2 = array;
foreach (string text in array2)
{
AssetBundle assetBundle = RPGStatusEffects.assetBundle;
val = ((assetBundle != null) ? assetBundle.LoadAsset<Sprite>(text) : null);
if ((Object)(object)val != (Object)null)
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Loaded purity_icon from asset bundle at " + text + "."));
}
break;
}
}
if ((Object)(object)val == (Object)null)
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: Failed to load purity_icon from asset bundle. Attempted paths: " + string.Join(", ", array) + "."));
if ((Object)(object)RPGStatusEffects.assetBundle != (Object)null)
{
Debug.Log((object)("RPGStatusEffects: Available assets in bundle: " + string.Join(", ", RPGStatusEffects.assetBundle.GetAllAssetNames()) + "."));
}
Debug.Log((object)"RPGStatusEffects: Falling back to cyan square for Purity icon.");
}
Texture2D val2 = new Texture2D(64, 64);
Color[] array3 = (Color[])(object)new Color[4096];
for (int j = 0; j < array3.Length; j++)
{
array3[j] = Color.cyan;
}
val2.SetPixels(array3);
val2.Apply();
val = Sprite.Create(val2, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
}
return val;
}
private static Sprite LoadTauntIcon()
{
return null;
}
private static Sprite LoadTauntingIcon()
{
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Expected O, but got Unknown
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
string[] array = new string[5] { "assets/custom/vaitems/icons/taunt_icon", "Assets/Custom/VAItems/Icons/taunt_icon", "assets/custom/VAitems/icons/taunt_icon", "Assets/Custom/VAItems/Icons/Taunt_Icon", "assets/custom/vaitems/icons/taunt_icon.png" };
Sprite val = null;
string[] array2 = array;
foreach (string text in array2)
{
AssetBundle assetBundle = RPGStatusEffects.assetBundle;
val = ((assetBundle != null) ? assetBundle.LoadAsset<Sprite>(text) : null);
if ((Object)(object)val != (Object)null)
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)("RPGStatusEffects: Loaded taunt_icon from asset bundle at " + text + "."));
}
break;
}
}
if ((Object)(object)val == (Object)null)
{
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.LogWarning((object)("RPGStatusEffects: Failed to load taunt_icon from asset bundle. Attempted paths: " + string.Join(", ", array) + "."));
if ((Object)(object)RPGStatusEffects.assetBundle != (Object)null)
{
Debug.Log((object)("RPGStatusEffects: Available assets in bundle: " + string.Join(", ", RPGStatusEffects.assetBundle.GetAllAssetNames()) + "."));
}
Debug.Log((object)"RPGStatusEffects: Falling back to yellow square for Taunting icon.");
}
Texture2D val2 = new Texture2D(64, 64);
Color[] array3 = (Color[])(object)new Color[4096];
for (int j = 0; j < array3.Length; j++)
{
array3[j] = Color.yellow;
}
val2.SetPixels(array3);
val2.Apply();
val = Sprite.Create(val2, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
}
return val;
}
public static StatusEffect GetEffect(string name)
{
CustomEffects.TryGetValue(name, out var value);
return value;
}
}
public class PurityEffect : StatusEffect
{
private static readonly HashSet<string> DebuffNames = new HashSet<string> { "Poison", "Burning", "Frost", "Wet", "Smoked", "Tared" };
public Sprite Icon { get; set; }
public float Duration { get; set; } = 10f;
public override void Setup(Character character)
{
((StatusEffect)this).Setup(character);
base.m_ttl = Duration;
base.m_name = "Purify";
base.m_icon = Icon;
Character character2 = base.m_character;
Player val = (Player)(object)((character2 is Player) ? character2 : null);
if (val == null)
{
return;
}
foreach (StatusEffect item in new List<StatusEffect>(((Character)val).GetSEMan().GetStatusEffects()))
{
if ((Object)(object)item != (Object)(object)this && DebuffNames.Contains(((Object)item).name))
{
((Character)val).GetSEMan().RemoveStatusEffect(item, true);
}
}
((Character)val).Message((MessageType)2, "All debuffs purified!", 0, (Sprite)null);
}
}
public class TauntEffect : StatusEffect
{
public Character Taunter { get; set; }
public float Duration { get; set; } = 15f;
public Sprite Icon { get; set; }
public override void Setup(Character character)
{
((StatusEffect)this).Setup(character);
base.m_ttl = Duration;
base.m_name = "Taunted";
base.m_icon = Icon;
if ((Object)(object)base.m_character != (Object)null)
{
base.m_character.Message((MessageType)1, "TAUNTED!", 0, (Sprite)null);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Setup TauntEffect on {1}, Duration: {2}s, Icon: {3}.", "RPGStatusEffects", ((Object)base.m_character).name, base.m_ttl, ((Object)(object)base.m_icon != (Object)null) ? "Assigned" : "Null"));
}
}
}
public override void UpdateStatusEffect(float dt)
{
((StatusEffect)this).UpdateStatusEffect(dt);
}
public override void Stop()
{
((StatusEffect)this).Stop();
if ((Object)(object)base.m_character != (Object)null)
{
base.m_character.Message((MessageType)1, "Taunt ended.", 0, (Sprite)null);
}
}
}
public class TauntingEffect : StatusEffect
{
public float Duration { get; set; } = 15f;
public Sprite Icon { get; set; }
public override void Setup(Character character)
{
((StatusEffect)this).Setup(character);
base.m_ttl = Duration;
base.m_name = "Taunting";
base.m_icon = Icon;
if ((Object)(object)base.m_character != (Object)null && base.m_character.IsPlayer())
{
base.m_character.Message((MessageType)1, "Taunting enemy!", 0, (Sprite)null);
if (RPGStatusEffects.Instance.configVerboseLogging.Value)
{
Debug.Log((object)string.Format("{0}: Setup TauntingEffect on player {1}, Duration: {2}s, Icon: {3}.", "RPGStatusEffects", ((Object)base.m_character).name, base.m_ttl, ((Object)(object)base.m_icon != (Object)null) ? "Assigned" : "Null"));
}
}
}
public override void UpdateStatusEffect(float dt)
{
((StatusEffect)this).UpdateStatusEffect(dt);
}
public override void Stop()
{
((StatusEffect)this).Stop();
if ((Object)(object)base.m_character != (Object)null && base.m_character.IsPlayer())
{
base.m_character.Message((MessageType)1, "Taunt expired.", 0, (Sprite)null);
}
}
}
}