Ticket #3241: t3241_kick_v4.1.patch
File t3241_kick_v4.1.patch, 25.6 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/common/network.js
5 5 { 6 6 case 0: return translate("Unknown reason"); 7 7 case 1: return translate("Unexpected shutdown"); 8 8 case 2: return translate("Incorrect network protocol version"); 9 9 case 3: return translate("Game has already started"); 10 case 4: return translate("You have been kicked from the match."); 11 case 5: return translate("You have been banned from the match."); 10 12 default: return sprintf(translate("\\[Invalid value %(id)s]"), { id: id }); 11 13 } 12 14 } 13 15 14 16 function reportDisconnect(reason) -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
1700 1700 1701 1701 var message = ""; 1702 1702 if ("text" in msg && msg.text) 1703 1703 message = escapeText(msg.text); 1704 1704 1705 // Kick / ban players 1706 if ("text" in msg) 1707 { 1708 let split = msg.text.split(/\s/); 1709 let kick = msg.text.indexOf("/kick") == 0; 1710 let ban = msg.text.indexOf("/ban") == 0; 1711 let playerGUID = Engine.GetPlayerGUID(); 1712 if (kick || ban) 1713 { 1714 if (!g_IsNetworked || !g_IsController || msg.guid != playerGUID) 1715 return; 1716 let trimmed = msg.text.substr(split[0].length + 1); 1717 let matched = ""; 1718 // Reject names which don't match or are a superset of the intended name. 1719 for each (let player in g_PlayerAssignments) 1720 if (trimmed.indexOf(player.name) == 0 && player.name.length > matched.length) 1721 matched = player.name; 1722 // Prevent the host from kicking him/herself 1723 if (matched.length && matched != g_PlayerAssignments[playerGUID].name) 1724 { 1725 // Sending the message takes a while, so we phrase this past tense. 1726 // The text should be translated for each client individually (see #3304) 1727 Engine.SendNetworkChat(matched + " has been " + (ban ? "banned" : "kicked") + "."); 1728 Engine.KickPlayer(matched, ban); 1729 } 1730 return; 1731 } 1732 } 1733 1705 1734 // TODO: Maybe host should have distinct font/color? 1706 1735 var color = "white"; 1707 1736 1708 1737 if (msg.guid && g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1) 1709 1738 { -
binaries/data/mods/public/gui/session/messages.js
241 241 obj.caption = translate("Connection to the server has been authenticated."); 242 242 obj.hidden = false; 243 243 break; 244 244 case "disconnected": 245 245 g_Disconnected = true; 246 obj.caption = translate("Connection to the server has been lost.") + "\n\n" + translate("The game has ended."); 246 obj.caption = translate("Connection to the server has been lost.") + "\n" + 247 getDisconnectReason(message.reason) + "\n" + translate("The game has ended."); 247 248 obj.hidden = false; 248 249 break; 249 250 default: 250 251 error("Unrecognised netstatus type '" + message.status + "'"); 251 252 break; … … 325 326 function submitChatInput() 326 327 { 327 328 var input = Engine.GetGUIObjectByName("chatInput"); 328 329 var text = input.caption; 329 330 var isCheat = false; 331 330 332 if (text.length) 331 333 { 334 // Check cheats 332 335 if (!g_IsObserver && g_Players[Engine.GetPlayerID()].cheatsEnabled) 333 336 { 334 337 for each (var cheat in Object.keys(cheats)) 335 338 { 336 339 // Line must start with the cheat. … … 374 377 isCheat = true; 375 378 break; 376 379 } 377 380 } 378 381 379 // Observers should only send messages to "/all" 380 if (!isCheat && (!g_IsObserver || text.indexOf("/") == -1 || text.indexOf("/all ") == 0)) 382 if (!isCheat) 381 383 { 382 if (Engine.GetGUIObjectByName("toggleTeamChat").checked) 383 text = "/team " + text; 384 385 if (g_IsNetworked) 386 Engine.SendNetworkChat(text); 384 if (text.trim() == "/list") 385 addChatMessage({ "type": "clientlist", "guid": "local"}); 387 386 else 388 addChatMessage({ "type": "message", "guid": "local", "text": text }); 387 { 388 if (Engine.GetGUIObjectByName("toggleTeamChat").checked) 389 text = "/team " + text; 390 391 if (g_IsNetworked) 392 Engine.SendNetworkChat(text); 393 else 394 addChatMessage({ "type": "message", "guid": "local", "text": text }); 395 } 389 396 } 390 397 input.caption = ""; // Clear chat input 391 398 } 392 399 393 400 input.blur(); // Remove focus … … 453 460 if (!g_IsNetworked && msg.player == Engine.GetPlayerID()) 454 461 formatted = translate("You have been defeated."); 455 462 else 456 463 formatted = sprintf(translate("%(player)s has been defeated."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 457 464 break; 465 case "clientlist": 466 let userlist = Object.keys(playerAssignments).sort(function(a,b) 467 { 468 let playerA = playerAssignments[a].player; 469 let playerB = playerAssignments[b].player; 470 if (playerA == -1 || playerB == -1) 471 return 1; 472 else 473 return playerA - playerB; 474 }).map(guid => playerAssignments[guid].name).join(","); 475 formatted = sprintf(translate("Users: %(users)s."), { "users": userlist }); 476 break; 458 477 case "diplomacy": 459 478 var message; 460 479 if (msg.player == Engine.GetPlayerID()) 461 480 { 462 481 [username, playerColor] = getUsernameAndColor(msg.player1); … … 601 620 } 602 621 603 622 // Parses chat messages for commands. 604 623 function parseChatCommands(msg, playerAssignments) 605 624 { 625 let ban = false; 606 626 // Only interested in messages that start with '/'. 607 627 if (!msg.text || msg.text[0] != '/') 608 628 return; 609 629 610 var sender; 630 let playerGUID = Engine.GetPlayerGUID(); 631 let sender; 611 632 if (playerAssignments[msg.guid]) 612 633 sender = playerAssignments[msg.guid].player; 613 634 else 614 635 sender = msg.player; 615 636 616 637 // TODO: It would be nice to display multiple different contexts. 617 638 // It should be made clear that only players matching the union of those receive the message. 618 639 var recurse = false; 619 640 var split = msg.text.split(/\s/); 620 641 let trimmed, matched; 621 642 // Parse commands embedded in the message. 622 643 switch (split[0]) 623 644 { 624 645 case "/all": 625 646 // Resets values that 'team' or 'enemy' may have set. … … 627 648 msg.hide = false; 628 649 recurse = true; 629 650 break; 630 651 case "/team": 631 652 // Check if we are in a team. 632 if ( g_Players[Engine.GetPlayerID()] && g_Players[Engine.GetPlayerID()].team != -1)653 if (!g_IsObserver && g_Players[Engine.GetPlayerID()] && g_Players[Engine.GetPlayerID()].team != -1) 633 654 { 634 655 if (g_Players[Engine.GetPlayerID()].team != g_Players[sender].team) 635 656 msg.hide = true; 636 657 else 637 658 msg.context = translate("Team"); … … 641 662 recurse = true; 642 663 break; 643 664 case "/ally": 644 665 case "/allies": 645 666 // Check if we sent the message, or are the sender's (mutual) ally 646 if ( Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isMutualAlly[Engine.GetPlayerID()]))667 if (!g_IsObserver && (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isMutualAlly[Engine.GetPlayerID()]))) 647 668 msg.context = translate("Ally"); 648 669 else 649 670 msg.hide = true; 650 671 651 672 recurse = true; 652 673 break; 653 674 case "/enemy": 654 675 case "/enemies": 655 676 // Check if we sent the message, or are the sender's enemy 656 if ( Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isEnemy[Engine.GetPlayerID()]))677 if (!g_IsObserver && (Engine.GetPlayerID() == sender || (g_Players[sender] && g_Players[sender].isEnemy[Engine.GetPlayerID()]))) 657 678 msg.context = translate("Enemy"); 658 679 else 659 680 msg.hide = true; 660 681 661 682 recurse = true; 662 683 break; 663 684 case "/me": 664 685 msg.action = true; 665 686 break; 687 case "/ban": 688 ban = true; // handle in the "kick" case 689 case "/kick": 690 msg.hide = true; 691 if (!g_IsNetworked || !g_IsController || msg.guid != playerGUID) 692 break; 693 trimmed = msg.text.substr(split[0].length + 1); 694 matched = ""; 695 // Reject names which don't match or are a superset of the intended name. 696 for each (let player in playerAssignments) 697 if (trimmed.indexOf(player.name) == 0 && player.name.length > matched.length) 698 matched = player.name; 699 // Prevent the host from kicking him/herself 700 if (matched.length && matched != g_PlayerAssignments[playerGUID].name) 701 { 702 Engine.KickPlayer(matched, ban); 703 // TODO: The text should be translated for each client individually (see #3304) 704 submitChatDirectly(matched + " has been " + (ban ? "banned" : "kicked") + "."); 705 } 706 return; 666 707 case "/msg": 667 var trimmed = msg.text.substr(split[0].length + 1); 668 var matched = ""; 708 trimmed = msg.text.substr(split[0].length + 1); 709 matched = ""; 710 711 // Don't show private messages from observers to players 712 if (g_PlayerAssignments[msg.guid].player == -1 && g_PlayerAssignments[playerGUID].player != -1) 713 { 714 msg.hide = true; 715 return; 716 } 669 717 670 718 // Reject names which don't match or are a superset of the intended name. 671 719 for each (var player in playerAssignments) 672 720 if (trimmed.indexOf(player.name + " ") == 0 && player.name.length > matched.length) 673 721 matched = player.name; 674 722 675 723 // If the local player's name was the longest one matched, show the message. 676 var playerName = g_Players[Engine.GetPlayerID()].name;677 if (matched.length && (m atched == playerName || sender == Engine.GetPlayerID()))724 // Show the message only for sender and recipient. 725 if (matched.length && (msg.guid == playerGUID || matched == g_PlayerAssignments[playerGUID].name)) 678 726 { 679 727 msg.context = translate("Private"); 680 728 msg.text = trimmed.substr(matched.length + 1); 681 729 msg.hide = false; // Might override team message hiding. 682 730 return; -
binaries/data/mods/public/gui/session/session.xml
5 5 <script file="gui/common/colorFades.js"/> 6 6 <script file="gui/common/functions_civinfo.js"/> 7 7 <script file="gui/common/functions_global_object.js"/> 8 8 <script file="gui/common/functions_utility.js"/> 9 9 <script file="gui/common/l10n.js"/> 10 <script file="gui/common/network.js"/> 10 11 <script file="gui/common/music.js"/> 11 12 <script file="gui/common/timer.js"/> 12 13 <script file="gui/common/tooltips.js"/> 13 14 <!-- load all scripts in this directory --> 14 15 <script directory="gui/session/"/> -
source/gui/scripting/ScriptFunctions.cpp
186 186 if (g_Game) 187 187 return g_Game->GetPlayerID(); 188 188 return -1; 189 189 } 190 190 191 std::string GetPlayerGUID(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) 192 { 193 if (g_NetServer) 194 return g_NetServer->GetHostGUID(); 195 else if (g_NetClient) 196 return g_NetClient->GetGUID(); 197 else 198 return ""; 199 } 200 191 201 void SetPlayerID(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int id) 192 202 { 193 203 if (g_Game) 194 204 g_Game->SetPlayerID(id); 195 205 } … … 345 355 SAFE_DELETE(g_NetServer); 346 356 SAFE_DELETE(g_NetClient); 347 357 SAFE_DELETE(g_Game); 348 358 } 349 359 360 void KickPlayer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring playerName, bool ban) 361 { 362 if (g_NetServer) 363 g_NetServer->KickPlayer(playerName, ban); 364 } 365 350 366 JS::Value PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate) 351 367 { 352 368 if (!g_NetClient) 353 369 return JS::UndefinedValue(); 354 370 … … 954 970 scriptInterface.RegisterFunction<void, JS::HandleValue, int, &StartGame>("StartGame"); 955 971 scriptInterface.RegisterFunction<void, &Script_EndGame>("EndGame"); 956 972 scriptInterface.RegisterFunction<void, std::wstring, &StartNetworkHost>("StartNetworkHost"); 957 973 scriptInterface.RegisterFunction<void, std::wstring, std::string, &StartNetworkJoin>("StartNetworkJoin"); 958 974 scriptInterface.RegisterFunction<void, &DisconnectNetworkGame>("DisconnectNetworkGame"); 975 scriptInterface.RegisterFunction<void, std::wstring, bool, &KickPlayer>("KickPlayer"); 959 976 scriptInterface.RegisterFunction<JS::Value, &PollNetworkClient>("PollNetworkClient"); 960 977 scriptInterface.RegisterFunction<void, JS::HandleValue, &SetNetworkGameAttributes>("SetNetworkGameAttributes"); 961 978 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer"); 962 979 scriptInterface.RegisterFunction<void, std::string, int, &SetNetworkPlayerStatus>("SetNetworkPlayerStatus"); 963 980 scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady"); … … 977 994 scriptInterface.RegisterFunction<void, &QuickLoad>("QuickLoad"); 978 995 979 996 // Misc functions 980 997 scriptInterface.RegisterFunction<std::wstring, std::wstring, &SetCursor>("SetCursor"); 981 998 scriptInterface.RegisterFunction<int, &GetPlayerID>("GetPlayerID"); 999 scriptInterface.RegisterFunction<std::string, &GetPlayerGUID>("GetPlayerGUID"); 982 1000 scriptInterface.RegisterFunction<void, int, &SetPlayerID>("SetPlayerID"); 983 1001 scriptInterface.RegisterFunction<void, std::string, &OpenURL>("OpenURL"); 984 1002 scriptInterface.RegisterFunction<std::wstring, &GetMatchID>("GetMatchID"); 985 1003 scriptInterface.RegisterFunction<void, &RestartInAtlas>("RestartInAtlas"); 986 1004 scriptInterface.RegisterFunction<bool, &AtlasIsAvailable>("AtlasIsAvailable"); -
source/network/NetClient.cpp
139 139 ENSURE(!m_Session); // must be called before we start the connection 140 140 141 141 m_UserName = username; 142 142 } 143 143 144 CStr CNetClient::GetGUID() 145 { 146 return m_GUID; 147 } 148 144 149 bool CNetClient::SetupConnection(const CStr& server) 145 150 { 146 151 CNetClientSession* session = new CNetClientSession(*this); 147 152 bool ok = session->Connect(PS_DEFAULT_PORT, server); 148 153 SetAndOwnSession(session); -
source/network/NetClient.h
86 86 * Set the user's name that will be displayed to all players. 87 87 * This must not be called after the connection setup. 88 88 */ 89 89 void SetUserName(const CStrW& username); 90 90 91 /** Returns the GUID of the client. */ 92 CStr GetGUID(); 93 91 94 /** 92 95 * Set up a connection to the remote networked server. 93 96 * @param server IP address or host name to connect to 94 97 * @return true on success, false on connection failure 95 98 */ -
source/network/NetHost.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … 60 60 enum NetDisconnectReason 61 61 { 62 62 NDR_UNKNOWN = 0, 63 63 NDR_UNEXPECTED_SHUTDOWN, 64 64 NDR_INCORRECT_PROTOCOL_VERSION, 65 NDR_SERVER_ALREADY_IN_GAME 65 NDR_SERVER_ALREADY_IN_GAME, 66 NDR_KICKED, 67 NDR_BANNED 66 68 }; 67 69 68 70 class CNetHost 69 71 { 70 72 public: -
source/network/NetServer.cpp
127 127 128 128 m_ServerTurnManager = NULL; 129 129 130 130 m_ServerName = DEFAULT_SERVER_NAME; 131 131 m_WelcomeMessage = DEFAULT_WELCOME_MESSAGE; 132 m_HostGUID = std::string(); 132 133 } 133 134 134 135 CNetServerWorker::~CNetServerWorker() 135 136 { 136 137 if (m_State != SERVER_STATE_UNCONNECTED) … … 604 605 session->SetFirstState(NSS_HANDSHAKE); 605 606 } 606 607 607 608 bool CNetServerWorker::HandleConnect(CNetServerSession* session) 608 609 { 610 CNetServerWorker& server = session->GetServer(); 611 612 // Disconnect banned IPs 613 std::string ipAddress = session -> GetIPAddress(); 614 if(std::find(server.m_BannedIPs.begin(), server.m_BannedIPs.end(), ipAddress) != server.m_BannedIPs.end()) 615 { 616 session->Disconnect(NDR_BANNED); 617 return false; 618 } 619 620 // Send handshake challenge 609 621 CSrvHandshakeMessage handshake; 610 622 handshake.m_Magic = PS_PROTOCOL_MAGIC; 611 623 handshake.m_ProtocolVersion = PS_PROTOCOL_VERSION; 612 624 handshake.m_SoftwareVersion = PS_PROTOCOL_VERSION; 613 625 return session->SendMessage(&handshake); … … 615 627 616 628 void CNetServerWorker::OnUserJoin(CNetServerSession* session) 617 629 { 618 630 AddPlayer(session->GetGUID(), session->GetUserName()); 619 631 632 if (m_HostGUID == "") 633 m_HostGUID = session->GetGUID(); 634 620 635 CGameSetupMessage gameSetupMessage(GetScriptInterface()); 621 636 gameSetupMessage.m_Data = m_GameAttributes.get(); 622 637 session->SendMessage(&gameSetupMessage); 623 638 624 639 CPlayerAssignmentMessage assignMessage; … … 630 645 { 631 646 RemovePlayer(session->GetGUID()); 632 647 633 648 if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING) 634 649 m_ServerTurnManager->UninitialiseClient(session->GetHostID()); // TODO: only for non-observers 635 636 // TODO: ought to switch the player controlled by that client637 // back to AI control, or something?638 650 } 639 651 640 652 void CNetServerWorker::AddPlayer(const CStr& guid, const CStrW& name) 641 653 { 642 654 // Find all player IDs in active use; we mustn't give them to a second player (excluding the unassigned ID: -1) … … 707 719 it->second.m_Status = 0; 708 720 709 721 SendPlayerAssignments(); 710 722 } 711 723 724 void CNetServerWorker::KickPlayer(const CStrW& playerName, bool ban) 725 { 726 if (ban) 727 { 728 // Add playername to blacklist 729 if (std::find(m_BannedPlayers.begin(), m_BannedPlayers.end(), playerName) == m_BannedPlayers.end()) 730 m_BannedPlayers.push_back(playerName); 731 732 // Add IP address to blacklist 733 std::string ipAddress = GetPlayerIPAddress(playerName); 734 if (std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end()) 735 m_BannedIPs.push_back(ipAddress); 736 } 737 738 // Disconnect everyone with that nick except the host 739 for (auto session : m_Sessions) 740 { 741 if (session->GetUserName() == playerName && session->GetGUID() != m_HostGUID) 742 session->Disconnect(ban ? NDR_BANNED : NDR_KICKED); 743 } 744 } 745 746 std::string CNetServerWorker::GetPlayerIPAddress(const CStrW& playerName) 747 { 748 std::string ipAddress = "(error)"; 749 for (auto session : m_Sessions) 750 { 751 if (session->GetUserName() == playerName) 752 return session->GetIPAddress(); 753 } 754 return ipAddress; 755 } 756 757 std::string CNetServerWorker::GetHostGUID() 758 { 759 return m_HostGUID; 760 } 761 712 762 void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid) 713 763 { 714 764 // Remove anyone who's already assigned to this player 715 765 for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it) 716 766 { … … 764 814 ENSURE(event->GetType() == (uint)NMT_CLIENT_HANDSHAKE); 765 815 766 816 CNetServerSession* session = (CNetServerSession*)context; 767 817 CNetServerWorker& server = session->GetServer(); 768 818 819 // Check protocol version 769 820 CCliHandshakeMessage* message = (CCliHandshakeMessage*)event->GetParamRef(); 770 821 if (message->m_ProtocolVersion != PS_PROTOCOL_VERSION) 771 822 { 772 823 session->Disconnect(NDR_INCORRECT_PROTOCOL_VERSION); 773 824 return false; 774 825 } 775 826 827 // Send handshake response 776 828 CSrvHandshakeResponseMessage handshakeResponse; 777 829 handshakeResponse.m_UseProtocolVersion = PS_PROTOCOL_VERSION; 778 830 handshakeResponse.m_Message = server.m_WelcomeMessage; 779 831 handshakeResponse.m_Flags = 0; 780 832 session->SendMessage(&handshakeResponse); … … 791 843 792 844 CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef(); 793 845 794 846 CStrW username = server.DeduplicatePlayerName(SanitisePlayerName(message->m_Name)); 795 847 848 // Disconnect banned usernames 849 if(std::find(server.m_BannedPlayers.begin(), server.m_BannedPlayers.end(), username) != server.m_BannedPlayers.end()) 850 { 851 session->Disconnect(NDR_BANNED); 852 return true; 853 } 854 796 855 bool isRejoining = false; 797 856 798 857 if (server.m_State != SERVER_STATE_PREGAME) 799 858 { 800 859 // isRejoining = true; // uncomment this to test rejoining even if the player wasn't connected previously … … 1145 1204 { 1146 1205 CScopeLock lock(m_Worker->m_WorkerMutex); 1147 1206 m_Worker->m_PlayerReadyQueue.push_back(std::make_pair(guid, ready)); 1148 1207 } 1149 1208 1209 void CNetServer::KickPlayer(const CStrW& playerName, bool ban) 1210 { 1211 CScopeLock lock(m_Worker->m_WorkerMutex); 1212 m_Worker->KickPlayer(playerName, ban); 1213 } 1214 1215 std::string CNetServer::GetHostGUID() 1216 { 1217 CScopeLock lock(m_Worker->m_WorkerMutex); 1218 return m_Worker->GetHostGUID(); 1219 } 1220 1150 1221 void CNetServer::ClearAllPlayerReady() 1151 1222 { 1152 1223 CScopeLock lock(m_Worker->m_WorkerMutex); 1153 1224 m_Worker->m_PlayerResetReadyQueue.push_back(false); 1154 1225 } -
source/network/NetServer.h
120 120 * The given GUID will be (re)assigned to the given player ID. 121 121 * Any player currently using that ID will be unassigned. 122 122 * The changes will be asynchronously propagated to all clients. 123 123 */ 124 124 void AssignPlayer(int playerID, const CStr& guid); 125 125 126 126 /** 127 127 * Call from the GUI to update the player readiness. 128 128 * The changes will be asynchronously propagated to all clients. 129 129 */ 130 130 void SetPlayerReady(const CStr& guid, int ready); … … 132 132 /** 133 133 * Call from the GUI to set the all player readiness to 0. 134 134 * The changes will be asynchronously propagated to all clients. 135 135 */ 136 136 void ClearAllPlayerReady(); 137 137 138 /** 139 * Disconnects a player from the gamesetup / session. 140 */ 141 void KickPlayer(const CStrW& playerName, bool ban); 142 143 /** 144 * Returns the GUID of the host. 145 */ 146 std::string GetHostGUID(); 147 138 148 /** 139 149 * Call from the GUI to asynchronously notify all clients that they should start loading the game. 140 150 */ 141 151 void StartGame(); 142 152 … … 181 191 * Send a message to the given network peer. 182 192 */ 183 193 bool SendMessage(ENetPeer* peer, const CNetMessage* message); 184 194 185 195 /** 196 * Disconnected a player from the match / gamesetup and optionally prevents him/her from rejoining. 197 */ 198 void KickPlayer(const CStrW& playerName, bool ban); 199 200 /** 186 201 * Send a message to all clients who have completed the full connection process 187 202 * (i.e. are in the pre-game or in-game states). 188 203 */ 189 204 bool Broadcast(const CNetMessage* message); 190 205 206 /** 207 * Returns the IP address of the given connected player. 208 */ 209 std::string GetPlayerIPAddress(const CStrW& playerName); 210 191 211 private: 192 212 friend class CNetServer; 193 213 friend class CNetFileReceiveTask_ServerRejoin; 194 214 195 215 CNetServerWorker(int autostartPlayers); … … 244 264 void SetTurnLength(u32 msecs); 245 265 246 266 void AddPlayer(const CStr& guid, const CStrW& name); 247 267 void RemovePlayer(const CStr& guid); 248 268 void SetPlayerReady(const CStr& guid, const int ready); 269 std::string GetHostGUID(); 249 270 void SendPlayerAssignments(); 250 271 void ClearAllPlayerReady(); 251 272 252 273 void SetupSession(CNetServerSession* session); 253 274 bool HandleConnect(CNetServerSession* session); … … 269 290 270 291 void ConstructPlayerAssignmentMessage(CPlayerAssignmentMessage& message); 271 292 272 293 void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session); 273 294 274 275 295 /** 276 296 * Internal script context for (de)serializing script messages, 277 297 * and for storing game attributes. 278 298 * (TODO: we shouldn't bother deserializing (except for debug printing of messages), 279 299 * we should just forward messages blindly and efficiently.) … … 285 305 /** 286 306 * Stores the most current game attributes. 287 307 */ 288 308 DefPersistentRooted<JS::Value> m_GameAttributes; 289 309 310 std::vector<std::string> m_BannedIPs; 311 std::vector<std::wstring> m_BannedPlayers; 312 290 313 int m_AutostartPlayers; 291 314 292 315 ENetHost* m_Host; 293 316 std::vector<CNetServerSession*> m_Sessions; 294 317 … … 301 324 302 325 u32 m_NextHostID; 303 326 304 327 CNetServerTurnManager* m_ServerTurnManager; 305 328 329 std::string m_HostGUID; 330 306 331 /** 307 332 * A copy of all simulation commands received so far, indexed by 308 333 * turn number, to simplify support for rejoining etc. 309 334 * TODO: verify this doesn't use too much RAM. 310 335 */ -
source/network/NetSession.cpp
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … 173 173 CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) : 174 174 m_Server(server), m_FileTransferer(this), m_Peer(peer) 175 175 { 176 176 } 177 177 178 std::string CNetServerSession::GetIPAddress() 179 { 180 char ipAddress[256] = "(error)"; 181 enet_address_get_host_ip(&(m_Peer->address), ipAddress, ARRAY_SIZE(ipAddress)); 182 return std::string(ipAddress); 183 } 184 178 185 void CNetServerSession::Disconnect(u32 reason) 179 186 { 180 187 Update((uint)NMT_CONNECTION_LOST, NULL); 181 188 182 189 enet_peer_disconnect(m_Peer, reason); -
source/network/NetSession.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … 121 121 122 122 u32 GetHostID() const { return m_HostID; } 123 123 void SetHostID(u32 id) { m_HostID = id; } 124 124 125 125 /** 126 * Returns the IP address of the client. 127 */ 128 std::string GetIPAddress(); 129 130 /** 126 131 * Sends a disconnection notification to the client, 127 132 * and sends a NMT_CONNECTION_LOST message to the session FSM. 128 133 * The server will receive a disconnection notification after a while. 129 134 * The server will not receive any further messages sent via this session. 130 135 */