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 YetAnotherTestMod v1.2.2
MyFirstPlugin.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using MyFirstPlugin.Patches; using Unity.Collections; using Unity.Netcode; 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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MyFirstPlugin")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("My first plugin")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MyFirstPlugin")] [assembly: AssemblyTitle("MyFirstPlugin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MyFirstPlugin { [BepInPlugin("Yakua.TestMod", "YetAnotherTestMod", "1.2.2")] public class TestModBase : BaseUnityPlugin { private const string pluginGUID = "Yakua.TestMod"; private const string pluginName = "YetAnotherTestMod"; private const string pluginVer = "1.2.2"; private readonly Harmony harmony = new Harmony("Yakua.TestMod"); internal ManualLogSource logger; public static TestModBase Instance { get; private set; } public static PluginConfig MyConfig { get; internal set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } MyConfig = new PluginConfig(((BaseUnityPlugin)this).Config); logger = Logger.CreateLogSource("Yakua.TestMod"); Debug.unityLogger.logEnabled = false; logger.LogInfo((object)"Plugin Yakua.TestMod is loaded!"); harmony.PatchAll(typeof(TestModBase)); harmony.PatchAll(typeof(PluginConfig)); harmony.PatchAll(typeof(TurretSpawner)); } } public class PluginConfig : SyncedInstance<PluginConfig> { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } public static ConfigEntry<bool> spawnTurrets { get; private set; } public static ConfigEntry<bool> spawnMultipleTurrets { get; private set; } public static ConfigEntry<bool> allowSpawnTurretsOutdoors { get; private set; } public static ConfigEntry<int> spawnTurretsChance { get; private set; } public static ConfigEntry<string> bannedCreatures { get; private set; } public static ConfigEntry<bool> despawnTurrets { get; private set; } public static ConfigEntry<int> despawnTurretTimeInSeconds { get; private set; } public PluginConfig(ConfigFile cfg) { InitInstance(this); spawnTurrets = cfg.Bind<bool>("General.Toggles", "SpawnTurrets", true, "Whether or not to spawn turrets on enemy death"); spawnMultipleTurrets = cfg.Bind<bool>("General.Toggles", "SpawnMultipleTurrets", false, "True to spawn turret on one player. False to spawn on all players"); allowSpawnTurretsOutdoors = cfg.Bind<bool>("General.Toggles", "AllowSpawnTurretsOutdoors", false, "True to spawn turret outdoors as well. False to spawn only indoors"); despawnTurrets = cfg.Bind<bool>("General.Toggles", "DespawnTurrets", true, "Do turrets despawn over time"); spawnTurretsChance = ConfigBindClamp("General", "SpawnTurretsChance", 20, "Chance to spawn turret on each individual player(in percents from 1 to 100)", 1, 100); bannedCreatures = cfg.Bind<string>("General", "BannedCreatures", "Manticoil, Red Locust Bees, Docile Locust Bees", "True to spawn turret outdoors as well. False to spawn only indoors"); despawnTurretTimeInSeconds = cfg.Bind<int>("General", "DespawnTurretsTimeInSeconds", 120, "Time that takes turrets to despawn"); ConfigEntry<int> ConfigBindClamp(string section, string key, int defaultValue, string description, int min, int max) { ConfigEntry<int> val = cfg.Bind<int>(section, key, defaultValue, description); val.Value = Mathf.Clamp(val.Value, min, max); return val; } } public static void RequestSync() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance<PluginConfig>.IsClient) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(SyncedInstance<PluginConfig>.IntSize, (Allocator)2, -1); try { SyncedInstance<PluginConfig>.MessageManager.SendNamedMessage("ModName_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance<PluginConfig>.IsHost) { return; } TestModBase.Instance.logger.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] array = SyncedInstance<PluginConfig>.SerializeToBytes(SyncedInstance<PluginConfig>.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + SyncedInstance<PluginConfig>.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); SyncedInstance<PluginConfig>.MessageManager.SendNamedMessage("ModName_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { TestModBase.Instance.logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance<PluginConfig>.IntSize)) { TestModBase.Instance.logger.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { TestModBase.Instance.logger.LogError((object)"Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncedInstance<PluginConfig>.SyncInstance(data); TestModBase.Instance.logger.LogInfo((object)"Successfully synced config with host."); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] public static void InitializeLocalPlayer() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (SyncedInstance<PluginConfig>.IsHost) { CustomMessagingManager messageManager = SyncedInstance<PluginConfig>.MessageManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } messageManager.RegisterNamedMessageHandler("CurYATM_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); SyncedInstance<PluginConfig>.Synced = true; return; } SyncedInstance<PluginConfig>.Synced = false; CustomMessagingManager messageManager2 = SyncedInstance<PluginConfig>.MessageManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } messageManager2.RegisterNamedMessageHandler("CurYATM_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] public static void PlayerLeave() { SyncedInstance<PluginConfig>.RevertSync(); } } [Serializable] public class SyncedInstance<T> { [NonSerialized] protected static int IntSize = 4; internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient => NetworkManager.Singleton.IsClient; internal static bool IsHost => NetworkManager.Singleton.IsHost; public static T Default { get; private set; } public static T Instance { get; private set; } public static bool Synced { get; internal set; } protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } internal static void SyncInstance(byte[] data) { Instance = DeserializeFromBytes(data); Synced = true; } internal static void RevertSync() { Instance = Default; Synced = false; } public static byte[] SerializeToBytes(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { TestModBase.Instance.logger.LogError((object)$"Error serializing instance: {arg}"); return null; } } public static T DeserializeFromBytes(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { TestModBase.Instance.logger.LogError((object)$"Error deserializing instance: {arg}"); return default(T); } } } public static class PluginInfo { public const string PLUGIN_GUID = "MyFirstPlugin"; public const string PLUGIN_NAME = "MyFirstPlugin"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace MyFirstPlugin.Patches { public class TurretSpawner { public static SelectableLevel currentLevel; public static Random turretSpawnRandom; private static IEnumerable<GameObject> spawnedTurrets; private static ulong currentEnemy = 9999999uL; [HarmonyPatch(typeof(RoundManager), "AdvanceHourAndSpawnNewBatchOfEnemies")] [HarmonyPrefix] private static void updateCurrentLevelInfo(ref SelectableLevel ___currentLevel) { currentLevel = ___currentLevel; } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPostfix] private static void updateCurrentTurretSeed(int randomSeed) { turretSpawnRandom = new Random(randomSeed + 24); TestModBase.Instance.logger.LogInfo((object)$"Generated a seed for turrets: {randomSeed + 24}"); } [HarmonyPatch(typeof(EnemyAI), "KillEnemyServerRpc")] [HarmonyPostfix] private static void SpawnTurretOnDeath(EnemyAI __instance) { TestModBase.Instance.logger.LogInfo((object)("Got into Initial Spawn Method called from " + __instance.enemyType.enemyName + ".")); if (!PluginConfig.spawnTurrets.Value || currentEnemy == ((NetworkBehaviour)__instance).NetworkObject.NetworkObjectId || !((NetworkBehaviour)__instance).IsHost) { return; } string[] array = PluginConfig.bannedCreatures.Value.Split(','); string[] array2 = array; foreach (string text in array2) { if (__instance.enemyType.enemyName == text) { return; } } currentEnemy = ((NetworkBehaviour)__instance).NetworkObject.NetworkObjectId; GameObject val = null; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; PlayerControllerB[] array3 = allPlayerScripts.Where((PlayerControllerB p) => p.isPlayerControlled && !p.isPlayerDead && (p.isInsideFactory | PluginConfig.allowSpawnTurretsOutdoors.Value)).ToArray(); TestModBase.Instance.logger.LogInfo((object)$"{__instance.enemyType.enemyName} has died. Trying to spawn turret on ({array3.Length}) suitable players."); SpawnableMapObject[] spawnableMapObjects = currentLevel.spawnableMapObjects; foreach (SpawnableMapObject val2 in spawnableMapObjects) { if ((Object)(object)val2.prefabToSpawn.GetComponentInChildren<Turret>() != (Object)null) { val = val2.prefabToSpawn; } } if ((Object)(object)val == (Object)null) { TestModBase.Instance.logger.LogInfo((object)"No turret found"); } else { SpawnTurrets(val, array3); } } private static void SpawnTurrets(GameObject turret, PlayerControllerB[] suitablePlayers) { if ((Object)(object)turret == (Object)null) { return; } if (!PluginConfig.spawnMultipleTurrets.Value) { Spawn(suitablePlayers[turretSpawnRandom.Next(0, suitablePlayers.Length)]); return; } foreach (PlayerControllerB player2 in suitablePlayers) { Spawn(player2); } GameObject Spawn(PlayerControllerB player) { //IL_008b: 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) int num = turretSpawnRandom.Next(1, 101); bool flag = ((num <= PluginConfig.spawnTurretsChance.Value) ? true : false); TestModBase.Instance.logger.LogInfo((object)$"Rolled: {num} out of {PluginConfig.spawnTurretsChance.Value}. Target: {player.playerUsername}"); NetworkObject networkObject; if (flag && (Object)(object)turret != (Object)null) { networkObject = null; try { networkObject = Object.Instantiate<GameObject>(turret, ((Component)player).transform.position, Quaternion.identity).GetComponent<NetworkObject>(); networkObject.Spawn(true); if (PluginConfig.despawnTurrets.Value) { ((MonoBehaviour)networkObject).StartCoroutine(WaitForDespawn()); } spawnedTurrets = CollectionExtensions.AddItem<GameObject>(spawnedTurrets, ((Component)networkObject).gameObject); } catch (Exception arg) { TestModBase.Instance.logger.LogWarning((object)$"Exception: {arg}"); } return ((Component)networkObject).gameObject; } if ((Object)(object)turret == (Object)null) { TestModBase.Instance.logger.LogInfo((object)"No turret object found for this map"); } return null; IEnumerator WaitForDespawn() { yield return (object)new WaitForSeconds((float)PluginConfig.despawnTurretTimeInSeconds.Value); networkObject.Despawn(true); } } } [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] [HarmonyPrefix] private static void DeleteTurretsOnShipLeave() { if (spawnedTurrets == null) { return; } NetworkObject val = default(NetworkObject); foreach (GameObject spawnedTurret in spawnedTurrets) { if (spawnedTurret.TryGetComponent<NetworkObject>(ref val)) { val.Despawn(true); } } spawnedTurrets = null; } } }