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 SharePermissions v1.0.7
SharePermissions.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("RED")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+aaa6ba81a3622ca3cfb7a1081aceefda53783ded")] [assembly: AssemblyProduct("SharePermissions")] [assembly: AssemblyTitle("SharePermissions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SharePermissions { internal class Events : IOnEventCallback { internal bool registered = false; internal string clientRandomString = string.Empty; private static Random random = new Random(); internal const byte EventCode = 184; internal static Events instance { get; private set; } = null; public Events() { instance = this; if (!registered) { PhotonNetwork.AddCallbackTarget((object)this); registered = true; } } public static void Init() { if (instance == null) { new Events(); } } internal static void SendCommand(string command, string secret, string fromSteamId, object[] args, ReceiverGroup receiverGroup) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown SharePermissions.Logger.LogInfo((object)("Send command: " + command + "; to: " + ((object)(ReceiverGroup)(ref receiverGroup)).ToString())); object[] array = new object[3 + args.Length]; array[0] = command; array[1] = ComputeSha256Hash(secret + fromSteamId); array[2] = fromSteamId; args.CopyTo(array, 3); PhotonNetwork.RaiseEvent((byte)184, (object)array, new RaiseEventOptions { Receivers = receiverGroup }, SendOptions.SendReliable); } private static string ComputeSha256Hash(string rawData) { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(rawData)); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } public void OnEvent(EventData photonEvent) { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) if (photonEvent.Code != 184) { return; } object[] array = (object[])photonEvent.CustomData; int sender = photonEvent.Sender; Room currentRoom = PhotonNetwork.CurrentRoom; Player val = ((currentRoom != null) ? currentRoom.GetPlayer(sender, false) : null); string text = null; bool flag = val != null && val.IsMasterClient; if (val != null) { foreach (PlayerAvatar item in SemiFunc.PlayerGetAll()) { PhotonView val2 = ((item != null) ? ((Component)item).GetComponent<PhotonView>() : null); if ((Object)(object)val2 != (Object)null && val2.Owner != null && val2.Owner.ActorNumber == sender) { text = SemiFunc.PlayerGetSteamID(item); break; } } } string text2 = array[0].ToString(); if (!SemiFunc.IsMasterClient()) { if (text2 == "InitModeratorAck" && flag) { string steamId = array[3].ToString(); Moderators.Instance.AddModerator(steamId); } } else { if (array.Length < 3) { return; } string value = array[1].ToString(); string nickName = val.NickName; string text3 = ComputeSha256Hash(SharePermissions.SecretCode.Value + text); if (text == null) { return; } SteamId val3 = default(SteamId); if (ulong.TryParse(text, out var result)) { SteamId val4 = default(SteamId); val4.Value = result; val3 = val4; } if (!((SteamId)(ref val3)).IsValid) { SharePermissions.Logger.LogWarning((object)("Invalid SteamID received in event from: " + nickName + " (" + text + ")")); return; } if (SharePermissions.SecretCode == null || !text3.Equals(value)) { SharePermissions.Logger.LogWarning((object)("Secret code is not equal, from: " + nickName + " (" + text + "); (your secret: " + text3 + ")")); return; } switch (text2) { case "KickPlayer": { string text7 = array[3].ToString(); string text8 = array[4].ToString(); PlayerAvatar val6 = SemiFunc.PlayerGetFromSteamID(text7); PhotonView val7 = ((val6 != null) ? ((Component)val6).GetComponent<PhotonView>() : null); bool flag2 = (Object)(object)val7 != (Object)null && val7.Owner != null && val7.Owner.IsMasterClient; bool flag3 = Moderators.Instance.IsModerator(text7); if (!flag2 && !flag3) { SharePermissions.LogWrite("Banning request " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")"); SharePermissions.Logger.LogInfo((object)("Banning request " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")")); if (text8 == "kick") { NetworkManager.instance.KickPlayer(val6); } else { NetworkManager.instance.BanPlayer(val6); } } else { SharePermissions.Logger.LogWarning((object)("Ignoring banning request for master client or moderator " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")")); } break; } case "KickGhostPlayer": { string text4 = array[3].ToString(); string text5 = array[4].ToString(); if (int.TryParse(text4, out var result2)) { Room currentRoom2 = PhotonNetwork.CurrentRoom; Player val5 = ((currentRoom2 != null) ? currentRoom2.GetPlayer(result2, false) : null); if (val5 != null) { if (val5.IsMasterClient) { SharePermissions.Logger.LogWarning((object)$"Ignoring ghost kick request for master client (ActorNumber: {result2}) from: {nickName}"); break; } string text6 = PlayerSteamIdCache.Instance.GetSteamId(result2) ?? val5.UserId; if (!string.IsNullOrEmpty(text6) && Moderators.Instance.IsModerator(text6)) { SharePermissions.Logger.LogWarning((object)$"Ignoring ghost kick request for moderator (ActorNumber: {result2}, SteamID: {text6}) from: {nickName}"); break; } PhotonNetwork.CloseConnection(val5); SharePermissions.LogWrite(string.Format("Ghost player kicked (ActorNumber: {0}, Name: {1}, SteamID: {2}) by: {3} ({4})", result2, val5.NickName, text6 ?? "unknown", nickName, text)); SharePermissions.Logger.LogInfo((object)string.Format("Ghost player connection closed: {0} (ActorNumber: {1}, SteamID: {2})", val5.NickName, result2, text6 ?? "unknown")); } else { SharePermissions.Logger.LogWarning((object)$"Ghost player with ActorNumber {result2} not found"); } } else { SharePermissions.Logger.LogWarning((object)("Invalid ActorNumber received for KickGhostPlayer: " + text4)); } break; } case "InitModerator": SharePermissions.Logger.LogInfo((object)("Network event: InitModerator command received for steamId: " + text)); Moderators.Instance.AddModerator(text); SendCommand("InitModeratorAck", "", SemiFunc.PlayerGetSteamID(PlayerAvatar.instance), new object[1] { text }, (ReceiverGroup)0); break; case "StartGame": SharePermissions.Logger.LogInfo((object)"Network event: StartGame command received."); SharePermissions.LogWrite("Start game request from player:" + nickName + "(" + text + ")"); SharePermissions.StartGameClick(); break; case "BackToLobby": SharePermissions.Logger.LogInfo((object)"Network event: BackToLobby command received."); SharePermissions.LogWrite("Return to lobby request from player:" + nickName + "(" + text + ")"); SharePermissions.ReturnLobbyClick(); break; default: SharePermissions.Logger.LogInfo((object)("Network event: Unknown command(" + array.Length + "): " + text2)); break; } } } } internal class Menu { private struct PlayerValidationResult { public bool IsValid; public bool IsSpoofed; public string Reason; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static BuilderDelegate <>9__3_0; public static BuilderDelegate <>9__3_1; public static ShouldCloseMenuDelegate <>9__13_0; public static Func<PlayerAvatar, bool> <>9__13_1; internal void <Init>b__3_0(Transform parent) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(306f, 12f)); ((TMP_Text)val.labelTMP).fontSize = 18f; } internal void <Init>b__3_1(Transform parent) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(166f, 86f)); ((TMP_Text)val.labelTMP).fontSize = 18f; } internal bool <openPlayerListMenu>b__13_0() { return false; } internal bool <openPlayerListMenu>b__13_1(PlayerAvatar pa) { return (Object)(object)pa != (Object)null; } } [CompilerGenerated] private sealed class <openPageInternal>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public REPOPopupPage page; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <openPageInternal>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.05f); <>1__state = 1; return true; case 1: <>1__state = -1; page.OpenPage(false); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool menuOpened; private static REPOPopupPage kickPage; private static MenuButtonPopUp menuButtonPopup; public static void Init() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown object obj = <>c.<>9__3_0; if (obj == null) { BuilderDelegate val = delegate(Transform parent) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) REPOButton val4 = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(306f, 12f)); ((TMP_Text)val4.labelTMP).fontSize = 18f; }; <>c.<>9__3_0 = val; obj = (object)val; } MenuAPI.AddElementToLobbyMenu((BuilderDelegate)obj); object obj2 = <>c.<>9__3_1; if (obj2 == null) { BuilderDelegate val2 = delegate(Transform parent) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) REPOButton val3 = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(166f, 86f)); ((TMP_Text)val3.labelTMP).fontSize = 18f; }; <>c.<>9__3_1 = val2; obj2 = (object)val2; } MenuAPI.AddElementToEscapeMenu((BuilderDelegate)obj2); SharePermissions.Logger.LogInfo((object)"Inited!"); } public static REPOPopupPage createMenu(string title) { REPOPopupPage val = MenuAPI.CreateREPOPopupPage(title, (PresetSide)0, false, true, -5f); addCloseButton(val); return val; } public static void toggleMenu() { if (!menuOpened) { openPlayerListMenu(); } else { closePage(kickPage); } } public static void addLabel(REPOPopupPage parent, string text) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown string text2 = text; parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) REPOLabel val = MenuAPI.CreateREPOLabel(text2, scrollView, default(Vector2)); return ((REPOElement)val).rectTransform; }, 0f, 0f); } public static void addButton(REPOPopupPage parent, string text, Action action) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown string text2 = text; Action action2 = action; parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(text2, action2, scrollView, default(Vector2)); return ((REPOElement)val).rectTransform; }, 0f, 0f); } public static void addKickButton(REPOPopupPage parent, string text, string text2, Action kickAction, Action banAction) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown string text3 = text; Action kickAction2 = kickAction; Action banAction2 = banAction; parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(text3, (Action)delegate { //IL_0015: Unknown result type (might be due to invalid IL or missing references) createCustomPopupMenu("Choose punishment", new Color(1f, 0.553f, 0f), "Player " + text3, kickAction2, banAction2, "Kick", "Ban"); }, scrollView, default(Vector2)); if (text3.Length > 24) { Vector2 labelSize = val.GetLabelSize(); labelSize.x = 250f; val.overrideButtonSize = labelSize; REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>(); val2.maxCharacters = 24; } return ((REPOElement)val).rectTransform; }, 0f, 0f); } public static void addPlayerActionButton(REPOPopupPage parent, string playerName, string steamId, Action kickAction, Action banAction, Action muteAction, Action unmuteAction) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown string playerName2 = playerName; string steamId2 = steamId; Action unmuteAction2 = unmuteAction; Action muteAction2 = muteAction; REPOPopupPage parent2 = parent; Action kickAction2 = kickAction; Action banAction2 = banAction; parent2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(playerName2, (Action)delegate { //IL_0054: Unknown result type (might be due to invalid IL or missing references) bool flag = MutedPlayers.Instance.IsMuted(steamId2); string muteButtonText = (flag ? "Unmute" : "Mute"); Action onMuteClicked = (flag ? unmuteAction2 : muteAction2); closePage(parent2); createPlayerActionPopup("Player Actions", new Color(1f, 0.553f, 0f), "Player: " + playerName2, kickAction2, banAction2, onMuteClicked, muteButtonText); }, scrollView, default(Vector2)); if (playerName2.Length > 24) { Vector2 labelSize = val.GetLabelSize(); labelSize.x = 250f; val.overrideButtonSize = labelSize; REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>(); val2.maxCharacters = 24; } return ((REPOElement)val).rectTransform; }, 0f, 0f); } private static void createPlayerActionPopup(string title, Color headerColor, string message, Action onKickClicked, Action onBanClicked, Action onMuteClicked, string muteButtonText) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown string message2 = message; Action onKickClicked2 = onKickClicked; Action onBanClicked2 = onBanClicked; string muteButtonText2 = muteButtonText; Action onMuteClicked2 = onMuteClicked; REPOPopupPage popupPage = MenuAPI.CreateREPOPopupPage(title, (PresetSide)0, false, true, -5f); popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) REPOLabel val4 = MenuAPI.CreateREPOLabel(message2, scrollView, default(Vector2)); return ((REPOElement)val4).rectTransform; }, 0f, 0f); popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) REPOButton val3 = MenuAPI.CreateREPOButton("Kick", (Action)delegate { closePage(popupPage); onKickClicked2?.Invoke(); }, scrollView, default(Vector2)); return ((REPOElement)val3).rectTransform; }, 0f, 0f); popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) REPOButton val2 = MenuAPI.CreateREPOButton("Ban", (Action)delegate { closePage(popupPage); onBanClicked2?.Invoke(); }, scrollView, default(Vector2)); return ((REPOElement)val2).rectTransform; }, 0f, 0f); popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(muteButtonText2, (Action)delegate { closePage(popupPage); onMuteClicked2?.Invoke(); }, scrollView, default(Vector2)); return ((REPOElement)val).rectTransform; }, 0f, 0f); popupPage.AddElement((BuilderDelegate)delegate(Transform transform) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Cancel", (Action)delegate { closePage(popupPage); }, transform, new Vector2(270f, 20f)); }); openPage(popupPage); } public static void closePage(REPOPopupPage page) { menuOpened = false; page.ClosePage(true); MenuManager.instance.PageRemove(page.menuPage); } public static void addCloseButton(REPOPopupPage parent) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown REPOPopupPage parent2 = parent; parent2.AddElement((BuilderDelegate)delegate(Transform transform) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Close", (Action)delegate { closePage(parent2); }, transform, new Vector2(270f, 20f)); }); } private static void openPlayerListMenu() { //IL_0053: 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_005e: Expected O, but got Unknown //IL_05fe: Unknown result type (might be due to invalid IL or missing references) //IL_0608: Expected O, but got Unknown REPOPopupPage playersMenu = createMenu("Mod menu"); PlayerAvatar instance = PlayerAvatar.instance; string fromSteamId = SemiFunc.PlayerGetSteamID(instance); string secret = SharePermissions.SecretCode.Value; REPOPopupPage obj = playersMenu; object obj2 = <>c.<>9__13_0; if (obj2 == null) { ShouldCloseMenuDelegate val = () => false; <>c.<>9__13_0 = val; obj2 = (object)val; } obj.onEscapePressed = (ShouldCloseMenuDelegate)obj2; kickPage = playersMenu; List<PlayerAvatar> list = (from pa in Object.FindObjectsOfType<PlayerAvatar>() where (Object)(object)pa != (Object)null select pa).ToList(); List<PlayerAvatar> list2 = new List<PlayerAvatar>(); List<PlayerAvatar> list3 = new List<PlayerAvatar>(); HashSet<int> actorNumbersWithAvatars = new HashSet<int>(); foreach (PlayerAvatar item in list) { PlayerValidationResult playerValidationResult = ValidateNetworkPlayer(item); if (playerValidationResult.IsValid) { list2.Add(item); PhotonView component = ((Component)item).GetComponent<PhotonView>(); if (((component != null) ? component.Owner : null) != null) { actorNumbersWithAvatars.Add(component.Owner.ActorNumber); } } else if (playerValidationResult.IsSpoofed) { list3.Add(item); } } List<Player> list4 = PhotonNetwork.PlayerList.Where((Player p) => !actorNumbersWithAvatars.Contains(p.ActorNumber)).ToList(); foreach (PlayerAvatar item2 in list2) { try { string playerSteamId = SemiFunc.PlayerGetSteamID(item2); if (string.IsNullOrEmpty(playerSteamId)) { continue; } string playerDisplayName = Moderators.Instance.GetPlayerDisplayName(item2); if (playerSteamId == fromSteamId) { addLabel(playersMenu, playerDisplayName + " (You)"); continue; } addPlayerActionButton(playersMenu, playerDisplayName, playerSteamId, delegate { Events.SendCommand("KickPlayer", secret, fromSteamId, new object[2] { playerSteamId, "kick" }, (ReceiverGroup)2); closePage(playersMenu); }, delegate { Events.SendCommand("KickPlayer", secret, fromSteamId, new object[2] { playerSteamId, "ban" }, (ReceiverGroup)2); closePage(playersMenu); }, delegate { MutedPlayers.Instance.MutePlayer(playerSteamId); closePage(playersMenu); }, delegate { MutedPlayers.Instance.UnmutePlayer(playerSteamId); closePage(playersMenu); }); } catch (Exception ex) { SharePermissions.Logger.LogWarning((object)$"Failed to add player to the menu: {item2} - {ex.Message}"); } } if (list4.Count > 0) { foreach (Player ghostPlayer in list4) { try { string text = ghostPlayer.NickName ?? $"Unknown_{ghostPlayer.ActorNumber}"; int actorNumber = ghostPlayer.ActorNumber; string text2 = PlayerSteamIdCache.Instance.GetSteamId(actorNumber) ?? ghostPlayer.UserId; string steamNickname = GetSteamNickname(text2); if (!string.IsNullOrEmpty(steamNickname) && steamNickname != text) { text = text + " (" + steamNickname + ")"; } string text3 = "<color=#FFAA00>[GHOST]</color> " + text; addGhostPlayerButton(playersMenu, text3, ghostPlayer, delegate { KickGhostPlayer(ghostPlayer, "kick"); closePage(playersMenu); }, delegate { KickGhostPlayer(ghostPlayer, "ban"); closePage(playersMenu); }); SharePermissions.Logger.LogWarning((object)string.Format("Ghost player detected: {0} (ActorNumber: {1}, SteamID: {2}, SteamNick: {3})", text, actorNumber, text2 ?? "null", steamNickname ?? "null")); } catch (Exception ex2) { SharePermissions.Logger.LogWarning((object)("Failed to add ghost player to menu: " + ex2.Message)); } } } if (list3.Count > 0) { foreach (PlayerAvatar spoofedPlayer in list3) { try { string text4 = ((Object)spoofedPlayer).name; string text5 = null; string text6 = null; try { text5 = SemiFunc.PlayerGetSteamID(spoofedPlayer); text4 = SemiFunc.PlayerGetName(spoofedPlayer) ?? text4; text6 = GetSteamNickname(text5); } catch { } string text7 = text4; if (!string.IsNullOrEmpty(text6) && text6 != text4) { text7 = text4 + " (" + text6 + ")"; } string text8 = "<color=#FF6600>[SPOOF]</color> " + text7; addSpoofedPlayerButton(playersMenu, text8, spoofedPlayer, delegate { KickSpoofedPlayer(spoofedPlayer, "kick"); closePage(playersMenu); }, delegate { KickSpoofedPlayer(spoofedPlayer, "ban"); closePage(playersMenu); }); SharePermissions.Logger.LogWarning((object)("Spoofed player added to menu: " + text4 + " (SteamID: " + (text5 ?? "null") + ", SteamNick: " + (text6 ?? "null") + ")")); } catch (Exception ex3) { SharePermissions.Logger.LogWarning((object)("Failed to add spoofed player to menu: " + ex3.Message)); } } } playersMenu.AddElement((BuilderDelegate)delegate(Transform transform) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.RunIsLobbyMenu()) { MenuAPI.CreateREPOButton("Start game", (Action)delegate { //IL_0015: Unknown result type (might be due to invalid IL or missing references) MenuAPI.OpenPopup("Confirm", new Color(1f, 0.553f, 0f), "Start the game or maybe 5 minutes wait?", (Action)delegate { Events.SendCommand("StartGame", secret, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2); closePage(playersMenu); }, (Action)null); }, transform, new Vector2(150f, 20f)); } else { MenuAPI.CreateREPOButton("Back to lobby", (Action)delegate { //IL_0015: Unknown result type (might be due to invalid IL or missing references) MenuAPI.OpenPopup("Confirm", new Color(1f, 0.553f, 0f), "Back to the lobby?", (Action)delegate { Events.SendCommand("BackToLobby", secret, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2); closePage(playersMenu); }, (Action)null); }, transform, new Vector2(150f, 20f)); } }); openPage(playersMenu); } public static void addSpoofedPlayerButton(REPOPopupPage parent, string text, PlayerAvatar spoofedPlayer, Action kickAction, Action banAction) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown string text2 = text; Action kickAction2 = kickAction; Action banAction2 = banAction; parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(text2, (Action)delegate { //IL_0015: Unknown result type (might be due to invalid IL or missing references) createCustomPopupMenu("Suspicious Player", new Color(1f, 0.2f, 0f), "This player may be spoofed!\n" + text2, kickAction2, banAction2, "Kick", "Ban"); }, scrollView, default(Vector2)); if (text2.Length > 24) { Vector2 labelSize = val.GetLabelSize(); labelSize.x = 250f; val.overrideButtonSize = labelSize; REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>(); val2.maxCharacters = 24; } return ((REPOElement)val).rectTransform; }, 0f, 0f); } private static void KickSpoofedPlayer(PlayerAvatar spoofedPlayer, string type) { try { string text = null; try { text = SemiFunc.PlayerGetSteamID(spoofedPlayer); } catch { } if (!string.IsNullOrEmpty(text)) { string fromSteamId = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance); string value = SharePermissions.SecretCode.Value; Events.SendCommand("KickPlayer", value, fromSteamId, new object[2] { text, type }, (ReceiverGroup)2); SharePermissions.Logger.LogInfo((object)("Sent kick command for spoofed player via SteamID: " + text)); return; } PhotonView component = ((Component)spoofedPlayer).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null && component.Owner != null && SemiFunc.IsMasterClient()) { if (type == "kick") { NetworkManager.instance.KickPlayer(spoofedPlayer); } else { NetworkManager.instance.BanPlayer(spoofedPlayer); } SharePermissions.Logger.LogInfo((object)("Kicked spoofed player directly: " + ((Object)spoofedPlayer).name)); } else if (SemiFunc.IsMasterClient()) { PhotonNetwork.Destroy(((Component)spoofedPlayer).gameObject); SharePermissions.Logger.LogInfo((object)("Destroyed spoofed player object: " + ((Object)spoofedPlayer).name)); } else { SharePermissions.Logger.LogWarning((object)"Cannot kick spoofed player - not master client and no valid identifiers"); } } catch (Exception ex) { SharePermissions.Logger.LogError((object)("Failed to kick spoofed player: " + ex.Message)); } } public static void addGhostPlayerButton(REPOPopupPage parent, string text, Player ghostPlayer, Action kickAction, Action banAction) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown string text2 = text; Player ghostPlayer2 = ghostPlayer; Action kickAction2 = kickAction; Action banAction2 = banAction; parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(text2, (Action)delegate { //IL_003b: Unknown result type (might be due to invalid IL or missing references) string message = $"Player: {ghostPlayer2.NickName}\nActorNumber: {ghostPlayer2.ActorNumber}\nNo avatar spawned!"; createCustomPopupMenu("Ghost Player", new Color(1f, 0.67f, 0f), message, kickAction2, banAction2, "Kick", "Ban"); }, scrollView, default(Vector2)); if (text2.Length > 24) { Vector2 labelSize = val.GetLabelSize(); labelSize.x = 250f; val.overrideButtonSize = labelSize; REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>(); val2.maxCharacters = 24; } return ((REPOElement)val).rectTransform; }, 0f, 0f); } private static void KickGhostPlayer(Player ghostPlayer, string type) { try { if (ghostPlayer == null) { SharePermissions.Logger.LogWarning((object)"Cannot kick null ghost player"); return; } string text = PlayerSteamIdCache.Instance.GetSteamId(ghostPlayer.ActorNumber) ?? ghostPlayer.UserId; if (!string.IsNullOrEmpty(text)) { PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(text); if ((Object)(object)val != (Object)null) { if (SemiFunc.IsMasterClient()) { if (type == "kick") { NetworkManager.instance.KickPlayer(val); } else { NetworkManager.instance.BanPlayer(val); } SharePermissions.Logger.LogInfo((object)("Kicked ghost player via found avatar: " + ghostPlayer.NickName)); } else { string fromSteamId = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance); string value = SharePermissions.SecretCode.Value; Events.SendCommand("KickPlayer", value, fromSteamId, new object[2] { text, type }, (ReceiverGroup)2); SharePermissions.Logger.LogInfo((object)("Sent kick command for ghost player: " + ghostPlayer.NickName)); } return; } } if (SemiFunc.IsMasterClient()) { PhotonNetwork.CloseConnection(ghostPlayer); SharePermissions.Logger.LogInfo((object)$"Closed connection for ghost player: {ghostPlayer.NickName} (ActorNumber: {ghostPlayer.ActorNumber})"); return; } string fromSteamId2 = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance); string value2 = SharePermissions.SecretCode.Value; Events.SendCommand("KickGhostPlayer", value2, fromSteamId2, new object[2] { ghostPlayer.ActorNumber.ToString(), type }, (ReceiverGroup)2); SharePermissions.Logger.LogInfo((object)$"Sent kick ghost command for: {ghostPlayer.NickName} (ActorNumber: {ghostPlayer.ActorNumber})"); } catch (Exception ex) { SharePermissions.Logger.LogError((object)("Failed to kick ghost player: " + ex.Message)); } } private static string GetSteamNickname(string steamIdString) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) if (string.IsNullOrEmpty(steamIdString)) { return null; } try { if (!ulong.TryParse(steamIdString, out var result)) { return null; } SteamId val = default(SteamId); val.Value = result; SteamId val2 = val; if (!((SteamId)(ref val2)).IsValid) { return null; } Friend val3 = default(Friend); ((Friend)(ref val3))..ctor(val2); string name = ((Friend)(ref val3)).Name; if (string.IsNullOrEmpty(name) || name == steamIdString) { return null; } return name; } catch (Exception ex) { SharePermissions.Logger.LogWarning((object)("Failed to get Steam nickname for " + steamIdString + ": " + ex.Message)); return null; } } private static PlayerValidationResult ValidateNetworkPlayer(PlayerAvatar player) { //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { PlayerValidationResult result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = false; result.Reason = "Null player"; return result; } try { PhotonView component = ((Component)player).GetComponent<PhotonView>(); PlayerValidationResult result; if ((Object)(object)component == (Object)null) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = true; result.Reason = "No PhotonView component"; return result; } if (component.Owner == null) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = true; result.Reason = "PhotonView has no owner"; return result; } int actorNumber = component.Owner.ActorNumber; if (!PhotonNetwork.PlayerList.Any((Player p) => p.ActorNumber == actorNumber)) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = true; result.Reason = $"ActorNumber {actorNumber} not in PhotonNetwork.PlayerList"; return result; } string text = SemiFunc.PlayerGetSteamID(player); if (string.IsNullOrEmpty(text)) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = false; result.Reason = "No Steam ID"; return result; } if (!ulong.TryParse(text, out var result2)) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = true; result.Reason = "Invalid Steam ID format: " + text; return result; } SteamId val = default(SteamId); val.Value = result2; SteamId val2 = val; if (!((SteamId)(ref val2)).IsValid) { result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = true; result.Reason = "Steam ID not valid: " + text; return result; } result = default(PlayerValidationResult); result.IsValid = true; result.IsSpoofed = false; result.Reason = "Valid"; return result; } catch (Exception ex) { PlayerValidationResult result = default(PlayerValidationResult); result.IsValid = false; result.IsSpoofed = false; result.Reason = "Exception: " + ex.Message; return result; } } [IteratorStateMachine(typeof(<openPageInternal>d__21))] private static IEnumerator openPageInternal(REPOPopupPage page) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <openPageInternal>d__21(0) { page = page }; } public static void openPage(REPOPopupPage page) { menuOpened = true; ((MonoBehaviour)MenuManager.instance).StartCoroutine(openPageInternal(page)); } private static void createCustomPopupMenu(string title, Color headerColor, string message, Action onLeftClicked, Action onRightClicked, string leftTitle = "Yes", string rightTitle = "No") { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)menuButtonPopup)) { menuButtonPopup = ((Component)MenuManager.instance).gameObject.AddComponent<MenuButtonPopUp>(); } menuButtonPopup.option1Event = new UnityEvent(); menuButtonPopup.option2Event = new UnityEvent(); if (onLeftClicked != null) { menuButtonPopup.option1Event.AddListener(new UnityAction(onLeftClicked.Invoke)); } if (onRightClicked != null) { menuButtonPopup.option2Event.AddListener(new UnityAction(onRightClicked.Invoke)); } MenuManager.instance.PagePopUpTwoOptions(menuButtonPopup, title, headerColor, message, leftTitle, rightTitle, true); } } [HarmonyPatch(typeof(LoadBalancingClient))] internal class LoadBalancingClientPatch { private const byte VoiceEventCode = 203; [HarmonyPatch("OnEvent")] [HarmonyPrefix] private static bool OnEvent_Prefix(EventData photonEvent) { if (photonEvent.Code == 203) { int sender = photonEvent.Sender; if (MutedPlayers.Instance.IsActorMuted(sender)) { return false; } Room currentRoom = PhotonNetwork.CurrentRoom; Player val = ((currentRoom != null) ? currentRoom.GetPlayer(sender, false) : null); if (val != null) { foreach (PlayerAvatar item in SemiFunc.PlayerGetAll()) { PhotonView val2 = ((item != null) ? ((Component)item).GetComponent<PhotonView>() : null); if ((Object)(object)val2 != (Object)null && val2.Owner != null && val2.Owner.ActorNumber == sender) { string text = SemiFunc.PlayerGetSteamID(item); if (!string.IsNullOrEmpty(text)) { MutedPlayers.Instance.RegisterActorNumber(text, sender); if (MutedPlayers.Instance.IsMuted(text)) { return false; } break; } break; } } } } return true; } } internal class Moderators { private static Moderators _instance; private HashSet<string> moderatorSteamIds = new HashSet<string>(); private const string ModeratorIcon = "[M]"; private const string HostIcon = "[H]"; internal static Moderators Instance { get { if (_instance == null) { _instance = new Moderators(); } return _instance; } } public Moderators() { _instance = this; } public void AddModerator(string steamId) { if (!string.IsNullOrEmpty(steamId) && !moderatorSteamIds.Contains(steamId)) { moderatorSteamIds.Add(steamId); SharePermissions.Logger.LogInfo((object)("Added moderator: " + steamId)); } } public void RemoveModerator(string steamId) { if (moderatorSteamIds.Contains(steamId)) { moderatorSteamIds.Remove(steamId); SharePermissions.Logger.LogInfo((object)("Removed moderator: " + steamId)); } } public bool IsModerator(string steamId) { return !string.IsNullOrEmpty(steamId) && moderatorSteamIds.Contains(steamId); } public bool IsModerator(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } string steamId = SemiFunc.PlayerGetSteamID(player); return IsModerator(steamId); } public bool IsHost(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } PhotonView component = ((Component)player).GetComponent<PhotonView>(); return (Object)(object)component != (Object)null && component.Owner != null && component.Owner.IsMasterClient; } public string GetPlayerDisplayName(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return ""; } string text = SemiFunc.PlayerGetName(player); string playerIcon = GetPlayerIcon(player); return string.IsNullOrEmpty(playerIcon) ? text : ("<color=#FFD700>" + playerIcon + "</color> " + text); } public string GetPlayerIcon(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return ""; } if (IsHost(player)) { return "[H]"; } if (IsModerator(player)) { return "[M]"; } return ""; } public string GetPlayerEmoji(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return ""; } if (IsHost(player)) { return "[H]"; } if (IsModerator(player)) { return "[M]"; } return ""; } public List<string> GetAllModerators() { return moderatorSteamIds.ToList(); } public void ClearModerators() { moderatorSteamIds.Clear(); SharePermissions.Logger.LogInfo((object)"Cleared all moderators"); } public int GetModeratorCount() { return moderatorSteamIds.Count; } public bool HasPermissions(PlayerAvatar player) { return IsHost(player) || IsModerator(player); } public bool HasPermissions(string steamId) { if (string.IsNullOrEmpty(steamId)) { return false; } PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(steamId); if ((Object)(object)val == (Object)null) { return IsModerator(steamId); } return HasPermissions(val); } public static void Init() { if (_instance == null) { new Moderators(); SharePermissions.Logger.LogInfo((object)"Moderators system initialized"); } } } internal class MutedPlayers { private static MutedPlayers _instance; private HashSet<string> mutedSteamIds = new HashSet<string>(); private Dictionary<string, int> steamIdToActorNumber = new Dictionary<string, int>(); internal static MutedPlayers Instance { get { if (_instance == null) { _instance = new MutedPlayers(); } return _instance; } } public MutedPlayers() { _instance = this; } public void MutePlayer(string steamId) { if (!string.IsNullOrEmpty(steamId) && !mutedSteamIds.Contains(steamId)) { mutedSteamIds.Add(steamId); SharePermissions.Logger.LogInfo((object)("Muted player: " + steamId)); } } public void UnmutePlayer(string steamId) { if (mutedSteamIds.Contains(steamId)) { mutedSteamIds.Remove(steamId); SharePermissions.Logger.LogInfo((object)("Unmuted player: " + steamId)); } } public bool IsMuted(string steamId) { return !string.IsNullOrEmpty(steamId) && mutedSteamIds.Contains(steamId); } public bool IsMuted(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } string steamId = SemiFunc.PlayerGetSteamID(player); return IsMuted(steamId); } public void ToggleMute(string steamId) { if (IsMuted(steamId)) { UnmutePlayer(steamId); } else { MutePlayer(steamId); } } public void RegisterActorNumber(string steamId, int actorNumber) { if (!string.IsNullOrEmpty(steamId)) { steamIdToActorNumber[steamId] = actorNumber; } } public bool IsActorMuted(int actorNumber) { foreach (KeyValuePair<string, int> item in steamIdToActorNumber) { if (item.Value == actorNumber && mutedSteamIds.Contains(item.Key)) { return true; } } return false; } public string GetSteamIdByActorNumber(int actorNumber) { foreach (KeyValuePair<string, int> item in steamIdToActorNumber) { if (item.Value == actorNumber) { return item.Key; } } return null; } public List<string> GetAllMutedPlayers() { return mutedSteamIds.ToList(); } public void ClearMutedPlayers() { mutedSteamIds.Clear(); steamIdToActorNumber.Clear(); SharePermissions.Logger.LogInfo((object)"Cleared all muted players"); } public int GetMutedCount() { return mutedSteamIds.Count; } public static void Init() { if (_instance == null) { new MutedPlayers(); SharePermissions.Logger.LogInfo((object)"MutedPlayers system initialized"); } } } [HarmonyPatch(typeof(NetworkConnect))] internal class NetworkConnectPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void Start_Postfix() { Events.Init(); PlayerSteamIdCache.Init(); } [HarmonyPatch("OnCreatedRoom")] [HarmonyPostfix] private static void OnCreatedRoom_Postfix() { SharePermissions.Logger.LogInfo((object)"onCreateRoom"); } [HarmonyPatch("OnJoinedRoom")] [HarmonyPostfix] private static void OnJoinedRoom_Postfix() { SharePermissions.Logger.LogInfo((object)"onJoinRoom"); PlayerSteamIdCache.Instance.RefreshFromAvatars(); if (!SemiFunc.IsMasterClient()) { PlayerAvatar instance = PlayerAvatar.instance; string fromSteamId = SemiFunc.PlayerGetSteamID(instance); string value = SharePermissions.SecretCode.Value; Events.SendCommand("InitModerator", value, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2); } } [HarmonyPatch("OnDisconnected")] [HarmonyPostfix] private static void OnDisconnected_Postfix() { SharePermissions.Logger.LogInfo((object)"Left room - clearing all moderators"); Moderators.Instance.ClearModerators(); MutedPlayers.Instance.ClearMutedPlayers(); PlayerSteamIdCache.Instance.Clear(); } } [HarmonyPatch(typeof(NetworkManager))] internal class NetworkManagerPatch { [HarmonyPatch("OnPlayerEnteredRoom")] [HarmonyPostfix] private static void OnPlayerEnteredRoom_Postfix(Player newPlayer) { if (newPlayer == null) { return; } foreach (PlayerAvatar item in SemiFunc.PlayerGetAll()) { if ((Object)(object)item == (Object)null) { continue; } PhotonView component = ((Component)item).GetComponent<PhotonView>(); if (((component != null) ? component.Owner : null) == null || component.Owner.ActorNumber != newPlayer.ActorNumber) { continue; } string text = SemiFunc.PlayerGetSteamID(item); if (!string.IsNullOrEmpty(text)) { PlayerSteamIdCache.Instance.RegisterPlayer(newPlayer.ActorNumber, text); } break; } } [HarmonyPatch("OnPlayerLeftRoom")] [HarmonyPostfix] private static void OnPlayerLeftRoom_Postfix(Player otherPlayer) { if (otherPlayer == null) { return; } string text = PlayerSteamIdCache.Instance.GetSteamId(otherPlayer.ActorNumber) ?? otherPlayer.UserId; if (!string.IsNullOrEmpty(text)) { if (Moderators.Instance.IsModerator(text)) { Moderators.Instance.RemoveModerator(text); SharePermissions.Logger.LogInfo((object)("Player " + otherPlayer.NickName + " (" + text + ") left - removed moderator status")); } if (MutedPlayers.Instance.IsMuted(text)) { MutedPlayers.Instance.UnmutePlayer(text); SharePermissions.Logger.LogInfo((object)("Player " + otherPlayer.NickName + " (" + text + ") left - removed mute status")); } } PlayerSteamIdCache.Instance.UnregisterPlayer(otherPlayer.ActorNumber); } } internal class PlayerSteamIdCache { private static PlayerSteamIdCache _instance; private readonly Dictionary<int, string> actorToSteamId = new Dictionary<int, string>(); internal static PlayerSteamIdCache Instance { get { if (_instance == null) { _instance = new PlayerSteamIdCache(); } return _instance; } } public PlayerSteamIdCache() { _instance = this; } public void RegisterPlayer(int actorNumber, string steamId) { if (actorNumber > 0 && !string.IsNullOrEmpty(steamId)) { if (actorToSteamId.TryGetValue(actorNumber, out string value) && value != steamId) { SharePermissions.Logger.LogWarning((object)$"ActorNumber {actorNumber} already registered with different SteamID: {value} -> {steamId}"); } actorToSteamId[actorNumber] = steamId; SharePermissions.Logger.LogInfo((object)$"Registered player mapping: ActorNumber {actorNumber} -> SteamID {steamId}"); } } public string GetSteamId(int actorNumber) { if (actorToSteamId.TryGetValue(actorNumber, out string value)) { return value; } return null; } public string GetSteamId(Player player) { if (player == null) { return null; } return GetSteamId(player.ActorNumber); } public void UnregisterPlayer(int actorNumber) { if (actorToSteamId.Remove(actorNumber)) { SharePermissions.Logger.LogInfo((object)$"Unregistered player mapping for ActorNumber {actorNumber}"); } } public void Clear() { actorToSteamId.Clear(); SharePermissions.Logger.LogInfo((object)"Cleared player Steam ID cache"); } public void RefreshFromAvatars() { List<PlayerAvatar> list = SemiFunc.PlayerGetAll(); if (list == null) { return; } foreach (PlayerAvatar item in list) { if ((Object)(object)item == (Object)null) { continue; } PhotonView component = ((Component)item).GetComponent<PhotonView>(); if (((component != null) ? component.Owner : null) != null) { int actorNumber = component.Owner.ActorNumber; string text = SemiFunc.PlayerGetSteamID(item); if (!string.IsNullOrEmpty(text)) { RegisterPlayer(actorNumber, text); } } } } public static void Init() { if (_instance == null) { new PlayerSteamIdCache(); SharePermissions.Logger.LogInfo((object)"PlayerSteamIdCache initialized"); } } } [HarmonyPatch(typeof(RunManager))] internal class RunPatch { private static bool lastKeyState; [HarmonyPatch("Update")] [HarmonyPostfix] private static void Update_Postfix(RunPatch __instance) { bool key = Input.GetKey((KeyCode)32); if (!lastKeyState && key) { if (SemiFunc.RunIsLobbyMenu()) { Menu.toggleMenu(); } lastKeyState = key; } else if (lastKeyState && !key) { lastKeyState = key; } } [HarmonyPrefix] [HarmonyPatch("RestartScene")] [HarmonyWrapSafe] private static void RestartScene_Prefix(RunManager __instance) { if (SharePermissions.IsReturningToLobby && __instance.restarting && !__instance.restartingDone && (Object)(object)GameDirector.instance != (Object)null && GameDirector.instance.PlayerList.All((PlayerAvatar p) => p.outroDone)) { SharePermissions.IsReturningToLobby = false; NetworkManager.instance.DestroyAll(); } } } [BepInPlugin("RED.SharePermissions", "SharePermissions", "1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SharePermissions : BaseUnityPlugin { private static string _logPath; public static bool IsReturningToLobby; internal static SharePermissions Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } public static ConfigEntry<string> SecretCode { get; private set; } private static string LogPath { get { if (!string.IsNullOrEmpty(_logPath)) { return _logPath; } try { _logPath = Path.Combine(Paths.ConfigPath, "sharepermissions.log"); } catch { _logPath = Path.Combine(Application.persistentDataPath, "sharepermissions.log"); } return _logPath; } } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); Menu.Init(); Moderators.Init(); Configuration(((BaseUnityPlugin)this).Config); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } public static void LogWrite(string line) { try { string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); string text2 = "[" + text + "] " + line; string directoryName = Path.GetDirectoryName(LogPath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.AppendAllText(LogPath, text2 + Environment.NewLine); } catch (Exception arg) { Logger.LogError((object)$"[SharePermissions] Log save failed: {arg}"); } } internal void Configuration(ConfigFile config) { SecretCode = config.Bind<string>("General", "SecretCode", "", "Code for share permission"); } public static void ReturnLobbyClick() { IsReturningToLobby = true; RunManager instance = RunManager.instance; int num = ((instance.levelCurrent == instance.levelShop) ? 1 : 0); instance.ChangeLevel(true, SemiFunc.RunIsArena(), (ChangeLevelType)3); SemiFunc.StatSetSaveLevel(num); instance.loadLevel = num; StatsManager.instance.SaveFileSave(); } public static void StartGameClick() { RunManager instance = RunManager.instance; instance.ChangeLevel(false, SemiFunc.RunIsArena(), (ChangeLevelType)0); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { } } }