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 SpringsTwitchIntegration v1.0.0
BepInEx/plugins/SpringsTwitchIntegration.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LC_API.GameInterfaceAPI.Features; using LC_API.Networking; using MoreCompany; using Newtonsoft.Json; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SpringsTwitchIntegration")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SpringsTwitchIntegration")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("724cdbfe-e650-4dd4-a64b-232e8d90cc5b")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace SpringsTwitchIntegration; [BepInPlugin("io.springwhisper.SpringsTwitchIntegration", "String's Twitch Integration", "1.0.0")] public class Plugin : BaseUnityPlugin { private const string modGUID = "io.springwhisper.SpringsTwitchIntegration"; private const string modName = "String's Twitch Integration"; private const string modVersion = "1.0.0"; private const string networkTopic = "CHAT_COMMAND"; private readonly Harmony harmony = new Harmony("io.springwhisper.SpringsTwitchIntegration"); public static Plugin Instance; public RoundManager roundManager; public IDictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>(); public SelectableLevel currentLevel; public EnemyVent[] currentLevelVents; public IDictionary<string, GameObject> spawnableObjects = new Dictionary<string, GameObject>(); public static ManualLogSource mls; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } mls = Logger.CreateLogSource("io.springwhisper.SpringsTwitchIntegration"); mls.LogInfo((object)"starting twitch integration"); Network.RegisterAll(); harmony.PatchAll(typeof(Plugin)); } [HarmonyPatch(typeof(RoundManager), "LoadNewLevel")] [HarmonyPrefix] private static bool ModifyLevel(ref SelectableLevel newLevel) { Instance.roundManager = RoundManager.Instance; Instance.PopulateAudioClips(); if (((NetworkBehaviour)Instance.roundManager).IsHost) { GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if (((Object)val).name == "Landmine") { Instance.spawnableObjects["landmine"] = val; } } } return true; } [HarmonyPatch(typeof(RoundManager), "AdvanceHourAndSpawnNewBatchOfEnemies")] [HarmonyPrefix] private static void updateCurrentLevelInfo(ref EnemyVent[] ___allEnemyVents, ref SelectableLevel ___currentLevel) { Instance.currentLevel = ___currentLevel; Instance.currentLevelVents = ___allEnemyVents; } public PlayerControllerB GetPlayer(string username = null) { mls.LogInfo((object)("getting player: " + username)); if (username == null) { mls.LogInfo((object)"returning host player"); return Instance.roundManager.playersManager.localPlayerController; } mls.LogInfo((object)"searching though nroaml player list"); PlayerControllerB[] allPlayerScripts = Instance.roundManager.playersManager.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val.playerUsername.ToLower() == username.ToLower()) { mls.LogInfo((object)("found player in normal: " + val.playerUsername)); return val; } } mls.LogInfo((object)"searching though morecompany player list"); foreach (PlayerControllerB notSupposedToExistPlayer in MainClass.notSupposedToExistPlayers) { if (notSupposedToExistPlayer.playerUsername.ToLower() == username.ToLower()) { mls.LogInfo((object)("found player in morecompany: " + notSupposedToExistPlayer.playerUsername)); return notSupposedToExistPlayer; } } mls.LogInfo((object)"no player found"); return null; } public PlayerControllerB GetPlayer(ulong clientId) { mls.LogInfo((object)("getting player: " + clientId)); PlayerControllerB[] allPlayerScripts = Instance.roundManager.playersManager.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { mls.LogInfo((object)("checking venilla player: " + val.playerClientId)); if (val.playerClientId == clientId) { mls.LogInfo((object)("found player: " + val.playerUsername)); return val; } } mls.LogInfo((object)("checking morecompany player: " + clientId)); foreach (PlayerControllerB notSupposedToExistPlayer in MainClass.notSupposedToExistPlayers) { mls.LogInfo((object)("checking morecompany player: " + notSupposedToExistPlayer.playerClientId)); if (notSupposedToExistPlayer.playerClientId == clientId) { mls.LogInfo((object)("found player from morecompany: " + notSupposedToExistPlayer.playerUsername)); return notSupposedToExistPlayer; } } return null; } private void PopulateAudioClips() { mls.LogInfo((object)"populating audio clips"); if (audioClips.Count > 0) { mls.LogInfo((object)"audio clips already populated"); return; } AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val in array) { if (((Object)val).name == "Spring1" || ((Object)val).name == "Spring2" || ((Object)val).name == "Spring3") { mls.LogInfo((object)("adding audio clip: " + ((Object)val).name)); audioClips.Add(((Object)val).name, val); } } } [NetworkMessage("CHAT_COMMAND", false)] private static void HandleBroadcast(ulong sender, BroadcastCommand msg) { if ((Object)(object)Instance.roundManager == (Object)null) { Instance.roundManager = RoundManager.Instance; } if (Instance.audioClips.Count == 0) { Instance.PopulateAudioClips(); } mls.LogInfo((object)("received broadcast: " + msg.command + " " + msg.item + " " + msg.targetClientId)); if (msg.command == "drop") { Instance.DropAllHeldItemsLocal(msg.targetClientId); } else if (msg.command == "fear") { Instance.FearPlayerLocal(msg.targetClientId); } else if (msg.command == "kill") { Instance.KillPlayerLocal(msg.targetClientId); } else if (msg.command == "hurt") { Instance.HurtPlayerLocal(msg.targetClientId); } else if (msg.command == "sound") { Instance.PlaySoundLocal(msg.item, msg.targetClientId); } else if (msg.command == "drunk") { Instance.MakeDrunkLocal(msg.targetClientId); } } public bool SpawnEnemy(string enemyName) { foreach (SpawnableEnemyWithRarity enemy in currentLevel.Enemies) { if (((Object)enemy.enemyType).name.ToLower() == enemyName.ToLower()) { SpawnInsideEnemy(enemy); return true; } } foreach (SpawnableEnemyWithRarity outsideEnemy in currentLevel.OutsideEnemies) { if (((Object)outsideEnemy.enemyType).name.ToLower() == enemyName.ToLower()) { SpawnOutsideEnemy(outsideEnemy); return true; } } foreach (KeyValuePair<string, GameObject> spawnableObject in spawnableObjects) { if (spawnableObject.Key.ToLower() == enemyName.ToLower()) { return SpawnMine(0uL); } } return false; } public void SpawnInsideEnemy(SpawnableEnemyWithRarity enemy) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) roundManager.SpawnEnemyOnServer(roundManager.allEnemyVents[Random.Range(0, roundManager.allEnemyVents.Length)].floorNode.position, roundManager.allEnemyVents[0].floorNode.eulerAngles.y, currentLevel.Enemies.IndexOf(enemy)); } public void SpawnOutsideEnemy(SpawnableEnemyWithRarity enemy) { //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_0059: Unknown result type (might be due to invalid IL or missing references) Object.Instantiate<GameObject>(currentLevel.OutsideEnemies[currentLevel.OutsideEnemies.IndexOf(enemy)].enemyType.enemyPrefab, GameObject.FindGameObjectsWithTag("OutsideAINode")[Random.Range(0, GameObject.FindGameObjectsWithTag("OutsideAINode").Length - 1)].transform.position, Quaternion.Euler(Vector3.zero)).gameObject.GetComponentInChildren<NetworkObject>().Spawn(true); } public void Wipe() { mls.LogInfo((object)"wiping"); mls.LogInfo((object)"searching though nroaml player list"); PlayerControllerB[] allPlayerScripts = Instance.roundManager.playersManager.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { Instance.KillPlayer(val.playerClientId); } mls.LogInfo((object)"searching though morecompany player list"); foreach (PlayerControllerB notSupposedToExistPlayer in MainClass.notSupposedToExistPlayers) { Instance.KillPlayer(notSupposedToExistPlayer.playerClientId); } } public void KillPlayer(ulong clientId) { mls.LogInfo((object)"broadcasting kill command"); BroadcastCommand broadcastCommand = new BroadcastCommand("kill", null, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); KillPlayerLocal(clientId); } public void KillPlayerLocal(ulong clientId) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) mls.LogInfo((object)("attempting to killing player: " + clientId)); PlayerControllerB player = GetPlayer(clientId); if (((NetworkBehaviour)player).IsOwner) { mls.LogInfo((object)("killing local player: " + player.playerUsername)); player.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1); } } public bool GiveItem(string itemName, string username = null) { PlayerControllerB player = GetPlayer(username); Player orAdd = Player.GetOrAdd(player); if ((Object)(object)player != (Object)null) { Item val = Item.CreateAndGiveItem(itemName, orAdd, true, false); if ((Object)(object)val.GrabbableObject.playerHeldBy != (Object)(object)player) { mls.LogInfo((object)"item not held by player, correcting"); val.GrabbableObject.playerHeldBy = player; } return true; } return false; } public void HurtPlayer(ulong clientId) { mls.LogInfo((object)"broadcasting hurt command"); BroadcastCommand broadcastCommand = new BroadcastCommand("hurt", null, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); HurtPlayerLocal(clientId); } public void HurtPlayerLocal(ulong clientId) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB player = GetPlayer(clientId); if (((NetworkBehaviour)player).IsOwner) { mls.LogInfo((object)("hurting local player: " + player.playerUsername)); player.DamagePlayer(40, true, true, (CauseOfDeath)0, 0, false, default(Vector3)); } } public void FearPlayer(ulong clientId) { mls.LogInfo((object)"broadcasting fear command"); BroadcastCommand broadcastCommand = new BroadcastCommand("fear", null, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); FearPlayerLocal(clientId); } public void FearPlayerLocal(ulong clientId) { PlayerControllerB player = GetPlayer(clientId); if (((NetworkBehaviour)player).IsOwner) { mls.LogInfo((object)("fearing " + player.playerUsername)); player.JumpToFearLevel(1f, true); } } public void DropAllHeldItems(ulong clientId) { mls.LogInfo((object)"broadcasting drop command"); BroadcastCommand broadcastCommand = new BroadcastCommand("drop", null, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); DropAllHeldItemsLocal(clientId); } private void DropAllHeldItemsLocal(ulong clientId) { mls.LogInfo((object)("dropping all items locally for player: " + clientId)); PlayerControllerB player = Instance.GetPlayer(clientId); if (((NetworkBehaviour)player).IsOwner) { mls.LogInfo((object)"player is owner, dropping all items"); player.DropAllHeldItemsAndSync(); } } public void PlaySound(string soundName, ulong clientId) { mls.LogInfo((object)"broadcasting sound command"); BroadcastCommand broadcastCommand = new BroadcastCommand("sound", soundName, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); PlaySoundLocal(soundName, clientId); } public void PlaySoundLocal(string soundName, ulong clientId) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown mls.LogInfo((object)("playing sound locally: " + soundName)); PlayerControllerB player = Instance.GetPlayer(clientId); if (((NetworkBehaviour)player).IsOwner && Instance.audioClips.ContainsKey(soundName)) { mls.LogInfo((object)("found sound clip: " + soundName)); AudioClip val = Instance.audioClips[soundName]; GameObject val2 = new GameObject("SoundPlayer"); Vector3 position = ((Component)player).transform.position; position.y += 1f; position.z += 1f; val2.transform.position = position; AudioSource obj = val2.AddComponent<AudioSource>(); obj.clip = val; obj.spatialBlend = 1f; obj.volume = 10f; obj.Play(); Object.Destroy((Object)val2, val.length); } else { mls.LogInfo((object)("sound clip not found: " + soundName)); } } public void MakeDrunk(ulong clientId) { mls.LogInfo((object)("making player drunk: " + clientId)); MakeDrunkLocal(clientId); BroadcastCommand broadcastCommand = new BroadcastCommand("drunk", null, clientId); Network.Broadcast<BroadcastCommand>("CHAT_COMMAND", broadcastCommand); } public void MakeDrunkLocal(ulong clientId) { mls.LogInfo((object)("making player drunk locally: " + clientId)); PlayerControllerB player = Instance.GetPlayer(clientId); if ((Object)(object)player != (Object)null) { player.drunkness = 20f; } } public bool SpawnMine(ulong clientId) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB player = Instance.GetPlayer(clientId); if ((Object)(object)player != (Object)null) { Vector3 val = Instance.roundManager.RandomlyOffsetPosition(((Component)player).transform.position, 10f, 4f); if (val != ((Component)player).transform.position) { try { Object.Instantiate<GameObject>(spawnableObjects["landmine"], val, Quaternion.Euler(0f, 0f, 0f)).GetComponent<NetworkObject>().Spawn(true); return true; } catch (Exception ex) { mls.LogError((object)("error spawning mine: " + ex.Message)); return false; } } } return false; } } public class BroadcastCommand { public string command; public string item; public ulong targetClientId; public BroadcastCommand(string command, string item, ulong targetClientId) { this.command = command; this.item = item; this.targetClientId = targetClientId; } } public class ServerCommand { public string command; public string item; public string user; public string from_user; public string channel; public ServerCommand(string command, string item, string user, string from_user, string channel) { this.command = command; this.item = item; this.user = user; this.from_user = from_user; this.channel = channel; } public ServerCommandResponse ToResponse(bool success, string data) { return ServerCommandResponse.FromServerCommand(this, success, data); } } public class ServerCommandResponse { public string command; public string item; public string user; public string from_user; public string channel; public bool success; public string data; public ServerCommandResponse(string command, string item, string user, string from_user, string channel, bool success, string data) { this.command = command; this.item = item; this.user = user; this.from_user = from_user; this.channel = channel; this.success = success; this.data = data; } public static ServerCommandResponse FromServerCommand(ServerCommand command, bool success, string data) { return new ServerCommandResponse(command.command, command.item, command.user, command.from_user, command.channel, success, data); } } public class WebSocketManager { private ManualLogSource mls; private Uri uri; private ClientWebSocket webSocket; private WebSocketManager(ManualLogSource mls, string url) { this.mls = mls; uri = new Uri(url); webSocket = new ClientWebSocket(); } public static async void Connect(string url, ManualLogSource mls) { WebSocketManager webSocket = new WebSocketManager(mls, url); while (true) { try { webSocket.webSocket = new ClientWebSocket(); webSocket.mls.LogInfo((object)("connecting to " + url)); int millisecondsDelay = 5000; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(millisecondsDelay); Task connectTask = webSocket.webSocket.ConnectAsync(webSocket.uri, cancellationTokenSource.Token); if (await Task.WhenAny(new Task[2] { connectTask, Task.Delay(millisecondsDelay, cancellationTokenSource.Token) }) == connectTask) { if (webSocket.webSocket.State == WebSocketState.Open) { webSocket.mls.LogInfo((object)"connected"); await webSocket.ReceiveMessageLoop(); } } else { webSocket.mls.LogInfo((object)"connection failed..."); } } catch { webSocket.mls.LogInfo((object)"websocket failed."); } await Task.Delay(TimeSpan.FromSeconds(1.0)); webSocket.mls.LogInfo((object)"websocket disconnected, reconnecting..."); } } public async Task ReceiveMessageLoop() { mls.LogInfo((object)"starting receive loop"); while (webSocket.State == WebSocketState.Open) { try { byte[] buffer = new byte[1024]; WebSocketReceiveResult webSocketReceiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); string @string = Encoding.UTF8.GetString(buffer, 0, webSocketReceiveResult.Count); mls.LogInfo((object)("got msg: " + @string)); ServerCommand serverCommand = JsonConvert.DeserializeObject<ServerCommand>(@string); if (serverCommand.command == "kill") { PlayerControllerB player = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player != (Object)null) { Plugin.Instance.KillPlayer(player.playerClientId); ServerCommandResponse resp = serverCommand.ToResponse(success: true, null); await SendMsg(resp); } } else if (serverCommand.command == "wipe") { Plugin.Instance.Wipe(); ServerCommandResponse resp2 = serverCommand.ToResponse(success: true, null); await SendMsg(resp2); } else if (serverCommand.command == "give") { if (Plugin.Instance.GiveItem(serverCommand.item, serverCommand.user)) { ServerCommandResponse resp3 = serverCommand.ToResponse(success: true, null); await SendMsg(resp3); } } else if (serverCommand.command == "spawn") { if (Plugin.Instance.SpawnEnemy(serverCommand.item)) { ServerCommandResponse resp4 = serverCommand.ToResponse(success: true, null); await SendMsg(resp4); } } else if (serverCommand.command == "fear") { PlayerControllerB player2 = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player2 != (Object)null) { Plugin.Instance.FearPlayer(player2.playerClientId); ServerCommandResponse resp5 = serverCommand.ToResponse(success: true, null); await SendMsg(resp5); } } else if (serverCommand.command == "drunk") { PlayerControllerB player3 = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player3 != (Object)null) { Plugin.Instance.MakeDrunk(player3.playerClientId); ServerCommandResponse resp6 = serverCommand.ToResponse(success: true, null); await SendMsg(resp6); } } else if (serverCommand.command == "drop") { PlayerControllerB player4 = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player4 != (Object)null) { player4.DropAllHeldItems(true, false); Plugin.Instance.DropAllHeldItems(player4.playerClientId); ServerCommandResponse resp7 = serverCommand.ToResponse(success: true, null); await SendMsg(resp7); } } else if (serverCommand.command == "hurt") { PlayerControllerB player5 = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player5 != (Object)null) { Plugin.Instance.HurtPlayer(player5.playerClientId); ServerCommandResponse resp8 = serverCommand.ToResponse(success: true, null); await SendMsg(resp8); } } else if (serverCommand.command == "sound") { PlayerControllerB player6 = Plugin.Instance.GetPlayer(serverCommand.user); if ((Object)(object)player6 != (Object)null) { Plugin.Instance.PlaySound("Spring1", player6.playerClientId); ServerCommandResponse resp9 = serverCommand.ToResponse(success: true, null); await SendMsg(resp9); } } else if (serverCommand.command == "lightsout") { Object.FindObjectOfType<ShipLights>().SetShipLightsBoolean(false); ServerCommandResponse resp10 = serverCommand.ToResponse(success: true, null); await SendMsg(resp10); } else if (serverCommand.command == "listplayers") { List<string> list = new List<string>(); foreach (Player active in Player.ActiveList) { list.Add(active.PlayerController.playerUsername); mls.LogInfo((object)("vanilla players: " + active.PlayerController.playerUsername)); } foreach (PlayerControllerB notSupposedToExistPlayer in MainClass.notSupposedToExistPlayers) { list.Add(notSupposedToExistPlayer.playerUsername); mls.LogInfo((object)("morecompany players: " + notSupposedToExistPlayer.playerUsername)); } ServerCommandResponse resp11 = serverCommand.ToResponse(success: true, string.Join(", ", list)); await SendMsg(resp11); } else if (serverCommand.command == "listenemies") { foreach (SpawnableEnemyWithRarity enemy in Plugin.Instance.currentLevel.Enemies) { mls.LogInfo((object)("inside enemies: " + ((Object)enemy.enemyType).name.ToLower())); } foreach (SpawnableEnemyWithRarity outsideEnemy in Plugin.Instance.currentLevel.OutsideEnemies) { mls.LogInfo((object)("outside enemies: " + ((Object)outsideEnemy.enemyType).name.ToLower())); } } else if (serverCommand.command == "listitems") { foreach (Item items in Plugin.Instance.roundManager.playersManager.allItemsList.itemsList) { mls.LogInfo((object)("item: " + items.itemName.ToLower())); } } else if (serverCommand.command == "listaudio") { AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>(); foreach (AudioClip val in array) { mls.LogInfo((object)("audio clip: " + ((Object)val).name)); } } } catch (Exception ex) { mls.LogError((object)("error: " + ex)); } } } private async Task SendMsg(ServerCommandResponse resp) { ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject((object)resp))); await webSocket.SendAsync(buffer, WebSocketMessageType.Text, endOfMessage: true, CancellationToken.None); } }