Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimAdminForge v0.4.0
ValheimAdminForge.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
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<ItemDrop>(); 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<KeyboardShortcut> ToggleKey; public static ConfigEntry<int> MaxQuantity; public static ConfigEntry<bool> AllowNonAdminWindow; public static ConfigEntry<int> WindowWidth; public static ConfigEntry<int> WindowHeight; public static ConfigEntry<float> WindowOpacity; public static ConfigEntry<string> WindowTextColor; public static ConfigEntry<string> WindowDimTextColor; public static ConfigEntry<int> ServerMaxQuantity; public static ConfigEntry<bool> ServerStrictItemCheck; public static ConfigEntry<float> ServerMaxActionRadius; public static ConfigEntry<int> ServerMaxCreatureSpawn; public static ConfigEntry<bool> ServerAllowBossSpawn; public static ConfigEntry<float> ServerMaxDespawnRadius; public static ConfigEntry<bool> ServerPlayerTags; public static ConfigEntry<float> 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<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)277, Array.Empty<KeyCode>()), "Opens/closes the Admin Forge window."); MaxQuantity = cfg.Bind<int>("General", "MaxQuantity", 100, new ConfigDescription("Upper bound for the quantity field.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 9999), Array.Empty<object>())); AllowNonAdminWindow = cfg.Bind<bool>("General", "AllowNonAdminWindow", false, "Let non-admins open the window anyway (every action is still refused by the server)."); WindowWidth = cfg.Bind<int>("Window", "Width", 640, new ConfigDescription("Admin Forge window width in pixels. Below ~560 the wider tabs (Creatures, World) clip.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(560, 3000), Array.Empty<object>())); WindowHeight = cfg.Bind<int>("Window", "Height", 720, new ConfigDescription("Admin Forge window height in pixels. Below ~560 the tab content overflows the window.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(560, 2000), Array.Empty<object>())); WindowOpacity = cfg.Bind<float>("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<float>(0.2f, 1f), Array.Empty<object>())); WindowTextColor = cfg.Bind<string>("Window", "TextColor", "#000000", "Primary text color as a hex string, e.g. #000000. Falls back to the default if unparsable."); WindowDimTextColor = cfg.Bind<string>("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<int>("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<int>(1, 100000), Array.Empty<object>())); ServerStrictItemCheck = cfg.Bind<bool>("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<float>("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<float>(5f, 500f), Array.Empty<object>())); ServerMaxCreatureSpawn = cfg.Bind<int>("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<int>(1, 200), Array.Empty<object>())); ServerAllowBossSpawn = cfg.Bind<bool>("Server", "AllowBossSpawn", false, "Allow spawning creatures flagged as bosses. Off by default — a stray Moder on a base ruins a server."); ServerMaxDespawnRadius = cfg.Bind<float>("Server", "MaxDespawnRadius", 100f, new ConfigDescription("Hard cap (metres) the server enforces on the Creatures-tab despawn / cleanup sweep.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 500f), Array.Empty<object>())); ServerPlayerTags = cfg.Bind<bool>("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<float>("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<float>(0f, 10f), Array.Empty<object>())); } } } 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<string> 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<string, IAdminCommand> _commands = new Dictionary<string, IAdminCommand>(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<long, RateWindow> _rate = new Dictionary<long, RateWindow>(); private static float _lastRatePrune; private static readonly List<GhostDrop> _pendingGhostDrops = new List<GhostDrop>(); private const float GhostDropDelay = 3f; private static readonly HashSet<string> _quietOnSuccess = new HashSet<string>(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<ZRpc, ZPackage> Safe(string name, Action<ZRpc, ZPackage> 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<long> list = new List<long>(); foreach (KeyValuePair<long, RateWindow> 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<ZPackage>("VAF_Request", AdminRpc.Safe("VAF_Request", AdminRpc.OnRequest)); peer.m_rpc.Register<ZPackage>("VAF_Hello", AdminRpc.Safe("VAF_Hello", AdminRpc.OnHello)); return; } peer.m_rpc.Register<ZPackage>("VAF_Exec", AdminRpc.Safe("VAF_Exec", AdminRpc.OnExec)); peer.m_rpc.Register<ZPackage>("VAF_Response", AdminRpc.Safe("VAF_Response", AdminRpc.OnResponse)); peer.m_rpc.Register<ZPackage>("VAF_AdminStatus", AdminRpc.Safe("VAF_AdminStatus", AdminRpc.OnAdminStatus)); peer.m_rpc.Register<ZPackage>("VAF_DropGhost", AdminRpc.Safe("VAF_DropGhost", AdminRpc.OnDropGhost)); peer.m_rpc.Register<ZPackage>("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<string, Tag> _byId = new Dictionary<string, Tag>(StringComparer.Ordinal); private static DateTime _fileStamp = DateTime.MinValue; private static string _lastSignature; private static readonly Dictionary<ZDOID, Tag> _clientTags = new Dictionary<ZDOID, Tag>(); 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<KeyValuePair<ZDOID, Tag>> list = new List<KeyValuePair<ZDOID, Tag>>(); 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<ZDOID, Tag>(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<ZDOID, Tag>(((Character)Player.m_localPlayer).GetZDOID(), value2)); } } StringBuilder stringBuilder = new StringBuilder(); ZPackage val = new ZPackage(); val.Write(list.Count); foreach (KeyValuePair<ZDOID, Tag> 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<string, Tag> 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 = "<color=" + tag.Color + ">[" + tag.Text + "]</color> " + __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 = "<color=orange>"; 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<string> { Count: not 0 } list) { int index = list.Count - 1; string value = "<color=" + tag.Color + ">[" + tag.Text + "]</color> "; int num = list[index].IndexOf("<color=orange>", StringComparison.Ordinal); if (num >= 0 && !list[index].Contains(value)) { list[index] = list[index].Insert(num + "<color=orange>".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<Type>(); if ((int)value != 2 && (int)value != 3) { return; } UserInfo value2 = val.Field("m_userInfo").GetValue<UserInfo>(); 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>(); string text = "<color=" + tag.Color + ">[" + tag.Text + "]</color> "; 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<PlayerInfo> 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<GUISkin> _staleSkins = new List<GUISkin>(); 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<GUISkin>(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<GUILayoutOption>()); 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<GUILayoutOption>()); 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<string>(); 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<CreatureEntry> _list = new FilteredList<CreatureEntry>(); 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<GUILayoutOption>()); 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<CreatureEntry> entries = CreatureCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<GUILayoutOption>()); 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<CreatureEntry> entries2 = entries; string filter = (_search ?? "").Trim(); string cacheKey = $"{CreatureCatalog.Version}|{originIdx}|{_modFilter}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List<CreatureEntry> m) { Fill(entries2, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries2.Count} creatures", Array.Empty<GUILayoutOption>()); ScrollList.Draw(_list.Matches, 30f, TabLayout.ListHeight(474f), ref _list.Scroll, DrawRow); DrawDetailPanel(); DrawDespawnBlock(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList<CreatureEntry> 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, string>((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<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("<b>Despawn</b> 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<GUILayoutOption>()); 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<GUILayoutOption>()); _despFish = GUILayout.Toggle(_despFish, new GUIContent(" fish", "Also remove fish."), Array.Empty<GUILayoutOption>()); _despBirds = GUILayout.Toggle(_despBirds, new GUIContent(" birds", "Also remove birds."), Array.Empty<GUILayoutOption>()); 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 ? " · <b>BOSS</b>" : ""); if (GUILayout.Button($"{e.DisplayName} <color={GuiStyles.DimColor}>{text} · {e.Faction} · {e.BaseHealth:0} hp{text2}</color>", 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<GUILayoutOption>()); } else { GUILayout.Label("<b>" + creatureEntry.DisplayName + "</b> <color=" + GuiStyles.DimColor + ">" + creatureEntry.PrefabName + "</color>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); 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<GUILayoutOption>()); 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<CreatureEntry> entries, string filter, List<CreatureEntry> 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<string>(); private static int _modNamesVersion = -1; private static readonly ModFilterRow _modPicker = new ModFilterRow(); private static readonly FilteredList<StatusEffectEntry> _list = new FilteredList<StatusEffectEntry>(); public static void Draw() { _list.BeginFrame(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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("<color=" + GuiStyles.DimColor + ">Dur 0 = effect default. Power > 0 needed for Poison / Burning / Frost to deal damage.</color>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<StatusEffectEntry> entries = StatusEffectCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); TargetSelector.Draw(); GUILayout.EndHorizontal(); string filter = (_search ?? "").Trim(); string cacheKey = $"{StatusEffectCatalog.Version}|{originIdx}|{_modFilter}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List<StatusEffectEntry> m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} effects", Array.Empty<GUILayoutOption>()); ScrollList.Draw(_list.Matches, 34f, TabLayout.ListHeight(423f), ref _list.Scroll, DrawRow); DrawDetailPanel(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList<StatusEffectEntry> 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, string>((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 + " <color=" + GuiStyles.DimColor + ">" + text + " · " + e.InternalName + text2 + "</color>", 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<GUILayoutOption>()); } else { GUILayout.Label("<b>" + statusEffectEntry.DisplayName + "</b> <color=" + GuiStyles.DimColor + ">" + statusEffectEntry.InternalName + "</color>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); if (!string.IsNullOrEmpty(statusEffectEntry.Tooltip)) { GUILayout.Label(statusEffectEntry.Tooltip, GuiStyles.Info, Array.Empty<GUILayoutOption>()); } 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<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<StatusEffectEntry> entries, string filter, List<StatusEffectEntry> 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<EventEntry> _list = new FilteredList<EventEntry>(); public static void Draw() { _list.BeginFrame(); DrawActiveHeader(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<EventEntry> entries = EventCatalog.Entries; string filter = (_search ?? "").Trim(); string cacheKey = $"{EventCatalog.Version}|{filter.ToLowerInvariant()}"; if (_list.KeyChanged(cacheKey)) { _list.Rebuild(delegate(List<EventEntry> m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} events", Array.Empty<GUILayoutOption>()); 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<GUILayoutOption>()); RandEventSystem instance = RandEventSystem.instance; RandomEvent val = (((Object)(object)instance != (Object)null) ? instance.GetCurrentRandomEvent() : null); GUILayout.Label((val == null) ? "<b>No event running.</b>" : $"<b>Active:</b> {val.m_name} <color={GuiStyles.DimColor}>{val.m_biome} · {val.m_duration:0}s</color>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); 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} <color={GuiStyles.DimColor}>{e.Biome} · {e.Duration:0}s</color>", 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<GUILayoutOption>()); } else { GUILayout.Label("<b>" + eventEntry.Name + "</b>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); if (!string.IsNullOrEmpty(eventEntry.StartMessage)) { GUILayout.Label("<color=" + GuiStyles.DimColor + ">“" + eventEntry.StartMessage + "”</color>", GuiStyles.Info, Array.Empty<GUILayoutOption>()); } 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<GUILayoutOption>()); if (eventEntry.RequiredKeys.Length != 0) { GUILayout.Label("Requires keys: " + FormatKeys(eventEntry.RequiredKeys), GuiStyles.Info, Array.Empty<GUILayoutOption>()); } if (eventEntry.Spawns.Length != 0) { GUILayout.Label("Spawns: " + string.Join(", ", eventEntry.Spawns), GuiStyles.Info, Array.Empty<GUILayoutOption>()); } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<string> list = new List<string>(keys.Length); foreach (string text in keys) { bool flag = (Object)(object)instance != (Object)null && instance.GetGlobalKey(text); list.Add(flag ? text : ("<color=#C04040>" + text + " (missing)</color>")); } return string.Join(", ", list.ToArray()); } private static void StartRandomFromList() { IReadOnlyList<EventEntry> 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<EventEntry> entries, string filter, List<EventEntry> 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<T> { private readonly List<T> _matches = new List<T>(); private string _key; private bool _pendingScrollReset; public Vector2 Scroll; public IReadOnlyList<T> 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<List<T>> 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<MethodBase> 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<MethodBase> 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<string>(); private static int _modNamesVersion = -1; private static readonly ModFilterRow _modPicker = new ModFilterRow(); private static readonly FilteredList<ItemEntry> _list = new FilteredList<ItemEntry>(); public static void Draw() { _list.BeginFrame(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<ItemEntry> entries = ItemCatalog.Entries; if (originIdx == 2) { DrawModRow(entries); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); 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<ItemEntry> m) { Fill(entries, filter, m); }); } GUILayout.Label($"{_list.Count} / {entries.Count} items", Array.Empty<GUILayoutOption>()); ScrollList.Draw(_list.Matches, 34f, TabLayout.ListHeight(438f), ref _list.Scroll, DrawRow); DrawDetailPanel(); _originIdx = originIdx2; } private static void DrawModRow(IReadOnlyList<ItemEntry> 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, string>((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