Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ConfigurationsForEveryone v1.0.0
ConfigurationsForEveryone.dll
Decompiled 16 hours agousing 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.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ConfigurationsForEveryone")] [assembly: AssemblyDescription("Adds server-synced BepInEx configs for items, pieces and creatures of Jotunn-based content mods that ship without any")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ConfigurationsForEveryone")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b7e2c1d4-9a8f-4c3e-bd21-7f0a4e6d2c91")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 ConfigurationsForEveryone { [BepInPlugin("IAmOnTheInternetAndItIsScary.ConfigurationsForEveryone", "ConfigurationsForEveryone", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ConfigurationsForEveryonePlugin : BaseUnityPlugin { [HarmonyPatch(typeof(FejdStartup), "Awake")] private static class FejdStartupPatch { private static bool built; [HarmonyPostfix] private static void Postfix() { if (!built) { built = true; ConfigBuilder.BuildAll("FejdStartup.Awake"); } } } internal const string ModName = "ConfigurationsForEveryone"; internal const string ModGUID = "IAmOnTheInternetAndItIsScary.ConfigurationsForEveryone"; internal const string ModVersion = "1.0.0"; internal static readonly ManualLogSource Log = Logger.CreateLogSource("ConfigurationsForEveryone"); internal static ConfigEntry<bool>? DebugLogging; private readonly Harmony _harmony = new Harmony("IAmOnTheInternetAndItIsScary.ConfigurationsForEveryone"); public void Awake() { DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug Logging", false, "Log every config value as it is applied to the game so you can confirm changes take effect"); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RefreshCommand()); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Debug("ConfigurationsForEveryone 1.0.0 loaded, waiting for the main menu to discover content"); } internal static void Debug(string message) { if (DebugLogging != null && DebugLogging.Value) { Log.LogInfo((object)message); } } } internal sealed class DiscoveredMod { public string Guid = ""; public string Name = ""; public string Version = ""; public readonly List<CustomItem> Items = new List<CustomItem>(); public readonly List<CustomPiece> Pieces = new List<CustomPiece>(); public readonly List<CustomCreature> Creatures = new List<CustomCreature>(); public int Count => Items.Count + Pieces.Count + Creatures.Count; } internal static class Discovery { private const BindingFlags InstanceNonPublic = BindingFlags.Instance | BindingFlags.NonPublic; public static int LastItemCount { get; private set; } public static int LastPieceCount { get; private set; } public static int LastCreatureCount { get; private set; } public static int LastUnattributed { get; private set; } public static List<DiscoveredMod> Run() { Dictionary<string, DiscoveredMod> dictionary = new Dictionary<string, DiscoveredMod>(StringComparer.OrdinalIgnoreCase); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (CustomItem item in ReadRegistry<CustomItem>(typeof(ItemManager), ItemManager.Instance, "Items")) { num++; DiscoveredMod mod = GetMod(dictionary, ((CustomEntity)item).SourceMod); if (mod == null) { num4++; } else { mod.Items.Add(item); } } foreach (CustomPiece item2 in ReadRegistry<CustomPiece>(typeof(PieceManager), PieceManager.Instance, "Pieces")) { num2++; DiscoveredMod mod2 = GetMod(dictionary, ((CustomEntity)item2).SourceMod); if (mod2 == null) { num4++; } else { mod2.Pieces.Add(item2); } } foreach (CustomCreature item3 in ReadRegistry<CustomCreature>(typeof(CreatureManager), CreatureManager.Instance, "Creatures")) { num3++; DiscoveredMod mod3 = GetMod(dictionary, ((CustomEntity)item3).SourceMod); if (mod3 == null) { num4++; } else { mod3.Creatures.Add(item3); } } LastItemCount = num; LastPieceCount = num2; LastCreatureCount = num3; LastUnattributed = num4; if (num4 > 0) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)$"{num4} registered entries had no resolvable source mod and were skipped"); } return (from m in dictionary.Values where m.Count > 0 orderby m.Name select m).ToList(); } private static DiscoveredMod? GetMod(Dictionary<string, DiscoveredMod> byGuid, BepInPlugin? sourceMod) { if (sourceMod == null || string.IsNullOrEmpty(sourceMod.GUID)) { return null; } if (!byGuid.TryGetValue(sourceMod.GUID, out DiscoveredMod value)) { value = new DiscoveredMod { Guid = sourceMod.GUID, Name = (string.IsNullOrEmpty(sourceMod.Name) ? sourceMod.GUID : sourceMod.Name), Version = (sourceMod.Version?.ToString() ?? "0.0.0") }; byGuid[sourceMod.GUID] = value; } return value; } private static IEnumerable<T> ReadRegistry<T>(Type managerType, object instance, string fieldName) where T : class { FieldInfo field = managerType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("Could not find " + managerType.Name + "." + fieldName + " - Jotunn version may have changed")); yield break; } object value = field.GetValue(instance); if (!(value is IEnumerable registry)) { yield break; } DictionaryEntry dictionaryEntry = default(DictionaryEntry); foreach (object entry in registry) { object value2 = entry; int num; if (entry is DictionaryEntry) { dictionaryEntry = (DictionaryEntry)entry; num = 1; } else { num = 0; } if (num != 0) { value2 = dictionaryEntry.Value; } else { PropertyInfo valueProperty = entry.GetType().GetProperty("Value"); if (valueProperty != null && entry.GetType().IsGenericType) { value2 = valueProperty.GetValue(entry); } } if (value2 is T typed) { yield return typed; } dictionaryEntry = default(DictionaryEntry); } } } internal sealed class ModConfig { public readonly ConfigFile File; private readonly BepInPlugin _metadata; private readonly Dictionary<string, string> _displayNames = new Dictionary<string, string>(StringComparer.Ordinal); public ModConfig(DiscoveredMod mod) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "ConfigurationsForEveryone"); Directory.CreateDirectory(text); string path = Sanitize(mod.Guid) + ".cfg"; _metadata = new BepInPlugin(mod.Guid, mod.Name, mod.Version); File = new ConfigFile(Path.Combine(text, path), true, _metadata) { SaveOnConfigSet = false }; File.SettingChanged += OnSettingChanged; RegisterForSync(); } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { ConfigEntryBase changedSetting = args.ChangedSetting; ConfigurationsForEveryonePlugin.Debug($"[{_metadata.Name}] {changedSetting.Definition.Section} > {changedSetting.Definition.Key} changed to '{changedSetting.BoxedValue}', applied and synced"); } public void SetDisplayName(string section, string displayName) { if (!string.IsNullOrEmpty(displayName) && displayName != section) { _displayNames[section] = displayName; } } public ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase? acceptableValues = null, int order = 0, Action<ConfigEntryBase>? customDrawer = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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 ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true, Order = order }; if (_displayNames.TryGetValue(section, out string value2)) { val.Category = value2 + " (" + section + ")"; } if (customDrawer != null) { val.CustomDrawer = customDrawer; } return File.Bind<T>(section, key, value, new ConfigDescription(description, acceptableValues, new object[1] { val })); } public void Save() { File.SaveOnConfigSet = true; File.Save(); } private void RegisterForSync() { try { SynchronizationManager.Instance.RegisterCustomConfig(File); } catch (Exception ex) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("Could not register " + _metadata.Name + " config for server sync: " + ex.Message)); } } public void CreateMenuProxy(GameObject host) { try { ProxyPlugin proxyPlugin = host.AddComponent<ProxyPlugin>(); OverwriteBackingField(typeof(BaseUnityPlugin), proxyPlugin, "Config", File); PluginInfo info = ((BaseUnityPlugin)proxyPlugin).Info; if (info != null) { OverwriteProperty(typeof(PluginInfo), info, "Metadata", _metadata); } } catch (Exception ex) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("Could not surface " + _metadata.Name + " in the configuration manager: " + ex.Message)); } } private static void OverwriteBackingField(Type owner, object instance, string propertyName, object value) { owner.GetField("<" + propertyName + ">k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(instance, value); } private static void OverwriteProperty(Type owner, object instance, string propertyName, object value) { MethodInfo methodInfo = owner.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public)?.GetSetMethod(nonPublic: true); if (methodInfo != null) { methodInfo.Invoke(instance, new object[1] { value }); } else { OverwriteBackingField(owner, instance, propertyName, value); } } private static string Sanitize(string name) { return Path.GetInvalidFileNameChars().Aggregate(name, (string current, char invalid) => current.Replace(invalid, '_')); } } [BepInPlugin("IAmOnTheInternetAndItIsScary.ConfigurationsForEveryone.Proxy", "ConfigurationsForEveryone Proxy", "1.0.0")] [BepInProcess("ConfigurationsForEveryone.ProxyNeverRuns")] internal class ProxyPlugin : BaseUnityPlugin { } internal static class ConfigBuilder { private static readonly HashSet<string> Configured = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static GameObject? _proxyHost; public static void BuildAll(string trigger) { try { List<DiscoveredMod> list = Discovery.Run(); if (list.Count == 0) { ConfigurationsForEveryonePlugin.Log.LogInfo((object)$"{trigger}: no RtD content found in the Jotunn registries yet ({Discovery.LastItemCount} item(s), {Discovery.LastPieceCount} piece(s), {Discovery.LastCreatureCount} creature(s) scanned)"); return; } int num = 0; foreach (DiscoveredMod item in list) { if (!Configured.Add(item.Guid)) { continue; } EnsureProxyHost(); ModConfig modConfig = new ModConfig(item); foreach (CustomCreature creature in item.Creatures) { try { Creatures.Bind(modConfig, creature); } catch (Exception ex) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)(item.Name + ": skipped a creature (" + ex.Message + ")")); } } foreach (CustomItem item2 in item.Items) { try { Items.Bind(modConfig, item2); } catch (Exception ex2) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)(item.Name + ": skipped an item (" + ex2.Message + ")")); } } foreach (CustomPiece piece in item.Pieces) { try { Pieces.Bind(modConfig, piece); } catch (Exception ex3) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)(item.Name + ": skipped a piece (" + ex3.Message + ")")); } } modConfig.Save(); modConfig.CreateMenuProxy(_proxyHost); num++; ConfigurationsForEveryonePlugin.Log.LogInfo((object)$"✓ {item.Name}: {item.Items.Count} item(s), {item.Pieces.Count} piece(s), {item.Creatures.Count} creature(s) configured"); } if (num > 0) { ConfigurationsForEveryonePlugin.Log.LogInfo((object)string.Format("✓ Generated synced config files for {0} new mod(s) under config/{1}", num, "ConfigurationsForEveryone")); } } catch (Exception arg) { ConfigurationsForEveryonePlugin.Log.LogError((object)$"Failed to build configs: {arg}"); } } private static void EnsureProxyHost() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_proxyHost)) { _proxyHost = new GameObject("ConfigurationsForEveryone_Proxies"); Object.DontDestroyOnLoad((Object)(object)_proxyHost); } } } internal static class Appliers { public const string KindItem = "item recipe(s)"; public const string KindPiece = "piece(s)"; public const string KindCreatureSpawn = "creature spawn(s)"; public const string KindCreatureTaming = "creature taming"; public const string KindCreatureDrops = "creature drops"; private static readonly List<(Action Run, string Kind)> Registered = new List<(Action, string)>(); public static void Register(Action applier, string kind) { Registered.Add((applier, kind)); } public static int RunAll() { int num = 0; Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (var (action, text) in Registered) { try { action(); num++; dictionary[text] = ((!dictionary.TryGetValue(text, out var value)) ? 1 : (value + 1)); } catch (Exception ex) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("Applier failed (" + text + "): " + ex.Message)); } } if (num > 0) { string text2 = string.Join(", ", from c in dictionary orderby c.Key select $"{c.Value} {c.Key}"); ConfigurationsForEveryonePlugin.Log.LogInfo((object)("Applied config to loaded content: " + text2)); } return num; } } internal sealed class ApplyScheduler : MonoBehaviour { private const float DebounceSeconds = 0.4f; private static ApplyScheduler? _instance; private static readonly Dictionary<Action, float> Pending = new Dictionary<Action, float>(); private static readonly List<Action> Due = new List<Action>(); public static void Schedule(Action applier) { EnsureInstance(); Pending[applier] = Time.realtimeSinceStartup + 0.4f; } private static void EnsureInstance() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_instance)) { GameObject val = new GameObject("ConfigurationsForEveryone_ApplyScheduler"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent<ApplyScheduler>(); } } private void Update() { if (Pending.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; Due.Clear(); foreach (KeyValuePair<Action, float> item in Pending) { if (realtimeSinceStartup >= item.Value) { Due.Add(item.Key); } } if (Due.Count == 0) { return; } foreach (Action item2 in Due) { Pending.Remove(item2); try { item2(); } catch (Exception ex) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("Applier failed: " + ex.Message)); } } ConfigurationsForEveryonePlugin.Debug($"Config edit settled, re-applied {Due.Count} group(s) to prefabs"); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { [HarmonyPostfix] private static void Postfix() { ConfigBuilder.BuildAll("ZNetScene.Awake"); Appliers.RunAll(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDBAwakePatch { [HarmonyPostfix] private static void Postfix() { ConfigBuilder.BuildAll("ObjectDB.Awake"); Appliers.RunAll(); } } internal static class Reqs { private const string MockPrefix = "JVLmock_"; public static string Localize(string? token, string fallback) { if (string.IsNullOrEmpty(token)) { return fallback; } try { if (Localization.instance == null) { return fallback; } string text = Localization.instance.Localize(token); return (string.IsNullOrWhiteSpace(text) || text.StartsWith("[")) ? fallback : text; } catch { return fallback; } } public static string CleanName(string? prefabName) { if (string.IsNullOrEmpty(prefabName)) { return ""; } return prefabName.StartsWith("JVLmock_") ? prefabName.Substring("JVLmock_".Length) : prefabName; } public static string SerializeRequirements(Requirement[]? requirements, bool includePerLevel = false) { if (requirements == null) { return ""; } return string.Join(",", from r in requirements where r != null && Object.op_Implicit((Object)(object)r.m_resItem) select includePerLevel ? $"{CleanName(((Object)r.m_resItem).name)}:{r.m_amount}:{r.m_amountPerLevel}" : $"{CleanName(((Object)r.m_resItem).name)}:{r.m_amount}"); } public static Requirement[] ParseRequirements(string value) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || string.IsNullOrWhiteSpace(value)) { return Array.Empty<Requirement>(); } return (from requirement in (from part in value.Split(new char[1] { ',' }) select part.Trim() into part where part.Length > 0 select part).Select((Func<string, Requirement>)delegate(string part) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) string[] array = part.Split(new char[1] { ':' }); string text = CleanName(array[0].Trim()); int result; int num = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result); int result2; int amountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : num); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); return ((Object)(object)val == (Object)null) ? ((Requirement)null) : new Requirement { m_resItem = val, m_amount = num, m_amountPerLevel = amountPerLevel, m_recover = true }; }) where requirement != null select (requirement)).ToArray(); } public static string SerializeDrops(List<Drop>? drops) { if (drops == null) { return ""; } return string.Join(",", from d in drops where d != null && Object.op_Implicit((Object)(object)d.m_prefab) select $"{CleanName(((Object)d.m_prefab).name)}:{d.m_amountMin}-{d.m_amountMax}:{(d.m_chance * 100f).ToString(CultureInfo.InvariantCulture)}"); } public static List<Drop> ParseDrops(string value) { //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown List<Drop> list = new List<Drop>(); if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || string.IsNullOrWhiteSpace(value)) { return list; } foreach (string item in from s in value.Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s) { string[] array = item.Split(new char[1] { ':' }); GameObject prefab = ZNetScene.instance.GetPrefab(CleanName(array[0].Trim())); if (Object.op_Implicit((Object)(object)prefab)) { int result = 1; int amountMax = 1; if (array.Length > 1) { string[] array2 = array[1].Split(new char[1] { '-' }); int.TryParse(array2[0], out result); amountMax = ((array2.Length > 1 && int.TryParse(array2[1], out var result2)) ? result2 : result); } float result3 = 100f; if (array.Length > 2) { float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out result3); } list.Add(new Drop { m_prefab = prefab, m_amountMin = result, m_amountMax = amountMax, m_chance = result3 / 100f, m_onePerPlayer = false, m_levelMultiplier = true }); } } return list; } } internal static class Creatures { private enum SpawnTime { Day, Night, Always } private enum SpawnArea { Center, Edge, Everywhere } private enum ForestSetting { Yes, No, Both } private static readonly FieldRef<BaseAI, Tameable> BaseAiTamableRef = AccessTools.FieldRefAccess<BaseAI, Tameable>("m_tamable"); public static void Bind(ModConfig config, CustomCreature creature) { GameObject prefab = creature.Prefab; if (!((Object)(object)prefab == (Object)null)) { string name = ((Object)prefab).name; Character val = default(Character); config.SetDisplayName(name, prefab.TryGetComponent<Character>(ref val) ? Reqs.Localize(val.m_name, name) : name); if (creature.Spawns.Count > 0) { BindSpawn(config, creature, name); } BindTaming(config, prefab, name); BindDrops(config, prefab, name); } } private static void BindSpawn(ModConfig config, CustomCreature creature, string section) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) SpawnData val = creature.Spawns[0]; ConfigEntry<bool> enabled = config.Bind(section, "Spawn Enabled", val.m_enabled, "Whether this creature spawns naturally in the world", null, 40); ConfigEntry<Biome> biome = config.Bind<Biome>(section, "Spawn Biome", val.m_biome, "Biome the creature spawns in", null, 39); ConfigEntry<SpawnArea> area = config.Bind(section, "Spawn Area", FromBiomeArea(val.m_biomeArea), "Where inside the biome the creature spawns", null, 38); ConfigEntry<SpawnTime> time = config.Bind(section, "Spawn Time", FromSpawnData(val), "Time of day the creature spawns", null, 37); ConfigEntry<int> maximum = config.Bind(section, "Maximum Count", val.m_maxSpawned, "Maximum number of this creature near the player before spawning stops", null, 36); ConfigEntry<float> interval = config.Bind(section, "Spawn Interval", val.m_spawnInterval, "Seconds between spawn attempts", null, 35); ConfigEntry<float> chance = config.Bind(section, "Spawn Chance", val.m_spawnChance, "Percent chance to spawn on each attempt", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 100f), 34); ConfigEntry<int> groupMin = config.Bind(section, "Group Size Min", val.m_groupSizeMin, "Minimum number spawned together", null, 33); ConfigEntry<int> groupMax = config.Bind(section, "Group Size Max", val.m_groupSizeMax, "Maximum number spawned together", null, 32); ConfigEntry<float> altitudeMin = config.Bind(section, "Altitude Min", val.m_minAltitude, "Minimum altitude required to spawn", null, 31); ConfigEntry<float> altitudeMax = config.Bind(section, "Altitude Max", val.m_maxAltitude, "Maximum altitude allowed to spawn", null, 30); ConfigEntry<float> oceanMin = config.Bind(section, "Ocean Depth Min", val.m_minOceanDepth, "Minimum ocean depth required to spawn", null, 29); ConfigEntry<float> oceanMax = config.Bind(section, "Ocean Depth Max", val.m_maxOceanDepth, "Maximum ocean depth allowed to spawn", null, 28); ConfigEntry<float> groundOffset = config.Bind(section, "Spawn Altitude", val.m_groundOffset, "Height above the ground the creature spawns at", null, 27); ConfigEntry<ForestSetting> forest = config.Bind(section, "Forest Condition", FromForest(val), "Whether the creature spawns in forests, outside forests, or both", null, 26); ConfigEntry<bool> huntPlayer = config.Bind(section, "Hunt Player", val.m_huntPlayer, "Whether the creature immediately hunts the player after spawning", null, 25); ConfigEntry<bool> canHaveStars = config.Bind(section, "Can Have Stars", val.m_maxLevel > 1, "Whether the creature can spawn with stars", null, 24); ConfigEntry<string> globalKey = config.Bind(section, "Required Global Key", val.m_requiredGlobalKey ?? "", "Global key required before the creature spawns", null, 23); ConfigEntry<string> environments = config.Bind(section, "Required Weather", string.Join(",", val.m_requiredEnvironments ?? new List<string>()), "Comma separated weather environment names required to spawn", null, 22); Action applySpawn = ApplySpawn; applySpawn(); Appliers.Register(applySpawn, "creature spawn(s)"); enabled.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; biome.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; area.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; time.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; maximum.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; interval.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; chance.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; groupMin.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; groupMax.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; altitudeMin.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; altitudeMax.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; oceanMin.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; oceanMax.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; groundOffset.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; forest.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; huntPlayer.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; canHaveStars.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; globalKey.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; environments.SettingChanged += delegate { ApplyScheduler.Schedule(applySpawn); }; void ApplySpawn() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) foreach (SpawnData spawn in creature.Spawns) { spawn.m_enabled = enabled.Value; spawn.m_biome = biome.Value; spawn.m_biomeArea = ToBiomeArea(area.Value); spawn.m_maxSpawned = maximum.Value; spawn.m_spawnInterval = interval.Value; spawn.m_spawnChance = chance.Value; spawn.m_groupSizeMin = groupMin.Value; spawn.m_groupSizeMax = groupMax.Value; spawn.m_minAltitude = altitudeMin.Value; spawn.m_maxAltitude = altitudeMax.Value; spawn.m_minOceanDepth = oceanMin.Value; spawn.m_maxOceanDepth = oceanMax.Value; spawn.m_groundOffset = groundOffset.Value; spawn.m_huntPlayer = huntPlayer.Value; spawn.m_maxLevel = ((!canHaveStars.Value) ? 1 : 3); spawn.m_requiredGlobalKey = globalKey.Value; spawn.m_requiredEnvironments = (from s in environments.Value.Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s).ToList(); SpawnData val2 = spawn; SpawnTime value = time.Value; bool spawnAtNight = (uint)(value - 1) <= 1u; val2.m_spawnAtNight = spawnAtNight; SpawnData val3 = spawn; value = time.Value; spawnAtNight = ((value == SpawnTime.Day || value == SpawnTime.Always) ? true : false); val3.m_spawnAtDay = spawnAtNight; SpawnData val4 = spawn; ForestSetting value2 = forest.Value; spawnAtNight = ((value2 == ForestSetting.Yes || value2 == ForestSetting.Both) ? true : false); val4.m_inForest = spawnAtNight; SpawnData val5 = spawn; value2 = forest.Value; spawnAtNight = (uint)(value2 - 1) <= 1u; val5.m_outsideForest = spawnAtNight; } ConfigurationsForEveryonePlugin.Debug($"[{section}] applied spawn: enabled={enabled.Value} biome={biome.Value} chance={chance.Value} max={maximum.Value}"); } } private static void BindTaming(ModConfig config, GameObject prefab, string section) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) Tameable val = default(Tameable); bool value = prefab.TryGetComponent<Tameable>(ref val); float value2 = (Object.op_Implicit((Object)(object)val) ? val.m_fedDuration : 0f); float value3 = (Object.op_Implicit((Object)(object)val) ? val.m_tamingTime : 1800f); bool value4 = Object.op_Implicit((Object)(object)val) && val.m_startsTamed; MonsterAI val2 = default(MonsterAI); string value5 = (prefab.TryGetComponent<MonsterAI>(ref val2) ? string.Join(",", from i in val2.m_consumeItems where Object.op_Implicit((Object)(object)i) && i.m_itemData != null && Object.op_Implicit((Object)(object)i.m_itemData.m_dropPrefab) select Reqs.CleanName(((Object)i.m_itemData.m_dropPrefab).name)) : ""); Character val3 = default(Character); Faction value6 = (Faction)((!prefab.TryGetComponent<Character>(ref val3)) ? 1 : ((int)val3.m_faction)); ConfigEntry<bool> canBeTamed = config.Bind(section, "Can Be Tamed", value, "Whether the creature can be tamed", null, 19); ConfigEntry<string> foodItems = config.Bind(section, "Food Items", value5, "Comma separated item names the creature eats to tame", null, 18); ConfigEntry<float> fedDuration = config.Bind(section, "Fed Duration", value2, "Seconds the creature stays fed after eating", null, 17); ConfigEntry<float> tamingTime = config.Bind(section, "Taming Time", value3, "Seconds it takes to fully tame the creature", null, 16); ConfigEntry<bool> spawnsTamed = config.Bind(section, "Spawns Tamed", value4, "Whether the creature spawns already tamed", null, 15); ConfigEntry<Faction> faction = config.Bind<Faction>(section, "Faction", value6, "Faction the creature belongs to", null, 14); Action applyTaming = ApplyTaming; Appliers.Register(applyTaming, "creature taming"); canBeTamed.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; foodItems.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; fedDuration.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; tamingTime.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; spawnsTamed.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; faction.SettingChanged += delegate { ApplyScheduler.Schedule(applyTaming); }; void ApplyTaming() { //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) Tameable val4 = prefab.GetComponent<Tameable>(); if (canBeTamed.Value && !Object.op_Implicit((Object)(object)val4)) { val4 = prefab.AddComponent<Tameable>(); BaseAI val5 = default(BaseAI); if (prefab.TryGetComponent<BaseAI>(ref val5)) { BaseAiTamableRef.Invoke(val5) = val4; } } else if (!canBeTamed.Value && Object.op_Implicit((Object)(object)val4)) { Object.Destroy((Object)(object)val4); val4 = null; } if (Object.op_Implicit((Object)(object)val4)) { val4.m_fedDuration = fedDuration.Value; val4.m_tamingTime = tamingTime.Value; val4.m_startsTamed = spawnsTamed.Value; } MonsterAI val6 = default(MonsterAI); if (prefab.TryGetComponent<MonsterAI>(ref val6) && Object.op_Implicit((Object)(object)ObjectDB.instance)) { val6.m_consumeItems = (from drop in (from s in foodItems.Value.Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s).Select(delegate(string name) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(Reqs.CleanName(name)); return (itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null; }) where (Object)(object)drop != (Object)null select (drop)).ToList(); } Character val7 = default(Character); if (prefab.TryGetComponent<Character>(ref val7)) { val7.m_faction = faction.Value; } ConfigurationsForEveryonePlugin.Debug($"[{section}] applied taming: canBeTamed={canBeTamed.Value} faction={faction.Value} spawnsTamed={spawnsTamed.Value} food='{foodItems.Value}'"); } } private static void BindDrops(ModConfig config, GameObject prefab, string section) { CharacterDrop component = prefab.GetComponent<CharacterDrop>(); string value = (Object.op_Implicit((Object)(object)component) ? Reqs.SerializeDrops(component.m_drops) : ""); ConfigEntry<string> drops = config.Bind(section, "Drops", value, "Comma separated itemName:min-max:chance drops when killed", null, 13, Drawer.Drops); Action applyDrops = ApplyDrops; Appliers.Register(applyDrops, "creature drops"); drops.SettingChanged += delegate { ApplyScheduler.Schedule(applyDrops); }; void ApplyDrops() { if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { ConfigurationsForEveryonePlugin.Debug("[" + section + "] drops not applied yet: world not loaded"); } else { List<Drop> list = Reqs.ParseDrops(drops.Value); if (list.Count == 0 && drops.Value.Trim().Length > 0) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("[" + section + "] drops '" + drops.Value + "' resolved to nothing, leaving existing drops unchanged")); } else { CharacterDrop val = prefab.GetComponent<CharacterDrop>(); if (!Object.op_Implicit((Object)(object)val)) { val = prefab.AddComponent<CharacterDrop>(); } val.m_drops = list; ConfigurationsForEveryonePlugin.Debug($"[{section}] applied {list.Count} drop(s) '{drops.Value}' (visible on next kill)"); } } } } private static SpawnTime FromSpawnData(SpawnData data) { if (data.m_spawnAtDay && data.m_spawnAtNight) { return SpawnTime.Always; } return data.m_spawnAtNight ? SpawnTime.Night : SpawnTime.Day; } private static SpawnArea FromBiomeArea(BiomeArea area) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if (1 == 0) { } SpawnArea result = (((int)area == 1) ? SpawnArea.Edge : (((int)area != 2) ? SpawnArea.Everywhere : SpawnArea.Center)); if (1 == 0) { } return result; } private static BiomeArea ToBiomeArea(SpawnArea area) { //IL_0011: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } BiomeArea result = (BiomeArea)(area switch { SpawnArea.Center => 2, SpawnArea.Edge => 1, _ => 3, }); if (1 == 0) { } return result; } private static ForestSetting FromForest(SpawnData data) { if (data.m_inForest && data.m_outsideForest) { return ForestSetting.Both; } return (!data.m_inForest) ? ForestSetting.No : ForestSetting.Yes; } } internal static class Items { public static void Bind(ModConfig config, CustomItem item) { GameObject itemPrefab = item.ItemPrefab; if ((Object)(object)itemPrefab == (Object)null) { return; } CustomRecipe recipe = item.Recipe; Recipe recipe2 = ((recipe != null) ? recipe.Recipe : null); string section; ConfigEntry<bool> craftable; ConfigEntry<int> craftAmount; ConfigEntry<string> station; ConfigEntry<int> stationLevel; ConfigEntry<string> resources; if (!((Object)(object)recipe2 == (Object)null)) { section = ((Object)itemPrefab).name; ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); bool flag = Object.op_Implicit((Object)(object)component) && component.m_itemData?.m_shared != null && component.m_itemData.m_shared.m_maxQuality > 1; config.SetDisplayName(section, Reqs.Localize((Object.op_Implicit((Object)(object)component) && component.m_itemData?.m_shared != null) ? component.m_itemData.m_shared.m_name : null, section)); craftable = config.Bind(section, "Craftable", recipe2.m_enabled, "Whether the item can be crafted", null, 40); craftAmount = config.Bind(section, "Craft Amount", recipe2.m_amount, "Number of items produced by a single craft", null, 39); station = config.Bind(section, "Crafting Station", Object.op_Implicit((Object)(object)recipe2.m_craftingStation) ? Reqs.CleanName(((Object)recipe2.m_craftingStation).name) : "", "Crafting station prefab name required to craft, empty for hand crafting", null, 38); stationLevel = config.Bind(section, "Crafting Station Level", recipe2.m_minStationLevel, "Minimum crafting station level required to craft", null, 37); resources = config.Bind(section, "Crafting Costs", Reqs.SerializeRequirements(recipe2.m_resources, flag), flag ? "Comma separated itemName:amount:perUpgradeLevel resources, the third number is added for each upgrade level" : "Comma separated itemName:amount resources required to craft", null, 36, flag ? Drawer.RequirementsWithUpgrade : Drawer.Requirements); Action apply = Apply; Appliers.Register(apply, "item recipe(s)"); craftable.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; craftAmount.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; station.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; stationLevel.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; resources.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; } void Apply() { recipe2.m_enabled = craftable.Value; recipe2.m_amount = craftAmount.Value; recipe2.m_minStationLevel = stationLevel.Value; if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { Requirement[] array = Reqs.ParseRequirements(resources.Value); if (array.Length != 0) { recipe2.m_resources = array; } } if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { if (string.IsNullOrEmpty(station.Value)) { recipe2.m_craftingStation = null; } else { GameObject prefab = ZNetScene.instance.GetPrefab(Reqs.CleanName(station.Value)); CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("[" + section + "] crafting station '" + station.Value + "' could not be resolved")); } recipe2.m_craftingStation = val; } } ConfigurationsForEveryonePlugin.Debug($"[{section}] applied item: craftable={craftable.Value} amount={craftAmount.Value} station='{station.Value}' level={stationLevel.Value} costs='{resources.Value}'"); } } } internal static class Pieces { public static void Bind(ModConfig config, CustomPiece customPiece) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) Piece piece = customPiece.Piece; string section; ConfigEntry<bool> buildable; ConfigEntry<PieceCategory> category; ConfigEntry<string> station; ConfigEntry<string> resources; if (!((Object)(object)piece == (Object)null)) { section = (Object.op_Implicit((Object)(object)customPiece.PiecePrefab) ? ((Object)customPiece.PiecePrefab).name : ((Object)piece).name); config.SetDisplayName(section, Reqs.Localize(piece.m_name, section)); buildable = config.Bind(section, "Buildable", piece.m_enabled, "Whether the piece can be built", null, 40); category = config.Bind<PieceCategory>(section, "Category", piece.m_category, "Build menu category the piece appears in", null, 39); station = config.Bind(section, "Crafting Station", Object.op_Implicit((Object)(object)piece.m_craftingStation) ? Reqs.CleanName(((Object)piece.m_craftingStation).name) : "", "Crafting station prefab name required to build, empty for none", null, 38); resources = config.Bind(section, "Build Costs", Reqs.SerializeRequirements(piece.m_resources), "Comma separated itemName:amount resources required to build", null, 37, Drawer.Requirements); Action apply = Apply; Appliers.Register(apply, "piece(s)"); buildable.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; category.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; station.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; resources.SettingChanged += delegate { ApplyScheduler.Schedule(apply); }; } void Apply() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) piece.m_enabled = buildable.Value; piece.m_category = category.Value; if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { Requirement[] array = Reqs.ParseRequirements(resources.Value); if (array.Length != 0) { piece.m_resources = array; } } if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { if (string.IsNullOrEmpty(station.Value)) { piece.m_craftingStation = null; } else { GameObject prefab = ZNetScene.instance.GetPrefab(Reqs.CleanName(station.Value)); CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { ConfigurationsForEveryonePlugin.Log.LogWarning((object)("[" + section + "] crafting station '" + station.Value + "' could not be resolved")); } piece.m_craftingStation = val; } } ConfigurationsForEveryonePlugin.Debug($"[{section}] applied piece: buildable={buildable.Value} category={category.Value} station='{station.Value}' costs='{resources.Value}'"); } } } internal static class Drawer { private struct Req { public string Name; public int Amount; public int PerLevel; } private struct DropRow { public string Name; public int Min; public int Max; public float Chance; } public static readonly Action<ConfigEntryBase> Requirements = delegate(ConfigEntryBase cfg) { Guard(cfg, delegate(ConfigEntryBase c) { DrawRequirements(c, withUpgrade: false); }); }; public static readonly Action<ConfigEntryBase> RequirementsWithUpgrade = delegate(ConfigEntryBase cfg) { Guard(cfg, delegate(ConfigEntryBase c) { DrawRequirements(c, withUpgrade: true); }); }; public static readonly Action<ConfigEntryBase> Drops = delegate(ConfigEntryBase cfg) { Guard(cfg, DrawDrops); }; private const int ButtonWidth = 24; private static GUIStyle? _textStyle; private static GUIStyle? _buttonStyle; private static GUIStyle? _centerLabelStyle; private static object? _configManager; private static bool _configManagerResolved; private static void EnsureStyles() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if (_textStyle == null) { _textStyle = new GUIStyle(GUI.skin.textField); _buttonStyle = new GUIStyle(GUI.skin.button); _centerLabelStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4 }; } } private static void Guard(ConfigEntryBase cfg, Action<ConfigEntryBase> draw) { try { EnsureStyles(); draw(cfg); } catch (Exception ex) { GUILayout.Label((string)cfg.BoxedValue, Array.Empty<GUILayoutOption>()); ConfigurationsForEveryonePlugin.Debug("drawer failed for '" + cfg.Definition.Key + "': " + ex.Message); } } private static int ColumnWidth() { if (!_configManagerResolved) { _configManagerResolved = true; try { Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); if (type != null && Object.op_Implicit((Object)(object)Chainloader.ManagerObject)) { _configManager = Chainloader.ManagerObject.GetComponent(type); } } catch { } } try { if (_configManager?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_configManager) is int num && num > 0) { return num; } } catch { } return 130; } private static void DrawRequirements(ConfigEntryBase cfg, bool withUpgrade) { List<Req> list = ParseReqs((string)cfg.BoxedValue); List<Req> list2 = new List<Req>(); bool flag = false; int num = 119 + (withUpgrade ? 77 : 0); int num2 = Math.Max(60, ColumnWidth() - num); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (list.Count == 0) { list.Add(new Req { Name = "", Amount = 1, PerLevel = 1 }); flag = true; } foreach (Req item in list) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); int num3 = item.Amount; if (int.TryParse(GUILayout.TextField(num3.ToString(), _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }), out var result) && result != num3) { num3 = result; flag = true; } GUILayout.Label("x", _centerLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) }); string text = GUILayout.TextField(item.Name, _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width((float)num2) }); flag = flag || text != item.Name; int num4 = item.PerLevel; if (withUpgrade) { if (int.TryParse(GUILayout.TextField(num4.ToString(), _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }), out var result2) && result2 != num4) { num4 = result2; flag = true; } GUILayout.Label("/lvl", _centerLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }); } bool flag2 = GUILayout.Button("✕", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); bool flag3 = GUILayout.Button("+", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); GUILayout.EndHorizontal(); if (flag2) { flag = true; } else { list2.Add(new Req { Name = text, Amount = num3, PerLevel = num4 }); } if (flag3) { flag = true; list2.Add(new Req { Name = "", Amount = 1, PerLevel = 1 }); } } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = SerializeReqs(list2, withUpgrade); } } private static string SerializeReqs(List<Req> reqs, bool withUpgrade) { return string.Join(",", reqs.Select((Req r) => withUpgrade ? $"{r.Name.Trim()}:{r.Amount}:{r.PerLevel}" : $"{r.Name.Trim()}:{r.Amount}")); } private static List<Req> ParseReqs(string value) { List<Req> list = new List<Req>(); if (string.IsNullOrWhiteSpace(value)) { return list; } foreach (string item in from p in value.Split(new char[1] { ',' }) select p.Trim() into p where p.Length > 0 select p) { string[] array = item.Split(new char[1] { ':' }); int result; int num = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result); int result2; int perLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : num); list.Add(new Req { Name = array[0].Trim(), Amount = num, PerLevel = perLevel }); } return list; } private static void DrawDrops(ConfigEntryBase cfg) { List<DropRow> list = ParseDrops((string)cfg.BoxedValue); List<DropRow> list2 = new List<DropRow>(); bool flag = false; int num = 201; int num2 = Math.Max(60, ColumnWidth() - num); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (list.Count == 0) { list.Add(new DropRow { Name = "", Min = 1, Max = 1, Chance = 100f }); flag = true; } foreach (DropRow item in list) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); int num3 = item.Min; if (int.TryParse(GUILayout.TextField(num3.ToString(), _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(35f) }), out var result) && result != num3) { num3 = result; flag = true; } GUILayout.Label("-", _centerLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(10f) }); int num4 = item.Max; if (int.TryParse(GUILayout.TextField(num4.ToString(), _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(35f) }), out var result2) && result2 != num4) { num4 = result2; flag = true; } string text = GUILayout.TextField(item.Name, _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width((float)num2) }); flag = flag || text != item.Name; float num5 = item.Chance; if (float.TryParse(GUILayout.TextField(num5.ToString(CultureInfo.InvariantCulture), _textStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }), out var result3) && Math.Abs(result3 - num5) > 1E-05f) { num5 = result3; flag = true; } GUILayout.Label("%", _centerLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) }); bool flag2 = GUILayout.Button("✕", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); bool flag3 = GUILayout.Button("+", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); GUILayout.EndHorizontal(); if (flag2) { flag = true; } else { list2.Add(new DropRow { Name = text, Min = num3, Max = num4, Chance = num5 }); } if (flag3) { flag = true; list2.Add(new DropRow { Name = "", Min = 1, Max = 1, Chance = 100f }); } } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = SerializeDrops(list2); } } private static string SerializeDrops(List<DropRow> drops) { return string.Join(",", drops.Select((DropRow d) => $"{d.Name.Trim()}:{d.Min}-{d.Max}:{d.Chance.ToString(CultureInfo.InvariantCulture)}")); } private static List<DropRow> ParseDrops(string value) { List<DropRow> list = new List<DropRow>(); if (string.IsNullOrWhiteSpace(value)) { return list; } foreach (string item in from s in value.Split(new char[1] { ',' }) select s.Trim() into s where s.Length > 0 select s) { string[] array = item.Split(new char[1] { ':' }); int result = 1; int max = 1; if (array.Length > 1) { string[] array2 = array[1].Split(new char[1] { '-' }); int.TryParse(array2[0], out result); max = ((array2.Length > 1 && int.TryParse(array2[1], out var result2)) ? result2 : result); } float result3 = 100f; if (array.Length > 2) { float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out result3); } list.Add(new DropRow { Name = array[0].Trim(), Min = result, Max = max, Chance = result3 }); } return list; } } internal sealed class RefreshCommand : ConsoleCommand { public override string Name => "cfe_refresh"; public override string Help => "Re-apply every ConfigurationsForEveryone setting to the loaded game content"; public override void Run(string[] args, Terminal context) { int num = Appliers.RunAll(); if (context != null) { context.AddString($"ConfigurationsForEveryone re-applied {num} setting group(s)"); } } } }