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 rcon v1.0.5
rcon.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using UnityEngine; using rcon.Internal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("rcon")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("rcon")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("61cbb59f-4d68-43c3-a12e-b2edaced107d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace rcon { public abstract class AbstractCommand : ICommand { protected BaseUnityPlugin Plugin { get; private set; } void ICommand.setOwner(BaseUnityPlugin owner) { Plugin = owner; } public abstract string onCommand(string[] args); } internal interface ICommand { void setOwner(BaseUnityPlugin owner); string onCommand(string[] args); } [BepInPlugin("nl.avii.plugins.rcon", "rcon", "1.1")] public class rcon : BaseUnityPlugin { public delegate string UnknownCommand(string command, string[] args); public delegate string ParamsAction(params object[] args); private AsynchronousSocketListener socketListener; private ConfigEntry<bool> Enabled; private ConfigEntry<int> Port; private ConfigEntry<string> Password; private Dictionary<string, Type> commands = new Dictionary<string, Type>(); private Dictionary<string, ParamsAction> customCommands = new Dictionary<string, ParamsAction>(); private Dictionary<string, BaseUnityPlugin> owners = new Dictionary<string, BaseUnityPlugin>(); public event UnknownCommand OnUnknownCommand; private rcon() { Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("rcon", "enabled", false, "Enable RCON Communication"); Port = ((BaseUnityPlugin)this).Config.Bind<int>("rcon", "port", 2458, "Port to use for RCON Communication"); Password = ((BaseUnityPlugin)this).Config.Bind<string>("rcon", "password", "ChangeMe", "Password to use for RCON Communication"); } private void OnEnable() { if (Enabled.Value) { socketListener = new AsynchronousSocketListener(); socketListener.OnMessage += SocketListener_OnMessage; ((BaseUnityPlugin)this).Logger.LogInfo((object)("RCON Listening on port: " + Port.Value)); socketListener.StartListening(Port.Value); } } private void SocketListener_OnMessage(Socket socket, int requestId, PacketType type, string payload) { switch (type) { case PacketType.Login: { string payload4 = "Login Success"; if (payload.Trim() != Password.Value.Trim()) { payload4 = "Login Failed"; requestId = -1; } byte[] buffer = PacketBuilder.CreatePacket(requestId, PacketType.Command, payload4); socket.Send(buffer); break; } case PacketType.Command: { if (payload[0] == '/') { payload = payload.Substring(1); } List<string> list = (from Match m in Regex.Matches(payload, "(?<=[ ][\\\"]|^[\\\"])[^\\\"]+(?=[\\\"][ ]|[\\\"]$)|(?<=[ ]|^)[^\\\" ]+(?=[ ]|$)") select m.Value).ToList(); string text = list[0].ToLower(); list.RemoveAt(0); if (!commands.ContainsKey(text) && !customCommands.ContainsKey(text)) { string text2 = this.OnUnknownCommand?.Invoke(text, list.ToArray()); PacketType type2 = PacketType.Command; if (text2.ToLower().Contains("unknown")) { type2 = PacketType.Error; } socket.Send(PacketBuilder.CreatePacket(requestId, type2, text2)); } else if (commands.ContainsKey(text)) { ICommand obj = (ICommand)Activator.CreateInstance(commands[text]); obj.setOwner(owners[text]); string payload2 = obj.onCommand(list.ToArray()); socket.Send(PacketBuilder.CreatePacket(requestId, type, payload2)); } else if (customCommands.ContainsKey(text)) { ParamsAction paramsAction = customCommands[text]; object[] args = list.ToArray(); string payload3 = paramsAction(args); socket.Send(PacketBuilder.CreatePacket(requestId, type, payload3)); } break; } default: ((BaseUnityPlugin)this).Logger.LogError((object)$"Unknown packet type: {type}"); break; } } private void Update() { if (Enabled.Value && socketListener != null) { socketListener.Update(); } } private void OnDisable() { if (Enabled.Value) { socketListener.Close(); } } public void RegisterCommand<T>(BaseUnityPlugin owner, string command) where T : AbstractCommand, new() { command = command.ToLower(); if (owners.ContainsKey(command)) { ((BaseUnityPlugin)this).Logger.LogError((object)(command + " already registered")); return; } owners[command] = owner; commands[command] = typeof(T); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Registering Command: " + command)); } public void RegisterCommand(BaseUnityPlugin owner, string command, ParamsAction action) { command = command.ToLower(); if (owners.ContainsKey(command)) { ((BaseUnityPlugin)this).Logger.LogError((object)(command + " already registered")); return; } owners[command] = owner; customCommands[command] = action; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Registering Command: " + command)); } public void UnRegisterCommand(BaseUnityPlugin owner, string command) { if (owners.ContainsKey(command) && !((Object)(object)owners[command] != (Object)(object)owner)) { owners.Remove(command); if (commands.ContainsKey(command)) { commands.Remove(command); } if (customCommands.ContainsKey(command)) { customCommands.Remove(command); } } } } } namespace rcon.Internal { internal static class PacketBuilder { internal static byte[] CreatePacket(int requestId, PacketType type, string payload) { int num = 12 + payload.Length + 2; int num2 = 8 + payload.Length + 2; byte[] array = new byte[num]; array[0] = (byte)num2; array[4] = (byte)requestId; array[8] = (byte)type; for (int i = 0; i < payload.Length; i++) { array[12 + i] = (byte)payload[i]; } return array; } } internal class AsynchronousSocketListener { internal delegate void MessageReceived(Socket socket, int requestId, PacketType type, string payload); private Socket listener; private List<StateObject> clients = new List<StateObject>(); internal event MessageReceived OnMessage; internal void StartListening(int port) { IPAddress any = IPAddress.Any; IPEndPoint localEP = new IPEndPoint(any, port); listener = new Socket(any.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { listener.Bind(localEP); listener.Listen(100); } catch (Exception ex) { Debug.LogError((object)ex.ToString()); } } private bool isConnected(Socket c) { try { if (c != null && c != null && c.Connected) { if (c.Poll(0, SelectMode.SelectRead)) { return c.Receive(new byte[1], SocketFlags.Peek) != 0; } return true; } return false; } catch { return false; } } internal void Update() { for (int i = 0; i < clients.Count; i++) { StateObject stateObject = clients[i]; if (!isConnected(stateObject.workSocket)) { Debug.Log((object)"Rcon client disconnected"); stateObject.workSocket.Close(); clients.Remove(stateObject); } } listener.BeginAccept(AcceptCallback, listener); } internal void AcceptCallback(IAsyncResult ar) { Socket socket = ((Socket)ar.AsyncState).EndAccept(ar); StateObject stateObject = new StateObject(); stateObject.workSocket = socket; clients.Add(stateObject); Debug.Log((object)"Rcon client connected"); socket.BeginReceive(stateObject.buffer, 0, 4096, SocketFlags.None, ReadCallback, stateObject); } private void ReadCallback(IAsyncResult ar) { _ = string.Empty; StateObject stateObject = (StateObject)ar.AsyncState; Socket workSocket = stateObject.workSocket; workSocket.EndReceive(ar); int num = BitConverter.ToInt32(stateObject.buffer, 0); int requestId = BitConverter.ToInt32(stateObject.buffer, 4); int type = BitConverter.ToInt32(stateObject.buffer, 8); num -= 10; byte[] array = new byte[num]; for (int i = 0; i < num; i++) { array[i] = stateObject.buffer[12 + i]; } this.OnMessage?.Invoke(workSocket, requestId, (PacketType)type, Encoding.ASCII.GetString(array)); stateObject.buffer = new byte[4096]; workSocket.BeginReceive(stateObject.buffer, 0, 4096, SocketFlags.None, ReadCallback, stateObject); } private void Send(Socket handler, string data) { byte[] bytes = Encoding.ASCII.GetBytes(data); handler.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, SendCallback, handler); } private void SendCallback(IAsyncResult ar) { try { Socket obj = (Socket)ar.AsyncState; int num = obj.EndSend(ar); Debug.Log((object)$"Sent {num} bytes to client."); obj.Shutdown(SocketShutdown.Both); obj.Close(); } catch (Exception ex) { Debug.LogError((object)ex.ToString()); } } internal void Close() { if (!listener.Connected) { return; } foreach (StateObject client in clients) { if (isConnected(client.workSocket)) { client.workSocket.Close(); } } listener.Close(); } } internal enum PacketType { Error = -1, MultiPacket = 0, Command = 2, LoginResponse = 2, Login = 3 } internal class StateObject { internal const int BufferSize = 4096; internal byte[] buffer = new byte[4096]; internal Socket workSocket; } }