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 AdminManager v1.0.2
AdminManager\AdminManager.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using AdminManager.Patches; using AdminManager.UI; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [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("AdminManager")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("AdminManager")] [assembly: AssemblyTitle("AdminManager")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } } namespace AdminManager { [BepInPlugin("adminmanager", "Admin Manager", "1.0.2")] public class Plugin : BaseUnityPlugin { private sealed class InvisibleVisual { public Player Player; public readonly Dictionary<Renderer, bool> Renderers = new Dictionary<Renderer, bool>(); public readonly Dictionary<Light, bool> Lights = new Dictionary<Light, bool>(); public readonly Dictionary<AudioSource, float> Sounds = new Dictionary<AudioSource, float>(); } private sealed class ClientGate { public ZNet Net; public ZNetPeer Peer; public string Nonce; public bool Required; public bool Verified; public bool Rejected; public bool Admitted; public ZPackage Pending; public float Deadline; public float DisconnectAt; } private sealed class KnownPlayer { public long Id; public string Name; public string Host; public long LastSeen; public bool Online; } private sealed class PendingTeleport { public long Requester; public long Peer; public string Description; public float Expires; } private sealed class OwnedFreeze { public Player Player; public Rigidbody Body; public RigidbodyConstraints Constraints; public Vector3 Position; public Quaternion Rotation; } private sealed class FreezeRequest { public long Owner; public long Requester; public bool Frozen; public bool Confirmed; public float Expires; } private sealed class ItemToken { public ZDOID Character; public Inventory Inventory; public ItemData Item; public string Fingerprint; public float Expires; } private sealed class InventoryAccess { public ZDOID Character; public int ClientRequest; public float Expires; public readonly HashSet<string> Tokens = new HashSet<string>(); } private sealed class ItemOperation { public long Requester; public long Owner; public int ClientRequest; public float Expires; } private sealed class InventoryEntry { public string Prefab; public string Name; public int Stack; public int X; public int Y; public bool Equipped; public string Token = ""; } private sealed class InventorySnapshot { public int Width; public int Height; public readonly List<InventoryEntry> Items = new List<InventoryEntry>(); } private sealed class InventoryRequest { public long Requester; public int ClientRequest; public ZDOID Character; public long Peer; public float Expires; } private sealed class PlayerPanelAction { public string Label; public Action Run; public bool Enabled; public bool Active; public string Icon; public PlayerPanelAction(string label, Action run, bool enabled = true, bool active = false, string icon = null) { Label = label; Run = run; Enabled = enabled; Active = active; Icon = icon; } } private sealed class CardDef { public readonly string Label; public readonly string Command; public readonly Func<bool> State; public readonly bool Toggle; public readonly string Perm; public CardDef(string label, string command, Func<bool> state, bool toggle, string perm) { Label = label; Command = command; State = state; Toggle = toggle; Perm = perm; } } private sealed class QuarantinePending { public long Requester; public bool Active; public float Expires; } private sealed class QuarantineSnapshot { public int Revision; public bool Local; public readonly HashSet<ZDOID> Characters = new HashSet<ZDOID>(); public readonly HashSet<long> Profiles = new HashSet<long>(); } private sealed class ChickenVisual { public Player Player; public GameObject Model; public Animator Animator; public readonly Dictionary<Renderer, bool> Hidden = new Dictionary<Renderer, bool>(); public readonly List<int> SpeedParameters = new List<int>(); } private sealed class ResourceState { public long Peer; public int CarryMode; public float Capacity; public bool UnlimitedStamina; } private sealed class WorldChoice { public string Id; public string Name; public string[] Keys = Array.Empty<string>(); } private sealed class WorldSetting { public string Id; public string Name; public string Default; public string Current; public List<WorldChoice> Choices = new List<WorldChoice>(); } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__11_0; public static Predicate<PlayerInfo> <>9__27_0; public static Func<KeyValuePair<string, List<long>>, string> <>9__37_0; public static Func<long, string> <>9__37_1; public static Func<char, bool> <>9__55_0; public static Comparison<KnownPlayer> <>9__103_0; public static Comparison<KnownPlayer> <>9__119_0; public static Func<bool> <>9__301_6; public static Func<string, string> <>9__429_0; public static Predicate<ZDOID> <>9__440_0; public static Func<WorldChoice, IEnumerable<string>> <>9__512_0; public static Func<string, string> <>9__513_1; public static Func<string, string> <>9__513_2; public static Func<string, string> <>9__514_0; public static Func<string, string> <>9__514_4; public static Predicate<string> <>9__514_1; public static Func<WorldSetting, IEnumerable<string>> <>9__515_3; public static Func<string, string> <>9__515_1; public static Func<string, string> <>9__515_2; public static Func<string, bool> <>9__519_0; public static Func<string, string> <>9__519_1; public static Func<KeyValuePair<string, string>, string> <>9__528_0; public static Func<WorldChoice, bool> <>9__535_1; public static Func<WorldChoice, bool> <>9__535_2; internal void <InitializeInvisibility>b__11_0(ConsoleEventArgs args) { if (args.Length != 1) { args.Context.AddString("Usage: aminvisible"); } else if ((Object)(object)m_instance != (Object)null) { m_instance.RequestInvisibility(); } } internal bool <InvisibleMapPostfix>b__27_0(PlayerInfo p) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) return m_instance.m_invisibleCharacters.Contains(p.m_characterID); } internal string <SerializeChickenEggTimes>b__37_0(KeyValuePair<string, List<long>> e) { return e.Key; } internal string <SerializeChickenEggTimes>b__37_1(long t) { return t.ToString(CultureInfo.InvariantCulture); } internal bool <ValidBuildFingerprint>b__55_0(char c) { if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) { if (c >= 'A') { return c <= 'F'; } return false; } return true; } internal int <DrawOnlineTeleportSelector>b__103_0(KnownPlayer a, KnownPlayer b) { return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase); } internal int <DrawOfflineTab>b__119_0(KnownPlayer a, KnownPlayer b) { return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase); } internal bool <DrawCommandGrid>b__301_6() { return InvisibleCharacter((Character)(object)Player.m_localPlayer); } internal string <SerializeQuarantineAccounts>b__429_0(string a) { return a; } internal bool <BroadcastQuarantine>b__440_0(ZDOID id) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance != null) { return ZDOMan.instance.GetZDO(id) == null; } return true; } internal IEnumerable<string> <ManagedWorldKeys>b__512_0(WorldChoice c) { return c.Keys; } internal string <DetectWorldChoice>b__513_1(string k) { return k.ToLowerInvariant(); } internal string <DetectWorldChoice>b__513_2(string k) { return k.ToLowerInvariant(); } internal string <BuildWorldKeyChanges>b__514_0(string k) { return k.ToLowerInvariant(); } internal string <BuildWorldKeyChanges>b__514_4(string k) { return k.ToLowerInvariant(); } internal bool <BuildWorldKeyChanges>b__514_1(string k) { return WorldKeyName(k) == "preset"; } internal IEnumerable<string> <WorldSettingsFingerprint>b__515_3(WorldSetting s) { return ManagedWorldKeys(s); } internal string <WorldSettingsFingerprint>b__515_1(string k) { return k.ToLowerInvariant(); } internal string <WorldSettingsFingerprint>b__515_2(string k) { return k; } internal bool <CaptureWorldSlider>b__519_0(string k) { return !string.IsNullOrWhiteSpace(k); } internal string <CaptureWorldSlider>b__519_1(string k) { return k.Trim().ToLowerInvariant(); } internal string <RPC_SetWorldSettings>b__528_0(KeyValuePair<string, string> c) { return c.Key + "=" + c.Value; } internal bool <DrawWorldSettingCard>b__535_1(WorldChoice c) { return c.Id == "on"; } internal bool <DrawWorldSettingCard>b__535_2(WorldChoice c) { return c.Id == "off"; } } private readonly Dictionary<long, ZDOID> m_invisiblePeers = new Dictionary<long, ZDOID>(); private readonly HashSet<ZDOID> m_invisibleCharacters = new HashSet<ZDOID>(); private readonly Dictionary<ZDOID, InvisibleVisual> m_invisibleVisuals = new Dictionary<ZDOID, InvisibleVisual>(); private int m_invisibleRevision; private int m_receivedInvisibleRevision = -1; private float m_nextInvisibleSync; private bool m_restorePublicPosition; private bool m_previousPublicPosition; private const int ChickenEggLimit = 3; private static readonly long ChickenEggWindow = TimeSpan.FromMinutes(10.0).Ticks; private readonly Dictionary<string, List<long>> m_chickenEggTimes = new Dictionary<string, List<long>>(StringComparer.Ordinal); private readonly Dictionary<string, float> m_chickenEggAttempts = new Dictionary<string, float>(StringComparer.Ordinal); private bool m_chickenEggStorageReady; private float m_nextChickenEggRequest; private const int ClientHandshakeProtocol = 1; private ConfigEntry<bool> m_requireMatchingClient; private string m_buildFingerprint = ""; private string m_connectionNotice = ""; private readonly Dictionary<ZRpc, ClientGate> m_clientGates = new Dictionary<ZRpc, ClientGate>(); private MethodInfo m_nativePeerInfo; private string m_feedback = ""; private float m_feedbackUntil; private bool m_feedbackError; private float m_actionRadius = 30f; private float m_nextRosterScan; private float m_nextRosterSave; private float m_nextRosterRequest; private long m_offlineSelection; private long m_teleportSelection; private string m_rosterSearch = ""; private Vector2 m_rosterScroll; private readonly Dictionary<long, KnownPlayer> m_knownPlayers = new Dictionary<long, KnownPlayer>(); private readonly Dictionary<int, PendingTeleport> m_pendingTeleports = new Dictionary<int, PendingTeleport>(); private int m_nextTeleport; private float m_nextWorldSave; private readonly Dictionary<ZDOID, OwnedFreeze> m_ownedFreezes = new Dictionary<ZDOID, OwnedFreeze>(); private readonly Dictionary<ZDOID, FreezeRequest> m_serverFreezes = new Dictionary<ZDOID, FreezeRequest>(); private float m_nextFreezeAudit; private readonly Dictionary<string, ItemToken> m_itemTokens = new Dictionary<string, ItemToken>(); private readonly Dictionary<long, InventoryAccess> m_inventoryAccess = new Dictionary<long, InventoryAccess>(); private readonly Dictionary<int, ItemOperation> m_itemOperations = new Dictionary<int, ItemOperation>(); private int m_nextItemOperation; private InventoryEntry m_selectedInventoryItem; private string m_itemAmount = "1"; private bool m_itemConfirm; private bool m_itemDelete; private bool m_itemActionPending; private float m_itemClientDeadline; private readonly Dictionary<int, InventoryRequest> m_inventoryRequests = new Dictionary<int, InventoryRequest>(); private readonly Dictionary<long, float> m_inventoryCooldowns = new Dictionary<long, float>(); private int m_nextInventoryRequest; private long m_inventoryTarget; private ZDOID m_inventoryCharacter = ZDOID.None; private int m_inventoryClientRequest; private InventorySnapshot m_inventoryPreview; private float m_inventoryReceived; private int m_inventoryColumnPage; private GUIStyle m_playerControlStyle; private GUIStyle m_playerCardLabel; public const string PluginGuid = "adminmanager"; public const string PluginVersion = "1.0.2"; internal static ManualLogSource Log; private bool m_show; private ConfigEntry<KeyboardShortcut> m_toggleKey; private int m_tab; private int m_selectedPlayerInstanceId; private RenderTexture m_previewRT; private Camera m_previewCamera; private GameObject m_previewCameraGO; private int m_previewPlayerInstanceId; private float m_previewYaw; private float m_previewPitch = 12f; private float m_previewDistance = 4.2f; private const float PreviewTargetHeight = 1.1f; private float m_cellW = 120f; private float m_cellH = 120f; private float m_pCellW = 96f; private float m_skipHours = 6f; private Harmony m_harmony; private FallbackSpriteFactory m_sprites; private Dictionary<string, Texture2D> m_icons; private Dictionary<string, string> m_iconPieceMap; private Dictionary<string, string> m_iconStatusMap; private Dictionary<string, string> m_uiSpriteMap; private Dictionary<string, string> m_uiOverlayMap; private readonly HashSet<string> m_uiIcons = new HashSet<string>(); private readonly HashSet<string> m_uiOverlayDone = new HashSet<string>(); private bool m_uiIconsLoaded; private int m_uiIconAttempts; private Dictionary<string, string> m_iconItemMap; private bool m_gameIconsLoaded; private GUIStyle m_windowStyle; private GUIStyle m_buttonStyle; private GUIStyle m_cardStyle; private GUIStyle m_centerLabel; private GUIStyle m_headerStyle; private GUIStyle m_tabActive; private GUIStyle m_tabIdle; private GUIStyle m_sectionStyle; private GUIStyle m_listPanelStyle; private GUIStyle m_dividerStyle; private Rect m_window = new Rect(20f, 20f, 360f, 520f); private Vector2 m_scroll; private readonly Vector2[] m_tabScroll = (Vector2[])(object)new Vector2[6]; private int m_scrollTab; private bool m_rpcRegistered; private ZRoutedRpc m_registeredRpc; private float m_nextPermRequest; private int m_lastPeerCount = -1; private readonly Dictionary<long, Dictionary<string, bool>> m_state = new Dictionary<long, Dictionary<string, bool>>(); private readonly Dictionary<long, bool> m_allowed = new Dictionary<long, bool>(); private static readonly HashSet<long> m_serverAllowed = new HashSet<long>(); private static readonly List<string> m_bans = new List<string>(); private static int m_bansVersion; private bool m_bansRequested; private static readonly Dictionary<string, bool> m_permGlobal = new Dictionary<string, bool>(); private static readonly Dictionary<long, HashSet<string>> m_permPlayers = new Dictionary<long, HashSet<string>>(); private static readonly HashSet<long> m_admins = new HashSet<long>(); private static readonly Dictionary<string, string> m_banNames = new Dictionary<string, string>(); private static bool m_permsLoaded; private static readonly List<string> PermKeys = new List<string> { "god", "fly", "freefly", "ghost", "nocost", "freebuild", "heal", "repairall", "removedrops", "clearstatus", "tame", "stopevent", "sleep", "killall", "killenemies", "time", "kill", "respawn", "kick", "ban", "carryweight", "unlimitedweight", "unlimitedstamina" }; private static readonly Dictionary<string, string> PermLabels = new Dictionary<string, string> { { "god", "God" }, { "fly", "Fly" }, { "freefly", "Free Fly" }, { "ghost", "Ghost" }, { "nocost", "No Cost" }, { "freebuild", "Build Cam" }, { "heal", "Heal" }, { "repairall", "Repair" }, { "removedrops", "Remove Drops" }, { "clearstatus", "Clear Status" }, { "tame", "Tame" }, { "stopevent", "Stop Event" }, { "sleep", "Sleep" }, { "killall", "Kill All" }, { "killenemies", "Kill Enemies" }, { "time", "Skip Time" }, { "kill", "Kill" }, { "respawn", "Respawn" }, { "kick", "Kick" }, { "ban", "Ban" }, { "carryweight", "Carry Cap" }, { "unlimitedweight", "Unlimited Carry" }, { "unlimitedstamina", "Unlimited Stamina" } }; private int m_permPlayerInstanceId; private bool m_permsRequested; private static Plugin m_instance; private readonly HashSet<string> m_quarantineAccounts = new HashSet<string>(StringComparer.Ordinal); private readonly HashSet<ZDOID> m_quarantineBots = new HashSet<ZDOID>(); private readonly HashSet<ZDOID> m_quarantineCharacters = new HashSet<ZDOID>(); private readonly HashSet<long> m_quarantineProfiles = new HashSet<long>(); private readonly Dictionary<ZDOID, ChickenVisual> m_chickenVisuals = new Dictionary<ZDOID, ChickenVisual>(); private bool m_localQuarantined; private float m_nextQuarantineSync; private float m_nextQuarantineVisual; private float m_nextQuarantineVisualWarning; private int m_quarantineRevision; private int m_receivedQuarantineRevision = -1; private readonly Dictionary<long, QuarantinePending> m_quarantinePending = new Dictionary<long, QuarantinePending>(); private static readonly HashSet<string> QuarantineBlockedButtons = new HashSet<string>(StringComparer.Ordinal) { "Inventory", "JoyInventory", "Map", "JoyMap", "Use", "JoyUse", "Attack", "JoyAttack", "SecondaryAttack", "JoySecondaryAttack", "Block", "JoyBlock", "Remove", "JoyRemove", "BuildMenu", "JoyBuildMenu", "OpenRadial", "OpenEmote", "JoyRadial", "GP", "JoyGP", "Sit", "Hide", "AutoPickup", "JoyAutoPickup", "RadialSecondaryInteract", "JoyRadialSecondaryInteract", "Hotbar1", "Hotbar2", "Hotbar3", "Hotbar4", "Hotbar5", "Hotbar6", "Hotbar7", "Hotbar8" }; private readonly Dictionary<long, ResourceState> m_resourceStates = new Dictionary<long, ResourceState>(); private ResourceState m_localResources = new ResourceState(); private string m_carryCapacityText = "1000"; private float m_nextResourceAudit; private readonly Dictionary<string, WorldSetting> m_worldCatalog = new Dictionary<string, WorldSetting>(StringComparer.Ordinal); private readonly List<WorldSetting> m_worldView = new List<WorldSetting>(); private readonly Dictionary<string, string> m_worldDraft = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<long, float> m_worldRequestTimes = new Dictionary<long, float>(); private string m_worldFingerprint = ""; private float m_nextWorldRefresh; private float m_nextWorldCatalogScan; private float m_worldApplyDeadline; private bool m_worldStale; private bool m_worldConfirm; private bool m_worldApplyPending; private bool m_worldSavePending; private MethodInfo m_addWorldKey; private MethodInfo m_removeWorldKey; private MethodInfo m_sendWorldKeys; private static readonly string[] WorldSettingOrder = new string[9] { "resources", "combat", "raids", "deathpenalty", "portals", "passive", "freebuild", "map", "playerraids" }; private GUIStyle PlayerControlStyle { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if (m_playerControlStyle == null) { m_playerControlStyle = new GUIStyle(m_buttonStyle) { margin = new RectOffset(0, 0, 0, 0), fontSize = 12, alignment = (TextAnchor)4 }; } return m_playerControlStyle; } } private static bool LocalQuarantined { get { if ((Object)(object)m_instance != (Object)null) { return m_instance.m_localQuarantined; } return false; } } private static bool InvisibleCharacter(Character player) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (player is Player && (Object)(object)m_instance != (Object)null) { return m_instance.m_invisibleCharacters.Contains(player.GetZDOID()); } return false; } private static IEnumerable<Tuple<Type, string, string>> InvisiblePatchTargets() { yield return Tuple.Create(typeof(EnemyHud), "TestShow", "InvisibleHudPrefix"); yield return Tuple.Create(typeof(Player), "GetHoverName", "InvisibleHoverPrefix"); yield return Tuple.Create(typeof(Player), "GetHoverText", "InvisibleHoverPrefix"); yield return Tuple.Create(typeof(ZNet), "SetPublicReferencePosition", "InvisiblePublicPositionPrefix"); } private void InitializeInvisibility() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown foreach (Tuple<Type, string, string> item in InvisiblePatchTargets()) { PatchResource(item.Item1, item.Item2, item.Item3, prefix: true); } PatchResource(typeof(ZNet), "GetOtherPublicPlayers", "InvisibleMapPostfix", prefix: false); PatchResource(typeof(ZNet), "UpdatePlayerList", "InvisiblePlayerListPostfix", prefix: false); object obj = <>c.<>9__11_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Length != 1) { args.Context.AddString("Usage: aminvisible"); } else if ((Object)(object)m_instance != (Object)null) { m_instance.RequestInvisibility(); } }; <>c.<>9__11_0 = val; obj = (object)val; } new ConsoleCommand("aminvisible", "Admin Manager: toggle player invisibility (admin only).", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void RegisterInvisibility() { ZRoutedRpc.instance.Register<bool>("AdminManager_InvisibleRequest", (Action<long, bool>)RPC_InvisibleRequest); ZRoutedRpc.instance.Register<ZPackage>("AdminManager_InvisibleState", (Action<long, ZPackage>)RPC_InvisibleState); } private void RequestInvisibility() { if (!IsLocalAdmin() || LocalQuarantined) { Feedback("Invisibility is admin-only.", error: true); return; } if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null) { Feedback("Load a character first.", error: true); return; } bool flag = !InvisibleCharacter((Character)(object)Player.m_localPlayer); if (ZNet.instance.IsServer()) { RPC_InvisibleRequest(ServerPeerId(), flag); return; } ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_InvisibleRequest", new object[1] { flag }); } private static void RPC_InvisibleRequest(long sender, bool enabled) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || DenyQuarantined(sender)) { return; } if (!IsAdminSender(sender)) { Reply(sender, "Invisibility is admin-only.", error: true); return; } ZDOID value = m_instance.InvisiblePeerCharacter(sender); if (((ZDOID)(ref value)).IsNone()) { Reply(sender, "Your character is not ready.", error: true); return; } if (enabled && !m_instance.m_invisiblePeers.ContainsKey(sender) && m_instance.m_invisiblePeers.Count >= 128) { Reply(sender, "Invisibility capacity reached.", error: true); return; } if (enabled) { m_instance.m_invisiblePeers[sender] = value; } else { m_instance.m_invisiblePeers.Remove(sender); } m_instance.m_invisibleRevision++; m_instance.BroadcastInvisibility(); Reply(sender, enabled ? "Invisible to players: body, equipment, nameplate and map marker hidden." : "Visible to players again."); Log.LogInfo((object)("Admin invisibility: peer=" + sender + " enabled=" + enabled)); } private ZDOID InvisiblePeerCharacter(long peer) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (peer != ServerPeerId()) { return ZNet.instance.GetPeer(peer)?.m_characterID ?? ZDOID.None; } return ZNet.instance.LocalPlayerCharacterID; } private void BroadcastInvisibility() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) m_invisibleCharacters.Clear(); m_invisibleCharacters.UnionWith(m_invisiblePeers.Values); ZPackage val = new ZPackage(); val.Write(m_invisibleRevision); val.Write(m_invisibleCharacters.Count); foreach (ZDOID invisibleCharacter in m_invisibleCharacters) { val.Write(invisibleCharacter); } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "AdminManager_InvisibleState", new object[1] { val }); } UpdateInvisibleVisuals(); } private static HashSet<ZDOID> ReadInvisibleCharacters(ZPackage packet, out int revision) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (packet == null || packet.Size() > 4096) { throw new ArgumentException("Invalid invisibility snapshot."); } revision = packet.ReadInt(); int num = packet.ReadInt(); if (revision < 0 || num < 0 || num > 128) { throw new ArgumentException("Invalid invisibility count/revision."); } HashSet<ZDOID> hashSet = new HashSet<ZDOID>(); for (int i = 0; i < num; i++) { ZDOID item = packet.ReadZDOID(); if (((ZDOID)(ref item)).IsNone() || !hashSet.Add(item)) { throw new ArgumentException("Invalid invisibility character."); } } if (packet.GetPos() != packet.Size()) { throw new ArgumentException("Trailing invisibility data."); } return hashSet; } private static void RPC_InvisibleState(long sender, ZPackage packet) { if ((Object)(object)m_instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || !IsServerMessage(sender)) { return; } try { int revision; HashSet<ZDOID> other = ReadInvisibleCharacters(packet, out revision); if (revision >= m_instance.m_receivedInvisibleRevision) { m_instance.m_receivedInvisibleRevision = revision; m_instance.m_invisibleCharacters.Clear(); m_instance.m_invisibleCharacters.UnionWith(other); m_instance.UpdateInvisibleVisuals(); } } catch (Exception ex) { Log.LogWarning((object)("Invalid invisibility state: " + ex.Message)); } } private void UpdateInvisibility(bool server) { //IL_004a: 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) if (!server || Time.unscaledTime < m_nextInvisibleSync) { return; } m_nextInvisibleSync = Time.unscaledTime + 1f; KeyValuePair<long, ZDOID>[] array = m_invisiblePeers.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<long, ZDOID> keyValuePair = array[i]; if (!IsAdminSender(keyValuePair.Key) || !(keyValuePair.Value == InvisiblePeerCharacter(keyValuePair.Key))) { m_invisiblePeers.Remove(keyValuePair.Key); m_invisibleRevision++; } } BroadcastInvisibility(); } private void UpdateInvisibleVisuals() { //IL_0056: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) KeyValuePair<ZDOID, InvisibleVisual>[] array = m_invisibleVisuals.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<ZDOID, InvisibleVisual> keyValuePair = array[i]; if ((Object)(object)keyValuePair.Value.Player == (Object)null || !m_invisibleCharacters.Contains(keyValuePair.Key) || QuarantinedCharacter(keyValuePair.Value.Player)) { RestoreInvisibleVisual(keyValuePair.Key); } } foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer == (Object)null || !InvisibleCharacter((Character)(object)allPlayer) || QuarantinedCharacter(allPlayer)) { continue; } ZDOID zDOID = ((Character)allPlayer).GetZDOID(); if (!m_invisibleVisuals.TryGetValue(zDOID, out var value)) { value = new InvisibleVisual { Player = allPlayer }; m_invisibleVisuals[zDOID] = value; } Renderer[] componentsInChildren = ((Component)allPlayer).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!value.Renderers.ContainsKey(val)) { value.Renderers[val] = val.forceRenderingOff; } val.forceRenderingOff = true; } Light[] componentsInChildren2 = ((Component)allPlayer).GetComponentsInChildren<Light>(true); foreach (Light val2 in componentsInChildren2) { if (!value.Lights.ContainsKey(val2)) { value.Lights[val2] = ((Behaviour)val2).enabled; } ((Behaviour)val2).enabled = false; } AudioSource[] componentsInChildren3 = ((Component)allPlayer).GetComponentsInChildren<AudioSource>(true); foreach (AudioSource val3 in componentsInChildren3) { if (!value.Sounds.ContainsKey(val3)) { value.Sounds[val3] = val3.volume; } val3.volume = 0f; } } if ((Object)(object)ZNet.instance == (Object)null) { return; } if (InvisibleCharacter((Character)(object)Player.m_localPlayer)) { if (!m_restorePublicPosition) { m_previousPublicPosition = ZNet.instance.IsReferencePositionPublic(); m_restorePublicPosition = true; } ZNet.instance.SetPublicReferencePosition(false); } else { RestoreInvisiblePublicPosition(); } } private void RestoreInvisibleVisual(ZDOID id) { //IL_0006: 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) if (!m_invisibleVisuals.TryGetValue(id, out var value)) { return; } foreach (KeyValuePair<Renderer, bool> renderer in value.Renderers) { if ((Object)(object)renderer.Key != (Object)null) { renderer.Key.forceRenderingOff = renderer.Value; } } foreach (KeyValuePair<Light, bool> light in value.Lights) { if ((Object)(object)light.Key != (Object)null) { ((Behaviour)light.Key).enabled = light.Value; } } foreach (KeyValuePair<AudioSource, float> sound in value.Sounds) { if ((Object)(object)sound.Key != (Object)null) { sound.Key.volume = sound.Value; } } m_invisibleVisuals.Remove(id); } private void RestoreInvisiblePublicPosition() { if (m_restorePublicPosition) { m_restorePublicPosition = false; if ((Object)(object)ZNet.instance != (Object)null) { ZNet.instance.SetPublicReferencePosition(m_previousPublicPosition); } } } private void ResetInvisibility() { //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_0034: Unknown result type (might be due to invalid IL or missing references) m_invisiblePeers.Clear(); m_invisibleCharacters.Clear(); ZDOID[] array = m_invisibleVisuals.Keys.ToArray(); foreach (ZDOID id in array) { RestoreInvisibleVisual(id); } RestoreInvisiblePublicPosition(); m_invisibleRevision = 0; m_receivedInvisibleRevision = -1; m_nextInvisibleSync = 0f; } private static bool InvisibleHudPrefix(Character c, ref bool __result) { if (!InvisibleCharacter(c)) { return true; } __result = false; return false; } private static bool InvisibleHoverPrefix(Player __instance, ref string __result) { if (!InvisibleCharacter((Character)(object)__instance)) { return true; } __result = ""; return false; } private static void InvisiblePublicPositionPrefix(ref bool pub) { if (InvisibleCharacter((Character)(object)Player.m_localPlayer)) { pub = false; } } private static void InvisibleMapPostfix(List<PlayerInfo> playerList) { if ((Object)(object)m_instance != (Object)null) { playerList.RemoveAll((PlayerInfo p) => m_instance.m_invisibleCharacters.Contains(p.m_characterID)); } } private static void InvisiblePlayerListPostfix(ZNet __instance) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_instance == (Object)null || !__instance.IsServer()) { return; } List<PlayerInfo> playerList = __instance.GetPlayerList(); for (int i = 0; i < playerList.Count; i++) { PlayerInfo val = playerList[i]; if (m_instance.m_invisibleCharacters.Contains(val.m_characterID)) { val.m_publicPosition = false; val.m_position = Vector3.zero; playerList[i] = val; } } } private static void PruneChickenEggTimes(List<long> times, long now) { times.RemoveAll((long time) => time <= now - ChickenEggWindow); } private static bool ReserveChickenEgg(List<long> times, long now) { if (now > 0) { DateTime maxValue = DateTime.MaxValue; if (now <= maxValue.Ticks) { PruneChickenEggTimes(times, now); if (times.Count >= 3) { return false; } times.Add(now); return true; } } return false; } private static string SerializeChickenEggTimes(Dictionary<string, List<long>> accounts, long now) { List<string> list = new List<string>(); foreach (KeyValuePair<string, List<long>> item in accounts.OrderBy<KeyValuePair<string, List<long>>, string>((KeyValuePair<string, List<long>> e) => e.Key, StringComparer.Ordinal)) { if (!ValidQuarantineAccount(item.Key)) { throw new FormatException("Invalid egg quota account."); } PruneChickenEggTimes(item.Value, now); if (item.Value.Count != 0) { list.Add(Encode(item.Key) + "|" + string.Join(",", item.Value.Select((long t) => t.ToString(CultureInfo.InvariantCulture)))); } } return string.Join("\n", list); } private static Dictionary<string, List<long>> ParseChickenEggTimes(string data, long now) { if (data == null || data.Length > 2097152) { throw new FormatException("Egg quota file is too large."); } Dictionary<string, List<long>> dictionary = new Dictionary<string, List<long>>(StringComparer.Ordinal); string[] array = data.Split(new char[1] { '\n' }); foreach (string text in array) { if (string.IsNullOrWhiteSpace(text)) { continue; } string[] array2 = text.Trim().Split(new char[1] { '|' }); if (array2.Length != 2) { throw new FormatException("Invalid egg quota entry."); } string text2 = Decode(array2[0]); if (!ValidQuarantineAccount(text2) || dictionary.ContainsKey(text2) || dictionary.Count >= 4096) { throw new FormatException("Invalid egg quota account."); } List<long> list = new List<long>(); string[] array3 = array2[1].Split(new char[1] { ',' }); int num = 0; while (num < array3.Length) { if (long.TryParse(array3[num], NumberStyles.None, CultureInfo.InvariantCulture, out var result) && result > 0) { long num2 = result; DateTime maxValue = DateTime.MaxValue; if (num2 <= maxValue.Ticks && list.Count < 3) { list.Add(result); num++; continue; } } throw new FormatException("Invalid egg quota timestamp."); } PruneChickenEggTimes(list, now); dictionary.Add(text2, list); } return dictionary; } private void LoadEggQuotas() { m_chickenEggStorageReady = false; m_chickenEggTimes.Clear(); try { string text = DataPath("quarantine_eggs"); if (text == null) { return; } if (File.Exists(text)) { foreach (KeyValuePair<string, List<long>> item in ParseChickenEggTimes(File.ReadAllText(text), DateTime.UtcNow.Ticks)) { m_chickenEggTimes.Add(item.Key, item.Value); } } m_chickenEggStorageReady = true; } catch (Exception ex) { Log.LogError((object)("Egg drops disabled: could not read the world's egg quota file. " + ex.Message)); } } private void SaveEggQuotas(long now) { string text = DataPath("quarantine_eggs"); if (!m_chickenEggStorageReady || text == null) { throw new InvalidOperationException("Egg quota storage is unavailable."); } string text2 = text + ".tmp"; File.WriteAllText(text2, SerializeChickenEggTimes(m_chickenEggTimes, now)); if (File.Exists(text)) { File.Replace(text2, text, text + ".bak"); } else { File.Move(text2, text); } } private void RegisterChickenEggs() { ZRoutedRpc.instance.Register("AdminManager_ChickenEgg", (Action<long>)RPC_ChickenEgg); ZRoutedRpc.instance.Register<string>("AdminManager_ChickenEggResult", (Action<long, string>)RPC_ChickenEggResult); } private void RequestChickenEgg() { if (LocalQuarantined && !((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null && !(Time.unscaledTime < m_nextChickenEggRequest)) { m_nextChickenEggRequest = Time.unscaledTime + 1f; ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_ChickenEgg", Array.Empty<object>()); } } private static void RPC_ChickenEgg(long sender) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && m_permsLoaded && m_instance.PeerQuarantined(sender)) { m_instance.TryDropChickenEgg(sender); } } private void EggResult(long peer, string message) { ZRoutedRpc.instance.InvokeRoutedRPC(peer, "AdminManager_ChickenEggResult", new object[1] { message }); } private static void RPC_ChickenEggResult(long sender, string message) { if (IsServerMessage(sender) && LocalQuarantined && !((Object)(object)Player.m_localPlayer == (Object)null) && !string.IsNullOrEmpty(message) && message.Length <= 256) { ((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } } private void TryDropChickenEgg(long sender) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) ZNetPeer peer = ZNet.instance.GetPeer(sender); object obj; if (peer == null) { obj = null; } else { ISocket socket = peer.m_socket; obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (!ValidQuarantineAccount(text) || !m_quarantineAccounts.Contains(text) || (m_chickenEggAttempts.TryGetValue(text, out var value) && Time.unscaledTime < value)) { return; } m_chickenEggAttempts[text] = Time.unscaledTime + 1f; if (!m_chickenEggStorageReady) { EggResult(sender, "Egg drops are unavailable; the server could not load their quota."); return; } ZDO val = ((!((ZDOID)(ref peer.m_characterID)).IsNone() && ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(peer.m_characterID) : null); GameObject val2 = ((val != null && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null); if (val == null || (Object)(object)val2 == (Object)null || (Object)(object)val2.GetComponent<Player>() == (Object)null || val.GetOwner() != sender) { return; } Player val3 = FindInventoryCharacter(peer.m_characterID); if ((Object)(object)val3 != (Object)null && ((Character)val3).IsDead()) { return; } Vector3 val4 = val.GetPosition() - val.GetRotation() * Vector3.forward * 0.65f + Vector3.up * 0.5f; if (!FinitePosition(val4)) { return; } GameObject val5 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("ChickenEgg") : null); ItemDrop val6 = (((Object)(object)val5 != (Object)null) ? val5.GetComponent<ItemDrop>() : null); if (val6?.m_itemData == null) { EggResult(sender, "Chicken eggs are unavailable in this session."); return; } long ticks = DateTime.UtcNow.Ticks; if (!m_chickenEggTimes.TryGetValue(text, out var value2)) { if (m_chickenEggTimes.Count >= 4096) { string[] array = m_chickenEggTimes.Keys.ToArray(); foreach (string key in array) { PruneChickenEggTimes(m_chickenEggTimes[key], ticks); if (m_chickenEggTimes[key].Count == 0) { m_chickenEggTimes.Remove(key); } } if (m_chickenEggTimes.Count >= 4096) { return; } } value2 = new List<long>(); m_chickenEggTimes.Add(text, value2); } if (!ReserveChickenEgg(value2, ticks)) { int num = (int)Math.Min(600.0, Math.Max(1.0, Math.Ceiling((double)(value2.Min() + ChickenEggWindow - ticks) / 10000000.0))); EggResult(sender, "Egg limit reached (3 per 10 minutes). Next egg in " + num / 60 + "m " + num % 60 + "s."); return; } ItemDrop val7 = null; try { SaveEggQuotas(ticks); ItemData obj2 = val6.m_itemData.Clone(); obj2.m_dropPrefab = val5; obj2.m_stack = 1; obj2.m_equipped = false; val7 = ItemDrop.DropItem(obj2, 1, val4, Quaternion.identity); ZNetView val8 = (((Object)(object)val7 != (Object)null) ? ((Component)val7).GetComponent<ZNetView>() : null); if ((Object)(object)val8 == (Object)null || !val8.IsValid()) { throw new InvalidOperationException("Egg pickup was not created."); } EggResult(sender, "Cluck! Egg laid (" + value2.Count + "/3 in the last 10 minutes)."); } catch (Exception ex) { if ((Object)(object)val7 != (Object)null) { ZNetView component = ((Component)val7).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { ZNetScene.instance.Destroy(((Component)val7).gameObject); } else { Object.Destroy((Object)(object)((Component)val7).gameObject); } } value2.RemoveAt(value2.Count - 1); try { SaveEggQuotas(ticks); } catch (Exception ex2) { Log.LogWarning((object)("Egg quota rollback could not be saved: " + ex2.Message)); } Log.LogWarning((object)("Chicken egg drop failed: " + ex.Message)); EggResult(sender, "Could not lay an egg; try again later."); } } private void ResetChickenEggs() { m_chickenEggTimes.Clear(); m_chickenEggAttempts.Clear(); m_chickenEggStorageReady = false; m_nextChickenEggRequest = 0f; } private static bool ValidBuildFingerprint(string hash) { if (hash != null && hash.Length == 64) { return hash.All((char c) => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } return false; } private static bool MatchingClientBuild(string expectedVersion, string expectedHash, string version, string hash) { if (!string.IsNullOrEmpty(expectedVersion) && string.Equals(expectedVersion, version, StringComparison.Ordinal) && ValidBuildFingerprint(expectedHash) && ValidBuildFingerprint(hash)) { return string.Equals(expectedHash, hash, StringComparison.OrdinalIgnoreCase); } return false; } private static bool ClientAdmissionAllowed(bool required, bool verified, bool rejected) { if (!rejected) { return !required || verified; } return false; } private static bool ValidHandshakeNonce(string nonce) { Guid result; if (nonce != null && nonce.Length == 32) { return Guid.TryParseExact(nonce, "N", out result); } return false; } private static bool MatchesHandshakeNonce(string expected, string received) { if (ValidHandshakeNonce(expected) && ValidHandshakeNonce(received)) { return string.Equals(expected, received, StringComparison.Ordinal); } return false; } private void InitializeClientCompatibility() { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_017f: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_01d5: Expected O, but got Unknown m_requireMatchingClient = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "RequireMatchingClient", true, "Server setting: require Admin Manager with the same version and DLL build before admitting clients. False allows missing/mismatched clients; remote features may be unavailable. Restart the host/server after changing this setting."); try { string location = typeof(Plugin).Assembly.Location; if (string.IsNullOrEmpty(location)) { location = ((BaseUnityPlugin)this).Info.Location; } using FileStream inputStream = File.OpenRead(location); using SHA256 sHA = SHA256.Create(); m_buildFingerprint = BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant(); } catch (Exception ex) { Log.LogError((object)("Cannot fingerprint Admin Manager; required-mode connections will be rejected: " + ex.Message)); } m_nativePeerInfo = AccessTools.Method(typeof(ZNet), "RPC_PeerInfo", new Type[2] { typeof(ZRpc), typeof(ZPackage) }, (Type[])null); if (m_nativePeerInfo == null) { throw new MissingMethodException("ZNet.RPC_PeerInfo"); } m_harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "OnNewConnection", new Type[1] { typeof(ZNetPeer) }, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientConnectionPrefix", (Type[])null, (Type[])null)) { priority = 800 }, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientConnectionPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); m_harmony.Patch((MethodBase)m_nativePeerInfo, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientPeerInfoPrefix", (Type[])null, (Type[])null)) { priority = 800 }, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientPeerInfoPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void ClientConnectionPrefix(ZNet __instance, ZNetPeer peer) { if (!((Object)(object)m_instance == (Object)null) && peer?.m_rpc != null) { ClientGate value = new ClientGate { Net = __instance, Peer = peer, Nonce = Guid.NewGuid().ToString("N"), Required = (__instance.IsServer() && m_instance.m_requireMatchingClient.Value) }; m_instance.m_clientGates[peer.m_rpc] = value; if (!__instance.IsServer()) { m_instance.m_connectionNotice = ""; } peer.m_rpc.Register<ZPackage>("AdminManager_ClientChallenge", (Action<ZRpc, ZPackage>)RPC_ClientChallenge); peer.m_rpc.Register<ZPackage>("AdminManager_ClientHello", (Action<ZRpc, ZPackage>)RPC_ClientHello); peer.m_rpc.Register<string>("AdminManager_ClientRejected", (Action<ZRpc, string>)RPC_ClientRejected); } } private static void ClientConnectionPostfix(ZNet __instance, ZNetPeer peer) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (!((Object)(object)m_instance == (Object)null) && __instance.IsServer() && peer?.m_rpc != null && m_instance.m_clientGates.TryGetValue(peer.m_rpc, out var value)) { ZPackage val = new ZPackage(); val.Write(1); val.Write(value.Nonce); val.Write("1.0.2"); val.Write(m_instance.m_buildFingerprint); val.Write(value.Required); peer.m_rpc.Invoke("AdminManager_ClientChallenge", new object[1] { val }); } } private static void RPC_ClientChallenge(ZRpc rpc, ZPackage package) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown if ((Object)(object)m_instance == (Object)null || !m_instance.m_clientGates.TryGetValue(rpc, out var value) || (Object)(object)value.Net != (Object)(object)ZNet.instance || value.Net.IsServer() || value.Rejected || package == null || package.Size() > 512) { return; } try { int num = package.ReadInt(); string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); bool flag = package.ReadBool(); if (package.GetPos() == package.Size() && ValidHandshakeNonce(text) && text2.Length <= 32 && ValidBuildFingerprint(text3)) { if (flag && (num != 1 || !MatchingClientBuild(text2, text3, "1.0.2", m_instance.m_buildFingerprint))) { m_instance.m_connectionNotice = "This server requires Admin Manager " + text2 + " with the exact same build. Install the server owner's package and restart Valheim."; } ZPackage val = new ZPackage(); val.Write(1); val.Write(text); val.Write("1.0.2"); val.Write(m_instance.m_buildFingerprint); rpc.Invoke("AdminManager_ClientHello", new object[1] { val }); } } catch (Exception ex) { Log.LogWarning((object)("Invalid Admin Manager server handshake: " + ex.Message)); } } private static void RPC_ClientHello(ZRpc rpc, ZPackage package) { if ((Object)(object)m_instance == (Object)null || !m_instance.m_clientGates.TryGetValue(rpc, out var value) || (Object)(object)value.Net != (Object)(object)ZNet.instance || !value.Net.IsServer() || value.Rejected || value.Verified || package == null || package.Size() > 512) { return; } try { int num = package.ReadInt(); string received = package.ReadString(); string version = package.ReadString(); string hash = package.ReadString(); if (package.GetPos() != package.Size() || !MatchesHandshakeNonce(value.Nonce, received)) { return; } bool flag = num == 1 && MatchingClientBuild("1.0.2", m_instance.m_buildFingerprint, version, hash); if (!flag && value.Required) { m_instance.RejectClient(value, "Incompatible Admin Manager build. Install Admin Manager 1.0.2 from the server owner and restart Valheim."); return; } value.Verified = flag; if (!flag) { Log.LogWarning((object)"Optional Admin Manager client build differs; remote tools may be unavailable."); } if (ClientAdmissionAllowed(value.Required, value.Verified, value.Rejected) && value.Pending != null) { ZPackage pending = value.Pending; value.Pending = null; m_instance.m_nativePeerInfo.Invoke(value.Net, new object[2] { rpc, pending }); } } catch (Exception ex) { Log.LogWarning((object)("Invalid Admin Manager client handshake: " + ex.Message)); if (value.Required) { m_instance.RejectClient(value, "Invalid Admin Manager handshake. Install the server owner's Admin Manager 1.0.2 build and restart Valheim."); } } } private static bool ClientPeerInfoPrefix(ZNet __instance, ZRpc rpc, ZPackage pkg) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown if ((Object)(object)m_instance == (Object)null || !__instance.IsServer()) { return true; } if (!m_instance.m_clientGates.TryGetValue(rpc, out var value)) { return !m_instance.m_requireMatchingClient.Value; } if (value.Rejected || value.Admitted) { return false; } if (ClientAdmissionAllowed(value.Required, value.Verified, value.Rejected)) { return true; } if (value.Pending == null) { if (pkg == null || pkg.Size() > 65536) { m_instance.RejectClient(value, "Invalid connection information."); return false; } int pos = pkg.GetPos(); value.Pending = new ZPackage(pkg.GetArray()); value.Pending.SetPos(pos); value.Deadline = Time.unscaledTime + 10f; } return false; } private static void ClientPeerInfoPostfix(ZNet __instance, ZRpc rpc) { if ((Object)(object)m_instance != (Object)null && __instance.IsServer() && m_instance.m_clientGates.TryGetValue(rpc, out var value) && value.Peer.IsReady()) { value.Admitted = true; } } private void RejectClient(ClientGate gate, string reason) { if (!gate.Rejected) { gate.Rejected = true; gate.Pending = null; gate.DisconnectAt = Time.unscaledTime + 1f; ManualLogSource log = Log; ISocket socket = gate.Peer.m_socket; log.LogWarning((object)("Admin Manager connection rejected (" + ((socket != null) ? socket.GetHostName() : null) + "): " + reason)); gate.Peer.m_rpc.Invoke("AdminManager_ClientRejected", new object[1] { reason }); gate.Peer.m_rpc.Invoke("Error", new object[1] { 3 }); } } private static void RPC_ClientRejected(ZRpc rpc, string reason) { if (!((Object)(object)m_instance == (Object)null) && m_instance.m_clientGates.TryGetValue(rpc, out var value) && !((Object)(object)value.Net != (Object)(object)ZNet.instance) && !value.Net.IsServer() && !string.IsNullOrEmpty(reason) && reason.Length <= 512) { value.Rejected = true; m_instance.m_connectionNotice = reason; Log.LogWarning((object)("Server rejected Admin Manager connection: " + reason)); ZNet.SetExternalError((ConnectionStatus)3); } } private void UpdateConnectionChecks() { KeyValuePair<ZRpc, ClientGate>[] array = m_clientGates.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<ZRpc, ClientGate> keyValuePair = array[i]; ClientGate value = keyValuePair.Value; if ((Object)(object)value.Net == (Object)null || (Object)(object)value.Net != (Object)(object)ZNet.instance || !value.Net.GetPeers().Contains(value.Peer)) { m_clientGates.Remove(keyValuePair.Key); } else if (value.Net.IsServer()) { if (!value.Rejected && value.Required && !value.Verified && value.Pending != null && Time.unscaledTime >= value.Deadline) { RejectClient(value, "Admin Manager 1.0.2 is required. Install the server owner's matching build and restart Valheim."); } if (value.Rejected && Time.unscaledTime >= value.DisconnectAt) { value.Net.Disconnect(value.Peer); m_clientGates.Remove(keyValuePair.Key); } } } } private void DrawConnectionNotice() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(m_connectionNotice)) { int depth = GUI.depth; GUI.depth = -2000; float num = Math.Min(560f, (float)Screen.width - 24f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 24f, num, 130f); GUI.Box(val, ""); GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 8f, num - 24f, 26f), "Admin Manager — connection requirement"); GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 36f, num - 24f, 54f), m_connectionNotice, new GUIStyle(GUI.skin.label) { wordWrap = true, richText = false }); if (GUI.Button(new Rect(((Rect)(ref val)).xMax - 112f, ((Rect)(ref val)).yMax - 32f, 100f, 24f), "Dismiss")) { m_connectionNotice = ""; } GUI.depth = depth; } } private void RegisterFeatures() { RegisterInventory(); RegisterWorldSettings(); RegisterResources(); RegisterInvisibility(); RegisterFreeze(); RegisterQuarantine(); RegisterInventoryModeration(); ZRoutedRpc instance = ZRoutedRpc.instance; instance.Register<string, bool>("AdminManager_Feedback", (Action<long, string, bool>)RPC_Feedback); instance.Register<string, float>("AdminManager_Area", (Action<long, string, float>)RPC_Area); instance.Register<long, bool>("AdminManager_Teleport", (Action<long, long, bool>)RPC_Teleport); instance.Register<int, Vector3, Quaternion>("AdminManager_TeleportApply", (Action<long, int, Vector3, Quaternion>)RPC_TeleportApply); instance.Register<int, bool>("AdminManager_TeleportResult", (Action<long, int, bool>)RPC_TeleportResult); instance.Register("AdminManager_GetRoster", (Action<long>)RPC_GetRoster); instance.Register<string>("AdminManager_Roster", (Action<long, string>)RPC_Roster); instance.Register<long>("AdminManager_OfflineBan", (Action<long, long>)RPC_OfflineBan); instance.Register("AdminManager_SaveWorld", (Action<long>)RPC_SaveWorld); } private void ResetFeatures() { //IL_0044: 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) m_previewPlayerInstanceId = 0; ResetModeration(); ResetWorldSettings(); ResetQuarantine(); ResetInvisibility(); ResetResources(); m_inventoryRequests.Clear(); m_inventoryCooldowns.Clear(); m_inventoryTarget = 0L; m_inventoryCharacter = ZDOID.None; m_inventoryPreview = null; m_knownPlayers.Clear(); m_pendingTeleports.Clear(); m_offlineSelection = 0L; m_teleportSelection = 0L; m_nextRosterScan = (m_nextRosterSave = (m_nextRosterRequest = (m_nextWorldSave = 0f))); m_feedback = ""; } private static void Feedback(string message, bool error = false) { if (!((Object)(object)m_instance == (Object)null)) { m_instance.m_feedback = message; m_instance.m_feedbackError = error; m_instance.m_feedbackUntil = Time.unscaledTime + 12f; } } private static void Reply(long peer, string message, bool error = false) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { if (peer == ServerPeerId()) { Feedback(message, error); } else if (ZNet.instance.GetPeer(peer) != null) { ZRoutedRpc.instance.InvokeRoutedRPC(peer, "AdminManager_Feedback", new object[2] { message, error }); } } } private static void RPC_Feedback(long sender, string message, bool error) { if (IsServerMessage(sender)) { Feedback(message, error); } } private void DrawFeedback() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) string obj = ((Time.unscaledTime > m_feedbackUntil) ? "" : m_feedback); GUIStyle val = new GUIStyle(GUI.skin.label) { wordWrap = true, richText = false }; val.normal.textColor = (m_feedbackError ? new Color(1f, 0.55f, 0.4f) : new Color(0.65f, 1f, 0.65f)); GUILayout.Label(obj, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }); } private void SendFeature(string rpc, params object[] args) { if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null) { Feedback("Load a world before using this action.", error: true); return; } Feedback("Waiting for the server..."); if (!ZNet.instance.IsServer()) { ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), rpc, args); return; } long sender = ServerPeerId(); switch (rpc) { case "AdminManager_Area": RPC_Area(sender, (string)args[0], (float)args[1]); break; case "AdminManager_Teleport": RPC_Teleport(sender, (long)args[0], (bool)args[1]); break; case "AdminManager_SaveWorld": RPC_SaveWorld(sender); break; case "AdminManager_OfflineBan": RPC_OfflineBan(sender, (long)args[0]); break; } } private static bool ValidRadius(float radius) { if (!float.IsNaN(radius) && !float.IsInfinity(radius) && radius >= 5f) { return radius <= 100f; } return false; } private static bool IsAreaCommand(string command) { switch (command) { default: return command == "killenemies"; case "removedrops": case "tame": case "killall": return true; } } private static bool TryPlayerLocation(long pid, out Vector3 position, out Quaternion rotation) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; rotation = Quaternion.identity; if (pid == 0L) { return false; } Player val = FindPlayerById(pid); if ((Object)(object)val != (Object)null) { position = ((Component)val).transform.position; rotation = ((Component)val).transform.rotation; return true; } if ((Object)(object)ZNet.instance == (Object)null) { return false; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (PeerPlayerId(peer) == pid && !((ZDOID)(ref peer.m_characterID)).IsNone()) { ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { return false; } position = zDO.GetPosition(); rotation = zDO.GetRotation(); return true; } } return false; } private static void RPC_Area(long sender, string command, float radius) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!IsAreaCommand(command) || !ValidRadius(radius)) { Reply(sender, "Invalid area action or radius.", error: true); return; } long pid = PlayerIdOfPeer(sender); if (!IsAdminSender(sender) && !HasPerm(pid, command)) { Reply(sender, "Permission denied.", error: true); return; } if (!TryPlayerLocation(pid, out var position, out var _)) { Reply(sender, "Your character is not ready.", error: true); return; } try { int num = 0; if (command == "tame") { Tameable.TameAllInArea(position, radius); Reply(sender, "Tame applied to eligible loaded creatures within " + radius.ToString("0") + " m."); return; } float num2 = radius * radius; Vector3 val2; if (command == "removedrops") { ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0); foreach (ItemDrop val in array) { if ((Object)(object)val == (Object)null) { continue; } val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude > num2) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { component.ClaimOwnership(); if (component.IsOwner()) { ZNetScene.instance.Destroy(((Component)val).gameObject); num++; } } } Reply(sender, "Removed " + num + " loaded item stacks within " + radius.ToString("0") + " m."); return; } foreach (Character item in new List<Character>(Character.GetAllCharacters())) { if (!((Object)(object)item == (Object)null) && !item.IsPlayer() && !((Object)(object)((Component)item).GetComponent<Piece>() != (Object)null) && (!(command == "killenemies") || !item.IsTamed())) { val2 = ((Component)item).transform.position - position; if (!(((Vector3)(ref val2)).sqrMagnitude > num2)) { item.Damage(new HitData(1E+10f)); num++; } } } Reply(sender, "Damage sent to " + num + " loaded creatures within " + radius.ToString("0") + " m."); } catch (Exception ex) { Log.LogWarning((object)("Area action failed: " + ex)); Reply(sender, "Area action failed; check the server log.", error: true); } } private void DrawWorldTools(bool admin) { if (admin) { if (GUILayout.Button("Save World", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { SendFeature("AdminManager_SaveWorld"); } GUILayout.Space(10f); } } private void DrawAreaTools() { if (CanUse("removedrops") || CanUse("tame") || CanUse("killall") || CanUse("killenemies")) { GUILayout.Space(14f); GUILayout.Label("Area actions", m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.Label("Action radius: " + m_actionRadius.ToString("0") + " m", m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); m_actionRadius = Mathf.Round(GUILayout.HorizontalSlider(m_actionRadius, 5f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) })); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Label("Applies to Remove Drops, Tame, Kill All and Kill Enemies in loaded areas.", m_centerLabel, Array.Empty<GUILayoutOption>()); } } private static void RPC_SaveWorld(long sender) { if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null) { return; } if (!IsAdminSender(sender)) { Reply(sender, "Permission denied: only admins can save the world.", error: true); return; } if (Time.unscaledTime < m_instance.m_nextWorldSave) { Reply(sender, "A save was recently requested; wait a few seconds.", error: true); return; } try { if (ZNet.instance.HardSaveBlock()) { Reply(sender, "Valheim is delaying another save; try again later.", error: true); return; } bool started = false; Action action = delegate { started = true; }; ZNet.WorldSaveStarted = (Action)Delegate.Combine(ZNet.WorldSaveStarted, action); try { ZNet.instance.SaveWorldAndPlayerProfiles(); } finally { ZNet.WorldSaveStarted = (Action)Delegate.Remove(ZNet.WorldSaveStarted, action); } m_instance.m_nextWorldSave = Time.unscaledTime + 15f; Reply(sender, started ? "World save started. Valheim will report completion." : "Valheim did not start the save; check its messages and server log.", !started); } catch (Exception ex) { Log.LogWarning((object)("Save World failed: " + ex)); Reply(sender, "World save request failed.", error: true); } } private void DrawTeleportTools(long pid, float available = 0f) { float available2 = ((available > 0f) ? available : Math.Max(200f, ((Rect)(ref m_window)).width - 100f)); bool enabled = pid != 0L && pid != (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0); DrawActionGroup("Teleport", available2, new PlayerPanelAction("Teleport to Player", delegate { SendFeature("AdminManager_Teleport", pid, false); }, enabled, active: false, "teleport"), new PlayerPanelAction("Bring Player", delegate { SendFeature("AdminManager_Teleport", pid, true); }, enabled, active: false, "bring")); } private void DrawOnlineTeleportSelector() { List<KnownPlayer> list = new List<KnownPlayer>(); foreach (KnownPlayer value in m_knownPlayers.Values) { if (IsOnline(value.Id) && (Object)(object)FindPlayerById(value.Id) == (Object)null) { list.Add(value); } } if (list.Count == 0) { return; } GUILayout.Space(10f); GUILayout.Label("Other online players (outside character view)", m_centerLabel, Array.Empty<GUILayoutOption>()); list.Sort((KnownPlayer a, KnownPlayer b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); int num = 0; foreach (KnownPlayer item in list) { if (IsOnline(item.Id) && (!((Object)(object)Player.m_localPlayer != (Object)null) || item.Id != Player.m_localPlayer.GetPlayerID())) { num++; if (GUILayout.Button(item.Name, (item.Id == m_teleportSelection) ? m_tabActive : m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) })) { m_teleportSelection = item.Id; RequestInventory(item.Id); } } } if (num == 0) { GUILayout.Label("No other online players.", m_centerLabel, Array.Empty<GUILayoutOption>()); } if (m_teleportSelection != 0L && IsOnline(m_teleportSelection)) { DrawTeleportTools(m_teleportSelection); DrawDistantFreezeTools(m_teleportSelection); DrawInventoryPreview(m_teleportSelection); } } private static void RPC_Teleport(long sender, long target, bool bring) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) if (DenyQuarantined(sender)) { return; } try { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null) { return; } if (!IsAdminSender(sender)) { Reply(sender, "Permission denied: only admins can teleport players.", error: true); return; } long num = PlayerIdOfPeer(sender); if (target == num || target == 0L || num == 0L) { Reply(sender, "Select another online player.", error: true); return; } if (!TryPlayerLocation(num, out var position, out var rotation) || !TryPlayerLocation(target, out var position2, out var rotation2)) { Reply(sender, "Both players must be online with their characters loaded.", error: true); return; } if (m_instance.ServerProfileFrozen(num) || m_instance.ServerProfileFrozen(target)) { Reply(sender, "Unfreeze the player before teleporting.", error: true); return; } long num2 = (bring ? target : num); Vector3 val = (bring ? position : position2); Quaternion val2 = (bring ? rotation : rotation2); val += val2 * new Vector3(2f, 1f, 0f); string text = (bring ? "Bring player" : "Teleport to player"); if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == num2) { bool flag = ((Character)Player.m_localPlayer).TeleportTo(val, val2, true); Reply(sender, flag ? (text + " started.") : "Teleport unavailable while already teleporting or attached.", !flag); return; } long num3 = 0L; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (PeerPlayerId(peer) == num2) { num3 = peer.m_uid; break; } } if (num3 == 0L) { Reply(sender, "The player disconnected.", error: true); return; } foreach (PendingTeleport value in m_instance.m_pendingTeleports.Values) { if (value.Peer == num3) { Reply(sender, "A teleport is already pending for this player.", error: true); return; } } int num4 = ++m_instance.m_nextTeleport; m_instance.m_pendingTeleports[num4] = new PendingTeleport { Requester = sender, Peer = num3, Description = text, Expires = Time.unscaledTime + 20f }; ZRoutedRpc.instance.InvokeRoutedRPC(num3, "AdminManager_TeleportApply", new object[3] { num4, val, val2 }); Reply(sender, text + " sent; waiting for the player's client."); } catch (Exception ex) { Log.LogWarning((object)("Teleport request failed: " + ex)); Reply(sender, "Teleport failed; check the server log.", error: true); } } private static void RPC_TeleportApply(long sender, int id, Vector3 pos, Quaternion rot) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (IsServerMessage(sender)) { bool flag = false; try { flag = (Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).TeleportTo(pos, rot, true); } catch (Exception ex) { Log.LogWarning((object)("Teleport failed: " + ex)); } ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_TeleportResult", new object[2] { id, flag }); Feedback(flag ? "Admin teleport started." : "Admin teleport could not start.", !flag); } } private static void RPC_TeleportResult(long sender, int id, bool accepted) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && m_instance.m_pendingTeleports.TryGetValue(id, out var value) && value.Peer == sender) { m_instance.m_pendingTeleports.Remove(id); Reply(value.Requester, accepted ? (value.Description + " started.") : "The player's client could not start the teleport.", !accepted); } } private void UpdateFeatures(bool server) { UpdateResources(server); UpdateWorldSettings(server); UpdateQuarantine(server); UpdateInvisibility(server); UpdateModeration(); if (server) { if (!m_permsLoaded) { return; } UpdateInventoryRequests(); if (Time.unscaledTime >= m_nextRosterScan) { m_nextRosterScan = Time.unscaledTime + 5f; RememberOnlinePlayers(); } if (Time.unscaledTime >= m_nextRosterSave) { m_nextRosterSave = Time.unscaledTime + 60f; SaveRoster(); } { foreach (int item in new List<int>(m_pendingTeleports.Keys)) { PendingTeleport pendingTeleport = m_pendingTeleports[item]; if (!(Time.unscaledTime < pendingTeleport.Expires)) { m_pendingTeleports.Remove(item); Reply(pendingTeleport.Requester, "No teleport response; check that the player has the same mod version.", error: true); } } return; } } if (m_show && IsLocalAdmin() && Time.unscaledTime >= m_nextRosterRequest) { m_nextRosterRequest = Time.unscaledTime + 10f; ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_GetRoster", Array.Empty<object>()); } } private void Remember(long id, string name, string host) { if (id != 0L) { bool flag = !m_knownPlayers.TryGetValue(id, out var value); if (value == null) { value = new KnownPlayer { Id = id }; m_knownPlayers[id] = value; } if (!string.IsNullOrWhiteSpace(name)) { flag |= value.Name != name; value.Name = name; } else if (string.IsNullOrWhiteSpace(value.Name)) { value.Name = "Player " + id; } flag |= !string.IsNullOrEmpty(host) && value.Host != host; if (!string.IsNullOrEmpty(host)) { value.Host = host; } value.LastSeen = DateTime.UtcNow.Ticks; if (flag) { SaveRoster(); } } } private void RememberOnlinePlayers() { if ((Object)(object)Player.m_localPlayer != (Object)null) { Remember(Player.m_localPlayer.GetPlayerID(), Player.m_localPlayer.GetPlayerName(), ""); } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { Remember(PeerPlayerId(peer), peer.m_playerName, (peer.m_socket != null) ? peer.m_socket.GetHostName() : ""); } } private static string Encode(string value) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? "")); } private static string Decode(string value) { return Encoding.UTF8.GetString(Convert.FromBase64String(value)); } private string SerializeRoster(bool privateData) { List<string> list = new List<string>(); foreach (KnownPlayer value in m_knownPlayers.Values) { list.Add(value.Id.ToString(CultureInfo.InvariantCulture) + "|" + Encode(value.Name) + "|" + Encode(privateData ? value.Host : "") + "|" + value.LastSeen.ToString(CultureInfo.InvariantCulture) + "|" + ((!privateData && IsOnline(value.Id)) ? "1" : "0")); } return string.Join("\n", list.ToArray()); } private void ParseRoster(string data) { Dictionary<long, KnownPlayer> dictionary = new Dictionary<long, KnownPlayer>(); string[] array = data.Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '|' }); if ((array2.Length != 4 && array2.Length != 5) || !long.TryParse(array2[0], out var result) || result == 0L || !long.TryParse(array2[3], out var result2)) { continue; } long num = result2; DateTime minValue = DateTime.MinValue; if (num < minValue.Ticks) { continue; } long num2 = result2; minValue = DateTime.MaxValue; if (num2 <= minValue.Ticks) { try { dictionary[result] = new KnownPlayer { Id = result, Name = Decode(array2[1]), Host = Decode(array2[2]), LastSeen = result2, Online = (array2.Length == 5 && array2[4] == "1") }; } catch (FormatException) { } } } m_knownPlayers.Clear(); foreach (KeyValuePair<long, KnownPlayer> item in dictionary) { m_knownPlayers[item.Key] = item.Value; } } private void LoadRoster() { m_knownPlayers.Clear(); try { string text = DataPath("players"); if (text != null && File.Exists(text)) { ParseRoster(File.ReadAllText(text)); } } catch (Exception ex) { Log.LogWarning((object)("Load player history failed: " + ex)); } HashSet<long> hashSet = new HashSet<long>(m_permPlayers.Keys); hashSet.UnionWith(m_admins); foreach (long item in hashSet) { if (item != 0L && !m_knownPlayers.ContainsKey(item)) { m_knownPlayers[item] = new KnownPlayer { Id = item, Name = "Player " + item, Host = "", LastSeen = 0L }; } } } private void SaveRoster() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !m_permsLoaded) { return; } try { string text = DataPath("players"); if (text != null) { string text2 = text + ".tmp"; File.WriteAllText(text2, SerializeRoster(privateData: true)); if (File.Exists(text)) { File.Replace(text2, text, text + ".bak"); } else { File.Move(text2, text); } } } catch (Exception ex) { Log.LogWarning((object)("Save player history failed: " + ex)); } } private static void RPC_GetRoster(long sender) { if (!DenyQuarantined(sender) && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && IsAdminSender(sender)) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "AdminManager_Roster", new object[1] { m_instance.SerializeRoster(privateData: false) }); } } private static void RPC_Roster(long sender, string data) { if (IsServerMessage(sender) && (Object)(object)m_instance != (Object)null) { m_instance.ParseRoster(data); } } private bool IsOnline(long id) { if ((Object)(object)FindPlayerById(id) != (Object)null) { return true; } if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (!ZNet.instance.IsServer()) { if (m_knownPlayers.TryGetValue(id, out var value)) { return value.Online; } return false; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (PeerPlayerId(peer) == id) { return true; } } return false; } private void DrawOfflineTab() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) GUILayout.Label("Previously connected players", m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.Label("Manage saved permissions and admin access while players are offline.", m_centerLabel, Array.Empty<GUILayoutOption>()); m_rosterSearch = GUILayout.TextField(m_rosterSearch, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Math.Min(520f, ((Rect)(ref m_window)).width - 64f)) }); m_rosterScroll = GUILayout.BeginScrollView(m_rosterScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(160f) }); List<KnownPlayer> list = new List<KnownPlayer>(m_knownPlayers.Values); list.Sort((KnownPlayer a, KnownPlayer b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); int num = 0; foreach (KnownPlayer item in list) { if (!IsOnline(item.Id) && (string.IsNullOrEmpty(m_rosterSearch) || (item.Name ?? "").IndexOf(m_rosterSearch, StringComparison.OrdinalIgnoreCase) >= 0 || item.Id.ToString().Contains(m_rosterSearch))) { num++; if (GUILayout.Button(item.Name, (item.Id == m_offlineSelection) ? m_tabActive : m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { m_offlineSelection = item.Id; } } } if (num == 0) { GUILayout.Label("No offline players recorded yet.", Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(12f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Math.Min(520f, ((Rect)(ref m_window)).width - 64f)) }); if (m_knownPlayers.TryGetValue(m_offlineSelection, out var value) && !IsOnline(value.Id)) { GUILayout.Label(value.Name, m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.Label("Player ID: " + value.Id, m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.Label("Inventory unavailable while offline.", m_centerLabel, Array.Empty<GUILayoutOption>()); GUILayout.Label("Last seen: " + ((value.LastSeen == 0L) ? "not recorded yet" : new DateTime(value.LastSeen, DateTimeKind.Utc).ToLocalTime().ToString("g")), m_centerLabel, Array.Empty<GUILayoutOption>()); if (GUILayout.Button(IsModAdmin(value.Id) ? "Remove mod Admin" : "Grant mod Admin", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ToggleAdmin(value.Id); } DrawQuarantineProfileTools(value.Id); if (GUILayout.Button("Ban this player", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { SendFeature("AdminManager_OfflineBan", value.Id); } } else { GUILayout.Label("Select an offline player.", m_centerLabel, Array.Empty<GUILayoutOption>()); } GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (m_knownPlayers.TryGetValue(m_offlineSelection, out value) && !IsOnline(value.Id)) { DrawPermGrid(value.Id); } } private static void RPC_OfflineBan(long sender, long id) { if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null) { return; } if (!IsAdminSender(sender)) { Reply(sender, "Permission denied.", error: true); return; } if (id == HostPlayerId() || !m_instance.m_knownPlayers.TryGetValue(id, out var value) || string.IsNullOrEmpty(value.Host)) { Reply(sender, "No saved account address is available for this player.", error: true); return; } if (m_instance.IsOnline(id)) { Reply(sender, "Player is online; use the Players tab.", error: true); return; } try { m_banNames[value.Host] = value.Name; ZNet.instance.Ban(value.Host); SaveBanNames(); SendBansTo(sender); Reply(sender, "Banned " + value.Name + " using their last recorded account."); } catch (Exception ex) { Log.LogWarning((object)("Offline ban failed: " + ex)); Reply(sender, "Ban failed; check the server log.", error: true); } } private void RegisterFreeze() { ZRoutedRpc.instance.Register<ZDOID, bool>("AdminManager_FreezeRequest", (Action<long, ZDOID, bool>)RPC_FreezeRequest); ZRoutedRpc.instance.Register<long, bool>("AdminManager_FreezePlayerRequest", (Action<long, long, bool>)RPC_FreezePlayerRequest); ZRoutedRpc.instance.Register<ZDOID, bool>("AdminManager_FreezeApply", (Action<long, ZDOID, bool>)RPC_FreezeApply); ZRoutedRpc.instance.Register<ZDOID, bool, bool>("AdminManager_FreezeResult", (Action<long, ZDOID, bool, bool>)RPC_FreezeResult); } private void ApplyFreezePatches() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown PatchResource(typeof(Player), "FixedUpdate", "FreezeFixedPostfix", prefix: false); PatchResource(typeof(Player), "TakeInput", "FreezeInputPostfix", prefix: false); PatchResource(typeof(Character), "TakeInput", "FreezeCharacterInputPostfix", prefix: false); PatchResource(typeof(PlayerController), "TakeInput", "FreezeControllerInputPostfix", prefix: false); MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2] { typeof(Character), typeof(bool) }, (Type[])null); m_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "FreezeAttackPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool FrozenCharacter(Player player) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)null && (Object)(object)m_instance != (Object)null) { return m_instance.m_ownedFreezes.ContainsKey(((Character)player).GetZDOID()); } return false; } private static void FreezeInputPostfix(Player __instance, ref bool __result) { if (FrozenCharacter(__instance)) { __result = false; } } private static void FreezeCharacterInputPostfix(Character __instance, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && FrozenCharacter(val)) { __result = false; } } private static void FreezeControllerInputPostfix(PlayerController __instance, bool look, ref bool __result) { if (!look && FrozenCharacter(((Component)__instance).GetComponent<Player>())) { __result = false; } } private static bool FreezeAttackPrefix(Humanoid __instance, ref bool __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && FrozenCharacter(val)) { __result = false; return false; } return true; } private static void FreezeFixedPostfix(Player __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00b8: 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_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_instance == (Object)null || !m_instance.m_ownedFreezes.TryGetValue(((Character)__instance).GetZDOID(), out var value)) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { m_instance.RemoveOwnedFreeze(((Character)__instance).GetZDOID()); return; } if ((Object)(object)value.Body != (Object)null) { value.Body.constraints = (RigidbodyConstraints)126; if (!value.Body.isKinematic) { value.Body.linearVelocity = Vector3.zero; value.Body.angularVelocity = Vector3.zero; } value.Body.position = value.Position; value.Body.rotation = value.Rotation; } ((Component)__instance).transform.SetPositionAndRotation(value.Position, value.Rotation); } private bool SetOwnedFreeze(ZDOID character, bool frozen) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!frozen) { RemoveOwnedFreeze(character); return true; } if (m_ownedFreezes.ContainsKey(character)) { return true; } Player val = FindInventoryCharacter(character); ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null); if ((Object)(object)val2 == (Object)null || !val2.IsValid() || !val2.IsOwner()) { return false; } Rigidbody component = ((Component)val).GetComponent<Rigidbody>(); if ((Object)(object)component == (Object)null) { return false; } m_ownedFreezes[character] = new OwnedFreeze { Player = val, Body = component, Constraints = component.constraints, Position = ((Component)val).transform.position, Rotation = ((Component)val).transform.rotation }; component.constraints = (RigidbodyConstraints)126; if (!component.isKinematic) { component.linearVelocity = Vector3.zero; component.angularVelocity = Vector3.zero; } if (val == Player.m_localPlayer) { Feedback("An admin froze your character.", error: true); } return true; } private void RemoveOwnedFreeze(ZDOID character) { //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_0026: Unknown result type (might be due to invalid IL or missing references) if (m_ownedFreezes.TryGetValue(character, out var value)) { if ((Object)(object)value.Body != (Object)null) { value.Body.constraints = value.Constraints; } m_ownedFreezes.Remove(character); if (value.Player == Player.m_localPlayer) { Feedback("Your character is unfrozen."); } } } private unsafe static void RPC_FreezeRequest(long sender, ZDOID character, bool frozen) { //IL_0052: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null) { return; } if (!IsAdminSender(sender)) { Reply(sender, "Permission denied: freeze is admin-only.", error: true); return; } if ((Object)(object)Player.m_localPlayer != (Object)null && character == ((Character)Player.m_localPlayer).GetZDOID()) { Reply(sender, "The host is protected from freeze.", error: true); return; } ZDO val = ((!((ZDOID)(ref character)).IsNone()) ? ZDOMan.instance.GetZDO(character) : null); Player val2 = FindInventoryCharacter(character); GameObject val3 = ((val != null && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null); if (val == null || ((Object)(object)val2 == (Obje