using 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.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using ValheimAdminForge.Catalog; using ValheimAdminForge.Commands; using ValheimAdminForge.Gui; using ValheimAdminForge.Net; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ValheimAdminForge")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: AssemblyInformationalVersion("0.4.0")] [assembly: AssemblyProduct("ValheimAdminForge")] [assembly: AssemblyTitle("ValheimAdminForge")] [assembly: AssemblyVersion("0.4.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 ValheimAdminForge { internal static class ItemSpawner { public static bool GiveToLocalPlayer(string prefabName, int amount) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return Fail(null, "can't spawn '" + prefabName + "': no local player"); } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return Fail(localPlayer, "can't spawn '" + prefabName + "': ObjectDB not ready"); } GameObject itemPrefab = instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab == (Object)null) { return Fail(localPlayer, "unknown item '" + prefabName + "'"); } ItemDrop component = itemPrefab.GetComponent(); if ((Object)(object)component == (Object)null) { return Fail(localPlayer, "'" + prefabName + "' is not an item (no ItemDrop)"); } int num = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); Inventory inventory = ((Humanoid)localPlayer).GetInventory(); int num2 = Mathf.Max(1, amount); int num3 = 0; while (num2 > 0) { int num4 = Mathf.Min(num2, num); if (!inventory.AddItem(itemPrefab, num4)) { break; } num3 += num4; num2 -= num4; } if (num3 == 0) { return Fail(localPlayer, "inventory full — gave 0x " + prefabName); } Plugin.Log.LogInfo((object)$"Gave {num3}x {prefabName} (requested {amount})"); ((Character)localPlayer).Message((MessageType)1, $"Spawned {num3}x {prefabName}", 0, (Sprite)null, false); return true; } private static bool Fail(Player player, string message) { Plugin.Log.LogWarning((object)message); if (player != null) { ((Character)player).Message((MessageType)1, message, 0, (Sprite)null, false); } return false; } } [BepInPlugin("com.skitale.valheimadminforge", "ValheimAdminForge", "0.4.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.skitale.valheimadminforge"; public const string PluginName = "ValheimAdminForge"; public const string PluginVersion = "0.4.0"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Loading ValheimAdminForge v0.4.0..."); PluginConfig.Init(((BaseUnityPlugin)this).Config); GuiStyles.Init(); AdminWindow.Init(); AdminRpc.Init(); _harmony = new Harmony("com.skitale.valheimadminforge"); PatchAllTolerant(); Log.LogInfo((object)"ValheimAdminForge loaded!"); } private void Update() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) AdminRpc.Tick(); MapPicker.Tick(); if (!MapPicker.IsArmed) { KeyboardShortcut value = PluginConfig.ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { AdminWindow.Toggle(); } } if (AdminWindow.IsOpen && Input.GetKeyDown((KeyCode)27)) { AdminWindow.IsOpen = false; } if (AdminWindow.IsOpen && (Object)(object)Player.m_localPlayer == (Object)null) { AdminWindow.IsOpen = false; } } private void OnGUI() { AdminWindow.Draw(); } private void PatchAllTolerant() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0) { try { new PatchClassProcessor(_harmony, type).Patch(); } catch (Exception ex) { Log.LogWarning((object)("skipped patch " + type.Name + ": " + ex.Message)); } } } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class PluginConfig { public static ConfigEntry ToggleKey; public static ConfigEntry MaxQuantity; public static ConfigEntry AllowNonAdminWindow; public static ConfigEntry WindowWidth; public static ConfigEntry WindowHeight; public static ConfigEntry WindowOpacity; public static ConfigEntry WindowTextColor; public static ConfigEntry WindowDimTextColor; public static ConfigEntry ServerMaxQuantity; public static ConfigEntry ServerStrictItemCheck; public static ConfigEntry ServerMaxActionRadius; public static ConfigEntry ServerMaxCreatureSpawn; public static ConfigEntry ServerAllowBossSpawn; public static ConfigEntry ServerMaxDespawnRadius; public static ConfigEntry ServerPlayerTags; public static ConfigEntry ServerTeleportSpread; public static void Init(ConfigFile cfg) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Expected O, but got Unknown //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown ToggleKey = cfg.Bind("General", "ToggleKey", new KeyboardShortcut((KeyCode)277, Array.Empty()), "Opens/closes the Admin Forge window."); MaxQuantity = cfg.Bind("General", "MaxQuantity", 100, new ConfigDescription("Upper bound for the quantity field.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 9999), Array.Empty())); AllowNonAdminWindow = cfg.Bind("General", "AllowNonAdminWindow", false, "Let non-admins open the window anyway (every action is still refused by the server)."); WindowWidth = cfg.Bind("Window", "Width", 640, new ConfigDescription("Admin Forge window width in pixels. Below ~560 the wider tabs (Creatures, World) clip.", (AcceptableValueBase)(object)new AcceptableValueRange(560, 3000), Array.Empty())); WindowHeight = cfg.Bind("Window", "Height", 720, new ConfigDescription("Admin Forge window height in pixels. Below ~560 the tab content overflows the window.", (AcceptableValueBase)(object)new AcceptableValueRange(560, 2000), Array.Empty())); WindowOpacity = cfg.Bind("Window", "Opacity", 0.8f, new ConfigDescription("Window background opacity (1 = solid). Very low values make the (also configurable) text hard to read against whatever's behind the window.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 1f), Array.Empty())); WindowTextColor = cfg.Bind("Window", "TextColor", "#000000", "Primary text color as a hex string, e.g. #000000. Falls back to the default if unparsable."); WindowDimTextColor = cfg.Bind("Window", "DimTextColor", "#000000", "Secondary/dim text color (prefab names, hints, detail text) as a hex string. Falls back to the default if unparsable."); ServerMaxQuantity = cfg.Bind("Server", "MaxQuantity", 1000, new ConfigDescription("Hard cap the server enforces on a single give request, regardless of what a client asks for.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100000), Array.Empty())); ServerStrictItemCheck = cfg.Bind("Server", "StrictItemCheck", false, "If true, reject any item OR status effect the server's own ObjectDB doesn't know. Off by default because many content mods (e.g. ValheimArmory) register content only client-side; the requesting admin's client still resolves and applies it."); ServerMaxActionRadius = cfg.Bind("Server", "MaxActionRadius", 100f, new ConfigDescription("Hard cap (metres) the server enforces on radius actions — the kill / tame / aggravate sweeps in the Players tab.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 500f), Array.Empty())); ServerMaxCreatureSpawn = cfg.Bind("Server", "MaxCreatureSpawn", 20, new ConfigDescription("Hard cap on how many creatures one spawn request may create, regardless of what a client asks for. Guards against lag / crashes.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 200), Array.Empty())); ServerAllowBossSpawn = cfg.Bind("Server", "AllowBossSpawn", false, "Allow spawning creatures flagged as bosses. Off by default — a stray Moder on a base ruins a server."); ServerMaxDespawnRadius = cfg.Bind("Server", "MaxDespawnRadius", 100f, new ConfigDescription("Hard cap (metres) the server enforces on the Creatures-tab despawn / cleanup sweep.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 500f), Array.Empty())); ServerPlayerTags = cfg.Bind("Server", "PlayerTags", true, "Enable per-player name tags. When on, the server reads / writes ValheimAdminForge.tags.json next to this file and broadcasts the tag table. Turn off to skip that entirely (no file is written)."); ServerTeleportSpread = cfg.Bind("Server", "TeleportSpread", 2f, new ConfigDescription("Radius (metres) admins land away from each other when teleporting to the same player, so they don't stack on top of them. 0 disables the offset.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); } } } namespace ValheimAdminForge.Net { internal static class AdminGuard { public static bool IsLocalPlayerAdminHint() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { return true; } if (instance.LocalPlayerIsAdminOrHost()) { return true; } if (AdminRpc.ServerSaysAdmin) { return true; } return !AdminRpc.ServerModAnswered; } public static AdminRequestContext ServerContextFor(ZRpc rpc) { ZNet instance = ZNet.instance; object obj; if (rpc == null) { obj = null; } else { ISocket socket = rpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } if (obj == null) { obj = string.Empty; } string text = (string)obj; long senderPeerId = 0L; if ((Object)(object)instance != (Object)null && rpc != null) { foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.m_rpc == rpc) { senderPeerId = peer.m_uid; break; } } } bool senderIsAdmin = !string.IsNullOrEmpty(text) && (Object)(object)instance != (Object)null && (instance.IsAdmin(text) || AdminListContains(instance, text)); return new AdminRequestContext(senderPeerId, text, senderIsAdmin); } public static AdminRequestContext LocalHostContext() { return new AdminRequestContext(0L, string.Empty, senderIsAdmin: true); } private static bool AdminListContains(ZNet znet, string candidate) { List adminList = znet.GetAdminList(); if (adminList == null || string.IsNullOrEmpty(candidate)) { return false; } string text = candidate.Trim(); string text2 = StripPlatformPrefix(text); foreach (string item in adminList) { if (!string.IsNullOrEmpty(item)) { string text3 = item.Trim(); if (text3 == text || StripPlatformPrefix(text3) == text2) { return true; } } } return false; } private static string StripPlatformPrefix(string s) { int num = s.IndexOf('_'); if (num < 0 || num + 1 >= s.Length) { return s; } return s.Substring(num + 1); } } internal static class AdminProtocol { public const int Version = 2; public const string RpcRequest = "VAF_Request"; public const string RpcExec = "VAF_Exec"; public const string RpcResponse = "VAF_Response"; public const string RpcHello = "VAF_Hello"; public const string RpcAdminStatus = "VAF_AdminStatus"; public const string RpcDropGhost = "VAF_DropGhost"; public const string RpcTags = "VAF_Tags"; public const float ResponseTimeout = 5f; } internal static class AdminRpc { private struct RateWindow { public float Start; public int Count; } private struct GhostDrop { public ZDOID Id; public Vector3 Pos; public float DueAt; } private static readonly Dictionary _commands = new Dictionary(StringComparer.Ordinal); private static float _pendingSince = -1f; private static bool _helloSent; private static bool _helloAnswered; private static bool _serverSaysAdmin; private static bool _versionWarned; private const int MaxRequestsPerSecond = 10; private static readonly Dictionary _rate = new Dictionary(); private static float _lastRatePrune; private static readonly List _pendingGhostDrops = new List(); private const float GhostDropDelay = 3f; private static readonly HashSet _quietOnSuccess = new HashSet(StringComparer.Ordinal) { "give_item", "apply_effect" }; private static float _tagPoll; public static bool ServerSaysAdmin => _serverSaysAdmin; public static bool ServerModAnswered => _helloAnswered; public static void Init() { Register(new GiveItemCommand()); Register(new ApplyEffectCommand()); Register(new TeleportCommand()); Register(new PlayerActionCommand()); Register(new SpawnCreatureCommand()); Register(new DespawnCommand()); Register(new EventCommand()); Register(new EnvCommand()); Register(new WorldCommand()); } public static void Register(IAdminCommand command) { _commands[command.Name] = command; } internal static Action Safe(string name, Action handler) { return delegate(ZRpc rpc, ZPackage pkg) { try { handler(rpc, pkg); } catch (Exception arg) { Plugin.Log.LogError((object)$"RPC '{name}' handler threw: {arg}"); } }; } public static void Send(string command, ZPackage args) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown ZRpc val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerRPC() : null); if (val == null) { HandleLocally(command, args); return; } ZPackage val2 = new ZPackage(); val2.Write(2); val2.Write(command); val2.Write(args); _pendingSince = Time.realtimeSinceStartup; val.Invoke("VAF_Request", new object[1] { val2 }); } private static void HandleLocally(string command, ZPackage args) { args.SetPos(0); if (!TryAuthorizeAndExec(AdminGuard.LocalHostContext(), 2, command, args, out var error)) { Toast("Admin Forge: " + error); } } public static void OnExec(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); ZPackage args = pkg.ReadPackage(); if (_commands.TryGetValue(text, out var value)) { try { value.Apply(args); } catch (Exception arg) { Plugin.Log.LogError((object)$"Apply '{text}' failed: {arg}"); } } } public static void OnResponse(ZRpc rpc, ZPackage pkg) { _pendingSince = -1f; bool num = pkg.ReadBool(); string text = pkg.ReadString(); string text2 = ((pkg.GetPos() < pkg.Size()) ? pkg.ReadString() : string.Empty); if (!num) { Toast("Admin Forge: " + text); } else if (!_quietOnSuccess.Contains(text2)) { Toast("Admin Forge: " + (string.IsNullOrEmpty(text2) ? "done" : text2) + " ✓"); } } public static void Tick() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown ProcessGhostDrops(); ServerTagTick(); DespawnCommand.Tick(); if (_pendingSince >= 0f && Time.realtimeSinceStartup - _pendingSince > 5f) { _pendingSince = -1f; Toast("Admin Forge: no response from server (mod not installed there?)"); } ZRpc val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerRPC() : null); if (val == null) { _helloSent = (_helloAnswered = (_serverSaysAdmin = false)); if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { PlayerTags.ClientClear(); } } else if (!_helloSent) { ZPackage val2 = new ZPackage(); val2.Write(2); val2.Write("0.4.0"); val.Invoke("VAF_Hello", new object[1] { val2 }); _helloSent = true; } } private static void ServerTagTick() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || !PluginConfig.ServerPlayerTags.Value) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _tagPoll < 2f) { return; } _tagPoll = realtimeSinceStartup; PlayerTags.ServerEnsureTemplate(); PlayerTags.ServerReloadIfChanged(); string signature; ZPackage val = PlayerTags.BuildBroadcast(out signature); if (val == null || !PlayerTags.SignatureChanged(signature)) { return; } foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.m_rpc != null) { peer.m_rpc.Invoke("VAF_Tags", new object[1] { val }); } } if (!instance.IsDedicated()) { PlayerTags.ClientReceive(val); } } public static void OnTags(ZRpc rpc, ZPackage pkg) { PlayerTags.ClientReceive(pkg); } public static void OnAdminStatus(ZRpc rpc, ZPackage pkg) { _helloAnswered = true; _serverSaysAdmin = pkg.ReadBool(); bool flag = pkg.ReadBool(); string text = pkg.ReadString(); Plugin.Log.LogDebug((object)$"[client] server admin verdict: {_serverSaysAdmin}, versionOk: {flag}"); if (!flag && !_versionWarned) { _versionWarned = true; Toast("Admin Forge: version mismatch — server " + text + ", you have 0.4.0. Update to match."); } } public static void OnHello(ZRpc rpc, ZPackage pkg) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } pkg.ReadInt(); string text = ((pkg.Size() > pkg.GetPos()) ? pkg.ReadString() : "?"); AdminRequestContext adminRequestContext = AdminGuard.ServerContextFor(rpc); if (!RateLimited(adminRequestContext.SenderPeerId)) { bool flag = text == "0.4.0"; ZPackage val = new ZPackage(); val.Write(adminRequestContext.SenderIsAdmin); val.Write(flag); val.Write("0.4.0"); rpc.Invoke("VAF_AdminStatus", new object[1] { val }); Plugin.Log.LogDebug((object)$"[server] hello from '{adminRequestContext.SenderHostName}' -> admin={adminRequestContext.SenderIsAdmin}, client v{text}"); if (!flag) { Plugin.Log.LogWarning((object)("[server] '" + adminRequestContext.SenderHostName + "' runs ValheimAdminForge " + text + ", server is 0.4.0")); } } } public static void OnRequest(ZRpc rpc, ZPackage pkg) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } int version = pkg.ReadInt(); string text = pkg.ReadString(); ZPackage args = pkg.ReadPackage(); AdminRequestContext ctx = AdminGuard.ServerContextFor(rpc); if (!RateLimited(ctx.SenderPeerId)) { bool flag; string error; if (ctx.SenderPeerId == 0L) { flag = false; error = "could not identify sender"; } else { flag = TryAuthorizeAndExec(in ctx, version, text, args, out error); } ZPackage val = new ZPackage(); val.Write(flag); val.Write(flag ? string.Empty : (error ?? "rejected")); val.Write(text); rpc.Invoke("VAF_Response", new object[1] { val }); if (flag) { Plugin.Log.LogInfo((object)$"[server] authorised '{text}' from '{ctx.SenderHostName}' (peer {ctx.SenderPeerId})"); return; } Plugin.Log.LogWarning((object)$"[server] DENIED '{text}' from '{ctx.SenderHostName}' (peer {ctx.SenderPeerId}): {error}"); } } private static bool TryAuthorizeAndExec(in AdminRequestContext ctx, int version, string command, ZPackage args, out string error) { //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown error = null; if (version != 2) { error = $"protocol mismatch (server {2}, client {version})"; return false; } if (!ctx.SenderIsAdmin) { error = "you are not a server admin"; return false; } if (!_commands.TryGetValue(command, out var value)) { error = "unknown command '" + command + "'"; return false; } args.SetPos(0); if (!value.Validate(in ctx, args, out var targetPeerId, out var execArgs, out error)) { return false; } ZPackage val = execArgs ?? args; if (value.Site == ExecutionSite.Server) { val.SetPos(0); try { value.Apply(val); } catch (Exception ex) { error = "apply failed: " + ex.Message; } return error == null; } if (value.Site == ExecutionSite.AllClients) { ZPackage val2 = new ZPackage(); val2.Write(command); val2.Write(val); ZNet instance = ZNet.instance; if ((Object)(object)instance != (Object)null) { foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.m_rpc != null) { peer.m_rpc.Invoke("VAF_Exec", new object[1] { val2 }); } } } val.SetPos(0); try { value.Apply(val); } catch (Exception ex2) { error = "apply failed: " + ex2.Message; } return error == null; } long num = ((targetPeerId == 0L) ? ctx.SenderPeerId : targetPeerId); if (num == 0L) { val.SetPos(0); try { value.Apply(val); } catch (Exception ex3) { error = "apply failed: " + ex3.Message; } } else { ZPackage val3 = new ZPackage(); val3.Write(command); val3.Write(val); ExecOn(FindPeer(num), val3, ref error); } if (error == null && value.TryGetMoveDestination(val, out var dest)) { BroadcastDropGhost(num, dest); } return error == null; } private static bool RateLimited(long peerId) { if (peerId == 0L) { return false; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _lastRatePrune > 60f) { _lastRatePrune = realtimeSinceStartup; List list = new List(); foreach (KeyValuePair item in _rate) { if (realtimeSinceStartup - item.Value.Start > 5f) { list.Add(item.Key); } } foreach (long item2 in list) { _rate.Remove(item2); } } if (!_rate.TryGetValue(peerId, out var value) || realtimeSinceStartup - value.Start >= 1f) { _rate[peerId] = new RateWindow { Start = realtimeSinceStartup, Count = 1 }; return false; } value.Count++; _rate[peerId] = value; return value.Count > 10; } private static void BroadcastDropGhost(long movedPeerId, Vector3 realPos) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_005e: 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) ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return; } ZDOID val = ((movedPeerId != 0L) ? (instance.GetPeer(movedPeerId)?.m_characterID ?? ZDOID.None) : (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Character)Player.m_localPlayer).GetZDOID() : ZDOID.None)); if (((ZDOID)(ref val)).IsNone()) { return; } ZPackage val2 = new ZPackage(); val2.Write(val); val2.Write(realPos); foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.m_uid != movedPeerId && peer.m_rpc != null) { peer.m_rpc.Invoke("VAF_DropGhost", new object[1] { val2 }); } } } public static void OnDropGhost(ZRpc rpc, ZPackage pkg) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) GhostDrop item = new GhostDrop { Id = pkg.ReadZDOID(), Pos = pkg.ReadVector3(), DueAt = Time.realtimeSinceStartup + 3f }; _pendingGhostDrops.Add(item); } private static void ProcessGhostDrops() { //IL_0049: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) for (int num = _pendingGhostDrops.Count - 1; num >= 0; num--) { GhostDrop ghostDrop = _pendingGhostDrops[num]; if (!(Time.realtimeSinceStartup < ghostDrop.DueAt)) { _pendingGhostDrops.RemoveAt(num); ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(ghostDrop.Id) : null); if (val != null && !val.IsOwner() && Vector3.Distance(val.GetPosition(), ghostDrop.Pos) > 1f) { val.SetPosition(ghostDrop.Pos); } foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && !((Object)(object)allPlayer == (Object)(object)Player.m_localPlayer) && !(((Character)allPlayer).GetZDOID() != ghostDrop.Id)) { Plugin.Log.LogDebug((object)("[ghost] clearing stale local copy of '" + allPlayer.GetPlayerName() + "'")); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)allPlayer).gameObject); } break; } } } } } private static void ExecOn(ZNetPeer peer, ZPackage exec, ref string error) { if (peer == null || peer.m_rpc == null) { error = "target player is not connected"; return; } peer.m_rpc.Invoke("VAF_Exec", new object[1] { exec }); } private static ZNetPeer FindPeer(long peerId) { if (!((Object)(object)ZNet.instance != (Object)null)) { return null; } return ZNet.instance.GetPeer(peerId); } private static void Toast(string message) { Plugin.Log.LogInfo((object)message); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)1, message, 0, (Sprite)null, false); } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] internal static class ZNetOnNewConnectionPatch { private static void Postfix(ZNet __instance, ZNetPeer peer) { if (peer?.m_rpc != null) { if (__instance.IsServer()) { peer.m_rpc.Register("VAF_Request", AdminRpc.Safe("VAF_Request", AdminRpc.OnRequest)); peer.m_rpc.Register("VAF_Hello", AdminRpc.Safe("VAF_Hello", AdminRpc.OnHello)); return; } peer.m_rpc.Register("VAF_Exec", AdminRpc.Safe("VAF_Exec", AdminRpc.OnExec)); peer.m_rpc.Register("VAF_Response", AdminRpc.Safe("VAF_Response", AdminRpc.OnResponse)); peer.m_rpc.Register("VAF_AdminStatus", AdminRpc.Safe("VAF_AdminStatus", AdminRpc.OnAdminStatus)); peer.m_rpc.Register("VAF_DropGhost", AdminRpc.Safe("VAF_DropGhost", AdminRpc.OnDropGhost)); peer.m_rpc.Register("VAF_Tags", AdminRpc.Safe("VAF_Tags", AdminRpc.OnTags)); } } } internal enum AnchorMode : byte { Requester, Target, Coords } internal static class CmdValidate { private const float MaxHorizontal = 20000f; public static bool Finite(float f) { if (!float.IsNaN(f)) { return !float.IsInfinity(f); } return false; } public static float Sane(float f, float fallback) { if (!Finite(f)) { return fallback; } return f; } public static bool InWorldBounds(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (Finite(p.x) && Finite(p.y) && Finite(p.z) && Mathf.Abs(p.x) <= 20000f && Mathf.Abs(p.z) <= 20000f && p.y >= -1000f) { return p.y <= 10000f; } return false; } public static bool IsIdentifier(string s, int maxLen = 64) { if (string.IsNullOrEmpty(s) || s.Length > maxLen) { return false; } foreach (char c in s) { if (char.IsWhiteSpace(c) || char.IsControl(c)) { return false; } } return true; } } internal readonly struct AdminRequestContext { public readonly long SenderPeerId; public readonly string SenderHostName; public readonly bool SenderIsAdmin; public AdminRequestContext(long senderPeerId, string senderHostName, bool senderIsAdmin) { SenderPeerId = senderPeerId; SenderHostName = senderHostName; SenderIsAdmin = senderIsAdmin; } } internal enum ExecutionSite { TargetClient, Server, AllClients } internal interface IAdminCommand { string Name { get; } ExecutionSite Site { get; } bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest); bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error); void Apply(ZPackage args); } internal static class PlayerTags { internal sealed class Tag { public readonly string Text; public readonly string Color; public Tag(string text, string color) { Text = text; Color = (string.IsNullOrEmpty(color) ? "#FFFFFF" : color); } } private static readonly Dictionary _byId = new Dictionary(StringComparer.Ordinal); private static DateTime _fileStamp = DateTime.MinValue; private static string _lastSignature; private static readonly Dictionary _clientTags = new Dictionary(); public static string FilePath => Path.Combine(Paths.ConfigPath, "ValheimAdminForge.tags.json"); public static void ServerReloadIfChanged() { try { if (!File.Exists(FilePath)) { if (_byId.Count > 0) { _byId.Clear(); _fileStamp = DateTime.MinValue; } return; } DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(FilePath); if (!(lastWriteTimeUtc == _fileStamp)) { _fileStamp = lastWriteTimeUtc; _byId.Clear(); ParseInto(File.ReadAllText(FilePath), _byId); Plugin.Log.LogInfo((object)$"[tags] loaded {_byId.Count} player tag(s) from {FilePath}"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[tags] can't read " + FilePath + ": " + ex.Message)); } } public static void ServerEnsureTemplate() { try { if (!File.Exists(FilePath)) { File.WriteAllText(FilePath, "{\n \"entries\": [\n { \"id\": \"0000000000000000\", \"tag\": \"MODER\", \"color\": \"#FF8800\" }\n ]\n}\n"); Plugin.Log.LogInfo((object)("[tags] wrote a template to " + FilePath)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[tags] can't write template: " + ex.Message)); } } public static ZPackage BuildBroadcast(out string signature) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) signature = null; ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return null; } List> list = new List>(); foreach (ZNetPeer peer in instance.GetPeers()) { if (peer != null && !((ZDOID)(ref peer.m_characterID)).IsNone()) { ISocket socket = peer.m_socket; string text = ((socket != null) ? socket.GetHostName() : null); if (!string.IsNullOrEmpty(text) && _byId.TryGetValue(StripPlatform(text.Trim()), out var value)) { list.Add(new KeyValuePair(peer.m_characterID, value)); } } } if (!instance.IsDedicated() && (Object)(object)Player.m_localPlayer != (Object)null) { string text2 = TryLocalSteamId(); if (!string.IsNullOrEmpty(text2) && _byId.TryGetValue(StripPlatform(text2), out var value2)) { list.Add(new KeyValuePair(((Character)Player.m_localPlayer).GetZDOID(), value2)); } } StringBuilder stringBuilder = new StringBuilder(); ZPackage val = new ZPackage(); val.Write(list.Count); foreach (KeyValuePair item in list) { val.Write(item.Key); val.Write(item.Value.Text); val.Write(item.Value.Color); stringBuilder.Append(item.Key).Append('=').Append(item.Value.Text) .Append(item.Value.Color) .Append(';'); } signature = stringBuilder.ToString(); return val; } public static bool SignatureChanged(string signature) { if (signature == _lastSignature) { return false; } _lastSignature = signature; return true; } public static void ClientReceive(ZPackage pkg) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) pkg.SetPos(0); _clientTags.Clear(); int num = pkg.ReadInt(); for (int i = 0; i < num; i++) { ZDOID key = pkg.ReadZDOID(); string text = pkg.ReadString(); string color = pkg.ReadString(); if (!((ZDOID)(ref key)).IsNone() && !string.IsNullOrEmpty(text)) { _clientTags[key] = new Tag(text, color); } } } public static Tag For(ZDOID characterId) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (((ZDOID)(ref characterId)).IsNone() || !_clientTags.TryGetValue(characterId, out var value)) { return null; } return value; } public static void ClientClear() { _clientTags.Clear(); } private static string TryLocalSteamId() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { IDistributionPlatform distributionPlatform = PlatformManager.DistributionPlatform; return (distributionPlatform != null) ? ((object)((IUser)distributionPlatform.LocalUser).PlatformUserID/*cast due to .constrained prefix*/).ToString() : null; } catch { return null; } } private static void ParseInto(string json, Dictionary map) { foreach (Match item in Regex.Matches(json, "\\{[^{}]*\\}")) { string text = Field(item.Value, "id"); string text2 = Field(item.Value, "tag"); if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2)) { map[StripPlatform(text.Trim())] = new Tag(text2.Trim(), Field(item.Value, "color")?.Trim()); } } } private static string Field(string obj, string key) { Match match = Regex.Match(obj, "\"" + key + "\"\\s*:\\s*\"([^\"]*)\""); if (!match.Success) { return null; } return match.Groups[1].Value; } private static string StripPlatform(string s) { int num = s.IndexOf('_'); if (num < 0 || num + 1 >= s.Length) { return s; } return s.Substring(num + 1); } } [HarmonyPatch(typeof(Player), "GetHoverName")] internal static class PlayerHoverNameTagPatch { private static void Postfix(Player __instance, ref string __result) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null)) { PlayerTags.Tag tag = PlayerTags.For(((Character)__instance).GetZDOID()); if (tag != null) { __result = "[" + tag.Text + "] " + __result; } } } } [HarmonyPatch] internal static class ChatTagPatch { private static readonly FieldInfo BufferField = AccessTools.Field(typeof(Terminal), "m_chatBuffer"); private static readonly MethodInfo UpdateChatMethod = AccessTools.Method(typeof(Terminal), "UpdateChat", (Type[])null, (Type[])null); private const string NameOpen = ""; private static MethodBase TargetMethod() { MethodInfo[] methods = typeof(Terminal).GetMethods(); foreach (MethodInfo methodInfo in methods) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (methodInfo.Name == "AddString" && parameters.Length == 4 && parameters[1].ParameterType == typeof(string) && parameters[2].ParameterType == typeof(Type)) { return methodInfo; } } return null; } private static void Postfix(Terminal __instance, PlatformUserID user) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) PlayerInfo val = default(PlayerInfo); if (!(__instance is Chat) || BufferField == null || !ZNet.TryGetPlayerByPlatformUserID(user, ref val)) { return; } PlayerTags.Tag tag = PlayerTags.For(val.m_characterID); if (tag != null && BufferField.GetValue(__instance) is List { Count: not 0 } list) { int index = list.Count - 1; string value = "[" + tag.Text + "] "; int num = list[index].IndexOf("", StringComparison.Ordinal); if (num >= 0 && !list[index].Contains(value)) { list[index] = list[index].Insert(num + "".Length, value); UpdateChatMethod?.Invoke(__instance, null); } } } } [HarmonyPatch(typeof(Chat), "UpdateWorldTextField")] internal static class ChatWorldTextTagPatch { private static void Postfix(object wt) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (wt == null) { return; } Traverse val = Traverse.Create(wt); Type value = val.Field("m_type").GetValue(); if ((int)value != 2 && (int)value != 3) { return; } UserInfo value2 = val.Field("m_userInfo").GetValue(); PlayerInfo val2 = default(PlayerInfo); if (value2 == null || !ZNet.TryGetPlayerByPlatformUserID(value2.UserId, ref val2)) { return; } PlayerTags.Tag tag = PlayerTags.For(val2.m_characterID); if (tag != null) { Traverse val3 = val.Field("m_textMeshField").Property("text", (object[])null); string value3 = val3.GetValue(); string text = "[" + tag.Text + "] "; if (!string.IsNullOrEmpty(value3) && !value3.StartsWith(text, StringComparison.Ordinal)) { val3.SetValue((object)(text + value3)); } } } } internal static class Targeting { public static bool Resolve(in AdminRequestContext ctx, ZDOID characterZdoid, out long peerId, out string error) { //IL_003c: 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) error = null; if (((ZDOID)(ref characterZdoid)).IsNone()) { peerId = ctx.SenderPeerId; return true; } ZNet instance = ZNet.instance; if ((Object)(object)instance != (Object)null) { foreach (ZNetPeer peer in instance.GetPeers()) { if (peer.m_characterID == characterZdoid) { peerId = peer.m_uid; return true; } } } peerId = 0L; error = "target player is not connected"; return false; } public static bool RefPos(in AdminRequestContext ctx, ZDOID anchor, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; if (((ZDOID)(ref anchor)).IsNone() && ctx.SenderPeerId == 0L) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } pos = ((Component)Player.m_localPlayer).transform.position; return true; } ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return false; } long num = (((ZDOID)(ref anchor)).IsNone() ? ctx.SenderPeerId : 0); ZDOID val = anchor; foreach (ZNetPeer peer in instance.GetPeers()) { if ((num != 0L) ? (peer.m_uid == num) : (peer.m_characterID == anchor)) { pos = peer.GetRefPos(); if (pos != Vector3.zero) { return true; } val = peer.m_characterID; break; } } List playerList = instance.GetPlayerList(); if (playerList != null) { foreach (PlayerInfo item in playerList) { if (item.m_characterID == val && item.m_position != Vector3.zero) { pos = item.m_position; return true; } } } return false; } } } namespace ValheimAdminForge.Gui { internal static class AdminWindow { [CompilerGenerated] private static class <>O { public static WindowFunction <0>__DrawContents; } public static bool IsOpen; private const int WindowId = 372480; private static Vector2 _pos = new Vector2(60f, 60f); private static readonly string[] Tabs = new string[6] { "Items", "Effects", "Players", "Creatures", "Events", "World" }; private static int _tab; private static float _lastTabError = -99f; private static string _tooltipSnapshot = string.Empty; private static Texture2D _flatWindowBg; private static GUIStyle _windowStyle; private static GUISkin _windowSkin; private static readonly List _staleSkins = new List(); private static GUISkin WindowSkin() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown foreach (GUISkin staleSkin in _staleSkins) { Object.Destroy((Object)(object)staleSkin); } _staleSkins.Clear(); if ((Object)(object)_windowSkin != (Object)null) { return _windowSkin; } GUI.skin = null; _windowSkin = Object.Instantiate(GUI.skin); GUISkin windowSkin = _windowSkin; GUIStyle val = new GUIStyle(_windowSkin.label); val.normal.textColor = GuiStyles.TextColor; windowSkin.label = val; return _windowSkin; } public static void Init() { PluginConfig.WindowTextColor.SettingChanged += delegate { if ((Object)(object)_windowSkin != (Object)null) { _staleSkins.Add(_windowSkin); } _windowSkin = null; }; } private static GUIStyle WindowStyle() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (_windowStyle != null) { return _windowStyle; } _flatWindowBg = new Texture2D(1, 1); _flatWindowBg.SetPixel(0, 0, new Color(0.7f, 0.7f, 0.7f)); _flatWindowBg.Apply(); ((Texture)_flatWindowBg).filterMode = (FilterMode)0; ((Texture)_flatWindowBg).wrapMode = (TextureWrapMode)1; _windowStyle = new GUIStyle(GUI.skin.window); _windowStyle.border = new RectOffset(0, 0, 0, 0); _windowStyle.normal.background = _flatWindowBg; _windowStyle.onNormal.background = _flatWindowBg; _windowStyle.focused.background = _flatWindowBg; _windowStyle.onFocused.background = _flatWindowBg; _windowStyle.hover.background = _flatWindowBg; _windowStyle.onHover.background = _flatWindowBg; _windowStyle.active.background = _flatWindowBg; _windowStyle.onActive.background = _flatWindowBg; return _windowStyle; } public static void Toggle() { if (!IsOpen && !PluginConfig.AllowNonAdminWindow.Value && !AdminGuard.IsLocalPlayerAdminHint()) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Admin Forge: admins only", 0, (Sprite)null, false); } } else { IsOpen = !IsOpen; } } public static void Draw() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (IsOpen) { float num = PluginConfig.WindowWidth.Value; float num2 = PluginConfig.WindowHeight.Value; GUISkin skin = GUI.skin; GUI.skin = WindowSkin(); Color backgroundColor2; Color backgroundColor = (backgroundColor2 = GUI.backgroundColor); backgroundColor2.a *= PluginConfig.WindowOpacity.Value; GUI.backgroundColor = backgroundColor2; Rect val = new Rect(_pos.x, _pos.y, num, num2); object obj = <>O.<0>__DrawContents; if (obj == null) { WindowFunction val2 = DrawContents; <>O.<0>__DrawContents = val2; obj = (object)val2; } Rect val3 = GUI.Window(372480, val, (WindowFunction)obj, "ADMIN FORGE", WindowStyle()); _pos.x = Mathf.Round(Mathf.Clamp(((Rect)(ref val3)).x, 0f - num + 80f, (float)(Screen.width - 80))); _pos.y = Mathf.Round(Mathf.Clamp(((Rect)(ref val3)).y, 0f, (float)(Screen.height - 40))); GUI.backgroundColor = backgroundColor; GUI.skin = skin; } } private static void DrawContents(int id) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Invalid comparison between Unknown and I4 //IL_0180: Unknown result type (might be due to invalid IL or missing references) float num = PluginConfig.WindowWidth.Value; GUI.backgroundColor = Color.white; GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("drag title bar to move", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }); GUILayout.FlexibleSpace(); if (GUILayout.Button("X", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(26f), GUILayout.Height(20f) })) { IsOpen = false; } GUILayout.EndHorizontal(); _tab = GUILayout.Toolbar(_tab, Tabs, Array.Empty()); try { switch (_tab) { case 1: EffectsTab.Draw(); break; case 2: PlayersTab.Draw(); break; case 3: CreaturesTab.Draw(); break; case 4: EventsTab.Draw(); break; case 5: WorldTab.Draw(); break; default: ItemsTab.Draw(); break; } } catch (Exception arg) { if (Time.realtimeSinceStartup - _lastTabError > 3f) { _lastTabError = Time.realtimeSinceStartup; Plugin.Log.LogError((object)$"Admin Forge: tab {_tab} draw threw: {arg}"); } return; } GUILayout.FlexibleSpace(); GUILayout.Label(_tooltipSnapshot, GuiStyles.Tooltip, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(num - 16f), GUILayout.Height(20f) }); if ((int)Event.current.type == 7) { _tooltipSnapshot = GUI.tooltip ?? string.Empty; } GUI.DragWindow(new Rect(0f, 0f, num, 18f)); } } internal static class CreaturesTab { private const float RowHeight = 30f; private static readonly string[] OriginTabs = new string[3] { "All", "Vanilla", "Modded" }; private static readonly string[] ScopeTabs = new string[3] { "Wild", "Tamed", "All" }; private static string _search = ""; private static int _originIdx; private static string _selectedPrefab; private static string _modFilter = ""; private static string[] _modNames = Array.Empty(); private static int _modNamesVersion = -1; private static readonly ModFilterRow _modPicker = new ModFilterRow(); private static int _count = 1; private static string _countText = "1"; private static int _level = 1; private static bool _tamed; private static string _healthText = "0"; private static string _scatterText = "3"; private static string _despRadiusText = "30"; private static int _despScope; private static string _despNameText = ""; private static int _despMinLevel; private static bool _despItems; private static bool _despFish; private static bool _despBirds; private static readonly PositionPicker _where = new PositionPicker(); private static readonly FilteredList _list = new FilteredList(); public static void Draw() { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Expected O, but got Unknown _list.BeginFrame(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.MinWidth(150f), GUILayout.Height(22f) }); if (GUILayout.Button("clear", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) })) { _search = ""; } GUILayout.Space(10f); GUILayout.Label("Origin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); int originIdx = _originIdx; int originIdx2 = GUILayout.Toolbar(originIdx, OriginTabs, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); GUILayout.EndHorizontal(); IReadOnlyList entries = CreatureCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent("Count", "How many to spawn. The server caps this at Server/MaxCreatureSpawn."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) }); string text = GUILayout.TextField(_countText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(22f) }); if (text != _countText) { _countText = text; if (int.TryParse(text, out var result)) { _count = Mathf.Max(1, result); } } GUILayout.Label(new GUIContent("Level", "Star level (1 = no stars, up to 9)."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(22f), GUILayout.Height(22f) })) { _level = Mathf.Max(1, _level - 1); } GUILayout.Label($"{_level}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) }); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(22f), GUILayout.Height(22f) })) { _level = Mathf.Min(9, _level + 1); } _tamed = GUILayout.Toggle(_tamed, new GUIContent(" Tamed", "Spawn friendly. Tameable creatures follow you; others just stay passive and won't attack."), Array.Empty()); GUILayout.Label(new GUIContent("HP", "Health override per creature. 0 = use the creature's own (scaled by level)."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }); _healthText = GUILayout.TextField(_healthText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(46f), GUILayout.Height(22f) }); GUILayout.Label(new GUIContent("Spread", "Random scatter radius (m) when spawning more than one."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _scatterText = GUILayout.TextField(_scatterText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(34f), GUILayout.Height(22f) }); GUILayout.EndHorizontal(); _where.Draw(); IReadOnlyList entries2 = entries; string filter = (_search ?? "").Trim(); string cacheKey = $"{CreatureCatalog.Version}|{originIdx}|{_modFilter}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List m) { Fill(entries2, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries2.Count} creatures", Array.Empty()); ScrollList.Draw(_list.Matches, 30f, TabLayout.ListHeight(474f), ref _list.Scroll, DrawRow); DrawDetailPanel(); DrawDespawnBlock(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList entries) { if (_modNamesVersion != CreatureCatalog.Version) { _modNamesVersion = CreatureCatalog.Version; _modNames = (from e in entries where !e.IsVanilla && !string.IsNullOrEmpty(e.ModName) select e.ModName).Distinct().OrderBy((string n) => n, StringComparer.OrdinalIgnoreCase).ToArray(); if (Array.IndexOf(_modNames, _modFilter) < 0) { _modFilter = ""; } } if (_modNames.Length != 0) { _modFilter = _modPicker.Draw(_modNames, _modFilter); } } private static void DrawDespawnBlock() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Despawn around", GuiStyles.Info, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); TargetSelector.Draw(); GUILayout.Label(new GUIContent("radius", "Metres around the target. Server caps at Server/MaxDespawnRadius."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) }); _despRadiusText = GUILayout.TextField(_despRadiusText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) }); _despScope = GUILayout.Toolbar(_despScope, ScopeTabs, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent("name", "Only creatures whose prefab name contains this. Blank = any."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) }); _despNameText = GUILayout.TextField(_despNameText ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(110f), GUILayout.Height(22f) }); GUILayout.Label(new GUIContent("lvl ≥", "Only creatures at this star level or higher. 0 = any."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(34f) }); if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(22f), GUILayout.Height(22f) })) { _despMinLevel = Mathf.Max(0, _despMinLevel - 1); } GUILayout.Label($"{_despMinLevel}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) }); if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(22f), GUILayout.Height(22f) })) { _despMinLevel = Mathf.Min(9, _despMinLevel + 1); } _despItems = GUILayout.Toggle(_despItems, new GUIContent(" items", "Also remove dropped items on the ground (tombstones are never touched)."), Array.Empty()); _despFish = GUILayout.Toggle(_despFish, new GUIContent(" fish", "Also remove fish."), Array.Empty()); _despBirds = GUILayout.Toggle(_despBirds, new GUIContent(" birds", "Also remove birds."), Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Despawn", "Remove matching objects — no loot, no death, no progress credit. Players and tombstones are always safe."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(80f), GUILayout.Height(22f) })) { RequestDespawn(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private static void RequestDespawn() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) float.TryParse(_despRadiusText, out var result); AdminRpc.Send("despawn", DespawnCommand.BuildArgs((result <= 0f) ? 20f : result, (byte)_despScope, _despNameText, _despMinLevel, _despItems, _despFish, _despBirds, TargetSelector.Current)); } private static void DrawRow(CreatureEntry e) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown GUILayout.BeginHorizontal((e.PrefabName == _selectedPrefab) ? GUIStyle.op_Implicit("box") : GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); string text = (e.IsVanilla ? "V" : ((e.ModName.Length > 0) ? e.ModName : "M")); string text2 = (e.IsBoss ? " · BOSS" : ""); if (GUILayout.Button($"{e.DisplayName} {text} · {e.Faction} · {e.BaseHealth:0} hp{text2}", GuiStyles.RowLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) })) { _selectedPrefab = e.PrefabName; } GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Spawn", "Spawn with the parameters above."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(58f), GUILayout.Height(24f) })) { _selectedPrefab = e.PrefabName; RequestSpawn(e.PrefabName); } GUILayout.EndHorizontal(); } private static void DrawDetailPanel() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(120f) }); CreatureEntry creatureEntry = CreatureCatalog.ByPrefab(_selectedPrefab); if (creatureEntry == null) { GUILayout.Label("Select a creature to see details.", Array.Empty()); } else { GUILayout.Label("" + creatureEntry.DisplayName + " " + creatureEntry.PrefabName + "", GuiStyles.Info, Array.Empty()); string text = (creatureEntry.IsVanilla ? "vanilla" : ((creatureEntry.ModName.Length > 0) ? ("modded (" + creatureEntry.ModName + ")") : "modded")); GUILayout.Label($"Faction: {creatureEntry.Faction} Base health: {creatureEntry.BaseHealth:0}\n" + "Boss: " + (creatureEntry.IsBoss ? "yes" : "no") + " Tameable: " + (creatureEntry.IsTameable ? "yes" : "no") + " Origin: " + text, GuiStyles.Info, Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent(string.Format("Spawn {0}x (lvl {1}{2})", _count, _level, _tamed ? ", tamed" : ""), "Spawn with the parameters above."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(200f), GUILayout.Height(26f) })) { RequestSpawn(creatureEntry.PrefabName); } } GUILayout.EndVertical(); } private static void RequestSpawn(string prefabName) { //IL_004f: 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) int.TryParse(_countText, out var result); float.TryParse(_healthText, out var result2); float.TryParse(_scatterText, out var result3); AdminRpc.Send("spawn_creature", SpawnCreatureCommand.BuildArgs(prefabName, Mathf.Max(1, result), _level, _tamed, result2, result3, _where.ModeByte, _where.Anchor, _where.Coords)); } private static void Fill(IReadOnlyList entries, string filter, List outList) { foreach (CreatureEntry entry in entries) { if ((_originIdx != 1 || entry.IsVanilla) && (_originIdx != 2 || !entry.IsVanilla) && (_originIdx != 2 || _modFilter.Length <= 0 || !(entry.ModName != _modFilter)) && (filter.Length <= 0 || entry.DisplayName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || entry.PrefabName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)) { outList.Add(entry); } } } } internal static class EffectsTab { private const float RowHeight = 34f; private static readonly string[] OriginTabs = new string[3] { "All", "Vanilla", "Modded" }; private static string _search = ""; private static int _originIdx; private static int _selectedHash; private static string _durationText = "0"; private static string _powerText = "0"; private static string _modFilter = ""; private static string[] _modNames = Array.Empty(); private static int _modNamesVersion = -1; private static readonly ModFilterRow _modPicker = new ModFilterRow(); private static readonly FilteredList _list = new FilteredList(); public static void Draw() { _list.BeginFrame(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.MinWidth(140f), GUILayout.Height(22f) }); if (GUILayout.Button("clear", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) })) { _search = ""; } GUILayout.Space(8f); GUILayout.Label("Dur s", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(38f) }); _durationText = GUILayout.TextField(_durationText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(46f), GUILayout.Height(22f) }); GUILayout.Label("Power", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); _powerText = GUILayout.TextField(_powerText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(46f), GUILayout.Height(22f) }); GUILayout.EndHorizontal(); GUILayout.Label("Dur 0 = effect default. Power > 0 needed for Poison / Burning / Frost to deal damage.", GuiStyles.Info, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Origin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); int originIdx = _originIdx; int originIdx2 = GUILayout.Toolbar(originIdx, OriginTabs, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); GUILayout.EndHorizontal(); IReadOnlyList entries = StatusEffectCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty()); TargetSelector.Draw(); GUILayout.EndHorizontal(); string filter = (_search ?? "").Trim(); string cacheKey = $"{StatusEffectCatalog.Version}|{originIdx}|{_modFilter}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} effects", Array.Empty()); ScrollList.Draw(_list.Matches, 34f, TabLayout.ListHeight(423f), ref _list.Scroll, DrawRow); DrawDetailPanel(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList entries) { if (_modNamesVersion != StatusEffectCatalog.Version) { _modNamesVersion = StatusEffectCatalog.Version; _modNames = (from e in entries where !e.IsVanilla && !string.IsNullOrEmpty(e.ModName) select e.ModName).Distinct().OrderBy((string n) => n, StringComparer.OrdinalIgnoreCase).ToArray(); if (Array.IndexOf(_modNames, _modFilter) < 0) { _modFilter = ""; } } if (_modNames.Length != 0) { _modFilter = _modPicker.Draw(_modNames, _modFilter); } } private static void DrawRow(StatusEffectEntry e) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown GUILayout.BeginHorizontal((e.NameHash == _selectedHash) ? GUIStyle.op_Implicit("box") : GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }); IconDrawer.Draw(e.Icon, 28f); string text = (e.IsVanilla ? "V" : ((e.ModName.Length > 0) ? e.ModName : "M")); string text2 = (string.IsNullOrEmpty(e.Category) ? "" : (" · " + e.Category)); if (GUILayout.Button(e.DisplayName + " " + text + " · " + e.InternalName + text2 + "", GuiStyles.RowLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { _selectedHash = e.NameHash; } GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Apply", "Apply this effect to the target (uses Dur / Power above)."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(26f) })) { RequestApply(e.NameHash, remove: false); } if (GUILayout.Button(new GUIContent("Clear", "Remove this effect from the target — for effects that ignore their timer."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(26f) })) { RequestApply(e.NameHash, remove: true); } GUILayout.EndHorizontal(); } private static void RequestApply(int nameHash, bool remove) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) float duration = Parse(_durationText, 0f, 3600f); float power = Parse(_powerText, 0f, 100000f); AdminRpc.Send("apply_effect", ApplyEffectCommand.BuildArgs(nameHash, TargetSelector.Current, duration, power, remove)); } private static float Parse(string text, float min, float max) { if (!float.TryParse(text, out var result)) { result = 0f; } return Mathf.Clamp(result, min, max); } private static void DrawDetailPanel() { GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(140f) }); StatusEffectEntry statusEffectEntry = StatusEffectCatalog.ByHash(_selectedHash); if (statusEffectEntry == null) { GUILayout.Label("Select an effect to see details.", Array.Empty()); } else { GUILayout.Label("" + statusEffectEntry.DisplayName + " " + statusEffectEntry.InternalName + "", GuiStyles.Info, Array.Empty()); if (!string.IsNullOrEmpty(statusEffectEntry.Tooltip)) { GUILayout.Label(statusEffectEntry.Tooltip, GuiStyles.Info, Array.Empty()); } string text = ((statusEffectEntry.Ttl > 0f) ? $"{statusEffectEntry.Ttl:0.#}s" : "until removed"); string text2 = (statusEffectEntry.IsVanilla ? "vanilla" : ((statusEffectEntry.ModName.Length > 0) ? ("modded (" + statusEffectEntry.ModName + ")") : "modded")); GUILayout.Label("Category: " + (string.IsNullOrEmpty(statusEffectEntry.Category) ? "-" : statusEffectEntry.Category) + " Duration: " + text + " Origin: " + text2, GuiStyles.Info, Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("Apply to me", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(110f), GUILayout.Height(26f) })) { RequestApply(statusEffectEntry.NameHash, remove: false); } if (GUILayout.Button("Remove", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(26f) })) { RequestApply(statusEffectEntry.NameHash, remove: true); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } private static void Fill(IReadOnlyList entries, string filter, List outList) { foreach (StatusEffectEntry entry in entries) { if ((_originIdx != 1 || entry.IsVanilla) && (_originIdx != 2 || !entry.IsVanilla) && (_originIdx != 2 || _modFilter.Length <= 0 || !(entry.ModName != _modFilter)) && (filter.Length == 0 || entry.DisplayName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || entry.InternalName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)) { outList.Add(entry); } } } } internal static class EventsTab { private const float RowHeight = 28f; private static string _search = ""; private static string _selectedName; private static string _detailSnapshotName; private static readonly PositionPicker _where = new PositionPicker(); private static readonly FilteredList _list = new FilteredList(); public static void Draw() { _list.BeginFrame(); DrawActiveHeader(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.MinWidth(160f), GUILayout.Height(22f) }); if (GUILayout.Button("clear", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) })) { _search = ""; } GUILayout.EndHorizontal(); _where.Draw(); IReadOnlyList entries = EventCatalog.Entries; string filter = (_search ?? "").Trim(); string cacheKey = $"{EventCatalog.Version}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} events", Array.Empty()); ScrollList.Draw(_list.Matches, 28f, TabLayout.ListHeight(340f), ref _list.Scroll, DrawRow); DrawDetailPanel(); } private static void DrawActiveHeader() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); RandEventSystem instance = RandEventSystem.instance; RandomEvent val = (((Object)(object)instance != (Object)null) ? instance.GetCurrentRandomEvent() : null); GUILayout.Label((val == null) ? "No event running." : $"Active: {val.m_name} {val.m_biome} · {val.m_duration:0}s", GuiStyles.Info, Array.Empty()); GUILayout.FlexibleSpace(); string obj = ((val == null) ? "Random" : "Stop"); string text = ((val == null) ? "Force-start a random event from the list at the chosen location." : "Stop the running event."); if (GUILayout.Button(new GUIContent(obj, text), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(80f), GUILayout.Height(22f) })) { if (val == null) { StartRandomFromList(); } else { Send(1, string.Empty); } } GUILayout.EndHorizontal(); } private static void DrawRow(EventEntry e) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown GUILayout.BeginHorizontal((e.Name == _selectedName) ? GUIStyle.op_Implicit("box") : GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }); if (GUILayout.Button($"{e.Name} {e.Biome} · {e.Duration:0}s", GuiStyles.RowLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) })) { _selectedName = e.Name; } GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Start", "Start this event at the chosen location."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(58f), GUILayout.Height(22f) })) { _selectedName = e.Name; Send(0, e.Name); } GUILayout.EndHorizontal(); } private static void DrawDetailPanel() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Expected O, but got Unknown if ((int)Event.current.type == 8) { _detailSnapshotName = _selectedName; } GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) }); EventEntry eventEntry = EventCatalog.ByName(_detailSnapshotName); if (eventEntry == null) { GUILayout.Label("Select an event to see details.", Array.Empty()); } else { GUILayout.Label("" + eventEntry.Name + "", GuiStyles.Info, Array.Empty()); if (!string.IsNullOrEmpty(eventEntry.StartMessage)) { GUILayout.Label("“" + eventEntry.StartMessage + "”", GuiStyles.Info, Array.Empty()); } GUILayout.Label($"Biome: {eventEntry.Biome} Duration: {eventEntry.Duration:0}s Range: {eventEntry.Range:0}m " + "Near base only: " + (eventEntry.NearBaseOnly ? "yes" : "no"), GuiStyles.Info, Array.Empty()); if (eventEntry.RequiredKeys.Length != 0) { GUILayout.Label("Requires keys: " + FormatKeys(eventEntry.RequiredKeys), GuiStyles.Info, Array.Empty()); } if (eventEntry.Spawns.Length != 0) { GUILayout.Label("Spawns: " + string.Join(", ", eventEntry.Spawns), GuiStyles.Info, Array.Empty()); } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button(new GUIContent("Start", "Start this event at the location chosen above."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(26f) })) { Send(0, eventEntry.Name); } if (GUILayout.Button(new GUIContent("Random", "Force-start a random event from the list instead."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(26f) })) { StartRandomFromList(); } if (GUILayout.Button(new GUIContent("Stop", "Stop whatever event is running."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(70f), GUILayout.Height(26f) })) { Send(1, string.Empty); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } private static string FormatKeys(string[] keys) { ZoneSystem instance = ZoneSystem.instance; List list = new List(keys.Length); foreach (string text in keys) { bool flag = (Object)(object)instance != (Object)null && instance.GetGlobalKey(text); list.Add(flag ? text : ("" + text + " (missing)")); } return string.Join(", ", list.ToArray()); } private static void StartRandomFromList() { IReadOnlyList readOnlyList = ((_list.Count > 0) ? _list.Matches : EventCatalog.Entries); if (readOnlyList.Count != 0) { EventEntry eventEntry = readOnlyList[Random.Range(0, readOnlyList.Count)]; _selectedName = eventEntry.Name; Send(0, eventEntry.Name); } } private static void Send(byte op, string name) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) AdminRpc.Send("event", EventCommand.BuildArgs(op, name, _where.ModeByte, _where.Anchor, _where.Coords)); } private static void Fill(IReadOnlyList entries, string filter, List outList) { foreach (EventEntry entry in entries) { if (filter.Length == 0 || entry.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || entry.StartMessage.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) { outList.Add(entry); } } } } internal sealed class FilteredList { private readonly List _matches = new List(); private string _key; private bool _pendingScrollReset; public Vector2 Scroll; public IReadOnlyList Matches => _matches; public int Count => _matches.Count; public void BeginFrame() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (_pendingScrollReset && (int)Event.current.type == 8) { _pendingScrollReset = false; Scroll = Vector2.zero; } } public bool KeyChanged(string cacheKey) { if (cacheKey == _key) { return false; } _key = cacheKey; return true; } public void Rebuild(Action> fill) { _matches.Clear(); fill(_matches); _pendingScrollReset = true; } } internal static class GuiStyles { private static string _dimColor; private static GUIStyle _rowLabel; private static GUIStyle _info; private static GUIStyle _tooltip; public static string DimColor => _dimColor ?? (_dimColor = Validate(PluginConfig.WindowDimTextColor.Value)); public static Color TextColor { get { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!ColorUtility.TryParseHtmlString(PluginConfig.WindowTextColor.Value, ref result)) { return Color.black; } return result; } } public static GUIStyle RowLabel { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown object obj = _rowLabel; if (obj == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { richText = true, alignment = (TextAnchor)3, wordWrap = false, padding = new RectOffset(4, 4, 2, 2) }; val.normal.textColor = TextColor; _rowLabel = val; obj = (object)val; } return (GUIStyle)obj; } } public static GUIStyle Info { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown object obj = _info; if (obj == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { richText = true, wordWrap = true }; val.normal.textColor = TextColor; _info = val; obj = (object)val; } return (GUIStyle)obj; } } public static GUIStyle Tooltip { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown object obj = _tooltip; if (obj == null) { GUIStyle val = new GUIStyle(GUI.skin.box) { alignment = (TextAnchor)3, richText = true, wordWrap = false, padding = new RectOffset(8, 8, 2, 2) }; val.normal.textColor = TextColor; _tooltip = val; obj = (object)val; } return (GUIStyle)obj; } } private static string Validate(string raw) { Color val = default(Color); if (!ColorUtility.TryParseHtmlString(raw, ref val)) { return "#000000"; } return raw; } public static void Init() { PluginConfig.WindowTextColor.SettingChanged += delegate { Invalidate(); }; PluginConfig.WindowDimTextColor.SettingChanged += delegate { Invalidate(); }; } private static void Invalidate() { _rowLabel = null; _info = null; _tooltip = null; _dimColor = null; } } internal static class IconDrawer { public static void Draw(Sprite sprite, float size) { //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) Rect rect = GUILayoutUtility.GetRect(size, size, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(size), GUILayout.Height(size) }); if ((int)Event.current.type == 7 && !((Object)(object)sprite == (Object)null) && !((Object)(object)sprite.texture == (Object)null)) { Texture2D texture = sprite.texture; Rect textureRect = sprite.textureRect; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height); GUI.DrawTextureWithTexCoords(rect, (Texture)(object)texture, val); } } } internal static class InputBlocker { [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class FreeCursor { private static void Postfix() { if (Blocking) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class SuppressTakeInput { private static void Postfix(ref bool __result) { if (Blocking) { __result = false; } } } [HarmonyPatch] private static class BlockBoolGetters { private static IEnumerable TargetMethods() { return new MethodInfo[9] { AccessTools.Method(typeof(ZInput), "GetButton", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetButtonUp", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetMouseButton", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetMouseButtonDown", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetMouseButtonUp", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetKey", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetKeyDown", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetKeyUp", (Type[])null, (Type[])null) }; } private static bool Prefix(ref bool __result) { if (!Blocking) { return true; } __result = false; return false; } } [HarmonyPatch] private static class BlockFloatGetters { private static IEnumerable TargetMethods() { return new MethodInfo[7] { AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyLeftStickX", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyLeftStickY", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyRightStickX", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyRightStickY", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyLTrigger", (Type[])null, (Type[])null), AccessTools.Method(typeof(ZInput), "GetJoyRTrigger", (Type[])null, (Type[])null) }; } private static bool Prefix(ref float __result) { if (!Blocking) { return true; } __result = 0f; return false; } } [HarmonyPatch(typeof(ZInput), "GetMouseDelta")] private static class BlockMouseDelta { private static bool Prefix(ref Vector2 __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!Blocking) { return true; } __result = Vector2.zero; return false; } } private static bool Blocking => AdminWindow.IsOpen; } internal static class ItemsTab { private const float RowHeight = 34f; private static readonly string[] CategoryTabs = new string[6] { "All", "Weapons", "Armor", "Food", "Resources", "Other" }; private static readonly string[] OriginTabs = new string[3] { "All", "Vanilla", "Modded" }; private static readonly string[] SortTabs = new string[2] { "Name", "Type" }; private static string _search = ""; private static int _categoryIdx; private static int _originIdx; private static int _sortIdx; private static int _quantity = 1; private static string _qtyText = "1"; private static string _selectedPrefab; private static string _modFilter = ""; private static string[] _modNames = Array.Empty(); private static int _modNamesVersion = -1; private static readonly ModFilterRow _modPicker = new ModFilterRow(); private static readonly FilteredList _list = new FilteredList(); public static void Draw() { _list.BeginFrame(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.MinWidth(160f), GUILayout.Height(22f) }); if (GUILayout.Button("clear", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) })) { _search = ""; } GUILayout.Space(10f); GUILayout.Label("Sort", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }); _sortIdx = GUILayout.Toolbar(_sortIdx, SortTabs, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }); GUILayout.EndHorizontal(); _categoryIdx = GUILayout.Toolbar(_categoryIdx, CategoryTabs, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Origin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); int originIdx = _originIdx; int originIdx2 = GUILayout.Toolbar(originIdx, OriginTabs, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) }); GUILayout.FlexibleSpace(); DrawQuantityStepper(); GUILayout.EndHorizontal(); IReadOnlyList entries = ItemCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty()); TargetSelector.Draw(); GUILayout.EndHorizontal(); string filter = (_search ?? "").Trim(); string cacheKey = $"{ItemCatalog.Version}|{_categoryIdx}|{originIdx}|{_modFilter}|{_sortIdx}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} items", Array.Empty()); ScrollList.Draw(_list.Matches, 34f, TabLayout.ListHeight(438f), ref _list.Scroll, DrawRow); DrawDetailPanel(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList entries) { if (_modNamesVersion != ItemCatalog.Version) { _modNamesVersion = ItemCatalog.Version; _modNames = (from e in entries where e.Origin == ItemOrigin.Modded && !string.IsNullOrEmpty(e.ModName) select e.ModName).Distinct().OrderBy((string n) => n, StringComparer.OrdinalIgnoreCase).ToArray(); if (Array.IndexOf(_modNames, _modFilter) < 0) { _modFilter = ""; } } if (_modNames.Length != 0) { _modFilter = _modPicker.Draw(_modNames, _modFilter); } } private static void DrawQuantityStepper() { GUILayout.Label("Qty", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }); if (GUILayout.Button("-10", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(34f), GUILayout.Height(22f) })) { SetQuantity(_quantity - 10); } if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(24f), GUILayout.Height(22f) })) { SetQuantity(_quantity - 1); } string text = GUILayout.TextField(_qtyText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(50f), GUILayout.Height(22f) }); if (text != _qtyText) { _qtyText = text; if (int.TryParse(text, out var result)) { _quantity = Mathf.Clamp(result, 1, PluginConfig.MaxQuantity.Value); } } if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(24f), GUILayout.Height(22f) })) { SetQuantity(_quantity + 1); } if (GUILayout.Button("+10", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(34f), GUILayout.Height(22f) })) { SetQuantity(_quantity + 10); } } private static void SetQuantity(int value) { _quantity = Mathf.Clamp(value, 1, PluginConfig.MaxQuantity.Value); _qtyText = _quantity.ToString(); } private static void DrawRow(ItemEntry e) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown GUILayout.BeginHorizontal((e.PrefabName == _selectedPrefab) ? GUIStyle.op_Implicit("box") : GUIStyle.none, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }); IconDrawer.Draw(e.Icon, 28f); string text = ((e.Origin == ItemOrigin.Vanilla) ? "V" : ((e.ModName.Length > 0) ? e.ModName : "M")); if (GUILayout.Button($"{e.DisplayName} {text} · {e.ItemType}", GuiStyles.RowLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { _selectedPrefab = e.PrefabName; } GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Give", "Give the quantity set above to the selected target."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(26f) })) { RequestGive(e.PrefabName); } GUILayout.EndHorizontal(); } private static void RequestGive(string prefabName) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) AdminRpc.Send("give_item", GiveItemCommand.BuildArgs(prefabName, _quantity, TargetSelector.Current)); } private static void DrawDetailPanel() { //IL_0109: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) }); ItemEntry itemEntry = ItemCatalog.ByPrefab(_selectedPrefab); if (itemEntry == null) { GUILayout.Label("Select an item to see details.", Array.Empty()); } else { GUILayout.Label("" + itemEntry.DisplayName + " " + itemEntry.PrefabName + "", GuiStyles.Info, Array.Empty()); if (!string.IsNullOrEmpty(itemEntry.Description)) { GUILayout.Label(itemEntry.Description, GuiStyles.Info, Array.Empty()); } string arg = ((itemEntry.Origin == ItemOrigin.Vanilla || itemEntry.ModName.Length == 0) ? itemEntry.Origin.ToString() : ("Modded (" + itemEntry.ModName + ")")); GUILayout.Label($"Type: {itemEntry.ItemType} Origin: {arg} " + $"Max stack: {itemEntry.MaxStackSize} Max quality: {itemEntry.MaxQuality}\n" + $"Weight: {itemEntry.Weight:0.##} Value: {itemEntry.Value} " + "Teleportable: " + (itemEntry.IsTeleportable ? "yes" : "no"), GuiStyles.Info, Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button($"Give {_quantity}", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(26f) })) { RequestGive(itemEntry.PrefabName); } } GUILayout.EndVertical(); } private static void Fill(IReadOnlyList entries, string filter, List outList) { foreach (ItemEntry entry in entries) { if ((_categoryIdx <= 0 || entry.Category == (ItemCategory)(_categoryIdx - 1)) && (_originIdx != 1 || entry.Origin == ItemOrigin.Vanilla) && (_originIdx != 2 || entry.Origin == ItemOrigin.Modded) && (_originIdx != 2 || _modFilter.Length <= 0 || !(entry.ModName != _modFilter)) && (filter.Length <= 0 || entry.DisplayName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || entry.PrefabName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)) { outList.Add(entry); } } if (_sortIdx != 1) { return; } outList.Sort(delegate(ItemEntry a, ItemEntry b) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) int num = a.Category.CompareTo(b.Category); if (num != 0) { return num; } num = ((Enum)a.ItemType/*cast due to .constrained prefix*/).CompareTo((object?)b.ItemType); return (num != 0) ? num : string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase); }); } } internal static class MapPicker { private static readonly MethodInfo ScreenToWorldPoint = typeof(Minimap).GetMethod("ScreenToWorldPoint", BindingFlags.Instance | BindingFlags.NonPublic); private const float ClickMaxDuration = 0.3f; private const float ClickMaxDrift = 10f; private const float WorldBound = 20000f; private static Action _onPicked; private static Vector2? _downPos; private static float _downTime; public static bool IsArmed => _onPicked != null; public static void Arm(Action onPicked) { Player localPlayer = Player.m_localPlayer; if (ScreenToWorldPoint == null) { if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Map picker unavailable (game update?)", 0, (Sprite)null, false); } } else if ((Object)(object)Minimap.instance == (Object)null) { if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Map isn't ready yet", 0, (Sprite)null, false); } } else if (Game.m_noMap) { if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Map is disabled on this world", 0, (Sprite)null, false); } } else { _onPicked = onPicked; _downPos = null; AdminWindow.IsOpen = false; Minimap.instance.SetMapMode((MapMode)2); } } public static void Tick() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (!IsArmed) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || (int)instance.m_mode != 2) { Stop(reopenWindow: true); } else if (Input.GetMouseButtonDown(0)) { _downPos = Vector2.op_Implicit(Input.mousePosition); _downTime = Time.time; } else if (Input.GetMouseButtonUp(0) && _downPos.HasValue) { Vector2 val = Vector2.op_Implicit(Input.mousePosition); bool num = Time.time - _downTime < 0.3f && Vector2.Distance(_downPos.Value, val) < 10f; _downPos = null; if (num) { TryPick(instance, val); } } } private static void TryPick(Minimap map, Vector2 screenPos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) Vector3 val; try { val = (Vector3)ScreenToWorldPoint.Invoke(map, new object[1] { Vector2.op_Implicit(screenPos) }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Admin Forge: map picker's ScreenToWorldPoint call failed: " + ex.Message)); Stop(reopenWindow: true); return; } if (!(Mathf.Abs(val.x) > 20000f) && !(Mathf.Abs(val.z) > 20000f)) { val.y = ((WorldGenerator.instance != null) ? WorldGenerator.instance.GetHeight(val.x, val.z) : 0f); Action onPicked = _onPicked; Stop(reopenWindow: true); onPicked?.Invoke(val); } } private static void Stop(bool reopenWindow) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 _onPicked = null; _downPos = null; if ((Object)(object)Minimap.instance != (Object)null && (int)Minimap.instance.m_mode == 2) { Minimap.instance.SetMapMode((MapMode)1); } if (reopenWindow) { AdminWindow.IsOpen = true; } } } internal sealed class ModFilterRow { private string _filter = ""; private readonly List _matches = new List(); public string Draw(IReadOnlyList names, string selected) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Mod", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); string text = GUILayout.TextField(_filter ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(22f) }); _matches.Clear(); for (int i = 0; i < names.Count; i++) { if (text.Length == 0 || names[i].IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { _matches.Add(names[i]); } } if (GUILayout.Button("All", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(22f) })) { selected = ""; } int num = (string.IsNullOrEmpty(selected) ? (-1) : _matches.IndexOf(selected)); if (num < 0 && !string.IsNullOrEmpty(selected)) { selected = ""; } if (GUILayout.Button((_matches.Count == 0) ? "(no match)" : _matches[(num >= 0) ? num : 0], (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(140f), GUILayout.Height(22f) }) && _matches.Count > 0) { selected = _matches[(num + 1) % _matches.Count]; } _filter = text; GUILayout.EndHorizontal(); return selected; } } internal static class PlayersTab { private static Vector2 _scroll; private static string _x = "0"; private static string _y = "0"; private static string _z = "0"; private static bool _instant = true; private static string _radiusText = "20"; private static string _skillAmountText = "10"; private static int _skillIdx; private static string[] _skills; public static void Draw() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList players = PlayerRoster.Players; GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label($"{players.Count} player(s) online", Array.Empty()); GUILayout.FlexibleSpace(); _instant = GUILayout.Toggle(_instant, " Instant (no loading screen)", Array.Empty()); GUILayout.EndHorizontal(); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(TabLayout.ListHeight(474f)) }); foreach (PlayerRef item in players) { DrawRow(item); } GUILayout.EndScrollView(); DrawCoordsRow(); DrawActionsSection(); } private static void DrawRow(PlayerRef p) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); string text = (p.PositionKnown ? $"({p.Position.x:0}, {p.Position.y:0}, {p.Position.z:0})" : "(position hidden on map)"); PlayerTags.Tag tag = PlayerTags.For(p.CharacterId); string text2 = ((tag != null) ? ("[" + tag.Text + "] ") : ""); GUILayout.Label(text2 + (p.IsSelf ? ("" + p.Name + " (you)") : p.Name) + " " + text + "", GuiStyles.RowLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(150f) }); GUILayout.FlexibleSpace(); if (!p.IsSelf) { if (GUILayout.Button(new GUIContent("Go to", "Teleport yourself to this player."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(58f), GUILayout.Height(24f) })) { Send(ZDOID.None, 1, Vector3.zero, p.CharacterId); } if (GUILayout.Button(new GUIContent("Bring", "Teleport this player to you."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(58f), GUILayout.Height(24f) })) { Send(p.CharacterId, 1, Vector3.zero, ZDOID.None); } } GUILayout.EndHorizontal(); } private static void DrawCoordsRow() { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); TargetSelector.Draw(); GUILayout.Label("to", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) }); _x = GUILayout.TextField(_x, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(56f), GUILayout.Height(22f) }); _y = GUILayout.TextField(_y, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(56f), GUILayout.Height(22f) }); _z = GUILayout.TextField(_z, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(56f), GUILayout.Height(22f) }); if (GUILayout.Button(new GUIContent("Map", "Pick X/Z/Y by clicking the map."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(22f) })) { MapPicker.Arm(delegate(Vector3 pos) { _x = pos.x.ToString("0.#"); _y = pos.y.ToString("0.#"); _z = pos.z.ToString("0.#"); }); } if (GUILayout.Button(new GUIContent("Go", "Teleport the selected target to X / Y / Z."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) })) { float.TryParse(_x, out var result); float.TryParse(_y, out var result2); float.TryParse(_z, out var result3); Send(TargetSelector.Current, 0, new Vector3(result, result2, result3), ZDOID.None); } GUILayout.EndHorizontal(); } private static void DrawActionsSection() { //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Expected O, but got Unknown GUILayout.Space(3f); GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Admin actions", GuiStyles.Info, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(96f) }); TargetSelector.Draw(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); if (ActBtn("God", "Invincible — takes no damage. Toggles on/off.")) { Act("god"); } if (ActBtn("Ghost", "Creatures don't notice or attack you. Toggles.")) { Act("ghost"); } if (ActBtn("Fly", "Debug flight — up/down with jump/crouch. Toggles.")) { Act("fly"); } if (ActBtn("NoCost", "Build and craft for free, no materials consumed. Toggles.")) { Act("nocost"); } if (ActBtn("Heal", "Refill health, stamina and eitr to maximum.")) { Act("heal"); } if (ActBtn("Die", "Kill the selected target instantly (blocked by god mode).")) { Act("die"); } if (ActBtn("Puke", "Clear all active food buffs (empty the stomach).")) { Act("puke"); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); if (ActBtn("Repair all", "Set every worn / equipped item to full durability.")) { Act("repairall"); } if (ActBtn("Clean inv", "Drop any items stuck on invalid inventory slots.")) { Act("inventoryclean"); } if (ActBtn("Explore map", "Reveal the entire map for the target.")) { Act("exploremap"); } if (ActBtn("Reset map", "Erase the target's map exploration.")) { Act("resetmap"); } if (ActBtn("Freefly (local)", "Detach your camera for screenshots. Your client only — ignores the target.")) { ToggleFreefly(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent("Radius", "Metres around the target for the sweep buttons. Server caps this at Server/MaxActionRadius."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); _radiusText = GUILayout.TextField(_radiusText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(46f), GUILayout.Height(22f) }); if (ActBtn("Kill all", "Lethal hit to every creature in range, tamed included. No loot (same as console killall).")) { ActRadius("killall"); } if (ActBtn("Kill enemies", "Lethal hit to wild / hostile creatures in range. Tamed are spared.")) { ActRadius("killenemies"); } if (ActBtn("Kill tame", "Lethal hit to tamed creatures in range only.")) { ActRadius("killtame"); } if (ActBtn("Tame", "Instantly tame every tameable creature in range.")) { ActRadius("tame"); } if (ActBtn("Aggravate", "Turn neutral creatures in range hostile.")) { ActRadius("aggravate"); } GUILayout.EndHorizontal(); EnsureSkills(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Skill", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); if (GUILayout.Button(new GUIContent(_skills[_skillIdx], "Cycle the skill for Raise / Reset. 'All' affects every skill."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(22f) })) { _skillIdx = (_skillIdx + 1) % _skills.Length; } GUILayout.Label(new GUIContent("Amt", "Skill levels to add on Raise (-100 to 100; level is capped at 100)."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }); _skillAmountText = GUILayout.TextField(_skillAmountText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(46f), GUILayout.Height(22f) }); if (ActBtn("Raise", "Add the amount to the selected skill.")) { ActSkill("raiseskill"); } if (ActBtn("Reset", "Set the selected skill back to level 0.")) { ActSkill("resetskill"); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private static bool ActBtn(string label, string tip) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return GUILayout.Button(new GUIContent(label, tip), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }); } private static void Act(string id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) AdminRpc.Send("player_action", PlayerActionCommand.BuildArgs(id, TargetSelector.Current, 0, 0f, string.Empty)); } private static void ActRadius(string id) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) float.TryParse(_radiusText, out var result); AdminRpc.Send("player_action", PlayerActionCommand.BuildArgs(id, TargetSelector.Current, 0, (result <= 0f) ? 20f : result, string.Empty)); } private static void ActSkill(string id) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) float.TryParse(_skillAmountText, out var result); AdminRpc.Send("player_action", PlayerActionCommand.BuildArgs(id, TargetSelector.Current, 0, result, _skills[_skillIdx])); } private static void ToggleFreefly() { if ((Object)(object)GameCamera.instance != (Object)null) { GameCamera.instance.ToggleFreeFly(); } } private static void EnsureSkills() { if (_skills != null) { return; } List list = new List(); string[] names = Enum.GetNames(typeof(SkillType)); foreach (string text in names) { if (text != "None") { list.Add(text); } } _skills = list.ToArray(); } private static void Send(ZDOID subject, byte mode, Vector3 coords, ZDOID anchor) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) AdminRpc.Send("teleport", TeleportCommand.BuildArgs(subject, mode, coords, anchor, _instant)); } } internal sealed class PositionPicker { private static readonly string[] Labels = new string[3] { "Me", "Target", "Coords" }; private AnchorMode _mode; private string _x = "0"; private string _y = "0"; private string _z = "0"; public byte ModeByte => (byte)_mode; public ZDOID Anchor { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (_mode != AnchorMode.Target) { return ZDOID.None; } return TargetSelector.Current; } } public Vector3 Coords { get { //IL_002d: Unknown result type (might be due to invalid IL or missing references) float.TryParse(_x, out var result); float.TryParse(_y, out var result2); float.TryParse(_z, out var result3); return new Vector3(result, result2, result3); } } public void Draw() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown AnchorMode mode = _mode; GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent("Where", "'At me' / 'At target' resolve the player's real position on the server."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); int num = GUILayout.Toolbar((int)mode, Labels, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) }); switch (mode) { case AnchorMode.Coords: _x = GUILayout.TextField(_x, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(22f) }); _y = GUILayout.TextField(_y, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(22f) }); _z = GUILayout.TextField(_z, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(52f), GUILayout.Height(22f) }); if (GUILayout.Button(new GUIContent("Map", "Pick X/Z/Y by clicking the map. Closes this window while you click; it reopens once you pick a spot (or cancel with Esc)."), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(22f) })) { MapPicker.Arm(delegate(Vector3 pos) { _x = pos.x.ToString("0.#"); _y = pos.y.ToString("0.#"); _z = pos.z.ToString("0.#"); }); } break; case AnchorMode.Target: TargetSelector.Draw(); break; } GUILayout.EndHorizontal(); _mode = (AnchorMode)num; } } internal static class ScrollList { public static void Draw(IReadOnlyList items, float rowHeight, float viewHeight, ref Vector2 scroll, Action drawRow) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) int count = items.Count; scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(viewHeight) }); int num = Mathf.Clamp(Mathf.FloorToInt(scroll.y / rowHeight), 0, Mathf.Max(0, count - 1)); int num2 = Mathf.CeilToInt(viewHeight / rowHeight) + 2; int num3 = Mathf.Min(count, num + num2); GUILayout.Space((float)num * rowHeight); for (int i = num; i < num3; i++) { drawRow(items[i]); } GUILayout.Space(Mathf.Max(0f, (float)(count - num3) * rowHeight)); GUILayout.EndScrollView(); } } internal static class TabLayout { public const float ItemsReserve = 438f; public const float EffectsReserve = 423f; public const float PlayersReserve = 474f; public const float CreaturesReserve = 474f; public const float EventsReserve = 340f; public const float WorldReserve = 430f; public static float ListHeight(float reserve) { return Mathf.Max(110f, (float)PluginConfig.WindowHeight.Value - reserve); } } internal static class TargetSelector { private static ZDOID _selected = ZDOID.None; private static string _filter = ""; private static string _sig = null; private static ZDOID[] _ids = (ZDOID[])(object)new ZDOID[1] { ZDOID.None }; private static string[] _names = new string[1] { "Self" }; private static readonly List _optLabels = new List(); private static readonly List _optIndex = new List(); public static ZDOID Current { get { //IL_0028: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((ZDOID)(ref _selected)).IsNone() && Array.IndexOf(_ids, _selected) < 0) { _selected = ZDOID.None; } return _selected; } } public static void Draw() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) if ((int)Event.current.type == 8) { SyncSnapshot(); } GUILayout.Label(new GUIContent("Target", "Who the tab's actions apply to. Self, or any online player."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(46f) }); string text = _filter ?? ""; string filter = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(22f) }); _optLabels.Clear(); _optIndex.Clear(); for (int i = 0; i < _names.Length; i++) { if (i == 0 || text.Length == 0 || _names[i].IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { _optLabels.Add(_names[i]); _optIndex.Add(i); } } int item = Array.IndexOf(_ids, _selected); int num = _optIndex.IndexOf(item); if (num < 0) { num = 0; } int num2 = Mathf.Clamp(_optLabels.Count, 1, 6); int num3 = GUILayout.SelectionGrid(num, _optLabels.ToArray(), num2, Array.Empty()); if (num3 != num && num3 >= 0 && num3 < _optIndex.Count) { _selected = _ids[_optIndex[num3]]; } _filter = filter; } private static void SyncSnapshot() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList players = PlayerRoster.Players; StringBuilder stringBuilder = new StringBuilder("self"); foreach (PlayerRef item in players) { if (!item.IsSelf) { stringBuilder.Append('|').Append(item.CharacterId).Append(item.Name); } } string text = stringBuilder.ToString(); if (text == _sig) { return; } _sig = text; List list = new List { ZDOID.None }; List list2 = new List { "Self" }; foreach (PlayerRef item2 in players) { if (!item2.IsSelf) { list.Add(item2.CharacterId); list2.Add(item2.Name); } } _ids = list.ToArray(); _names = list2.ToArray(); if (!((ZDOID)(ref _selected)).IsNone() && Array.IndexOf(_ids, _selected) < 0) { _selected = ZDOID.None; } } } internal static class WorldTab { private static string _todText = "0.50"; private static string _windAngle = "0"; private static string _windIntensity = "1"; private static string _skipSecs = "600"; private static string _keyText = ""; private static string _envSearch = ""; private static string[] _envNames; private static int _envNamesCount = -1; private static int _envIdx; private static int _knownIdx; private static Vector2 _keyScroll; private static string _envMatchKey; private static string[] _envMatches = new string[0]; private static readonly KeyValuePair[] KnownKeys = new KeyValuePair[14] { new KeyValuePair("noportals", "Disables all portals."), new KeyValuePair("nobossportals", "Disables the portals in boss arenas."), new KeyValuePair("nomap", "Disables the map and minimap for everyone."), new KeyValuePair("passivemobs", "All creatures ignore players (won't attack)."), new KeyValuePair("nobuildcost", "Building costs no materials."), new KeyValuePair("nocraftcost", "Crafting and upgrading cost no materials."), new KeyValuePair("noworkbench", "Build anywhere without a crafting station in range."), new KeyValuePair("allpiecesunlocked", "Every build piece is available."), new KeyValuePair("allrecipesunlocked", "Every crafting recipe is available."), new KeyValuePair("dungeonbuild", "Allow building inside dungeons / crypts."), new KeyValuePair("nobuildingfall", "Build pieces don't collapse without support."), new KeyValuePair("teleportall", "Any item can be carried through a portal."), new KeyValuePair("noheavysnow", "Disables the Deep North blizzard."), new KeyValuePair("allheavysnow", "Forces the Deep North blizzard everywhere.") }; public static void Draw() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Expected O, but got Unknown //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Expected O, but got Unknown //IL_054d: Unknown result type (might be due to invalid IL or missing references) //IL_056a: Expected O, but got Unknown //IL_062e: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_06c0: Unknown result type (might be due to invalid IL or missing references) //IL_06dd: Expected O, but got Unknown //IL_072c: Unknown result type (might be due to invalid IL or missing references) //IL_0749: Unknown result type (might be due to invalid IL or missing references) //IL_074e: Unknown result type (might be due to invalid IL or missing references) EnsureEnvNames(); GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.Label(new GUIContent("Time of day", "Force the sky to a fixed point in the cycle (0 = midnight, 0.5 = noon) on every client. While this is set, Skip time has no visible effect — Clear it first."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); _todText = GUILayout.TextField(_todText, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(50f), GUILayout.Height(22f) }); GUILayout.Label("0..1", GuiStyles.Info, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); if (Btn("Set", 50f)) { float.TryParse(_todText, out var result); Env(0, Mathf.Clamp01(result), 0f, "", b: false); } if (Btn("Clear", 56f)) { Env(0, -1f, 0f, "", b: false); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.Label(new GUIContent("Weather", "Force an environment (weather preset) on every client. Type to filter, click the name to cycle matches."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); string text = GUILayout.TextField(_envSearch ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(22f) }); if (text != _envSearch) { _envSearch = text; _envIdx = 0; } string text2 = FilteredEnv(); if (GUILayout.Button(text2 ?? "(no match)", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(160f), GUILayout.Height(22f) }) && text2 != null) { _envIdx++; } if (Btn("Set", 50f) && text2 != null) { Env(1, 0f, 0f, text2, b: false); } if (Btn("Clear", 56f)) { Env(1, 0f, 0f, "", b: false); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.Label(new GUIContent("Wind", "Force wind angle (deg) and intensity (0..1) on every client."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); GUILayout.Label("angle", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); _windAngle = GUILayout.TextField(_windAngle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(48f), GUILayout.Height(22f) }); GUILayout.Label("power", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(42f) }); _windIntensity = GUILayout.TextField(_windIntensity, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(22f) }); if (Btn("Set", 50f)) { float.TryParse(_windAngle, out var result2); float.TryParse(_windIntensity, out var result3); Env(2, result2, Mathf.Clamp01(result3), "", b: false); } if (Btn("Reset", 56f)) { Env(2, 0f, -1f, "", b: false); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.Label(new GUIContent("Spawns", "Toggle natural monster spawning on every client + the server."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); GUILayout.Label("currently " + (SpawnSystem.m_nospawn ? "OFF" : "ON") + "", GuiStyles.Info, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }); if (Btn("Enable", 66f)) { Env(3, 0f, 0f, "", b: false); } if (Btn("Disable", 66f)) { Env(3, 0f, 0f, "", b: true); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.Label(new GUIContent("Skip time", "Advance the shared net time. Affects everyone. No visible effect while a Time-of-day override is set."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); _skipSecs = GUILayout.TextField(_skipSecs, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(60f), GUILayout.Height(22f) }); GUILayout.Label("sec", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }); if (Btn("Skip", 56f)) { float.TryParse(_skipSecs, out var result4); World(0, result4, ""); } if (Btn("To morning", 92f)) { World(1, 0f, ""); } GUILayout.EndHorizontal(); GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(new GUIContent("Global key", "Server world keys. Free text for boss / mod keys; use the picker below for the common toggles."), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); _keyText = GUILayout.TextField(_keyText ?? "", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(180f), GUILayout.Height(22f) }); if (Btn("Set key", 70f)) { World(2, 0f, _keyText); } if (Btn("Remove", 70f)) { World(3, 0f, _keyText); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("known", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }); KeyValuePair keyValuePair = KnownKeys[_knownIdx]; if (GUILayout.Button(new GUIContent(keyValuePair.Key, keyValuePair.Value), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(180f), GUILayout.Height(22f) })) { _knownIdx = (_knownIdx + 1) % KnownKeys.Length; } if (Btn("Set", 50f)) { World(2, 0f, keyValuePair.Key); } if (Btn("Remove", 70f)) { World(3, 0f, keyValuePair.Key); } GUILayout.Label(new GUIContent("?", keyValuePair.Value), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) }); GUILayout.EndHorizontal(); List list = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.GetGlobalKeys() : null); GUILayout.Label($"{list?.Count ?? 0} keys set", GuiStyles.Info, Array.Empty()); _keyScroll = GUILayout.BeginScrollView(_keyScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(TabLayout.ListHeight(430f)) }); if (list != null) { foreach (string item in list) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(item, GuiStyles.RowLabel, Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button("x", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(24f), GUILayout.Height(20f) })) { World(3, 0f, item); } GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); GUILayout.EndVertical(); } private static bool Btn(string label, float w) { return GUILayout.Button(label, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(w), GUILayout.Height(22f) }); } private static void Env(int op, float f1, float f2, string s, bool b) { AdminRpc.Send("env_override", EnvCommand.BuildArgs(op, f1, f2, s, b)); } private static void World(int op, float f, string s) { AdminRpc.Send("world_state", WorldCommand.BuildArgs(op, f, s)); } private static string FilteredEnv() { string text = (_envSearch ?? "").Trim(); string text2 = $"{_envNamesCount}|{text.ToLowerInvariant()}"; if (text2 != _envMatchKey) { _envMatchKey = text2; List list = new List(); string[] envNames = _envNames; foreach (string text3 in envNames) { if (text.Length == 0 || text3.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { list.Add(text3); } } _envMatches = list.ToArray(); } if (_envMatches.Length == 0) { return null; } return _envMatches[(_envIdx % _envMatches.Length + _envMatches.Length) % _envMatches.Length]; } private static void EnsureEnvNames() { EnvMan instance = EnvMan.instance; int num = (((Object)(object)instance != (Object)null && instance.m_environments != null) ? instance.m_environments.Count : 0); if (_envNames != null && num == _envNamesCount) { return; } if (num == 0) { _envNames = _envNames ?? new string[0]; return; } List list = new List(num); foreach (EnvSetup environment in instance.m_environments) { if (environment != null && !string.IsNullOrEmpty(environment.m_name)) { list.Add(environment.m_name); } } list.Sort(StringComparer.OrdinalIgnoreCase); _envNames = list.ToArray(); _envNamesCount = num; _envMatchKey = null; } } } namespace ValheimAdminForge.Commands { internal sealed class ApplyEffectCommand : IAdminCommand { public const string CommandName = "apply_effect"; public const float MaxDuration = 3600f; public const float MaxPower = 100000f; public string Name => "apply_effect"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(int nameHash, ZDOID target, float duration, float power, bool remove) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(nameHash); val.Write(target); val.Write(duration); val.Write(power); val.Write(remove); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) targetPeerId = 0L; execArgs = null; error = null; int num = args.ReadInt(); ZDOID characterZdoid = args.ReadZDOID(); float num2 = args.ReadSingle(); float num3 = args.ReadSingle(); bool flag = args.ReadBool(); if (num == 0) { error = "no effect specified"; return false; } if (!flag && (num2 < 0f || num2 > 3600f || num3 < 0f || num3 > 100000f)) { error = "duration or power out of range"; return false; } bool flag2 = (Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ObjectDB.instance.GetStatusEffect(num) != (Object)null; if (!flag && !flag2) { if (PluginConfig.ServerStrictItemCheck.Value) { error = "that status effect is not registered on the server"; return false; } Plugin.Log.LogWarning((object)$"[server] status effect {num} unknown to server ObjectDB — authorising anyway"); } return Targeting.Resolve(in ctx, characterZdoid, out targetPeerId, out error); } public void Apply(ZPackage args) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) int num = args.ReadInt(); args.ReadZDOID(); float num2 = args.ReadSingle(); float num3 = args.ReadSingle(); bool flag = args.ReadBool(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } string text = StatusEffectCatalog.ByHash(num)?.DisplayName ?? num.ToString(); if (flag) { ((Character)localPlayer).GetSEMan().RemoveStatusEffect(num, false); ((Character)localPlayer).Message((MessageType)1, "Removed " + text, 0, (Sprite)null, false); return; } StatusEffect val; try { val = ((Character)localPlayer).GetSEMan().AddStatusEffect(num, true, 0, 0f, (short)(-1)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("AddStatusEffect(" + text + ") threw: " + ex.Message)); ((Character)localPlayer).Message((MessageType)1, "Couldn't fully apply " + text + " (broken effect data)", 0, (Sprite)null, false); return; } if ((Object)(object)val == (Object)null) { return; } if (num2 > 0f) { val.m_ttl = num2; } if (num3 > 0f) { SE_Poison val2 = (SE_Poison)(object)((val is SE_Poison) ? val : null); if (val2 == null) { SE_Burning val3 = (SE_Burning)(object)((val is SE_Burning) ? val : null); if (val3 == null) { SE_Frost val4 = (SE_Frost)(object)((val is SE_Frost) ? val : null); if (val4 != null) { val4.AddDamage(num3); } } else { if (((StatusEffect)val3).m_ttl <= 0f) { ((StatusEffect)val3).m_ttl = ((num2 > 0f) ? num2 : 10f); } val3.AddFireDamage(num3); } } else { val2.AddDamage(num3); } } ((Character)localPlayer).Message((MessageType)1, "Applied " + text, 0, (Sprite)null, false); } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class DespawnCommand : IAdminCommand { private struct Job { public float DueAt; public Vector3 Centre; public float Radius; public int Scope; public int MinLevel; public string Name; public bool Items; public bool Fish; public bool Birds; } public const string CommandName = "despawn"; public const byte ScopeWild = 0; public const byte ScopeTamed = 1; public const byte ScopeAll = 2; private static Job? _retry; public string Name => "despawn"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(float radius, byte scope, string nameFilter, int minLevel, bool items, bool fish, bool birds, ZDOID anchor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0032: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(radius); val.Write((int)scope); val.Write(nameFilter ?? string.Empty); val.Write(minLevel); val.Write(items); val.Write(fish); val.Write(birds); val.Write(anchor); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown targetPeerId = 0L; execArgs = null; error = null; float num = args.ReadSingle(); int num2 = args.ReadInt(); string text = args.ReadString(); int num3 = args.ReadInt(); bool flag = args.ReadBool(); bool flag2 = args.ReadBool(); bool flag3 = args.ReadBool(); ZDOID characterZdoid = args.ReadZDOID(); if (!Targeting.Resolve(in ctx, characterZdoid, out targetPeerId, out error)) { return false; } if (!CmdValidate.Finite(num) || num <= 0f) { num = 20f; } num = Mathf.Clamp(num, 1f, PluginConfig.ServerMaxDespawnRadius.Value); num3 = Mathf.Clamp(num3, 0, 9); execArgs = new ZPackage(); execArgs.Write(num); execArgs.Write(num2); execArgs.Write(text ?? string.Empty); execArgs.Write(num3); execArgs.Write(flag); execArgs.Write(flag2); execArgs.Write(flag3); return true; } public void Apply(ZPackage args) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) float radius = args.ReadSingle(); int scope = args.ReadInt(); string text = args.ReadString(); int minLevel = args.ReadInt(); bool items = args.ReadBool(); bool fish = args.ReadBool(); bool birds = args.ReadBool(); Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Vector3 position = ((Component)localPlayer).transform.position; int num = Sweep(position, radius, scope, text, minLevel, items, fish, birds); _retry = new Job { DueAt = Time.realtimeSinceStartup + 1.5f, Centre = position, Radius = radius, Scope = scope, MinLevel = minLevel, Name = text, Items = items, Fish = fish, Birds = birds }; ((Character)localPlayer).Message((MessageType)1, string.Format("Despawned {0} object{1}", num, (num == 1) ? "" : "s"), 0, (Sprite)null, false); } } public static void Tick() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (_retry.HasValue && !(Time.realtimeSinceStartup < _retry.Value.DueAt)) { Job value = _retry.Value; _retry = null; if ((Object)(object)Player.m_localPlayer != (Object)null) { Sweep(value.Centre, value.Radius, value.Scope, value.Name, value.MinLevel, value.Items, value.Fish, value.Birds); } } } private static int Sweep(Vector3 c, float radius, int scope, string nameFilter, int minLevel, bool items, bool fish, bool birds) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; bool flag = !string.IsNullOrEmpty(nameFilter); int num2 = 0; Vector3 val; foreach (Character item in new List(Character.GetAllCharacters())) { if ((Object)(object)item == (Object)null || item.IsPlayer() || (Object)(object)((Component)item).GetComponent() != (Object)null) { continue; } val = ((Component)item).transform.position - c; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { bool flag2 = item.IsTamed(); if (!(scope == 0 && flag2) && (scope != 1 || flag2) && (minLevel <= 1 || item.GetLevel() >= minLevel) && (!flag || ((Object)item).name.IndexOf(nameFilter, StringComparison.OrdinalIgnoreCase) >= 0) && DestroyView(((Component)item).gameObject)) { num2++; } } } if (items) { ItemDrop[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (ItemDrop val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.IsPiece() && !((Object)(object)((Component)val2).GetComponentInParent() != (Object)null)) { val = ((Component)val2).transform.position - c; if (!(((Vector3)(ref val)).sqrMagnitude > num) && DestroyView(((Component)val2).gameObject)) { num2++; } } } } if (fish) { Fish[] array2 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Fish val3 in array2) { if (!((Object)(object)val3 == (Object)null)) { val = ((Component)val3).transform.position - c; if (!(((Vector3)(ref val)).sqrMagnitude > num) && DestroyView(((Component)val3).gameObject)) { num2++; } } } } if (birds) { RandomFlyingBird[] array3 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (RandomFlyingBird val4 in array3) { if (!((Object)(object)val4 == (Object)null)) { val = ((Component)val4).transform.position - c; if (!(((Vector3)(ref val)).sqrMagnitude > num) && DestroyView(((Component)val4).gameObject)) { num2++; } } } } return num2; } private static bool DestroyView(GameObject go) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) ZNetView component = go.GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { Object.Destroy((Object)(object)go); return true; } component.ClaimOwnership(); ZDO zDO = component.GetZDO(); component.Destroy(); if (zDO != null && ZDOMan.instance != null) { ZDOMan.instance.RemoveFromSector(zDO, zDO.GetSectorIndex()); } return true; } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class EnvCommand : IAdminCommand { public const string CommandName = "env_override"; public const int OpTod = 0; public const int OpEnv = 1; public const int OpWind = 2; public const int OpNoSpawn = 3; public string Name => "env_override"; public ExecutionSite Site => ExecutionSite.AllClients; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(int op, float f1, float f2, string s, bool b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0013: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(op); val.Write(f1); val.Write(f2); val.Write(s ?? string.Empty); val.Write(b); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown targetPeerId = 0L; execArgs = null; error = null; int num = args.ReadInt(); float num2 = args.ReadSingle(); float num3 = args.ReadSingle(); string text = args.ReadString(); bool flag = args.ReadBool(); switch (num) { default: error = $"unknown env op {num}"; return false; case 0: num2 = (CmdValidate.Finite(num2) ? Mathf.Clamp(num2, -1f, 1f) : (-1f)); break; case 2: num2 = CmdValidate.Sane(num2, 0f) % 360f; num3 = (CmdValidate.Finite(num3) ? num3 : (-1f)); if (num3 >= 0f) { num3 = Mathf.Clamp01(num3); } break; case 1: if (!string.IsNullOrEmpty(text) && !IsKnownEnvironment(text)) { error = "unknown environment '" + text + "'"; return false; } break; case 3: break; } execArgs = new ZPackage(); execArgs.Write(num); execArgs.Write(num2); execArgs.Write(num3); execArgs.Write(text ?? string.Empty); execArgs.Write(flag); return true; } public void Apply(ZPackage args) { int num = args.ReadInt(); float num2 = args.ReadSingle(); float num3 = args.ReadSingle(); string text = args.ReadString(); bool nospawn = args.ReadBool(); EnvMan instance = EnvMan.instance; switch (num) { case 0: if ((Object)(object)instance == (Object)null) { return; } if (num2 < 0f) { instance.m_debugTimeOfDay = false; break; } instance.m_debugTimeOfDay = true; instance.m_debugTime = Mathf.Clamp01(num2); break; case 1: if ((Object)(object)instance == (Object)null) { return; } instance.m_debugEnv = text ?? string.Empty; break; case 2: if ((Object)(object)instance == (Object)null) { return; } if (num3 < 0f) { instance.ResetDebugWind(); } else { instance.SetDebugWind(num2, num3); } break; case 3: SpawnSystem.m_nospawn = nospawn; break; } if (AdminGuard.IsLocalPlayerAdminHint()) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "World override applied", 0, (Sprite)null, false); } } } private static bool IsKnownEnvironment(string name) { EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null || instance.m_environments == null) { return true; } foreach (EnvSetup environment in instance.m_environments) { if (environment != null && string.Equals(environment.m_name, name, StringComparison.Ordinal)) { return true; } } return false; } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class EventCommand : IAdminCommand { public const string CommandName = "event"; public const byte OpStartAt = 0; public const byte OpStop = 1; public const byte OpRandom = 2; public string Name => "event"; public ExecutionSite Site => ExecutionSite.Server; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(byte op, string name, byte anchorMode, ZDOID anchor, Vector3 coords) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write((int)op); val.Write(name ?? string.Empty); val.Write((int)anchorMode); val.Write(anchor); val.Write(coords); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) targetPeerId = 0L; execArgs = null; error = null; byte b = (byte)args.ReadInt(); string text = args.ReadString(); AnchorMode anchorMode = (AnchorMode)args.ReadInt(); ZDOID val = args.ReadZDOID(); Vector3 val2 = args.ReadVector3(); if (b != 0 && b != 1 && b != 2) { error = $"unknown event op {b}"; return false; } RandEventSystem instance = RandEventSystem.instance; if ((Object)(object)instance == (Object)null) { error = "the event system isn't ready on the server"; return false; } Vector3 pos = Vector3.zero; if (b == 0) { if (string.IsNullOrEmpty(text) || !instance.HaveEvent(text)) { error = "unknown event '" + text + "'"; return false; } if (anchorMode == AnchorMode.Coords) { pos = val2; } else if (!Targeting.RefPos(in ctx, (anchorMode == AnchorMode.Target) ? val : ZDOID.None, out pos)) { error = "the anchor position isn't available"; return false; } if (!CmdValidate.InWorldBounds(pos)) { error = "event position is out of bounds"; return false; } } execArgs = new ZPackage(); execArgs.Write((int)b); execArgs.Write(text ?? string.Empty); execArgs.Write(pos); return true; } public void Apply(ZPackage args) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) byte b = (byte)args.ReadInt(); string text = args.ReadString(); Vector3 val = args.ReadVector3(); RandEventSystem instance = RandEventSystem.instance; if (!((Object)(object)instance == (Object)null)) { switch (b) { case 0: instance.SetRandomEventByName(text, val); break; case 1: instance.ResetRandomEvent(); break; case 2: instance.StartRandomEvent(); break; } } } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class GiveItemCommand : IAdminCommand { public const string CommandName = "give_item"; public string Name => "give_item"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(string prefabName, int amount, ZDOID target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(prefabName); val.Write(amount); val.Write(target); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) targetPeerId = 0L; execArgs = null; error = null; string text = args.ReadString(); int num = args.ReadInt(); ZDOID characterZdoid = args.ReadZDOID(); if (string.IsNullOrEmpty(text)) { error = "no item specified"; return false; } if (!((Object)(object)ObjectDB.instance != (Object)null) || !((Object)(object)ObjectDB.instance.GetItemPrefab(text) != (Object)null)) { if (PluginConfig.ServerStrictItemCheck.Value) { error = "item '" + text + "' is not registered on the server"; return false; } Plugin.Log.LogWarning((object)("[server] '" + text + "' unknown to server ObjectDB — authorising anyway (Server/StrictItemCheck=false)")); } int value = PluginConfig.ServerMaxQuantity.Value; if (num < 1 || num > value) { error = $"amount {num} out of range (1..{value})"; return false; } return Targeting.Resolve(in ctx, characterZdoid, out targetPeerId, out error); } public void Apply(ZPackage args) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) string prefabName = args.ReadString(); int amount = args.ReadInt(); args.ReadZDOID(); ItemSpawner.GiveToLocalPlayer(prefabName, amount); } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class PlayerActionCommand : IAdminCommand { public const string CommandName = "player_action"; public const string God = "god"; public const string Ghost = "ghost"; public const string Fly = "fly"; public const string NoCost = "nocost"; public const string Heal = "heal"; public const string Die = "die"; public const string Puke = "puke"; public const string RepairAll = "repairall"; public const string CleanInventory = "inventoryclean"; public const string ExploreMap = "exploremap"; public const string ResetMap = "resetmap"; public const string RaiseSkill = "raiseskill"; public const string ResetSkill = "resetskill"; public const string KillAll = "killall"; public const string KillEnemies = "killenemies"; public const string KillTame = "killtame"; public const string Tame = "tame"; public const string Aggravate = "aggravate"; private static readonly HashSet Known = new HashSet(StringComparer.Ordinal) { "god", "ghost", "fly", "nocost", "heal", "die", "puke", "repairall", "inventoryclean", "exploremap", "resetmap", "raiseskill", "resetskill", "killall", "killenemies", "killtame", "tame", "aggravate" }; private static readonly HashSet RadiusActions = new HashSet(StringComparer.Ordinal) { "killall", "killenemies", "killtame", "tame", "aggravate" }; private static readonly HashSet SkillActions = new HashSet(StringComparer.Ordinal) { "raiseskill", "resetskill" }; public string Name => "player_action"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(string actionId, ZDOID target, int i, float f, string s) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_003c: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(actionId ?? string.Empty); val.Write(target); val.Write(i); val.Write(f); val.Write(s ?? string.Empty); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown targetPeerId = 0L; execArgs = null; error = null; string text = args.ReadString(); ZDOID characterZdoid = args.ReadZDOID(); int num = args.ReadInt(); float num2 = args.ReadSingle(); string text2 = args.ReadString(); if (!Known.Contains(text)) { error = "unknown action '" + text + "'"; return false; } if (RadiusActions.Contains(text)) { if (float.IsNaN(num2) || num2 <= 0f) { num2 = 20f; } num2 = Mathf.Clamp(num2, 1f, PluginConfig.ServerMaxActionRadius.Value); } if (SkillActions.Contains(text)) { if (string.IsNullOrEmpty(text2) || !IsValidSkill(text2)) { error = "unknown skill '" + text2 + "'"; return false; } if (text == "raiseskill") { num2 = Mathf.Clamp(float.IsNaN(num2) ? 1f : num2, -100f, 100f); } } if (!Targeting.Resolve(in ctx, characterZdoid, out targetPeerId, out error)) { return false; } execArgs = new ZPackage(); execArgs.Write(text); execArgs.Write(num); execArgs.Write(num2); execArgs.Write(text2 ?? string.Empty); return true; } public void Apply(ZPackage args) { //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_0307: 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_031c: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) string text = args.ReadString(); args.ReadInt(); float num = args.ReadSingle(); string text2 = args.ReadString(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || text == null) { return; } switch (text.Length) { case 3: switch (text[0]) { case 'g': if (text == "god") { localPlayer.SetGodMode(!((Character)localPlayer).InGodMode()); Toast(localPlayer, $"God mode: {((Character)localPlayer).InGodMode()}"); } break; case 'f': if (text == "fly") { localPlayer.ToggleDebugFly(); } break; case 'd': if (text == "die") { ((Character)localPlayer).Damage(new HitData { m_damage = { m_damage = 99999f }, m_hitType = (HitType)14 }); } break; case 'e': break; } break; case 4: switch (text[0]) { case 'h': if (text == "heal") { ((Character)localPlayer).Heal(((Character)localPlayer).GetMaxHealth(), true); ((Character)localPlayer).AddStamina(((Character)localPlayer).GetMaxStamina()); ((Character)localPlayer).AddEitr(((Character)localPlayer).GetMaxEitr()); Toast(localPlayer, "Healed"); } break; case 'p': if (text == "puke") { localPlayer.ClearFood(); Toast(localPlayer, "Stomach cleared"); } break; case 't': if (text == "tame") { Tameable.TameAllInArea(((Component)localPlayer).transform.position, num); Toast(localPlayer, "Tamed nearby creatures"); } break; } break; case 9: switch (text[0]) { case 'r': if (text == "repairall") { RepairWorn(localPlayer); } break; case 'a': if (text == "aggravate") { BaseAI.AggravateAllInArea(((Component)localPlayer).transform.position, num, (AggravatedReason)0); Toast(localPlayer, "Aggravated nearby creatures"); } break; } break; case 10: switch (text[1]) { case 'x': if (text == "exploremap" && (Object)(object)Minimap.instance != (Object)null) { Minimap.instance.ExploreAll(); Toast(localPlayer, "Map explored"); } break; case 'a': if (text == "raiseskill") { RaiseSkillAction(localPlayer, text2, num); } break; case 'e': if (text == "resetskill") { Skills skills = ((Character)localPlayer).GetSkills(); if (skills != null) { skills.CheatResetSkill(text2); } } break; } break; case 8: switch (text[0]) { case 'r': if (text == "resetmap" && (Object)(object)Minimap.instance != (Object)null) { Minimap.instance.Reset(); Toast(localPlayer, "Map exploration reset"); } break; case 'k': if (text == "killtame") { Toast(localPlayer, $"Removed {Sweep(((Component)localPlayer).transform.position, num, includeTamed: true, onlyTamed: true)} tame creatures"); } break; } break; case 5: if (text == "ghost") { localPlayer.SetGhostMode(!((Character)localPlayer).InGhostMode()); Toast(localPlayer, $"Ghost mode: {((Character)localPlayer).InGhostMode()}"); } break; case 6: if (text == "nocost") { localPlayer.SetNoPlacementCost(!localPlayer.PlacementCostDisabled); Toast(localPlayer, $"No build cost: {localPlayer.PlacementCostDisabled}"); } break; case 14: if (text == "inventoryclean") { ((Humanoid)localPlayer).DropInvalidItems(); Toast(localPlayer, "Dropped items on invalid slots"); } break; case 7: if (text == "killall") { Toast(localPlayer, $"Removed {Sweep(((Component)localPlayer).transform.position, num, includeTamed: true, onlyTamed: false)} creatures"); } break; case 11: if (text == "killenemies") { Toast(localPlayer, $"Removed {Sweep(((Component)localPlayer).transform.position, num, includeTamed: false, onlyTamed: false)} creatures"); } break; case 12: case 13: break; } } private static void RaiseSkillAction(Player player, string name, float amount) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_003c: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) Skills skills = ((Character)player).GetSkills(); if ((Object)(object)skills == (Object)null) { return; } SkillType result; if (string.Equals(name, "All", StringComparison.OrdinalIgnoreCase)) { foreach (SkillType value in Enum.GetValues(typeof(SkillType))) { if ((int)value != 0 && (int)value != 999) { Raise(skills, value, amount); } } Toast(player, $"All skills increased by {amount}"); } else if (Enum.TryParse(name, ignoreCase: true, out result) && (int)result != 0) { Raise(skills, result, amount); Toast(player, $"Skill increased {name}: {(int)skills.GetSkillLevel(result)}"); } } private static void Raise(Skills skills, SkillType type, float amount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) skills.GetSkillLevel(type); foreach (Skill skill in skills.GetSkillList()) { if (skill?.m_info != null && skill.m_info.m_skill == type) { skill.m_level = Mathf.Clamp(skill.m_level + amount, 0f, 100f); break; } } } private static void RepairWorn(Player player) { List list = new List(); ((Humanoid)player).GetInventory().GetWornItems(list); foreach (ItemData item in list) { item.m_durability = item.GetMaxDurability(); } Toast(player, $"Repaired {list.Count} items"); } private static int Sweep(Vector3 center, float radius, bool includeTamed, bool onlyTamed) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown int num = 0; foreach (Character item in new List(Character.GetAllCharacters())) { if (!((Object)(object)item == (Object)null) && !item.IsPlayer() && !((Object)(object)((Component)item).GetComponent() != (Object)null)) { bool flag = item.IsTamed(); if ((!onlyTamed || flag) && (!(!onlyTamed && flag) || includeTamed) && !(Vector3.Distance(center, ((Component)item).transform.position) > radius)) { item.Damage(new HitData(1E+10f)); num++; } } } return num; } private static bool IsValidSkill(string name) { if (string.Equals(name, "All", StringComparison.OrdinalIgnoreCase)) { return true; } string[] names = Enum.GetNames(typeof(SkillType)); foreach (string text in names) { if (text != "None" && string.Equals(text, name, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static void Toast(Player player, string message) { ((Character)player).Message((MessageType)1, message, 0, (Sprite)null, false); } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } [HarmonyPatch(typeof(Character), "RaiseSkill")] internal static class RaiseSkillPatch { private static bool Prefix(Character __instance) { if ((Object)(object)__instance != (Object)null && __instance.IsTamed()) { return !((Object)(object)((Component)__instance).GetComponent() == (Object)null); } return true; } } internal sealed class SpawnCreatureCommand : IAdminCommand { public const string CommandName = "spawn_creature"; private const float MaxHorizontal = 20000f; private const float MaxHealthOverride = 100000f; public string Name => "spawn_creature"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(string prefab, int count, int level, bool tamed, float health, float scatter, byte posMode, ZDOID anchor, Vector3 coords) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0032: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(prefab ?? string.Empty); val.Write(count); val.Write(level); val.Write(tamed); val.Write(health); val.Write(scatter); val.Write((int)posMode); val.Write(anchor); val.Write(coords); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) targetPeerId = 0L; execArgs = null; error = null; string text = args.ReadString(); int num = args.ReadInt(); int num2 = args.ReadInt(); bool flag = args.ReadBool(); float num3 = args.ReadSingle(); float num4 = args.ReadSingle(); AnchorMode anchorMode = (AnchorMode)args.ReadInt(); ZDOID val = args.ReadZDOID(); Vector3 val2 = args.ReadVector3(); ZNetScene instance = ZNetScene.instance; GameObject val3 = (((Object)(object)instance != (Object)null) ? instance.GetPrefab(text) : null); Character val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent() : null); if ((Object)(object)val4 == (Object)null) { error = "'" + text + "' is not a creature the server knows"; return false; } if (val4.m_boss && !PluginConfig.ServerAllowBossSpawn.Value) { error = "boss spawns are disabled on this server (Server/AllowBossSpawn)"; return false; } num = Mathf.Clamp(num, 1, PluginConfig.ServerMaxCreatureSpawn.Value); num2 = Mathf.Clamp(num2, 1, 9); num4 = Mathf.Clamp(float.IsNaN(num4) ? 0f : num4, 0f, 50f); num3 = ((num3 > 0f && !float.IsNaN(num3)) ? Mathf.Clamp(num3, 1f, 100000f) : 0f); Vector3 pos; if (anchorMode == AnchorMode.Target) { if (!Targeting.Resolve(in ctx, val, out targetPeerId, out error)) { return false; } if (!Targeting.RefPos(in ctx, val, out pos)) { error = "target player position is not available"; return false; } } else { targetPeerId = 0L; if (anchorMode == AnchorMode.Coords) { pos = val2; } else if (!Targeting.RefPos(in ctx, ZDOID.None, out pos)) { error = "your position is not available"; return false; } } if (!IsFinite(pos.x) || !IsFinite(pos.y) || !IsFinite(pos.z) || Mathf.Abs(pos.x) > 20000f || Mathf.Abs(pos.z) > 20000f || pos.y < -1000f || pos.y > 10000f) { error = "spawn position is out of bounds"; return false; } execArgs = new ZPackage(); execArgs.Write(text); execArgs.Write(num); execArgs.Write(num2); execArgs.Write(flag); execArgs.Write(num3); execArgs.Write(num4); execArgs.Write(pos); return true; } public void Apply(ZPackage args) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) string text = args.ReadString(); int num = args.ReadInt(); int num2 = args.ReadInt(); bool flag = args.ReadBool(); float num3 = args.ReadSingle(); float num4 = args.ReadSingle(); Vector3 val = args.ReadVector3(); ZNetScene instance = ZNetScene.instance; GameObject val2 = (((Object)(object)instance != (Object)null) ? instance.GetPrefab(text) : null); if ((Object)(object)val2 == (Object)null) { return; } int num5 = 0; for (int i = 0; i < num; i++) { Vector3 val3 = val + Vector3.up * 0.5f + ((num == 1) ? Vector3.zero : (Random.insideUnitSphere * num4)); GameObject obj = Object.Instantiate(val2, val3, Quaternion.identity); ZNetView component = obj.GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set(ZDOVars.s_cheated, true); } Character component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { if (num2 > 1) { component2.SetLevel(num2); } if (flag) { component2.SetTamed(true); } if (num3 > 0f) { component2.SetMaxHealth(num3); component2.SetHealth(num3); } } num5++; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, (num5 == 1) ? ("Spawned " + text) : $"Spawned {num5}x {text}", 0, (Sprite)null, false); } } private static bool IsFinite(float f) { if (!float.IsNaN(f)) { return !float.IsInfinity(f); } return false; } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class TeleportCommand : IAdminCommand { public const string CommandName = "teleport"; public const byte ModeCoords = 0; public const byte ModeToPlayer = 1; private const float MaxHorizontal = 20000f; private static readonly FieldInfo MaxAirAltitude = typeof(Character).GetField("m_maxAirAltitude", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo TeleportTimer = typeof(Player).GetField("m_teleportTimer", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo TeleportCooldown = typeof(Player).GetField("m_teleportCooldown", BindingFlags.Instance | BindingFlags.NonPublic); public string Name => "teleport"; public ExecutionSite Site => ExecutionSite.TargetClient; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) execArgs.SetPos(0); dest = execArgs.ReadVector3(); return true; } public static ZPackage BuildArgs(ZDOID subject, byte mode, Vector3 coords, ZDOID anchor, bool instant) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(subject); val.Write((int)mode); val.Write(coords); val.Write(anchor); val.Write(instant); return val; } public unsafe bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_000d: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) targetPeerId = 0L; execArgs = null; error = null; ZDOID characterZdoid = args.ReadZDOID(); int num = args.ReadInt(); Vector3 val = args.ReadVector3(); ZDOID anchor = args.ReadZDOID(); bool flag = args.ReadBool(); if (!Targeting.Resolve(in ctx, characterZdoid, out targetPeerId, out error)) { return false; } Vector3 pos; if (num == 1) { if (!Targeting.RefPos(in ctx, anchor, out pos)) { error = "target player position is not available"; return false; } ApplySpread((targetPeerId != 0L) ? targetPeerId.GetHashCode() : ((object)(*(ZDOID*)(&characterZdoid))/*cast due to .constrained prefix*/).GetHashCode(), PluginConfig.ServerTeleportSpread.Value, ref pos); } else { pos = val; } if (!IsFinite(pos.x) || !IsFinite(pos.y) || !IsFinite(pos.z) || Mathf.Abs(pos.x) > 20000f || Mathf.Abs(pos.z) > 20000f || pos.y < -1000f || pos.y > 10000f) { error = "destination is out of bounds"; return false; } execArgs = new ZPackage(); execArgs.Write(pos); execArgs.Write(flag); return true; } public void Apply(ZPackage args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = args.ReadVector3(); bool flag = args.ReadBool(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float num = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetSolidHeight(val, ref num, 1000) && val.y > num + 0.5f) { val.y = num + 0.5f; } bool flag2 = (Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(val); float num2 = default(float); bool flag3 = Vector3.Distance(((Component)localPlayer).transform.position, val) <= 96f && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val, ref num2); if (flag && (flag2 || flag3)) { Rigidbody component = ((Component)localPlayer).GetComponent(); if ((Object)(object)component != (Object)null) { component.linearVelocity = Vector3.zero; } ((Component)localPlayer).transform.position = val; MaxAirAltitude?.SetValue(localPlayer, val.y); if ((Object)(object)component != (Object)null) { Physics.SyncTransforms(); } if ((Object)(object)EnvMan.instance != (Object)null) { EnvMan.instance.ForceInstantEnvironmentSwitch(); } ((Character)localPlayer).ResetCloth(); ((Character)localPlayer).Message((MessageType)1, "Teleported", 0, (Sprite)null, false); } else { TeleportCooldown?.SetValue(localPlayer, 2f); if (!((Character)localPlayer).TeleportTo(val, ((Component)localPlayer).transform.rotation, true)) { ((Character)localPlayer).Message((MessageType)1, "Teleport busy, try again", 0, (Sprite)null, false); return; } TeleportTimer?.SetValue(localPlayer, 8.01f); ((Character)localPlayer).Message((MessageType)1, flag2 ? "Teleporting" : "Teleporting (far — loading screen)", 0, (Sprite)null, false); } ((MonoBehaviour)localPlayer).StartCoroutine(SuppressFallDamageUntilLanded(localPlayer)); } private static IEnumerator SuppressFallDamageUntilLanded(Player player) { float deadline = Time.time + 20f; while ((Object)(object)player != (Object)null && !((Character)player).IsOnGround() && Time.time < deadline) { MaxAirAltitude?.SetValue(player, ((Component)player).transform.position.y); yield return null; } } private static void ApplySpread(int seed, float radius, ref Vector3 dest) { if (!(radius <= 0f)) { float num = (float)(seed & 0xFFFF) / 65535f * (float)Math.PI * 2f; dest.x += Mathf.Cos(num) * radius; dest.z += Mathf.Sin(num) * radius; } } private static bool IsFinite(float f) { if (!float.IsNaN(f)) { return !float.IsInfinity(f); } return false; } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } internal sealed class WorldCommand : IAdminCommand { public const string CommandName = "world_state"; public const int OpSkipTime = 0; public const int OpSkipMorning = 1; public const int OpSetKey = 2; public const int OpRemoveKey = 3; private const float MaxSkipSeconds = 604800f; public string Name => "world_state"; public ExecutionSite Site => ExecutionSite.Server; public bool TryGetMoveDestination(ZPackage execArgs, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) dest = default(Vector3); return false; } public static ZPackage BuildArgs(int op, float f, string s) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(op); val.Write(f); val.Write(s ?? string.Empty); return val; } public bool Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown targetPeerId = 0L; execArgs = null; error = null; int num = args.ReadInt(); float num2 = args.ReadSingle(); string text = args.ReadString(); switch (num) { case 0: num2 = Mathf.Clamp(CmdValidate.Sane(num2, 0f), 0f, 604800f); break; case 2: case 3: if (!CmdValidate.IsIdentifier(text)) { error = "invalid global key name"; return false; } break; default: error = $"unknown world op {num}"; return false; case 1: break; } execArgs = new ZPackage(); execArgs.Write(num); execArgs.Write(num2); execArgs.Write(text ?? string.Empty); return true; } public void Apply(ZPackage args) { int num = args.ReadInt(); float num2 = args.ReadSingle(); string text = args.ReadString(); switch (num) { case 0: if ((Object)(object)ZNet.instance != (Object)null) { ZNet.instance.SetNetTime(ZNet.instance.GetTimeSeconds() + (double)num2); } break; case 1: if ((Object)(object)ZNet.instance != (Object)null && (Object)(object)EnvMan.instance != (Object)null) { double timeSeconds = ZNet.instance.GetTimeSeconds(); int day = EnvMan.instance.GetDay(timeSeconds); double morningStartSec = EnvMan.instance.GetMorningStartSec(day + 1); if (morningStartSec > timeSeconds) { ZNet.instance.SetNetTime(morningStartSec); } } break; case 2: { ZoneSystem instance2 = ZoneSystem.instance; if (instance2 != null) { instance2.SetGlobalKey(text); } break; } case 3: { ZoneSystem instance = ZoneSystem.instance; if (instance != null) { instance.RemoveGlobalKey(text); } break; } } } bool IAdminCommand.Validate(in AdminRequestContext ctx, ZPackage args, out long targetPeerId, out ZPackage execArgs, out string error) { return Validate(in ctx, args, out targetPeerId, out execArgs, out error); } } } namespace ValheimAdminForge.Catalog { internal static class CatalogLoc { public static string Resolve(string token) { if (string.IsNullOrEmpty(token)) { return string.Empty; } if (Localization.instance == null) { return token; } try { return Localization.instance.Localize(token); } catch (Exception) { return token; } } public static string ResolveOr(string token, string rawFallback) { string text = Resolve(token); if (Localization.instance != null && text.StartsWith("$", StringComparison.Ordinal)) { return rawFallback; } return text; } } internal static class CreatureCatalog { private static readonly LazyCatalog _cat = new LazyCatalog(Build); private static Dictionary _byPrefab; public static int Version => _cat.Version; public static IReadOnlyList Entries => _cat.Entries; public static void Invalidate() { _cat.Invalidate(); _byPrefab = null; } public static CreatureEntry ByPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } if (_byPrefab == null) { _byPrefab = new Dictionary(StringComparer.Ordinal); foreach (CreatureEntry entry in Entries) { _byPrefab[entry.PrefabName] = entry; } } _byPrefab.TryGetValue(prefabName, out var value); return value; } private static List Build() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return new List(); } List list = new List(); HashSet hashSet = new HashSet(StringComparer.Ordinal); foreach (GameObject prefab in instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && hashSet.Add(((Object)prefab).name)) { Character component = prefab.GetComponent(); if (!((Object)(object)component == (Object)null) && !(component is Player) && !string.IsNullOrEmpty(component.m_name)) { string displayName = CatalogLoc.ResolveOr(component.m_name, ((Object)prefab).name); list.Add(new CreatureEntry(prefab, component, displayName)); } } } list.Sort((CreatureEntry a, CreatureEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); return list; } public static void LogSummary() { IReadOnlyList entries = Entries; int num = entries.Count((CreatureEntry e) => e.IsVanilla); int num2 = entries.Count((CreatureEntry e) => e.IsBoss); Plugin.Log.LogInfo((object)$"CreatureCatalog: {entries.Count} creatures ({num} vanilla, {entries.Count - num} modded, {num2} bosses)"); string[] array = (from g in (from e in entries where !e.IsVanilla && !string.IsNullOrEmpty(e.ModName) group e by e.ModName).OrderBy, string>((IGrouping g) => g.Key, StringComparer.OrdinalIgnoreCase) select $"{g.Key} x{g.Count()}").ToArray(); Plugin.Log.LogInfo((object)((array.Length == 0) ? "CreatureCatalog: no modded creature could be attributed to a specific mod" : ("CreatureCatalog: attributed to " + string.Join(", ", array)))); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { [HarmonyPriority(0)] private static void Postfix() { CreatureCatalog.Invalidate(); JotunnAttribution.Invalidate(); if ((ZNetScene.instance?.m_prefabs?.Count).GetValueOrDefault() > 100) { try { CreatureCatalog.LogSummary(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("creature catalog summary failed: " + ex.Message)); } } } } internal sealed class CreatureEntry { public readonly GameObject Prefab; public readonly string PrefabName; public readonly string DisplayName; public readonly Faction Faction; public readonly bool IsBoss; public readonly bool IsTameable; public readonly float BaseHealth; public readonly bool IsVanilla; public readonly string ModName; public CreatureEntry(GameObject prefab, Character character, string displayName) { //IL_0032: 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) Prefab = prefab; PrefabName = ((Object)prefab).name; DisplayName = (string.IsNullOrEmpty(displayName) ? ((Object)prefab).name : displayName); Faction = character.m_faction; IsBoss = character.m_boss; IsTameable = (Object)(object)prefab.GetComponent() != (Object)null; BaseHealth = character.m_health; IsVanilla = VanillaSnapshot.IsVanillaCreature(((Object)prefab).name); ModName = (IsVanilla ? "" : ModAttribution.CreatureModName(((Object)prefab).name)); } } internal static class EventCatalog { private static readonly LazyCatalog _cat = new LazyCatalog(Build); private static Dictionary _byName; public static int Version => _cat.Version; public static IReadOnlyList Entries => _cat.Entries; public static void Invalidate() { _cat.Invalidate(); _byName = null; } public static EventEntry ByName(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (_byName == null) { _byName = new Dictionary(StringComparer.Ordinal); foreach (EventEntry entry in Entries) { _byName[entry.Name] = entry; } } _byName.TryGetValue(name, out var value); return value; } private static List Build() { RandEventSystem instance = RandEventSystem.instance; if ((Object)(object)instance == (Object)null || instance.m_events == null) { return new List(); } List list = new List(instance.m_events.Count); foreach (RandomEvent @event in instance.m_events) { if (@event != null && !string.IsNullOrEmpty(@event.m_name)) { list.Add(new EventEntry(@event)); } } list.Sort((EventEntry a, EventEntry b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); return list; } public static void LogSummary() { Plugin.Log.LogInfo((object)$"EventCatalog: {Entries.Count} random events"); } } [HarmonyPatch(typeof(RandEventSystem), "Awake")] internal static class RandEventSystemAwakePatch { [HarmonyPriority(0)] private static void Postfix() { EventCatalog.Invalidate(); try { EventCatalog.LogSummary(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("event catalog summary failed: " + ex.Message)); } } } internal sealed class EventEntry { public readonly string Name; public readonly string StartMessage; public readonly Biome Biome; public readonly float Duration; public readonly float Range; public readonly bool NearBaseOnly; public readonly string[] RequiredKeys; public readonly string[] Spawns; public EventEntry(RandomEvent ev) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Name = ev.m_name ?? string.Empty; StartMessage = CatalogLoc.Resolve(ev.m_startMessage); Biome = ev.m_biome; Duration = ev.m_duration; Range = ev.m_eventRange; NearBaseOnly = ev.m_nearBaseOnly; RequiredKeys = ((ev.m_requiredGlobalKeys != null) ? ev.m_requiredGlobalKeys.ToArray() : new string[0]); List list = new List(); if (ev.m_spawn != null) { foreach (SpawnData item in ev.m_spawn) { if (item != null && !((Object)(object)item.m_prefab == (Object)null)) { list.Add((item.m_groupSizeMax > 1) ? $"{((Object)item.m_prefab).name} x{item.m_groupSizeMax}" : ((Object)item.m_prefab).name); } } } Spawns = list.ToArray(); } } internal static class HarmonyPatchAttribution { [HarmonyPatch(typeof(FejdStartup), "Awake")] private static class EarlySetup { [HarmonyPriority(0)] private static void Postfix() { WrapAll(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ItemsSetup { [HarmonyPriority(800)] private static void Prefix(ObjectDB __instance) { _awakingDb = __instance; WrapAll(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class CreaturesSetup { [HarmonyPriority(800)] private static void Prefix(ZNetScene __instance) { _awakingScene = __instance; WrapAll(); } } private const string JotunnGuid = "com.jotunn.jotunn"; private static readonly Dictionary _itemOwners = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary _creatureOwners = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary _statusEffectOwners = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary _wrappedOwner = new Dictionary(); private static readonly Dictionary>> _before = new Dictionary>>(); private static readonly Dictionary>> _beforeEffects = new Dictionary>>(); private static Harmony _wrapper; private static ZNetScene _awakingScene; private static ObjectDB _awakingDb; private static List ScenePrefabs() { ZNetScene val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance : _awakingScene); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_prefabs; } private static ObjectDB Db() { if (!((Object)(object)ObjectDB.instance != (Object)null)) { return _awakingDb; } return ObjectDB.instance; } public static string ItemOwner(string prefabName) { if (string.IsNullOrEmpty(prefabName) || !_itemOwners.TryGetValue(prefabName, out var value)) { return null; } return value; } public static string CreatureOwner(string prefabName) { if (string.IsNullOrEmpty(prefabName) || !_creatureOwners.TryGetValue(prefabName, out var value)) { return null; } return value; } public static string StatusEffectOwner(string effectName) { if (string.IsNullOrEmpty(effectName) || !_statusEffectOwners.TryGetValue(effectName, out var value)) { return null; } return value; } private static void WrapAll() { WrapOtherPatches(typeof(ObjectDB), "Awake", isItems: true); WrapOtherPatches(typeof(ZNetScene), "Awake", isItems: false); } private static void WrapOtherPatches(Type targetType, string methodName, bool isItems) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null); Patches val = ((methodInfo != null) ? Harmony.GetPatchInfo((MethodBase)methodInfo) : null); if (val == null) { return; } _wrapper = (Harmony)(((object)_wrapper) ?? ((object)new Harmony("com.skitale.valheimadminforge.modattrib"))); HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatchAttribution), isItems ? "ItemWrapPrefix" : "CreatureWrapPrefix", (Type[])null, (Type[])null)); HarmonyMethod val3 = new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatchAttribution), isItems ? "ItemWrapPostfix" : "CreatureWrapPostfix", (Type[])null, (Type[])null)); foreach (Patch item in val.Prefixes.Concat(val.Postfixes)) { if (!(item.owner == "com.skitale.valheimadminforge") && !(item.owner == "com.jotunn.jotunn") && !(item.PatchMethod == null) && !_wrappedOwner.ContainsKey(item.PatchMethod)) { _wrappedOwner[item.PatchMethod] = ResolveModName(item.owner, item.PatchMethod); try { _wrapper.Patch((MethodBase)item.PatchMethod, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { Plugin.Log.LogDebug((object)("Admin Forge: couldn't wrap " + item.owner + "'s patch on " + targetType.Name + "." + methodName + ": " + ex.Message)); } } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Admin Forge: mod-attribution wrap setup failed for " + targetType.Name + "." + methodName + ": " + ex2.Message)); } } private static string ResolveModName(string owner, MethodBase patchMethod) { if (Chainloader.PluginInfos.TryGetValue(owner, out var value) && ((value != null) ? value.Metadata : null) != null) { return value.Metadata.Name; } Assembly assembly = patchMethod.DeclaringType?.Assembly; if (assembly != null) { foreach (PluginInfo value2 in Chainloader.PluginInfos.Values) { if ((Object)(object)((value2 != null) ? value2.Instance : null) != (Object)null && ((object)value2.Instance).GetType().Assembly == assembly) { return value2.Metadata.Name; } } } return null; } private static void ItemWrapPrefix(MethodBase __originalMethod) { ObjectDB val = Db(); Snapshot(__originalMethod, ((Object)(object)val != (Object)null) ? val.m_items : null); SnapshotEffects(__originalMethod, ((Object)(object)val != (Object)null) ? val.m_StatusEffects : null); } private static void ItemWrapPostfix(MethodBase __originalMethod) { ObjectDB val = Db(); Diff(__originalMethod, ((Object)(object)val != (Object)null) ? val.m_items : null, _itemOwners); DiffEffects(__originalMethod, ((Object)(object)val != (Object)null) ? val.m_StatusEffects : null, _statusEffectOwners); } private static void CreatureWrapPrefix(MethodBase __originalMethod) { Snapshot(__originalMethod, ScenePrefabs()); } private static void CreatureWrapPostfix(MethodBase __originalMethod) { Diff(__originalMethod, ScenePrefabs(), _creatureOwners); } private static void Snapshot(MethodBase originalMethod, List list) { HashSet item = ((list != null) ? new HashSet(list) : new HashSet()); if (!_before.TryGetValue(originalMethod, out var value)) { value = (_before[originalMethod] = new Stack>()); } value.Push(item); } private static void Diff(MethodBase originalMethod, List list, Dictionary owners) { if (!_before.TryGetValue(originalMethod, out var value) || value.Count == 0) { return; } HashSet hashSet = value.Pop(); if (list == null || !_wrappedOwner.TryGetValue(originalMethod, out var value2) || value2 == null) { return; } foreach (GameObject item in list) { if ((Object)(object)item != (Object)null && !hashSet.Contains(item)) { owners[((Object)item).name] = value2; } } } private static void SnapshotEffects(MethodBase originalMethod, List list) { HashSet item = ((list != null) ? new HashSet(list) : new HashSet()); if (!_beforeEffects.TryGetValue(originalMethod, out var value)) { value = (_beforeEffects[originalMethod] = new Stack>()); } value.Push(item); } private static void DiffEffects(MethodBase originalMethod, List list, Dictionary owners) { if (!_beforeEffects.TryGetValue(originalMethod, out var value) || value.Count == 0) { return; } HashSet hashSet = value.Pop(); if (list == null || !_wrappedOwner.TryGetValue(originalMethod, out var value2) || value2 == null) { return; } foreach (StatusEffect item in list) { if ((Object)(object)item != (Object)null && !hashSet.Contains(item)) { owners[((Object)item).name] = value2; } } } } internal static class ItemCatalog { private static readonly LazyCatalog _cat = new LazyCatalog(Build); private static Dictionary _byPrefab; public static int Version => _cat.Version; public static IReadOnlyList Entries => _cat.Entries; public static void Invalidate() { _cat.Invalidate(); _byPrefab = null; } public static ItemEntry ByPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } if (_byPrefab == null) { _byPrefab = new Dictionary(StringComparer.Ordinal); foreach (ItemEntry entry in Entries) { _byPrefab[entry.PrefabName] = entry; } } _byPrefab.TryGetValue(prefabName, out var value); return value; } private static List Build() { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null) { return new List(); } List list = new List(instance.m_items.Count); foreach (GameObject item in instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent(); if (!((Object)(object)component == (Object)null)) { SharedData val = component.m_itemData?.m_shared; if (val != null && val.m_icons != null && val.m_icons.Length != 0 && !string.IsNullOrEmpty(val.m_name) && (int)val.m_itemType != 0) { string displayName = CatalogLoc.ResolveOr(val.m_name, ((Object)item).name); string description = CatalogLoc.Resolve(val.m_description); list.Add(new ItemEntry(item, component, displayName, description)); } } } list.Sort((ItemEntry a, ItemEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); return list; } public static void LogSummary() { ManualLogSource log = Plugin.Log; IReadOnlyList entries = Entries; int num = entries.Count((ItemEntry e) => e.Origin == ItemOrigin.Vanilla); int num2 = entries.Count((ItemEntry e) => e.Origin == ItemOrigin.Modded); log.LogInfo((object)$"ItemCatalog: {entries.Count} spawnable items ({num} vanilla, {num2} modded)"); foreach (IGrouping item in from e in entries group e by e.Category into g orderby g.Key.ToString() select g) { log.LogDebug((object)$" {item.Key}: {item.Count()}"); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDbAwakePatch { [HarmonyPriority(0)] private static void Postfix() { ItemCatalog.Invalidate(); StatusEffectCatalog.Invalidate(); JotunnAttribution.Invalidate(); if ((ObjectDB.instance?.m_items?.Count).GetValueOrDefault() > 200) { try { ItemCatalog.LogSummary(); StatusEffectCatalog.LogSummary(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("catalog summary failed: " + ex.Message)); } } } } internal enum ItemOrigin { Vanilla, Modded } internal enum ItemCategory { Weapons, Armor, Food, Resources, Other } internal sealed class ItemEntry { public readonly GameObject Prefab; public readonly string PrefabName; public readonly string DisplayName; public readonly string Description; public readonly Sprite Icon; public readonly ItemType ItemType; public readonly ItemCategory Category; public readonly ItemOrigin Origin; public readonly string ModName; public readonly int MaxStackSize; public readonly int MaxQuality; public readonly float Weight; public readonly int Value; public readonly bool IsTeleportable; public ItemEntry(GameObject prefab, ItemDrop itemDrop, string displayName, string description) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) SharedData shared = itemDrop.m_itemData.m_shared; Prefab = prefab; PrefabName = ((Object)prefab).name; DisplayName = (string.IsNullOrEmpty(displayName) ? ((Object)prefab).name : displayName); Description = description ?? string.Empty; Icon = ((shared.m_icons != null && shared.m_icons.Length != 0) ? shared.m_icons[0] : null); ItemType = shared.m_itemType; Category = Categorize(shared.m_itemType); Origin = ((!VanillaSnapshot.IsVanilla(((Object)prefab).name)) ? ItemOrigin.Modded : ItemOrigin.Vanilla); ModName = ((Origin == ItemOrigin.Modded) ? ModAttribution.ItemModName(((Object)prefab).name) : ""); MaxStackSize = Mathf.Max(1, shared.m_maxStackSize); MaxQuality = Mathf.Max(1, shared.m_maxQuality); Weight = shared.m_weight; Value = shared.m_value; IsTeleportable = shared.m_teleportable; } public static ItemCategory Categorize(ItemType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected I4, but got Unknown switch (type - 1) { case 2: case 3: case 13: case 14: case 19: case 21: return ItemCategory.Weapons; case 4: case 5: case 6: case 10: case 11: case 16: case 17: case 23: return ItemCategory.Armor; case 1: case 20: return ItemCategory.Food; case 0: case 8: case 22: return ItemCategory.Resources; default: return ItemCategory.Other; } } } internal static class JotunnAttribution { private const string JotunnGuid = "com.jotunn.jotunn"; private static Dictionary _items; private static Dictionary _creatures; private static Dictionary _statusEffects; private static Dictionary Items => _items ?? (_items = Build("GetItems", "ItemPrefab")); private static Dictionary Creatures => _creatures ?? (_creatures = Build("GetCreatures", "Prefab")); private static Dictionary StatusEffects => _statusEffects ?? (_statusEffects = Build("GetStatusEffects", "StatusEffect")); public static void Invalidate() { _items = null; _creatures = null; _statusEffects = null; } public static (string Guid, string Name)? ItemOwner(string prefabName) { return Lookup(Items, prefabName); } public static (string Guid, string Name)? CreatureOwner(string prefabName) { return Lookup(Creatures, prefabName); } public static (string Guid, string Name)? StatusEffectOwner(string effectName) { return Lookup(StatusEffects, effectName); } private static (string, string)? Lookup(Dictionary map, string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } if (!map.TryGetValue(prefabName, out var value)) { return null; } return value; } private static Dictionary Build(string registryGetterName, string prefabPropertyName) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); try { if (!Chainloader.PluginInfos.ContainsKey("com.jotunn.jotunn")) { return dictionary; } if (!(((AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Jotunn")?.GetType("Jotunn.Utils.ModRegistry"))?.GetMethod(registryGetterName, BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null))?.Invoke(null, null) is IEnumerable enumerable)) { return dictionary; } PropertyInfo propertyInfo = null; PropertyInfo propertyInfo2 = null; foreach (object item in enumerable) { if (item == null) { continue; } Type type = item.GetType(); if (propertyInfo == null || propertyInfo.DeclaringType != type) { propertyInfo = type.GetProperty(prefabPropertyName); } if (propertyInfo2 == null) { propertyInfo2 = type.GetProperty("SourceMod") ?? propertyInfo2; } object? obj = propertyInfo?.GetValue(item); Object val = (Object)((obj is Object) ? obj : null); if (val != null && !(val == (Object)null)) { object? obj2 = propertyInfo2?.GetValue(item); BepInPlugin val2 = (BepInPlugin)((obj2 is BepInPlugin) ? obj2 : null); if (val2 != null) { dictionary[val.name] = (val2.GUID, val2.Name); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Admin Forge: Jotunn mod-attribution lookup (" + registryGetterName + ") failed: " + ex.Message)); dictionary.Clear(); } return dictionary; } } internal sealed class LazyCatalog { private readonly Func> _build; private List _entries; public int Version { get; private set; } public IReadOnlyList Entries => _entries ?? (_entries = _build()); public LazyCatalog(Func> build) { _build = build; } public void Invalidate() { _entries = null; Version++; } } internal static class ModAttribution { public static string ItemModName(string prefabName) { return JotunnAttribution.ItemOwner(prefabName)?.Name ?? HarmonyPatchAttribution.ItemOwner(prefabName) ?? ""; } public static string CreatureModName(string prefabName) { return JotunnAttribution.CreatureOwner(prefabName)?.Name ?? HarmonyPatchAttribution.CreatureOwner(prefabName) ?? ""; } public static string StatusEffectModName(string effectName) { return JotunnAttribution.StatusEffectOwner(effectName)?.Name ?? HarmonyPatchAttribution.StatusEffectOwner(effectName) ?? ""; } } internal static class ModAttributionDiagnostic { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ItemsPatch { private static void Prefix() { if (!_itemsLogged) { _itemsLogged = true; LogPatchOwners(typeof(ObjectDB), "Awake"); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class CreaturesPatch { private static void Prefix() { if (!_creaturesLogged) { _creaturesLogged = true; LogPatchOwners(typeof(ZNetScene), "Awake"); } } } private static bool _itemsLogged; private static bool _creaturesLogged; private static void LogPatchOwners(Type type, string methodName) { MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); Patches val = ((methodInfo != null) ? Harmony.GetPatchInfo((MethodBase)methodInfo) : null); if (val == null) { Plugin.Log.LogInfo((object)("Admin Forge: mod-attribution check — nothing patches " + type.Name + "." + methodName)); return; } string[] array = (from p in val.Prefixes.Concat(val.Postfixes).Concat(val.Transpilers).Concat(val.Finalizers) select p.owner).Distinct().OrderBy((string o) => o, StringComparer.Ordinal).ToArray(); Plugin.Log.LogInfo((object)((array.Length == 0) ? ("Admin Forge: mod-attribution check — " + type.Name + "." + methodName + " has patch entries but no owners?") : ("Admin Forge: mod-attribution check — " + type.Name + "." + methodName + " patched by: " + string.Join(", ", array)))); } } internal sealed class PlayerRef { public readonly string Name; public readonly ZDOID CharacterId; public readonly Vector3 Position; public readonly bool PositionKnown; public readonly bool IsSelf; public PlayerRef(string name, ZDOID characterId, Vector3 position, bool positionKnown, bool isSelf) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Name = name; CharacterId = characterId; Position = position; PositionKnown = positionKnown; IsSelf = isSelf; } } internal static class PlayerRoster { private const float RefreshInterval = 1f; private static readonly List _players = new List(); private static float _lastRefresh = -999f; public static IReadOnlyList Players { get { if (Time.realtimeSinceStartup - _lastRefresh > 1f) { Rebuild(); } return _players; } } private static void Rebuild() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) _lastRefresh = Time.realtimeSinceStartup; _players.Clear(); ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return; } ZDOID val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Character)Player.m_localPlayer).GetZDOID() : ZDOID.None); List playerList = instance.GetPlayerList(); if (playerList == null) { return; } foreach (PlayerInfo item in playerList) { bool flag = !((ZDOID)(ref val)).IsNone() && item.m_characterID == val; Vector3 position = ((flag && (Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : item.m_position); bool positionKnown = flag || item.m_publicPosition; _players.Add(new PlayerRef(item.m_name, item.m_characterID, position, positionKnown, flag)); } } } internal sealed class StatusEffectEntry { public readonly int NameHash; public readonly string InternalName; public readonly string DisplayName; public readonly string Category; public readonly string Tooltip; public readonly Sprite Icon; public readonly float Ttl; public readonly bool IsVanilla; public readonly string ModName; public StatusEffectEntry(StatusEffect se, string displayName, string tooltip) { NameHash = se.NameHash(); InternalName = se.m_name ?? string.Empty; DisplayName = (string.IsNullOrEmpty(displayName) ? InternalName : displayName); Category = se.m_category ?? string.Empty; Tooltip = tooltip ?? string.Empty; Icon = se.m_icon; Ttl = se.m_ttl; IsVanilla = VanillaSnapshot.IsVanillaStatusEffect(((Object)se).name); ModName = (IsVanilla ? "" : ModAttribution.StatusEffectModName(((Object)se).name)); } } internal static class StatusEffectCatalog { private static readonly LazyCatalog _cat = new LazyCatalog(Build); private static Dictionary _byHash; public static int Version => _cat.Version; public static IReadOnlyList Entries => _cat.Entries; public static void Invalidate() { _cat.Invalidate(); _byHash = null; } public static StatusEffectEntry ByHash(int nameHash) { if (_byHash == null) { _byHash = new Dictionary(); foreach (StatusEffectEntry entry in Entries) { _byHash[entry.NameHash] = entry; } } _byHash.TryGetValue(nameHash, out var value); return value; } private static List Build() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_StatusEffects == null) { return new List(); } HashSet hashSet = new HashSet(); List list = new List(instance.m_StatusEffects.Count); foreach (StatusEffect statusEffect in instance.m_StatusEffects) { if (!((Object)(object)statusEffect == (Object)null) && !string.IsNullOrEmpty(statusEffect.m_name)) { int item = statusEffect.NameHash(); if (hashSet.Add(item)) { string displayName = CatalogLoc.ResolveOr(statusEffect.m_name, statusEffect.m_name); list.Add(new StatusEffectEntry(statusEffect, displayName, CatalogLoc.Resolve(statusEffect.m_tooltip))); } } } list.Sort((StatusEffectEntry a, StatusEffectEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); return list; } public static void LogSummary() { Plugin.Log.LogInfo((object)$"StatusEffectCatalog: {Entries.Count} effects"); } } internal static class VanillaSnapshot { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ItemsPatch { [HarmonyPriority(800)] private static void Prefix(ObjectDB __instance) { if (__instance.m_items != null) { foreach (GameObject item in __instance.m_items) { if ((Object)(object)item != (Object)null) { _items.Add(((Object)item).name); } } } if (__instance.m_StatusEffects == null) { return; } foreach (StatusEffect statusEffect in __instance.m_StatusEffects) { if ((Object)(object)statusEffect != (Object)null) { _statusEffects.Add(((Object)statusEffect).name); } } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class CreaturesPatch { [HarmonyPriority(800)] private static void Prefix(ZNetScene __instance) { if (__instance.m_prefabs == null) { return; } foreach (GameObject prefab in __instance.m_prefabs) { if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent() != (Object)null) { _creatures.Add(((Object)prefab).name); } } } } private static readonly HashSet _items = new HashSet(); private static readonly HashSet _creatures = new HashSet(); private static readonly HashSet _statusEffects = new HashSet(); public static int Count => _items.Count; public static int CreatureCount => _creatures.Count; public static bool IsVanilla(string prefabName) { return _items.Contains(prefabName); } public static bool IsVanillaCreature(string prefabName) { return _creatures.Contains(prefabName); } public static bool IsVanillaStatusEffect(string effectName) { return _statusEffects.Contains(effectName); } } }