using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("AdminPanelCompanion")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+cce838eb8597c27a7129cf93456d314294a36c68")] [assembly: AssemblyProduct("AdminPanelCompanion")] [assembly: AssemblyTitle("AdminPanelCompanion")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AdminPanelCompanion { [BepInPlugin("com.halitb.adminpanelcompanion", "AdminPanelCompanion", "2.1.1")] public class CompanionPlugin : BaseUnityPlugin { [HarmonyPatch] private static class RpcRegistration { [HarmonyPatch(typeof(ZNet), "Awake")] [HarmonyPostfix] private static void ZNetAwakePostfix() { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register("AP_SrvGive", (Action)OnServerGive); ZRoutedRpc.instance.Register("AP_SrvSpawn", (Action)OnServerSpawn); ZRoutedRpc.instance.Register("AP_SrvReqInv", (Action)OnServerRequestInventory); ZRoutedRpc.instance.Register("AP_SrvUndo", (Action)OnServerUndo); ZRoutedRpc.instance.Register("AP_SrvTeleport", (Action)OnServerTeleport); ZRoutedRpc.instance.Register("AP_SrvHeal", (Action)OnServerHeal); ZRoutedRpc.instance.Register("AP_SrvKick", (Action)OnServerKick); ZRoutedRpc.instance.Register("AP_SrvBan", (Action)OnServerBan); ZRoutedRpc.instance.Register("AP_SrvUnban", (Action)OnServerUnban); ZRoutedRpc.instance.Register("AP_SrvBroadcast", (Action)OnServerBroadcast); ZRoutedRpc.instance.Register("AP_SrvMsg", (Action)OnServerMessage); ZRoutedRpc.instance.Register("AP_SrvEvent", (Action)OnServerEvent); ZRoutedRpc.instance.Register("AP_SrvPeaceful", (Action)OnServerPeaceful); ZRoutedRpc.instance.Register("AP_GiveItem", (Method)OnGiveItem); ZRoutedRpc.instance.Register("AP_InvRequest", (Action)OnInventoryRequest); ZRoutedRpc.instance.Register("AP_Teleport", (Action)OnTeleport); ZRoutedRpc.instance.Register("AP_HealSelf", (Action)OnHealSelf); ZRoutedRpc.instance.Register("AP_Msg", (Action)OnMessage); } } } [HarmonyPatch(typeof(ZRoutedRpc), "RPC_RoutedRPC")] private static class RouteRpcSanitizer { private static void Prefix(ZRpc rpc, ZPackage pkg) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || pkg == null) { return; } long num = 0L; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null && peer.m_rpc == rpc) { num = peer.m_uid; break; } } if (num == 0L) { return; } int pos = pkg.GetPos(); try { pkg.SetPos(8); if (pkg.ReadLong() != num) { pkg.SetPos(8); pkg.Write(num); } } catch { } finally { pkg.SetPos(pos); } } } public const string PluginGuid = "com.halitb.adminpanelcompanion"; public const string PluginName = "AdminPanelCompanion"; public const string PluginVersion = "2.1.1"; internal static CompanionPlugin Instance; private static readonly List LastSpawnBatch = new List(); private static bool IsDedicatedServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } private void Awake() { Instance = this; Harmony.CreateAndPatchAll(typeof(RpcRegistration), (string)null); try { Harmony.CreateAndPatchAll(typeof(RouteRpcSanitizer), (string)null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("RoutedRPC sender-sanitizer patch failed (server security reduced): " + ex.Message)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"AdminPanelCompanion 2.1.1 loaded."); } private static void Log(string msg) { CompanionPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)msg); } } private static long ServerUid() { return (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null)?.m_uid ?? 0; } private static bool SenderIsServer(long sender) { return sender == ServerUid(); } private static string BareId(string host) { if (string.IsNullOrEmpty(host) || !host.Contains("_")) { return host; } return host.Substring(host.IndexOf('_') + 1); } private static SyncedList GetList(string field) { object? obj = AccessTools.Field(typeof(ZNet), field)?.GetValue(ZNet.instance); return (SyncedList)((obj is SyncedList) ? obj : null); } private static bool SenderIsAdmin(long sender) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } ZNetPeer peer = ZNet.instance.GetPeer(sender); string text = ((peer != null && peer.m_socket != null) ? peer.m_socket.GetHostName() : null); if (string.IsNullOrEmpty(text)) { return false; } SyncedList list = GetList("m_adminList"); int num; if (list != null) { if (!list.Contains(text)) { num = (list.Contains(BareId(text)) ? 1 : 0); if (num == 0) { goto IL_006b; } } else { num = 1; } goto IL_0081; } num = 0; goto IL_006b; IL_006b: Log($"DENIED admin action from non-admin {text} (peer {sender})"); goto IL_0081; IL_0081: return (byte)num != 0; } private static void OnServerGive(long sender, ZPackage pkg) { if (IsDedicatedServer && SenderIsAdmin(sender)) { long num; string text; int num3; string text2; int num2; try { num = pkg.ReadLong(); text = pkg.ReadString(); num2 = pkg.ReadInt(); num3 = pkg.ReadInt(); text2 = pkg.ReadString(); } catch (Exception ex) { Log("AP_SrvGive: malformed packet dropped (" + ex.Message + ")"); return; } if (!string.IsNullOrEmpty(text) && num2 > 0) { num2 = Mathf.Min(num2, 100000); Log($"Admin {sender} gives {num2}x {text} (q{num3}) to peer {num}"); ZRoutedRpc.instance.InvokeRoutedRPC(num, "AP_GiveItem", new object[4] { text, num2, num3, text2 }); } } } private static void OnServerSpawn(long sender, ZPackage pkg) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) if (!IsDedicatedServer || !SenderIsAdmin(sender)) { return; } int num; string text; Vector3 val; int num3; bool flag; string text2; int num2; try { num = pkg.ReadInt(); text = pkg.ReadString(); val = pkg.ReadVector3(); num2 = pkg.ReadInt(); num3 = pkg.ReadInt(); flag = pkg.ReadBool(); text2 = pkg.ReadString(); } catch (Exception ex) { Log("AP_SrvSpawn: malformed packet dropped (" + ex.Message + ")"); return; } if (string.IsNullOrEmpty(text)) { return; } num2 = Mathf.Clamp(num2, 0, 100); GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(text) : null); if ((Object)(object)val2 == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { val2 = ObjectDB.instance.GetItemPrefab(text); } if ((Object)(object)val2 == (Object)null) { Log("AP_SrvSpawn: prefab '" + text + "' not found"); return; } Log($"Admin {sender} spawns {num2}x {text} (kind {num}) at {val}"); LastSpawnBatch.Clear(); if (num == 0) { ItemDrop component = val2.GetComponent(); int num4 = ((!((Object)(object)component != (Object)null)) ? 1 : component.m_itemData.m_shared.m_maxStackSize); if (num4 < 1) { num4 = 1; } int num5 = num2; while (num5 > 0) { int num6 = Mathf.Min(num5, num4); num5 -= num6; GameObject obj = Object.Instantiate(val2, val, Quaternion.identity); RememberSpawn(obj); ItemDrop component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_itemData.m_stack = num6; component2.m_itemData.m_quality = Mathf.Clamp(num3, 1, component2.m_itemData.m_shared.m_maxQuality); component2.m_itemData.m_durability = component2.m_itemData.GetMaxDurability(); } } return; } Vector3 val3 = default(Vector3); for (int i = 0; i < num2; i++) { ((Vector3)(ref val3))..ctor(Random.Range(-1.5f, 1.5f), 0.5f, Random.Range(-1.5f, 1.5f)); GameObject val4 = Object.Instantiate(val2, val + val3, Quaternion.identity); RememberSpawn(val4); Character component3 = val4.GetComponent(); if (!((Object)(object)component3 != (Object)null)) { continue; } if (num3 > 1) { component3.SetLevel(Mathf.Clamp(num3, 1, 10)); } if (flag) { component3.SetTamed(true); } if (!flag || string.IsNullOrEmpty(text2)) { continue; } ZNetView component4 = val4.GetComponent(); if (component4 != null) { ZDO zDO = component4.GetZDO(); if (zDO != null) { zDO.Set("TamedName", text2); } } } } private static void RememberSpawn(GameObject go) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) ZNetView component = go.GetComponent(); ZDO val = (((Object)(object)component != (Object)null) ? component.GetZDO() : null); if (val != null) { LastSpawnBatch.Add(val.m_uid); } } private static void OnServerUndo(long sender) { //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_002c: Unknown result type (might be due to invalid IL or missing references) if (!IsDedicatedServer || !SenderIsAdmin(sender)) { return; } int num = 0; foreach (ZDOID item in LastSpawnBatch) { ZDO zDO = ZDOMan.instance.GetZDO(item); if (zDO != null) { ZNetView val = ZNetScene.instance.FindInstance(zDO); ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { val2.ClaimOwnership(); val2.Destroy(); num++; } else { ZDOMan.instance.DestroyZDO(zDO); num++; } } } Log($"Admin {sender} undo: removed {num} spawned objects"); LastSpawnBatch.Clear(); } private static void OnServerRequestInventory(long sender, long targetUid) { if (IsDedicatedServer && SenderIsAdmin(sender)) { ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "AP_InvRequest", new object[1] { sender }); } } private static void OnServerTeleport(long sender, ZPackage pkg) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0072: Unknown result type (might be due to invalid IL or missing references) if (IsDedicatedServer && SenderIsAdmin(sender)) { long num; Vector3 val; try { num = pkg.ReadLong(); val = pkg.ReadVector3(); } catch (Exception ex) { Log("AP_SrvTeleport: malformed packet dropped (" + ex.Message + ")"); return; } Log($"Admin {sender} teleports peer {num} to {val}"); ZRoutedRpc.instance.InvokeRoutedRPC(num, "AP_Teleport", new object[1] { val }); } } private static void OnServerHeal(long sender, long targetUid) { if (IsDedicatedServer && SenderIsAdmin(sender)) { ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "AP_HealSelf", Array.Empty()); } } private static string HostOfPeer(long uid) { if ((Object)(object)ZNet.instance == (Object)null) { return null; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_uid == uid) { return (peer.m_socket != null) ? peer.m_socket.GetHostName() : null; } } return null; } private static bool KickByUid(long uid) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_uid != uid) { continue; } MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "InternalKick", new Type[1] { typeof(ZNetPeer) }, (Type[])null) ?? AccessTools.Method(typeof(ZNet), "Kick", new Type[1] { typeof(ZNetPeer) }, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(ZNet.instance, new object[1] { peer }); } else { ZRpc rpc = peer.m_rpc; if (rpc != null) { ISocket socket = rpc.GetSocket(); if (socket != null) { socket.Close(); } } } return true; } return false; } private static void OnServerKick(long sender, long uid) { if (IsDedicatedServer && SenderIsAdmin(sender)) { bool flag = KickByUid(uid); Log(string.Format("Admin {0} kick peer {1}: {2}", sender, uid, flag ? "kicked" : "peer not found")); } } private static void OnServerBan(long sender, long uid) { if (!IsDedicatedServer || !SenderIsAdmin(sender)) { return; } string text = BareId(HostOfPeer(uid)); if (!string.IsNullOrEmpty(text)) { SyncedList list = GetList("m_bannedList"); if (list != null && !list.Contains(text)) { list.Add(text); } } bool flag = KickByUid(uid); Log(string.Format("Admin {0} ban peer {1} ({2}): {3}", sender, uid, text ?? "unknown", flag ? "kicked" : "peer not found")); } private static void OnServerUnban(long sender, string host) { if (IsDedicatedServer && SenderIsAdmin(sender)) { SyncedList list = GetList("m_bannedList"); string text = BareId(host); if (list != null) { list.Remove(text); list.Remove(host); } Log($"Admin {sender} unbans {text}"); } } private static void OnServerBroadcast(long sender, string text) { if (IsDedicatedServer && SenderIsAdmin(sender)) { Log("Admin broadcast: " + text); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "AP_Msg", new object[1] { text }); } } private static void OnServerMessage(long sender, long targetUid, string text) { if (IsDedicatedServer && SenderIsAdmin(sender)) { ZRoutedRpc.instance.InvokeRoutedRPC(targetUid, "AP_Msg", new object[1] { text }); } } private static void OnServerEvent(long sender, string eventName, Vector3 pos) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (IsDedicatedServer && SenderIsAdmin(sender) && !((Object)(object)RandEventSystem.instance == (Object)null)) { Log($"Admin {sender} starts event '{eventName}' at {pos}"); RandEventSystem.instance.SetRandomEventByName(eventName, pos); } } private static void OnServerPeaceful(long sender, bool peaceful) { if (!IsDedicatedServer || !SenderIsAdmin(sender)) { return; } if (!((AccessTools.Field(typeof(RandEventSystem), "m_events") ?? AccessTools.Field(typeof(RandEventSystem), "m_randomEvents"))?.GetValue(RandEventSystem.instance) is IList list)) { Log("Peaceful toggle: event list not found"); return; } int num = 0; foreach (object item in list) { FieldInfo fieldInfo = AccessTools.Field(item.GetType(), "m_enabled"); if (!(fieldInfo == null)) { fieldInfo.SetValue(item, !peaceful); num++; } } if (peaceful && (Object)(object)RandEventSystem.instance != (Object)null) { RandEventSystem.instance.ResetRandomEvent(); } Log(string.Format("Peaceful mode {0} ({1} events toggled)", peaceful ? "ON" : "OFF", num)); } private static void OnGiveItem(long sender, string prefabName, int amount, int quality, string crafter) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !SenderIsServer(sender)) { return; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); if ((Object)(object)val == (Object)null) { return; } ItemDrop component = val.GetComponent(); if ((Object)(object)component == (Object)null || component.m_itemData.m_shared.m_icons == null || component.m_itemData.m_shared.m_icons.Length == 0) { return; } int num = component.m_itemData.m_shared.m_maxStackSize; if (num < 1) { num = 1; } int num2 = amount; while (num2 > 0) { int num3 = Mathf.Min(num2, num); num2 -= num3; ItemData val2 = component.m_itemData.Clone(); val2.m_dropPrefab = val; val2.m_stack = num3; val2.m_quality = Mathf.Clamp(quality, 1, val2.m_shared.m_maxQuality); val2.m_durability = val2.GetMaxDurability(); if (!string.IsNullOrEmpty(crafter)) { val2.m_crafterID = 1L; val2.m_crafterName = crafter; } if (!((Humanoid)localPlayer).GetInventory().AddItem(val2)) { ItemDrop component2 = Object.Instantiate(val, ((Component)localPlayer).transform.position + Vector3.up, Quaternion.identity).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_itemData.m_stack = num3; component2.m_itemData.m_quality = Mathf.Clamp(quality, 1, component2.m_itemData.m_shared.m_maxQuality); } } } ((Character)localPlayer).Message((MessageType)2, $"An admin granted you {amount}x {prefabName}!", 0, (Sprite)null); } private static void OnInventoryRequest(long sender, long replyTo) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !SenderIsServer(sender)) { return; } ZPackage val = new ZPackage(); val.Write(localPlayer.GetPlayerName()); List allItems = ((Humanoid)localPlayer).GetInventory().GetAllItems(); val.Write(allItems.Count); foreach (ItemData item in allItems) { val.Write(((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : item.m_shared.m_name); val.Write(item.m_stack); val.Write(item.m_quality); } ZRoutedRpc.instance.InvokeRoutedRPC(replyTo, "AP_InvData", new object[1] { val }); } private static void OnTeleport(long sender, Vector3 pos) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_002a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && SenderIsServer(sender)) { ((Character)localPlayer).TeleportTo(pos + Vector3.up, ((Component)localPlayer).transform.rotation, true); ((Character)localPlayer).Message((MessageType)2, "An admin teleported you!", 0, (Sprite)null); } } private static void OnHealSelf(long sender) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && SenderIsServer(sender)) { ((Character)localPlayer).Heal(((Character)localPlayer).GetMaxHealth(), true); ((Character)localPlayer).Message((MessageType)2, "An admin healed you!", 0, (Sprite)null); } } private static void OnMessage(long sender, string text) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && SenderIsServer(sender)) { ((Character)localPlayer).Message((MessageType)2, "[Server] " + text, 0, (Sprite)null); } } } }