// get the trusted player IDs from the commandline private static void GetTrustedPlayerIds() { if (trustedPlayers != null) { return; // already set } trustedPlayers = new List <MPBanEntry>(); string idstring = null; if (!GameMod.Core.GameMod.FindArgVal("-trustedPlayerIds", out idstring) || String.IsNullOrEmpty(idstring)) { return; // no trustedPlayerIds specified; } string[] ids = idstring.Split(',', ';', ':', '|'); foreach (string id in ids) { MPBanEntry entry = new MPBanEntry(null, null, id); if (entry.IsValid()) { bool doAdd = true; foreach (MPBanEntry e in trustedPlayers) { if (e.matches(entry, "TRUSTED PLAYER: ")) { doAdd = false; } } if (doAdd) { Debug.LogFormat("MPChatCommands: adding trusted player {0}", entry.Describe()); trustedPlayers.Add(entry); } } } }
// check if the entry matches some player public bool matches(MPBanEntry candidate, string prefix = "") { /* name isn't a good criteria, so ignore it * if (!String.IsNullOrEmpty(name) && !String.IsNullOrEmpty(candidate.name)) { * if (name == candidate.name) { * Debug.LogFormat("{0}player {1} matches ban list entry {1} by NAME", prefix, candidate.Describe(), Describe()); * return true; * } * * }*/ if (!String.IsNullOrEmpty(address) && !String.IsNullOrEmpty(candidate.address)) { if (address == candidate.address) { Debug.LogFormat("{0}player {1} matches entry {2} by ADDRESS", prefix, candidate.Describe(), Describe()); return(true); } } if (!String.IsNullOrEmpty(id) && !String.IsNullOrEmpty(candidate.id)) { if (id == candidate.id) { Debug.LogFormat("{0}player {1} matches entry {2} by ID", prefix, candidate.Describe(), Describe()); return(true); } } // does not match return(false); }
// helper function to send a lobby chat message private static void SendToLobbyHelper(LobbyChatMessage lmsg, int connection_id, bool authOnly, bool unblockedOnly) { bool doSend = true; if (authOnly || unblockedOnly) { MPBanEntry entry = MPChatCommand.FindPlayerEntryForConnection(connection_id, true); if (authOnly) { doSend = doSend && MPChatCommand.CheckPermission(entry); } if (doSend && unblockedOnly) { if (entry != null) { doSend = !MPBanPlayers.IsBanned(entry, MPBanMode.BlockChat); } else { doSend = false; } } } if (doSend) { NetworkServer.SendToClient(connection_id, 75, lmsg); } }
// Find the player name string based on a connection ID public static string FindPlayerNameForConnection(int conn_id, bool inLobby) { MPBanEntry entry = FindPlayerEntryForConnection(conn_id, inLobby); if (entry != null && !String.IsNullOrEmpty(entry.name)) { return(entry.name); } return(""); }
// Remove all entries matching a candidate from the ban list public static int Unban(MPBanEntry candidate, MPBanMode mode = MPBanMode.Ban) { var banList = GetList(mode); int cnt = banList.RemoveAll(entry => entry.matches(candidate, "UNBAN: ")); if (cnt > 0) { OnUpdate(mode, false); } return(cnt); }
// Check if this player is banned public static bool IsBanned(MPBanEntry candidate, MPBanMode mode = MPBanMode.Ban) { var banList = GetList(mode); foreach (var entry in banList) { if (entry.matches(candidate, "BAN CHECK: ")) { return(true); } } // no ban entry matches this player.. return(false); }
// Check if a player is an authenticated player on this server public static bool IsAuthenticatedPlayer(MPBanEntry playerEntry) { if (playerEntry == null || !playerEntry.IsValid()) { Debug.LogFormat("IsAuthenticatedPlayer without valid player"); return(false); } foreach (MPBanEntry e in authenticatedPlayers) { if (e.matches(playerEntry, "AUTHENTICATED PLAYER: ")) { return(true); } } return(false); }
// Annoys all Players which are actively annoy-banned // Doesn't work in the lobby public static void AnnoyPlayers() { if (GetList(MPBanMode.Annoy).Count < 1) { // no bans active return; } foreach (var p in Overload.NetworkManager.m_Players) { MPBanEntry candidate = new MPBanEntry(p); if (IsBanned(candidate, MPBanMode.Annoy)) { AnnoyPlayer(p); } } }
// Check if a player is a trusted player on this server public static bool IsTrustedPlayer(MPBanEntry entry) { if (entry == null || String.IsNullOrEmpty(entry.id)) { return(false); } GetTrustedPlayerIds(); foreach (MPBanEntry e in trustedPlayers) { if (e.matches(entry, "TRUSTED PLAYER: ")) { Debug.LogFormat("MPChatCommands: player {0} id {0} is trusted on this server", entry.name, entry.id); return(true); } } return(false); }
// check if a specific player has chat command permissions public static bool CheckPermission(MPBanEntry entry) { if (entry == null) { return(false); } if (MPBanPlayers.MatchCreator != null && entry.matches(MPBanPlayers.MatchCreator, "MATCH CREATOR: ")) { // the match creator is always authenticated return(true); } if (String.IsNullOrEmpty(entry.id)) { return(false); } // Trusted Players always have permission if (IsTrustedPlayer(entry)) { return(true); } return(IsAuthenticatedPlayer(entry)); }
// Kicks all players who are BANNED (Lobby and otherwise) public static void KickBannedPlayers() { if (GetList(MPBanMode.Ban).Count < 1) { // no bans active return; } MatchState s = NetworkMatch.GetMatchState(); bool inLobby = (s == MatchState.LOBBY || s == MatchState.LOBBY_LOAD_COUNTDOWN); if (inLobby) { // Kick Lobby Players foreach (KeyValuePair <int, PlayerLobbyData> p in NetworkMatch.m_players) { if (p.Value != null) { MPBanEntry candidate = new MPBanEntry(p.Value); if (IsBanned(candidate, MPBanMode.Ban)) { KickPlayer(p.Value, true); } } } } else { foreach (var p in Overload.NetworkManager.m_Players) { MPBanEntry candidate = new MPBanEntry(p); if (IsBanned(candidate, MPBanMode.Ban)) { KickPlayer(p, true); } } } }
// Add a player to the Ban List public static bool Ban(MPBanEntry candidate, MPBanMode mode = MPBanMode.Ban, bool permanent = false) { if (!candidate.IsValid()) { return(false); } candidate.permanent = permanent; var banList = GetList(mode); foreach (var entry in banList) { if (entry.matches(candidate, "BAN already matched: ")) { // Update it entry.Set(candidate); OnUpdate(mode, true); return(false); } } banList.Add(candidate); Debug.LogFormat("BAN: player {0} is NOW banned in mode: {1}", candidate.Describe(), mode); OnUpdate(mode, true); return(true); }
// set authentication status of player by id private static bool SetAuth(bool allowed, MPBanEntry playerEntry) { if (playerEntry == null || !playerEntry.IsValid()) { Debug.LogFormat("SETAUTH called without valid player"); return(false); } if (allowed) { Debug.LogFormat("AUTH: player {0} is authenticated", playerEntry.name); bool doAdd = true; foreach (MPBanEntry entry in authenticatedPlayers) { if (entry.matches(playerEntry, "AUTHENTICATED PLAYER: ")) { entry.Set(playerEntry); doAdd = false; } } if (doAdd) { authenticatedPlayers.Add(playerEntry); } } else { // de-auth Debug.LogFormat("AUTH: player {0} is NOT authenticated any more", playerEntry.name); if (authenticatedPlayers.RemoveAll(entry => entry.matches(playerEntry, "AUTHENTICATED PLAYER: ")) < 1) { return(false); } } return(true); }
// Select a player by a pattern public bool SelectPlayer(string pattern) { selectedPlayerEntry = null; selectedPlayer = null; selectedPlayerLobbyData = null; selectedPlayerConnectionId = -1; if (inLobby) { selectedPlayerLobbyData = FindPlayerInLobby(pattern); if (selectedPlayerLobbyData != null) { selectedPlayerEntry = new MPBanEntry(selectedPlayerLobbyData); selectedPlayerConnectionId = selectedPlayerLobbyData.m_id; if (selectedPlayerConnectionId >= NetworkServer.connections.Count) { selectedPlayerConnectionId = -1; } return(true); } } else { selectedPlayer = FindPlayer(pattern); if (selectedPlayer != null) { selectedPlayerEntry = new MPBanEntry(selectedPlayer); selectedPlayerConnectionId = (selectedPlayer.connectionToClient != null)?selectedPlayer.connectionToClient.connectionId:-1; if (selectedPlayerConnectionId >= NetworkServer.connections.Count) { selectedPlayerConnectionId = -1; } return(true); } } return(false); }
private static IEnumerator MatchStart(int connectionId) { var newPlayer = Server.FindPlayerByConnectionId(connectionId); MPBanEntry newPlayerEntry = new MPBanEntry(newPlayer); // prevent banned players from JIP into our match // there is already a delayed Disconnect going on, just // prevent this player from entering the JIP code if (MPBanPlayers.IsBanned(newPlayerEntry)) { yield break; } float pregameWait = 3f; if (!newPlayer.m_mp_name.StartsWith("OBSERVER")) { foreach (Player player in Overload.NetworkManager.m_Players) { if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip")) { NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage { playerId = newPlayer.netId, ready = false }); } } MPJoinInProgress.SetReady(newPlayer, false, true); // special case: do not disable the player completely, as this would prevent this player to be sent to new clients joining before we finally switch to ready } pregameWait = SendPreGame(connectionId, pregameWait); yield return(new WaitForSeconds(pregameWait)); Server.SendLoadoutDataToClients(); if (newPlayer.m_mp_name.StartsWith("OBSERVER")) { Debug.LogFormat("Enabling spectator for {0}", newPlayer.m_mp_name); newPlayer.Networkm_spectator = true; Debug.LogFormat("Enabled spectator for {0}", newPlayer.m_mp_name); yield return(null); // make sure spectator change is received before sending MatchStart } else { foreach (Player player in Overload.NetworkManager.m_Players) { if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip")) { NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage { playerId = newPlayer.netId, ready = true }); } } MPJoinInProgress.SetReady(newPlayer, true); } if (NetworkMatch.GetMatchState() != MatchState.PLAYING) { yield break; } IntegerMessage modeMsg = new IntegerMessage((int)NetworkMatch.GetMode()); NetworkServer.SendToClient(connectionId, CustomMsgType.MatchStart, modeMsg); SendMatchState(connectionId); NetworkSpawnPlayer.Respawn(newPlayer.c_player_ship); MPTweaks.Send(connectionId); //if (!newPlayer.m_spectator && RearView.MPNetworkMatchEnabled) // newPlayer.CallTargetAddHUDMessage(newPlayer.connectionToClient, "REARVIEW ENABLED", -1, true); CTF.SendJoinUpdate(newPlayer); Race.SendJoinUpdate(newPlayer); foreach (Player player in Overload.NetworkManager.m_Players) { if (player.connectionToClient.connectionId == connectionId) { continue; } // Resend mode for existing player to move h2h -> anarchy NetworkServer.SendToClient(player.connectionToClient.connectionId, CustomMsgType.MatchStart, modeMsg); if (!newPlayer.m_spectator) { player.CallTargetAddHUDMessage(player.connectionToClient, String.Format(Loc.LS("{0} JOINED MATCH"), newPlayer.m_mp_name), -1, true); } //Debug.Log("JIP: spawning on new client net " + player.netId + " lobby " + player.connectionToClient.connectionId); NetworkServer.SendToClient(connectionId, CustomMsgType.Respawn, new RespawnMessage { m_net_id = player.netId, lobby_id = player.connectionToClient.connectionId, m_pos = player.transform.position, m_rotation = player.transform.rotation, use_loadout1 = player.m_use_loadout1 }); } ServerStatLog.Connected(newPlayer.m_mp_name); MPBanPlayers.ApplyAllBans(); // make sure the newly connected player gets proper treatment if he is BANNED }
// Set MPBanEntry from another entry public void Set(MPBanEntry other) { Set(other.name, other.address, other.id); timeCreated = other.timeCreated; }
private static void Postfix(ref bool __result, int connection_id, int version, string player_name, string player_session_id, string player_id, string player_uid) { MPBanPlayers.JoiningPlayerIsBanned = false; MPBanPlayers.JoiningPlayerIsAnnoyed = false; MPBanPlayers.JoiningPlayerConnectionId = connection_id; MPBanPlayers.JoiningPlayerLobbyData = null; if (__result) { // the player has been accepted by the game's matchmaking MPBanEntry candidate = new MPBanEntry(player_name, connection_id, player_id); bool isCreator = false; if (!MPBanPlayers.MatchCreatorIsInGame && MPBanPlayers.PlayerWithPrivateMatchData != null && !String.IsNullOrEmpty(MPBanPlayers.PlayerWithPrivateMatchData.id) && !String.IsNullOrEmpty(candidate.id)) { if (candidate.id == MPBanPlayers.PlayerWithPrivateMatchData.id) { Debug.LogFormat("MPBanPlayers: Match creator entered the lobby: {0}", player_name); isCreator = true; MPBanPlayers.MatchCreatorIsInGame = true; } } // check if player is banned MPBanPlayers.JoiningPlayerIsBanned = MPBanPlayers.IsBanned(candidate); MPBanPlayers.JoiningPlayerIsAnnoyed = MPBanPlayers.IsBanned(candidate, MPBanMode.Annoy); if (isCreator && MPBanPlayers.JoiningPlayerIsAnnoyed) { // annoyed players are treated as Banned for creating new matches MPBanPlayers.JoiningPlayerIsBanned = true; } if (MPBanPlayers.JoiningPlayerIsBanned) { // banned player entered the lobby // NOTE: we cannot just say __accept = false, because this causes all sorts of troubles later MPBanPlayers.KickPlayer(connection_id, player_name, true); if (isCreator) { Debug.LogFormat("Creator for this match {0} is BANNED, ending match", candidate.name); GameManager.m_gm.StartCoroutine(DelayedEndMatch()); } } else { // unbanned player entered the lobby if (isCreator) { bool haveModifiedState = MPBanPlayers.HasModifiedState() || MPChatCommand.HasModifiedState(); bool doReset = true; if (MPChatCommand.CheckPermission(candidate)) { Debug.Log("MPBanPlayers: same game creator as last match, or with permissions"); doReset = false; } MPBanPlayers.MatchCreator = candidate; if (doReset) { Debug.Log("MPBanPlayers: new game creator, resetting bans and permissions"); MPBanPlayers.Reset(); MPChatCommand.Reset(); if (haveModifiedState) { MPChatTools.SendTo(true, "cleared all bans and permissions", connection_id); } } else { if (haveModifiedState) { MPChatTools.SendTo(true, "keeping bans and permissions from previous match", connection_id); } } } } } }
// Execute a command: Returns true if the caller should forward the chat message // to the clients, and false if not (when it was a special command for the server) public bool Execute() { if (!IsEnabled()) { // chat commands are not enabled return(true); } if (cmd == Command.None) { // there might be BlockChat-Banned players, and we can just ignore their ramblings if (MPBanPlayers.GetList(MPBanMode.BlockChat).Count > 0) { MPBanEntry we = FindPlayerEntryForConnection(sender_conn, inLobby); if (we != null && MPBanPlayers.IsBanned(we, MPBanMode.BlockChat)) { // send the message back to the sender ONLY MPChatTools.SendTo(inLobby, sender_message, sender_conn, -1, false, false, sender_name, sender_team, isTeamMessage, sender_conn); return(false); } } return(true); } senderEntry = FindPlayerEntryForConnection(sender_conn, inLobby); if (senderEntry == null || String.IsNullOrEmpty(senderEntry.name)) { Debug.LogFormat("CHATCMD {0}: {1} {2}: failed to identify sender", cmd, cmdName, arg); return(false); } Debug.LogFormat("CHATCMD {0}: {1} {2} by {3}", cmd, cmdName, arg, senderEntry.name); if (needAuth) { if (!CheckPermission(senderEntry)) { ReturnToSender(String.Format("You do not have the permission for command {0}!", cmd)); Debug.LogFormat("CHATCMD {0}: client is not authenticated!", cmd); return(false); } } bool result = false; switch (cmd) { case Command.GivePerm: result = DoPerm(true); break; case Command.RevokePerm: result = DoPerm(false); break; case Command.Auth: result = DoAuth(); break; case Command.Kick: result = DoKickBan(true, false, MPBanMode.Ban); break; case Command.Ban: result = DoKickBan(false, true, MPBanMode.Ban); break; case Command.Annoy: result = DoKickBan(false, true, MPBanMode.Annoy); break; case Command.KickBan: result = DoKickBan(true, true, MPBanMode.Ban); break; case Command.Unban: result = DoUnban(MPBanMode.Ban); break; case Command.Unannoy: result = DoUnban(MPBanMode.Annoy); break; case Command.BlockChat: result = DoKickBan(false, true, MPBanMode.BlockChat); break; case Command.UnblockChat: result = DoUnban(MPBanMode.BlockChat); break; case Command.End: result = DoEnd(); break; case Command.Start: result = DoStart(); break; case Command.Status: result = DoStatus(); break; case Command.Say: result = DoSay(); break; case Command.Test: result = DoTest(); break; default: Debug.LogFormat("CHATCMD {0}: {1} {2} was not handled by server", cmd, cmdName, arg); result = true; // treat it as normal chat message break; } return(result); }
// Send a chat message // Set connection_id to the ID of a specific client, or to -1 to send to all // clients except except_connection_id (if that is >= 0) // If authOnly is true, only send to clients which are authenticated for chat // commands. // If unblockedOnly is true, only send to clients which are not BlockChat-BANNED // You need to already know if we are currently in Lobby or not public static bool SendTo(bool inLobby, string msg, int connection_id = -1, int except_connection_id = -1, bool authOnly = false, bool unblockedOnly = false, string sender_name = "Server", MpTeam team = MpTeam.TEAM0, bool isTeamMessage = false, int sender_connection_id = -1) { bool toAll = (connection_id < 0); if (!toAll) { if (connection_id >= NetworkServer.connections.Count || NetworkServer.connections[connection_id] == null) { return(false); } } if (inLobby) { var lmsg = new LobbyChatMessage(sender_connection_id, sender_name, team, msg, isTeamMessage); if (toAll) { if (except_connection_id < 0 && !authOnly && !unblockedOnly) { NetworkServer.SendToAll(75, lmsg); } else { foreach (NetworkConnection c in NetworkServer.connections) { if (c != null && c.connectionId != except_connection_id) { SendToLobbyHelper(lmsg, c.connectionId, authOnly, unblockedOnly); } } } } else { SendToLobbyHelper(lmsg, connection_id, authOnly, unblockedOnly); } } else { if (isTeamMessage) { msg = Loc.LS("[TEAM]") + " " + msg; } foreach (var p in Overload.NetworkManager.m_Players) { if (p != null && p.connectionToClient != null) { if ((toAll && p.connectionToClient.connectionId != except_connection_id) || (p.connectionToClient.connectionId == connection_id)) { bool doSend = true; if (authOnly || unblockedOnly) { MPBanEntry entry = new MPBanEntry(p); if (authOnly) { doSend = doSend && MPChatCommand.CheckPermission(entry); } if (doSend && unblockedOnly) { doSend = !MPBanPlayers.IsBanned(entry, MPBanMode.BlockChat); } } if (doSend) { p.CallTargetSendFullChat(p.connectionToClient, connection_id, sender_name, team, msg); } } } } } return(true); }
// Check if a client on a specific connection id is authenticated public static bool CheckPermission(int connection_id, bool inLobby) { MPBanEntry entry = FindPlayerEntryForConnection(connection_id, inLobby); return(CheckPermission(entry)); }
// Construct a MPChatCommand from a Chat message public MPChatCommand(string message, int sender_connection_id, string sender_player_name, MpTeam sender_player_team, bool isInLobby) { cmd = Command.None; isTeamMessage = NetworkMessageManager.IsTeamMessage(message); if (isTeamMessage) { message = NetworkMessageManager.StripTeamPrefix(message); } sender_conn = sender_connection_id; sender_name = sender_player_name; sender_team = sender_player_team; sender_message = message; needAuth = false; inLobby = isInLobby; senderEntry = null; if (message == null || message.Length < 2 || message[0] != '/') { // not a valid command return; } // is there an additonal argument to this command? // Arguments are separated with space int split = message.IndexOf(' '); if (split > 0) { cmdName = message.Substring(1, split - 1); if (split + 1 < message.Length) { arg = message.Substring(split + 1, message.Length - split - 1); } } else { cmdName = message.Substring(1, message.Length - 1); } // detect the command cmdName = cmdName.ToUpper(); if (cmdName == "GP" || cmdName == "GIVEPERM") { cmd = Command.GivePerm; needAuth = true; } else if (cmdName == "RP" || cmdName == "REVOKEPERM") { cmd = Command.RevokePerm; needAuth = true; } else if (cmdName == "AUTH") { cmd = Command.Auth; needAuth = false; } else if (cmdName == "K" || cmdName == "KICK") { cmd = Command.Kick; needAuth = true; } else if (cmdName == "B" || cmdName == "BAN") { cmd = Command.Ban; needAuth = true; } else if (cmdName == "A" || cmdName == "ANNOY") { cmd = Command.Annoy; needAuth = true; } else if (cmdName == "UA" || cmdName == "UNANNOY") { cmd = Command.Unannoy; needAuth = true; } else if (cmdName == "KB" || cmdName == "KICKBAN") { cmd = Command.KickBan; needAuth = true; } else if (cmdName == "UB" || cmdName == "UNBAN") { cmd = Command.Unban; needAuth = true; } else if (cmdName == "BC" || cmdName == "BLOCKCHAT") { cmd = Command.BlockChat; needAuth = true; } else if (cmdName == "UBC" || cmdName == "UNBLOCKCHAT") { cmd = Command.UnblockChat; needAuth = true; } else if (cmdName == "E" || cmdName == "END") { cmd = Command.End; needAuth = true; } else if (cmdName == "S" || cmdName == "START") { cmd = Command.Start; needAuth = true; } else if (cmdName == "STATUS") { cmd = Command.Status; } else if (cmdName == "SAY" || cmdName == "CHAT") { cmd = Command.Say; } else if (cmdName == "T" || cmdName == "TEST") { cmd = Command.Test; } }