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 SpawnTweaks v1.1.0
SpawnTweaks.dll
Decompiled 2 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using ModHub; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 SpawnTweaks { internal static class SpawnMenu { private const string Id = "spawntweaks"; private const float W = 660f; private const float H = 600f; private const float Pad = 48f; private const float RowH = 34f; private const float Gap = 12f; private static bool _enabled; private static bool _fixed; private static bool _dirty; private static float _stars; private static float _rate; private static float _maxMobs; private static string _status; private static float _statusUntil; public static bool IsOpen { get; private set; } public static void Open() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { LoadDraft(); IsOpen = true; ModHubAPI.SetInputBlock("spawntweaks", true); } } public static void Close() { IsOpen = false; ModHubAPI.SetInputBlock("spawntweaks", false); } public static void Update() { if (IsOpen && (Object)(object)Player.m_localPlayer == (Object)null) { Close(); } else if (IsOpen && Input.GetKeyDown((KeyCode)27)) { Close(); } } private static void LoadDraft() { _enabled = SpawnTweaksPlugin.Enabled; _stars = SpawnTweaksPlugin.StarChance; _rate = SpawnTweaksPlugin.SpawnRate; _maxMobs = SpawnTweaksPlugin.MaxMobs; _fixed = SpawnTweaksPlugin.AffectCreatureSpawners; _dirty = false; } public static void Draw() { //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_0028: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } if (!_dirty) { LoadDraft(); } Vector2 screen = HubUI.BeginScaled(); try { DrawWindow(screen); } finally { HubUI.EndScaled(); } } private static void DrawWindow(Vector2 screen) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) Rect val = HubUI.Centered(screen, 660f, 600f); HubUI.Window(val, "Spawn", false); if (HubUI.CloseButton(val)) { Close(); return; } if (GUI.Button(new Rect(((Rect)(ref val)).x + 22f, ((Rect)(ref val)).y + 22f, 30f, 30f), "<", HubUI.ButtonStyle)) { Close(); ModHubAPI.OpenHub(); return; } bool canEdit = SpawnTweaksPlugin.CanEdit; float num = ((Rect)(ref val)).x + 48f; float num2 = 564f; float num3 = ((Rect)(ref val)).y + 92f; string text = (HubNet.IsServer ? "Ты хост — настройки применяются ко всем игрокам." : ((!SpawnTweaksPlugin.HasServerValues) ? "На сервере нет SpawnTweaks — меняется только твой конфиг." : (SpawnTweaksPlugin.sIsAdmin ? "Ты админ — изменения уйдут на сервер всем игрокам." : "<color=#B03A34>Настройки сервера. Менять может только админ.</color>"))); GUI.Label(new Rect(num, num3, num2, 26f), text, HubUI.LabelDimStyle); num3 += 38f; bool enabled = GUI.enabled; GUI.enabled = canEdit; bool flag = HubUI.Toggle(new Rect(num, num3, num2, 34f), _enabled, "Мод включён"); if (flag != _enabled) { _enabled = flag; _dirty = true; } num3 += 52f; HubUI.Header(new Rect(num, num3, num2, 28f), "Звёзды"); num3 += 34f; float num4 = HubUI.SliderText(new Rect(num, num3, num2, 34f), "Шанс звезды", _stars, 0f, 100f, $"{_stars:0}%", "0.##", -1f); num4 = Mathf.Round(num4); if (!Mathf.Approximately(num4, _stars)) { _stars = num4; _dirty = true; } num3 += 38f; float num5 = _stars / 100f; GUI.Label(new Rect(num, num3, num2, 24f), $"1+ звезда: {num5 * 100f:0.#}% 2 звезды: {num5 * num5 * 100f:0.#}% (ваниль: 10%)", HubUI.LabelDimStyle); num3 += 42f; HubUI.Header(new Rect(num, num3, num2, 28f), "Спавн"); num3 += 34f; float num6 = HubUI.SliderText(new Rect(num, num3, num2, 34f), "Частота спавна", _rate, 0.1f, 10f, $"x{_rate:0.0}", "0.##", -1f); num6 = Mathf.Round(num6 * 10f) / 10f; if (!Mathf.Approximately(num6, _rate)) { _rate = num6; _dirty = true; } num3 += 46f; float num7 = HubUI.SliderText(new Rect(num, num3, num2, 34f), "Макс. мобов рядом", _maxMobs, 0.1f, 10f, $"x{_maxMobs:0.0}", "0.##", -1f); num7 = Mathf.Round(num7 * 10f) / 10f; if (!Mathf.Approximately(num7, _maxMobs)) { _maxMobs = num7; _dirty = true; } num3 += 46f; bool flag2 = HubUI.Toggle(new Rect(num, num3, num2, 34f), _fixed, "Лагеря и деревни (звёзды и скорость респавна)"); if (flag2 != _fixed) { _fixed = flag2; _dirty = true; } float num8 = ((Rect)(ref val)).yMax - 96f; float num9 = (num2 - 24f) / 3f; if (HubUI.Button(new Rect(num, num8, num9, 40f), "Ванилла")) { _stars = 10f; _rate = 1f; _maxMobs = 1f; _dirty = true; } GUI.enabled = enabled && _dirty; if (HubUI.Button(new Rect(num + num9 + 12f, num8, num9, 40f), "Отменить")) { LoadDraft(); } GUI.enabled = enabled && canEdit && _dirty; if (HubUI.Button(new Rect(num + (num9 + 12f) * 2f, num8, num9, 40f), _dirty ? "Применить *" : "Применить")) { Apply(); } GUI.enabled = enabled; string text2 = ((Time.unscaledTime < _statusUntil) ? _status : "Esc — закрыть"); GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).yMax - 46f, ((Rect)(ref val)).width - 48f, 22f), text2, HubUI.LabelCenterStyle); } private static void Apply() { if (HubNet.IsServer || !SpawnTweaksPlugin.HasServerValues) { ConfigSync.ApplyLocal(_enabled, _stars, _rate, _maxMobs, _fixed); SetStatus("Сохранено"); } else { if (!ConfigSync.SendToServer(_enabled, _stars, _rate, _maxMobs, _fixed)) { SetStatus("Нет связи с сервером"); return; } SetStatus("Отправлено на сервер"); } _dirty = false; } private static void SetStatus(string text) { _status = text; _statusUntil = Time.unscaledTime + 3f; } } [BepInPlugin("kaefchik.spawntweaks", "SpawnTweaks", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SpawnTweaksPlugin : BaseUnityPlugin { public const string GUID = "kaefchik.spawntweaks"; public const string NAME = "SpawnTweaks"; public const string VERSION = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> cEnabled; internal static ConfigEntry<float> cStarChance; internal static ConfigEntry<float> cSpawnRate; internal static ConfigEntry<float> cMaxMobs; internal static ConfigEntry<bool> cAffectCreatureSpawners; internal static bool HasServerValues; internal static bool sEnabled; internal static bool sAffectCreatureSpawners; internal static float sStarChance; internal static float sSpawnRate; internal static float sMaxMobs; internal static bool sIsAdmin; private FileSystemWatcher _watcher; private volatile bool _reloadPending; private bool _dirty; public static bool CanEdit => HubNet.IsServer || !HasServerValues || sIsAdmin; public static bool Enabled => HasServerValues ? sEnabled : cEnabled.Value; public static float StarChance => HasServerValues ? sStarChance : cStarChance.Value; public static float SpawnRate => HasServerValues ? sSpawnRate : cSpawnRate.Value; public static float MaxMobs => HasServerValues ? sMaxMobs : cMaxMobs.Value; public static bool AffectCreatureSpawners => HasServerValues ? sAffectCreatureSpawners : cAffectCreatureSpawners.Value; private void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; cEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Enable the mod. Server config overrides clients."); cStarChance = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Stars", "StarChancePercent", 25f, new ConfigDescription("Chance (%) for a mob to get each next star. Vanilla = 10. 25 = ~1 of 4 mobs has 1+ star, ~1 of 16 has 2 stars. Only mobs that can have stars in vanilla are affected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); cSpawnRate = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Spawn", "SpawnRateMultiplier", 1f, new ConfigDescription("How often ALL mobs spawn. 2 = twice as often. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); cMaxMobs = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Spawn", "MaxMobsMultiplier", 1f, new ConfigDescription("Multiplier for the max amount of ALL mobs around the player. 2 = twice as many. 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); cAffectCreatureSpawners = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Spawn", "AffectFixedSpawners", true, "Also affect fixed spawners (camps, dungeons, villages): star chance and respawn speed."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { _dirty = true; }; _watcher = new FileSystemWatcher(Paths.ConfigPath, "kaefchik.spawntweaks.cfg"); _watcher.Changed += delegate { _reloadPending = true; }; _watcher.Created += delegate { _reloadPending = true; }; _watcher.IncludeSubdirectories = false; _watcher.EnableRaisingEvents = true; SpawnApplier.Init(); new Harmony("kaefchik.spawntweaks").PatchAll(); Action action = SpawnMenu.Open; Action action2 = SpawnMenu.Close; ModHubAPI.Register("spawntweaks", "Spawn", action, "TrophyGreydwarf", (Sprite)null, (Color?)null, "Частота спавна мобов и шанс звёзд", 40, (Func<bool>)null, action2, (Func<bool>)(() => SpawnMenu.IsOpen)); Log.LogInfo((object)"SpawnTweaks 1.1.0 loaded"); } private void Update() { SpawnMenu.Update(); if (_reloadPending) { _reloadPending = false; try { ((BaseUnityPlugin)this).Config.Reload(); _dirty = true; } catch (Exception ex) { Log.LogWarning((object)("Config reload failed: " + ex.Message)); } } if (_dirty) { _dirty = false; ConfigSync.BroadcastIfServer(); if (!HasServerValues) { SpawnApplier.ReapplyAll(); } } } private void OnGUI() { SpawnMenu.Draw(); } private void OnDestroy() { _watcher?.Dispose(); } } internal static class SpawnApplier { private class SpawnOrig { public float Interval; public int MaxSpawned; public float LevelChance; } private class FixedOrig { public float LevelChance; public float Respawn; } private static readonly Dictionary<SpawnData, SpawnOrig> _spawnData = new Dictionary<SpawnData, SpawnOrig>(); private static readonly ConditionalWeakTable<CreatureSpawner, FixedOrig> _fixed = new ConditionalWeakTable<CreatureSpawner, FixedOrig>(); private static FieldInfo fOverrideLevelup; private static FieldInfo fFixedLevelup; private static FieldInfo fFixedRespawn; public static void Init() { fOverrideLevelup = AccessTools.Field(typeof(SpawnData), "m_overrideLevelupChance"); fFixedLevelup = AccessTools.Field(typeof(CreatureSpawner), "m_levelupChance"); fFixedRespawn = AccessTools.Field(typeof(CreatureSpawner), "m_respawnTimeMinuts"); if (fOverrideLevelup == null) { SpawnTweaksPlugin.Log.LogWarning((object)"SpawnData.m_overrideLevelupChance not found — star chance for world spawns won't work on this game version."); } if (fFixedLevelup == null) { SpawnTweaksPlugin.Log.LogWarning((object)"CreatureSpawner.m_levelupChance not found — star chance for fixed spawners won't work."); } if (fFixedRespawn == null) { SpawnTweaksPlugin.Log.LogWarning((object)"CreatureSpawner.m_respawnTimeMinuts not found — respawn speed for fixed spawners won't work."); } } private static bool CanHaveStars(int maxLevel) { return maxLevel > 1; } public static void Apply(SpawnData d) { if (d == null) { return; } if (!_spawnData.TryGetValue(d, out var value)) { value = new SpawnOrig { Interval = d.m_spawnInterval, MaxSpawned = d.m_maxSpawned, LevelChance = ((fOverrideLevelup != null) ? ((float)fOverrideLevelup.GetValue(d)) : (-1f)) }; _spawnData[d] = value; } d.m_spawnInterval = value.Interval; d.m_maxSpawned = value.MaxSpawned; fOverrideLevelup?.SetValue(d, value.LevelChance); if (SpawnTweaksPlugin.Enabled) { float num = Mathf.Max(0.1f, SpawnTweaksPlugin.SpawnRate); d.m_spawnInterval = Mathf.Max(1f, value.Interval / num); d.m_maxSpawned = Mathf.Max(1, Mathf.RoundToInt((float)value.MaxSpawned * SpawnTweaksPlugin.MaxMobs)); if (CanHaveStars(d.m_maxLevel)) { fOverrideLevelup?.SetValue(d, SpawnTweaksPlugin.StarChance); } } } public static void Apply(CreatureSpawner cs) { if ((Object)(object)cs == (Object)null) { return; } if (!_fixed.TryGetValue(cs, out var value)) { value = new FixedOrig { LevelChance = ((fFixedLevelup != null) ? ((float)fFixedLevelup.GetValue(cs)) : 10f), Respawn = ((fFixedRespawn != null) ? ((float)fFixedRespawn.GetValue(cs)) : 0f) }; _fixed.Add(cs, value); } fFixedLevelup?.SetValue(cs, value.LevelChance); fFixedRespawn?.SetValue(cs, value.Respawn); if (SpawnTweaksPlugin.Enabled && SpawnTweaksPlugin.AffectCreatureSpawners) { if (CanHaveStars(cs.m_maxLevel)) { fFixedLevelup?.SetValue(cs, SpawnTweaksPlugin.StarChance); } if (value.Respawn > 0f) { float num = Mathf.Max(0.1f, SpawnTweaksPlugin.SpawnRate); fFixedRespawn?.SetValue(cs, Mathf.Max(0.5f, value.Respawn / num)); } } } public static void ReapplyAll() { foreach (SpawnData item in _spawnData.Keys.ToList()) { Apply(item); } CreatureSpawner[] array = Object.FindObjectsOfType<CreatureSpawner>(); foreach (CreatureSpawner cs in array) { Apply(cs); } } } [HarmonyPatch(typeof(SpawnSystem), "Awake")] internal static class Patch_SpawnSystem_Awake { private static void Postfix(SpawnSystem __instance) { if (__instance.m_spawnLists == null) { return; } foreach (SpawnSystemList spawnList in __instance.m_spawnLists) { if ((Object)(object)spawnList == (Object)null || spawnList.m_spawners == null) { continue; } foreach (SpawnData spawner in spawnList.m_spawners) { SpawnApplier.Apply(spawner); } } } } [HarmonyPatch(typeof(CreatureSpawner), "Awake")] internal static class Patch_CreatureSpawner_Awake { private static void Postfix(CreatureSpawner __instance) { SpawnApplier.Apply(__instance); } } internal static class ConfigSync { public const string RPC = "SpawnTweaks_SyncConfig"; public const string RPC_SET = "SpawnTweaks_SetConfig"; private const int ProtocolVersion = 2; public static ZPackage Build(bool receiverIsAdmin) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(2); val.Write(receiverIsAdmin); val.Write(SpawnTweaksPlugin.cEnabled.Value); val.Write(SpawnTweaksPlugin.cStarChance.Value); val.Write(SpawnTweaksPlugin.cSpawnRate.Value); val.Write(SpawnTweaksPlugin.cMaxMobs.Value); val.Write(SpawnTweaksPlugin.cAffectCreatureSpawners.Value); return val; } public static void Receive(ZRpc rpc, ZPackage p) { if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { int num = p.ReadInt(); if (num != 2) { SpawnTweaksPlugin.Log.LogWarning((object)$"Server SpawnTweaks protocol {num} != {2}. Update the mod on both sides."); return; } SpawnTweaksPlugin.sIsAdmin = p.ReadBool(); SpawnTweaksPlugin.sEnabled = p.ReadBool(); SpawnTweaksPlugin.sStarChance = p.ReadSingle(); SpawnTweaksPlugin.sSpawnRate = p.ReadSingle(); SpawnTweaksPlugin.sMaxMobs = p.ReadSingle(); SpawnTweaksPlugin.sAffectCreatureSpawners = p.ReadBool(); SpawnTweaksPlugin.HasServerValues = true; SpawnTweaksPlugin.Log.LogInfo((object)$"Server config: stars {SpawnTweaksPlugin.sStarChance}%, spawn rate x{SpawnTweaksPlugin.sSpawnRate}, max mobs x{SpawnTweaksPlugin.sMaxMobs}"); SpawnApplier.ReapplyAll(); } } public static void BroadcastIfServer() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null) { ZRpc rpc = peer.m_rpc; if (rpc != null) { rpc.Invoke("SpawnTweaks_SyncConfig", new object[1] { Build(HubNet.IsAdmin(peer)) }); } } } } public static bool SendToServer(bool enabled, float stars, float rate, float maxMobs, bool fixedSpawners) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown ZRpc val = HubNet.ServerRpc(); if (val == null) { return false; } ZPackage val2 = new ZPackage(); val2.Write(2); val2.Write(enabled); val2.Write(stars); val2.Write(rate); val2.Write(maxMobs); val2.Write(fixedSpawners); val.Invoke("SpawnTweaks_SetConfig", new object[1] { val2 }); return true; } public static void ReceiveSet(ZRpc rpc, ZPackage p) { if (HubNet.IsServer) { ZNetPeer val = HubNet.FindPeer(rpc); if (!HubNet.IsAdmin(val)) { SpawnTweaksPlugin.Log.LogWarning((object)("Ignored SpawnTweaks settings from non-admin " + (val?.m_playerName ?? "?"))); } else if (p.ReadInt() == 2) { ApplyLocal(p.ReadBool(), p.ReadSingle(), p.ReadSingle(), p.ReadSingle(), p.ReadBool()); SpawnTweaksPlugin.Log.LogInfo((object)("SpawnTweaks settings changed by admin " + val.m_playerName)); } } } public static void ApplyLocal(bool enabled, float stars, float rate, float maxMobs, bool fixedSpawners) { SpawnTweaksPlugin.cEnabled.Value = enabled; SpawnTweaksPlugin.cStarChance.Value = Mathf.Clamp(stars, 0f, 100f); SpawnTweaksPlugin.cSpawnRate.Value = Mathf.Clamp(rate, 0.1f, 10f); SpawnTweaksPlugin.cMaxMobs.Value = Mathf.Clamp(maxMobs, 0.1f, 10f); SpawnTweaksPlugin.cAffectCreatureSpawners.Value = fixedSpawners; } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] internal static class Patch_ZNet_OnNewConnection { private static void Postfix(ZNetPeer peer) { if (peer != null) { ZRpc rpc = peer.m_rpc; if (rpc != null) { rpc.Register<ZPackage>("SpawnTweaks_SyncConfig", (Action<ZRpc, ZPackage>)ConfigSync.Receive); } } if (peer != null) { ZRpc rpc2 = peer.m_rpc; if (rpc2 != null) { rpc2.Register<ZPackage>("SpawnTweaks_SetConfig", (Action<ZRpc, ZPackage>)ConfigSync.ReceiveSet); } } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] internal static class Patch_ZNet_RPC_PeerInfo { private static void Postfix(ZNet __instance, ZRpc rpc) { if (__instance.IsServer() && rpc != null) { rpc.Invoke("SpawnTweaks_SyncConfig", new object[1] { ConfigSync.Build(HubNet.IsAdmin(HubNet.FindPeer(rpc))) }); } } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] internal static class Patch_ZNet_OnDestroy { private static void Postfix() { SpawnTweaksPlugin.HasServerValues = false; SpawnTweaksPlugin.sIsAdmin = false; } } }