using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Common;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SimpleJson;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BronzeAgeChest")]
[assembly: AssemblyDescription("https://thunderstore.io/c/valheim/p/probablykory/BronzeAgeChest/")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("BronzeAgeChest")]
[assembly: AssemblyCopyright("Copyright probablykory © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.8")]
[assembly: AssemblyCompany("probablykory")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.8.0")]
[module: <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[<140a1b61-9b0f-45d5-865a-7e7a0d70c359>Embedded]
internal sealed class <140a1b61-9b0f-45d5-865a-7e7a0d70c359>EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[<140a1b61-9b0f-45d5-865a-7e7a0d70c359>Embedded]
[CompilerGenerated]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public <d3f99811-048d-4877-8cce-f85228c1c50b>RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BronzeAgeChest
{
public static class RequirementsEntry
{
public static RequirementConfig[] Deserialize(string reqs)
{
return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Expected O, but got Unknown
string[] array = r.Split(new char[1] { ':' });
int result;
int result2;
return new RequirementConfig
{
Item = array[0],
Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0),
Recover = true
};
}).ToArray();
}
public static string Serialize(RequirementConfig[] reqs)
{
return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}"));
}
}
internal class Entries
{
private Action<object, EventArgs> _action;
public string Name { get; set; } = string.Empty;
public ConfigEntry<string> Table { get; set; }
public ConfigEntry<int> MinTableLevel { get; set; }
public ConfigEntry<int> Amount { get; set; }
public ConfigEntry<string> Requirements { get; set; }
public static Entries GetFromProps(IPlugin instance, string name, string table, string requirements)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
Entries entries = new Entries();
entries.Name = name;
entries.Table = instance.Config(entries.Name, "Table", table, new ConfigDescription("Crafting station needed to construct " + entries.Name + ".", (AcceptableValueBase)(object)CraftingStations.GetAcceptableValueList(), new object[1] { ConfigHelper.GetAdminOnlyFlag() }));
entries.Requirements = instance.Config(entries.Name, "Requirements", requirements, new ConfigDescription("The required items to construct " + entries.Name + ".", (AcceptableValueBase)(object)new AcceptableValueConfigNote("You must use valid spawn item codes."), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true,
CustomDrawer = SharedDrawers.DrawReqConfigTable()
} }));
return entries;
}
private void OnSettingChanged(object sender, EventArgs e)
{
if (_action != null)
{
_action(sender, e);
}
}
public void AddSettingsChangedHandler(Action<object, EventArgs> action)
{
_action = action;
Table.SettingChanged += OnSettingChanged;
MinTableLevel.SettingChanged += OnSettingChanged;
Amount.SettingChanged += OnSettingChanged;
Requirements.SettingChanged += OnSettingChanged;
}
public void RemoveSettingsChangedHandler()
{
Table.SettingChanged -= OnSettingChanged;
MinTableLevel.SettingChanged -= OnSettingChanged;
Amount.SettingChanged -= OnSettingChanged;
Requirements.SettingChanged -= OnSettingChanged;
_action = null;
}
}
public static class Extensions
{
private static Dictionary<string, CustomPiece> dictPieces;
public static Piece GetPiece(Piece piece)
{
Piece val = null;
foreach (KeyValuePair<string, PieceTable> item in ReflectionHelper.GetPrivateField<Dictionary<string, PieceTable>>((object)PieceManager.Instance, "PieceTableMap"))
{
foreach (GameObject piece2 in item.Value.m_pieces)
{
Piece component = piece2.GetComponent<Piece>();
if (!string.IsNullOrEmpty(((Object)component).name) && ((Object)component).name.Equals(((Object)piece).name))
{
val = component;
break;
}
}
if ((Object)(object)val != (Object)null)
{
break;
}
}
return val;
}
public static bool Update(this CustomPiece piece, PieceConfig newPiece)
{
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Expected O, but got Unknown
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Expected O, but got Unknown
if ((Object)(object)ZNetScene.instance != (Object)null)
{
Piece piece2 = GetPiece(piece.Piece);
if ((Object)(object)piece2 == (Object)null)
{
ManualLogSource logger = Get.Plugin.Logger;
object obj;
if (piece == null)
{
obj = null;
}
else
{
Piece piece3 = piece.Piece;
obj = ((piece3 != null) ? ((Object)piece3).name : null);
}
logger.LogError((object)("Error updating piece " + (string?)obj + ", did not find existing piece in available piece tables."));
return false;
}
piece2.m_craftingStation = ZNetScene.instance.GetPrefab(newPiece.CraftingStation).GetComponent<CraftingStation>();
piece2.m_resources = newPiece.GetRequirements();
Requirement[] resources = piece2.m_resources;
foreach (Requirement val in resources)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val.m_resItem).name.Replace("JVLmock_", ""));
if ((Object)(object)itemPrefab != (Object)null)
{
val.m_resItem = itemPrefab.GetComponent<ItemDrop>();
}
}
if (dictPieces == null)
{
Dictionary<string, CustomPiece> privateField = ReflectionHelper.GetPrivateField<Dictionary<string, CustomPiece>>((object)PieceManager.Instance, "Pieces");
if (privateField != null)
{
dictPieces = privateField;
}
}
if (dictPieces != null)
{
dictPieces.Remove(((Object)((Component)piece2).gameObject).name);
dictPieces.Add(((Object)((Component)piece2).gameObject).name, new CustomPiece(((Component)piece2).gameObject, piece.PieceTable, false));
}
return true;
}
PieceManager.Instance.RemovePiece(((Object)piece.PiecePrefab).name);
PieceManager.Instance.AddPiece(new CustomPiece(piece.PiecePrefab, false, newPiece));
return false;
}
}
[BepInPlugin("probablykory.BronzeAgeChest", "BronzeAgeChest", "1.0.8")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class BronzeAgeChest : BaseUnityPlugin, IPlugin
{
public const string PluginAuthor = "probablykory";
public const string PluginName = "BronzeAgeChest";
public const string PluginVersion = "1.0.8";
public const string PluginGUID = "probablykory.BronzeAgeChest";
internal static BronzeAgeChest Instance;
internal AssetBundle assetBundle;
private static ConfigEntry<bool> isDebugEnabled = null;
private CustomPiece bronzeChest;
private const string Name = "$piece_chest_bronze";
private const string PieceTable = "Hammer";
private const string Category = "Furniture";
private static Dictionary<string, string> DefaultEnglishLanguageStrings = new Dictionary<string, string> { { "$piece_chest_bronze", "Rugged Chest" } };
public ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("BronzeAgeChest");
public bool Debug
{
get
{
if (isDebugEnabled == null)
{
return true;
}
return isDebugEnabled.Value;
}
}
public Entries Entry { get; protected set; }
private void Awake()
{
Instance = this;
assetBundle = AssetUtils.LoadAssetBundleFromResources("bronzechest");
isDebugEnabled = this.Config("1 - General", "Debugging Enabled", value: false, "If on, mod will output alot more information in the debug log level.");
InitializeFeatures();
AddDefaultLocalizations();
PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
LocalizationManager.OnLocalizationAdded += OnLocalizationAdded;
SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized;
((BaseUnityPlugin)this).Config.ConfigReloaded += OnConfigReloaded;
new ConfigWatcher(this);
}
private void InitializeFeatures()
{
Entry = Entries.GetFromProps(Instance, "BronzeChest", "Workbench", "Wood:15,Bronze:1,BronzeNails:10");
}
private void UpdateFeatures()
{
bronzeChest.Update(getPieceFromEntry(Entry));
}
private void OnVanillaPrefabsAvailable()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
this.LogDebugOnly("Vanilla Prefabs Available received.");
bronzeChest = new CustomPiece(assetBundle, "piece_chest_bronze", true, getPieceFromEntry(Entry));
PieceManager.Instance.AddPiece(bronzeChest);
PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
}
private void OnConfigReloaded(object sender, EventArgs e)
{
UpdateFeatures();
}
private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e)
{
UpdateFeatures();
}
private PieceConfig getPieceFromEntry(Entries entry)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
return new PieceConfig
{
Name = "$piece_chest_bronze",
CraftingStation = CraftingStations.GetInternalName(entry.Table.Value),
PieceTable = "Hammer",
Category = "Furniture",
Requirements = RequirementsEntry.Deserialize(entry.Requirements.Value)
};
}
private void AddDefaultLocalizations()
{
this.LogDebugOnly("AddLocalizations called.");
CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
string text = "English";
localization.AddTranslation(ref text, DefaultEnglishLanguageStrings);
}
private void OnLocalizationAdded()
{
this.LogDebugOnly("Localization Added received.");
string location = ((object)Instance).GetType().Assembly.Location;
char directorySeparatorChar = Path.DirectorySeparatorChar;
string text = location.Replace(directorySeparatorChar + "BronzeAgeChest.dll", "");
if (Paths.PluginPath.Equals(text))
{
text = Utility.CombinePaths(new string[2]
{
Paths.PluginPath,
"BronzeAgeChest"
});
}
string text2 = Utility.CombinePaths(new string[4] { text, "Translations", "English", "english.json" });
string directoryName = Path.GetDirectoryName(text2);
if (!Directory.Exists(directoryName) || !File.Exists(text2))
{
Directory.CreateDirectory(directoryName);
string contents = SimpleJson.SerializeObject((object)DefaultEnglishLanguageStrings);
File.WriteAllText(text2, contents);
this.LogInfo("Default localizations written to " + text2);
}
LocalizationManager.OnLocalizationAdded -= OnLocalizationAdded;
}
ConfigFile IPlugin.get_Config()
{
return ((BaseUnityPlugin)this).Config;
}
}
}
namespace Microsoft.CodeAnalysis
{
[Microsoft.CodeAnalysis.Embedded]
[CompilerGenerated]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
[CompilerGenerated]
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]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
[Microsoft.CodeAnalysis.Embedded]
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 Common
{
internal class AcceptableValueConfigNote : AcceptableValueBase
{
public virtual string Note { get; }
public AcceptableValueConfigNote(string note)
: base(typeof(string))
{
if (string.IsNullOrEmpty(note))
{
throw new ArgumentException("A string with atleast 1 character is needed", "Note");
}
Note = note;
}
public override object Clamp(object value)
{
return value;
}
public override bool IsValid(object value)
{
return !string.IsNullOrEmpty(value as string);
}
public override string ToDescriptionString()
{
return "# Note: " + Note;
}
}
internal static class ConfigHelper
{
public static ConfigurationManagerAttributes GetAdminOnlyFlag()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
return new ConfigurationManagerAttributes
{
IsAdminOnly = true
};
}
public static ConfigurationManagerAttributes GetTags(Action<ConfigEntryBase> action)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
return new ConfigurationManagerAttributes
{
CustomDrawer = action
};
}
public static ConfigurationManagerAttributes GetTags()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
return new ConfigurationManagerAttributes();
}
public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, ConfigDescription description)
{
return instance.Config.Bind<T>(group, name, value, description);
}
public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, string description)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
return instance.Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { GetAdminOnlyFlag() }));
}
}
internal static class RequirementsEntry
{
public static RequirementConfig[] Deserialize(string reqs)
{
return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Expected O, but got Unknown
string[] array = r.Split(new char[1] { ':' });
int result;
int result2;
return new RequirementConfig
{
Item = array[0],
Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0),
Recover = true
};
}).ToArray();
}
public static string Serialize(RequirementConfig[] reqs)
{
return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}"));
}
}
internal static class SharedDrawers
{
private static BaseUnityPlugin configManager;
private static BaseUnityPlugin GetConfigManager()
{
if ((Object)(object)configManager == (Object)null && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance))
{
configManager = value.Instance;
}
return configManager;
}
public static int GetRightColumnWidth()
{
int result = 130;
BaseUnityPlugin val = GetConfigManager();
if ((Object)(object)val != (Object)null)
{
PropertyInfo propertyInfo = ((object)val)?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic);
if (propertyInfo != null)
{
result = (int)propertyInfo.GetValue(val);
}
}
return result;
}
public static void ReloadConfigDisplay()
{
BaseUnityPlugin val = GetConfigManager();
if ((Object)(object)val != (Object)null)
{
object obj = ((object)val).GetType()?.GetProperty("DisplayingWindow")?.GetValue(val);
if (obj is bool && (bool)obj)
{
((object)val).GetType().GetMethod("BuildSettingList").Invoke(val, Array.Empty<object>());
}
}
}
public static Action<ConfigEntryBase> DrawReqConfigTable(bool hasUpgrades = false)
{
return delegate(ConfigEntryBase cfg)
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Expected O, but got Unknown
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Expected O, but got Unknown
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Expected O, but got Unknown
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Expected O, but got Unknown
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Expected O, but got Unknown
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Expected O, but got Unknown
List<RequirementConfig> list = new List<RequirementConfig>();
bool flag = false;
int rightColumnWidth = GetRightColumnWidth();
GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
foreach (RequirementConfig item in RequirementsEntry.Deserialize((string)cfg.BoxedValue).ToList())
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
string text = GUILayout.TextField(item.Item, new GUIStyle(GUI.skin.textField)
{
fixedWidth = rightColumnWidth - 33 - (hasUpgrades ? 37 : 0) - 21 - 21 - 12
}, Array.Empty<GUILayoutOption>());
string text2 = (string.IsNullOrEmpty(text) ? item.Item : text);
flag = flag || text2 != item.Item;
int num = item.Amount;
if (int.TryParse(GUILayout.TextField(num.ToString(), new GUIStyle(GUI.skin.textField)
{
fixedWidth = 33f
}, Array.Empty<GUILayoutOption>()), out var result) && result != num)
{
num = result;
flag = true;
}
int num2 = item.AmountPerLevel;
if (hasUpgrades && int.TryParse(GUILayout.TextField(num2.ToString(), new GUIStyle(GUI.skin.textField)
{
fixedWidth = 33f
}, Array.Empty<GUILayoutOption>()), out var result2) && result2 != num2)
{
num2 = result2;
flag = true;
}
if (GUILayout.Button("x", new GUIStyle(GUI.skin.button)
{
fixedWidth = 21f
}, Array.Empty<GUILayoutOption>()))
{
flag = true;
}
else
{
list.Add(new RequirementConfig
{
Item = text2,
Amount = num,
AmountPerLevel = num2
});
}
if (GUILayout.Button("+", new GUIStyle(GUI.skin.button)
{
fixedWidth = 21f
}, Array.Empty<GUILayoutOption>()))
{
flag = true;
list.Add(new RequirementConfig
{
Item = "<Prefab Name>",
Amount = 1
});
}
GUILayout.EndHorizontal();
}
GUILayout.EndVertical();
if (flag)
{
cfg.BoxedValue = RequirementsEntry.Serialize(list.ToArray());
}
};
}
}
internal class ConfigWatcher
{
private BaseUnityPlugin configurationManager;
private IPlugin plugin;
public ConfigWatcher(IPlugin plugin)
{
if (plugin == null)
{
throw new ArgumentNullException("plugin");
}
this.plugin = plugin;
CheckForConfigManager();
}
private void InitializeWatcher()
{
string fileName = Path.GetFileName(plugin.Config.ConfigFilePath);
new Watcher(Path.GetDirectoryName(plugin.Config.ConfigFilePath), fileName).FileChanged += OnFileChanged;
Get.Plugin.LogDebugOnly("File system watcher initialized.");
}
private void CheckForConfigManager()
{
PluginInfo value;
if (GUIManager.IsHeadless())
{
InitializeWatcher();
}
else if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out value) && Object.op_Implicit((Object)(object)value.Instance))
{
configurationManager = value.Instance;
Get.Plugin.LogDebugOnly("Configuration manager found, hooking DisplayingWindowChanged");
EventInfo @event = ((object)configurationManager).GetType().GetEvent("DisplayingWindowChanged");
if (@event != null)
{
Action<object, object> action = OnConfigManagerDisplayingWindowChanged;
Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method);
@event.AddEventHandler(configurationManager, handler);
}
}
else
{
InitializeWatcher();
}
}
private void OnFileChanged(object sender, FileSystemEventArgs e)
{
string configFilePath = plugin.Config.ConfigFilePath;
if (!File.Exists(configFilePath))
{
return;
}
try
{
plugin.Config.SaveOnConfigSet = false;
plugin.Config.Reload();
plugin.Config.SaveOnConfigSet = true;
}
catch
{
Get.Plugin.LogError("There was an issue with your " + Path.GetFileName(configFilePath) + " file.");
Get.Plugin.LogError("Please check the format and spelling.");
}
}
private void OnConfigManagerDisplayingWindowChanged(object sender, object e)
{
if (!(bool)((object)configurationManager).GetType().GetProperty("DisplayingWindow").GetValue(configurationManager, null))
{
plugin.Config.SaveOnConfigSet = false;
plugin.Config.Reload();
plugin.Config.SaveOnConfigSet = true;
}
}
}
internal class CustomSyncedValueBase
{
private class Patches
{
[HarmonyPatch(typeof(ZNet), "Shutdown")]
[HarmonyPostfix]
private static void ZNet_Shutdown()
{
if (ZNetExtension.IsClientInstance(ZNet.instance))
{
foreach (CustomSyncedValueBase syncedValue in SyncedValues)
{
syncedValue.OnResetFromServer();
}
return;
}
foreach (CustomSyncedValueBase syncedValue2 in SyncedValues)
{
syncedValue2.OnServerShutdown();
}
}
}
public readonly string Name;
public readonly Type Type;
private object? boxedValue;
public object? LocalBaseValue;
private CustomRPC customRPC;
private static readonly HashSet<CustomSyncedValueBase> SyncedValues = new HashSet<CustomSyncedValueBase>();
private static Harmony harmony = null;
public bool IsSourceOfTruth { get; private set; } = true;
public object? BoxedValue
{
get
{
return boxedValue;
}
set
{
boxedValue = value;
this.ValueChanged?.Invoke(this, value);
}
}
public event Action<object, object>? ValueChanged;
protected CustomSyncedValueBase(string name, Type type, object? initialValue)
{
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Expected O, but got Unknown
//IL_00af: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
Name = name;
Type = type;
SyncedValues.Add(this);
if (harmony == null)
{
harmony = (Harmony)AccessTools.Field(typeof(Main), "Harmony").GetValue(null);
harmony.PatchAll(typeof(Patches));
Get.Plugin.LogDebugOnly("Jotunn's harmony instance obtained, CustomSyncedValueBase+Patches applied.");
}
boxedValue = initialValue;
customRPC = NetworkManager.Instance.AddRPC(Name + "_CustomSyncedValue_RPC", new CoroutineHandler(OnServerReceive), new CoroutineHandler(OnClientReceive));
SynchronizationManager.Instance.AddInitialSynchronization(customRPC, (Func<ZPackage>)GetPackage);
}
public void SendPackage()
{
if ((Object)(object)ZNet.instance == (Object)null)
{
Get.Plugin.LogDebugOnly("SendPackage called but am not connected.");
}
if (!SynchronizationManager.Instance.PlayerIsAdmin)
{
Get.Plugin.LogDebugOnly("SendPackage called but Player is not admin.");
}
if ((Object)(object)ZNet.instance != (Object)null && SynchronizationManager.Instance.PlayerIsAdmin)
{
ZPackage package = GetPackage();
if (ZNetExtension.IsClientInstance(ZNet.instance))
{
customRPC.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), package);
}
else
{
customRPC.SendPackage(ZNet.instance.m_peers, package);
}
}
}
private ZPackage GetPackage()
{
return new PackageEntry
{
key = Name,
type = Type,
value = boxedValue
}.ToPackage();
}
private IEnumerator OnServerReceive(long sender, ZPackage package)
{
Get.Plugin.LogDebugOnly($"Server received RPC: {sender} {package}");
yield return null;
ParsedEntries parsedEntries = package.ReadEntries();
if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value))
{
BoxedValue = (LocalBaseValue = value.value);
Get.Plugin.LogDebugOnly($"Set local and boxed: {value.value}");
customRPC.SendPackage(ZNet.instance.m_peers.Where((ZNetPeer x) => x.m_uid != sender).ToList(), package);
}
else
{
OnReceiveError(parsedEntries);
}
}
private IEnumerator OnClientReceive(long sender, ZPackage package)
{
Get.Plugin.LogDebugOnly($"Client received RPC: {sender} {package}");
yield return null;
ParsedEntries parsedEntries = package.ReadEntries();
if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value))
{
IsSourceOfTruth = false;
if (LocalBaseValue == null)
{
LocalBaseValue = BoxedValue;
}
BoxedValue = value.value;
Get.Plugin.LogDebugOnly($"Set source of truth: {IsSourceOfTruth}, {Environment.NewLine}local: {LocalBaseValue} {Environment.NewLine}boxed: {BoxedValue}");
}
else
{
OnReceiveError(parsedEntries);
}
}
private void OnReceiveError(ParsedEntries entries)
{
Get.Plugin.LogWarning(Name + "_CustomSyncedValue_RPC recieved package without expected key: " + Name);
string text = "";
foreach (KeyValuePair<string, PackageEntry> entry in entries)
{
text += $"{entry.Key} - {entry.Value.type} - {entry.Value.value?.ToString()} {Environment.NewLine}";
}
Get.Plugin.LogWarning("Result: " + Environment.NewLine + text);
}
private void OnResetFromServer()
{
BoxedValue = LocalBaseValue;
IsSourceOfTruth = true;
LocalBaseValue = null;
}
private void OnServerShutdown()
{
}
}
internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase
{
public T Value
{
get
{
return (T)base.BoxedValue;
}
set
{
base.BoxedValue = value;
if (base.BoxedValue != null)
{
SendPackage();
}
}
}
public CustomSyncedValue(string name, T value = default(T))
: base(name, typeof(T), value)
{
}
public void AssignLocalValue(T value)
{
if (base.IsSourceOfTruth && SynchronizationManager.Instance.PlayerIsAdmin)
{
Value = value;
}
else
{
LocalBaseValue = value;
}
}
}
internal class ParsedEntries : Dictionary<string, PackageEntry>
{
}
internal class PackageEntry
{
public string key;
public Type type;
public object? value;
}
internal class InvalidDeserializationTypeException : Exception
{
public string expected;
public string received;
public string field = "";
}
internal static class PackageUtils
{
public static string GetPackageTypeString(Type type)
{
return type.AssemblyQualifiedName;
}
public static void AddValue(this ZPackage package, object? value)
{
Type type = value?.GetType();
if (value is Enum)
{
value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture);
}
else
{
if (value is ICollection collection)
{
package.Write(collection.Count);
{
foreach (object item in collection)
{
package.AddValue(item);
}
return;
}
}
if ((object)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(GetPackageTypeString(fieldInfo.FieldType));
package.AddValue(fieldInfo.GetValue(value));
}
return;
}
}
ZRpc.Serialize(new object[1] { value }, ref package);
}
public static void AddEntry(this ZPackage package, PackageEntry entry)
{
package.Write(entry.key);
package.Write((entry.value == null) ? "" : GetPackageTypeString(entry.type));
package.AddValue(entry.value);
}
public static ZPackage ToPackage(this PackageEntry packageEntry)
{
return new List<PackageEntry> { packageEntry }.ToPackage();
}
public static ZPackage ToPackage(this IEnumerable<PackageEntry> packageEntries)
{
//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(packageEntries?.Count() ?? 0);
foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>())
{
val.AddEntry(item);
}
return val;
}
public static object ReadValueWithType(this ZPackage package, Type type)
{
if ((object)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 != GetPackageTypeString(fieldInfo.FieldType))
{
throw new InvalidDeserializationTypeException
{
received = text,
expected = GetPackageTypeString(fieldInfo.FieldType),
field = fieldInfo.Name
};
}
fieldInfo.SetValue(uninitializedObject, package.ReadValueWithType(fieldInfo.FieldType));
}
return uninitializedObject;
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
{
int num2 = package.ReadInt();
IDictionary dictionary = (IDictionary)Activator.CreateInstance(type);
Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments);
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 = package.ReadValueWithType(type2);
dictionary.Add(field.GetValue(obj), field2.GetValue(obj));
}
return dictionary;
}
if (type != typeof(List<string>) && type.IsGenericType)
{
Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]);
if ((object)type3 != null && 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] { package.ReadValueWithType(type.GenericTypeArguments[0]) });
}
return obj2;
}
}
ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type);
List<object> source = new List<object>();
ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source);
return source.FirstOrDefault();
}
public static ParsedEntries ReadEntries(this ZPackage package)
{
ParsedEntries parsedEntries = new ParsedEntries();
int num = package.ReadInt();
for (int i = 0; i < num; i++)
{
string key = package.ReadString();
string text = package.ReadString();
Type type = Type.GetType(text);
if (text == "" || type != null)
{
object obj;
try
{
obj = ((text == "") ? null : package.ReadValueWithType(type));
}
catch (InvalidDeserializationTypeException ex)
{
Get.Plugin.LogWarning("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text);
continue;
}
if (obj != null)
{
parsedEntries[key] = new PackageEntry
{
key = key,
type = type,
value = obj
};
}
continue;
}
Get.Plugin.LogWarning("Got invalid type " + text + ", abort reading of received configs");
return new ParsedEntries();
}
return parsedEntries;
}
public static void Test()
{
}
}
internal interface IPlugin
{
ConfigFile Config { get; }
bool Debug { get; }
ManualLogSource Logger { get; }
}
internal static class LoggingExtensions
{
private static readonly Dictionary<string, ManualLogSource> logSources = new Dictionary<string, ManualLogSource>();
internal static ManualLogSource GetLogger(this IPlugin mod)
{
if (mod.Debug)
{
Type declaringType = new StackFrame(2).GetMethod().DeclaringType;
if (!logSources.TryGetValue(declaringType.FullName, out var value))
{
value = Logger.CreateLogSource(declaringType.FullName);
logSources.Add(declaringType.FullName, value);
}
return value;
}
return mod.Logger;
}
public static void LogDebugOnly(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogDebug(data);
}
}
public static void LogDebug(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogDebug(data);
}
else
{
mod.Logger.LogDebug(data);
}
}
public static void LogInfo(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogInfo(data);
}
else
{
mod.Logger.LogInfo(data);
}
}
public static void LogMessage(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogMessage(data);
}
else
{
mod.Logger.LogMessage(data);
}
}
public static void LogWarning(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogWarning(data);
}
else
{
mod.Logger.LogWarning(data);
}
}
public static void LogError(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogError(data);
}
else
{
mod.Logger.LogError(data);
}
}
public static void LogFatal(this IPlugin mod, object data)
{
if (mod.Debug)
{
mod.GetLogger().LogFatal(data);
}
else
{
mod.Logger.LogFatal(data);
}
}
}
internal static class Get
{
private static IPlugin cachedModRef;
public static IPlugin Plugin
{
get
{
if (cachedModRef == null)
{
cachedModRef = AccessTools.Field((from p in new StackFrame(0).GetMethod().DeclaringType.Assembly.GetTypes()
where typeof(IPlugin).IsAssignableFrom(p)
select p).FirstOrDefault(), "Instance").GetValue(null) as IPlugin;
cachedModRef.LogDebugOnly("Caching static mod reference");
}
return cachedModRef;
}
}
}
internal class Watcher
{
private FileSystemWatcher fileSystemWatcher;
public bool EnableRaisingEvents
{
get
{
if (fileSystemWatcher != null)
{
return fileSystemWatcher.EnableRaisingEvents;
}
return false;
}
set
{
if (fileSystemWatcher != null)
{
fileSystemWatcher.EnableRaisingEvents = value;
}
}
}
public event Action<object, FileSystemEventArgs>? FileChanged;
public Watcher(string path, string filter)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
if (filter == null)
{
throw new ArgumentNullException("filter");
}
Get.Plugin.LogDebugOnly("Watcher created for " + path + ", " + filter);
fileSystemWatcher = new FileSystemWatcher(path, filter);
fileSystemWatcher.Changed += OnCreatedChangedOrRenamed;
fileSystemWatcher.Created += OnCreatedChangedOrRenamed;
fileSystemWatcher.Renamed += OnCreatedChangedOrRenamed;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void OnCreatedChangedOrRenamed(object sender, FileSystemEventArgs args)
{
Get.Plugin.LogDebugOnly($"OnCreatedChangedOrRenamed triggered {args.Name}, {args.ChangeType}");
this.FileChanged?.Invoke(sender, args);
}
}
}