mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 20:26:48 +00:00 
			
		
		
		
	Added master server stuff
This commit is contained in:
		
							parent
							
								
									02a447c589
								
							
						
					
					
						commit
						c695923825
					
				
					 7 changed files with 268 additions and 6 deletions
				
			
		|  | @ -48,6 +48,7 @@ set(SERVER | |||
|     Networking.cpp | ||||
|     Utils.cpp | ||||
|     Log.cpp | ||||
|     MasterClient.cpp | ||||
|     Script/Script.cpp Script/ScriptFunction.cpp | ||||
|     Script/ScriptFunctions.cpp | ||||
|     Script/Functions/Translocations.cpp Script/Functions/Stats.cpp Script/Functions/Items.cpp | ||||
|  |  | |||
							
								
								
									
										172
									
								
								apps/openmw-mp/MasterClient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								apps/openmw-mp/MasterClient.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,172 @@ | |||
| //
 | ||||
| // Created by koncord on 14.08.16.
 | ||||
| //
 | ||||
| 
 | ||||
| #include <RakSleep.h> | ||||
| #include <Getche.h> | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| #include <RakPeerInterface.h> | ||||
| #include "MasterClient.hpp" | ||||
| #include "Log.hpp" | ||||
| #include "Networking.hpp" | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| bool MasterClient::sRun = false; | ||||
| 
 | ||||
| MasterClient::MasterClient(std::string queryAddr, unsigned short queryPort, std::string serverAddr, | ||||
|                            unsigned short serverPort) : queryAddr(queryAddr), queryPort(queryPort), | ||||
|                                                         serverAddr(serverAddr), serverPort(serverPort) | ||||
| { | ||||
|     httpConnection = RakNet::HTTPConnection2::GetInstance(); | ||||
|     tcpInterface.Start(0, 64); | ||||
|     tcpInterface.AttachPlugin(httpConnection); | ||||
|     players = 0; | ||||
|     maxPlayers = 0; | ||||
|     motd = ""; | ||||
|     timeout = 1000; // every 1 seconds
 | ||||
| } | ||||
| 
 | ||||
| void MasterClient::SetPlayers(unsigned pl) | ||||
| { | ||||
|     mutexData.lock(); | ||||
|     players = pl; | ||||
|     mutexData.unlock(); | ||||
| } | ||||
| 
 | ||||
| void MasterClient::SetMaxPlayers(unsigned pl) | ||||
| { | ||||
|     mutexData.lock(); | ||||
|     maxPlayers = pl; | ||||
|     mutexData.unlock(); | ||||
| } | ||||
| 
 | ||||
| void MasterClient::SetMOTD(std::string &motd) | ||||
| { | ||||
|     mutexData.lock(); | ||||
|     this->motd = motd.substr(0, 200); | ||||
|     mutexData.unlock(); | ||||
| } | ||||
| 
 | ||||
| RakNet::RakString MasterClient::Send(std::string motd, unsigned players, unsigned maxPlayers, bool update) | ||||
| { | ||||
|     /*static unsigned short oldServerPort, oldQueryPort;
 | ||||
|     static string oldMotd; | ||||
|     static unsigned oldPlayers, oldMaxPlayers;*/ | ||||
|     std::stringstream sstr; | ||||
|     mutexData.lock(); | ||||
|     sstr << "{"; | ||||
|     sstr << "\"port\": " << serverPort << ", "; | ||||
|     sstr << "\"query_port\": " << queryPort << ", "; | ||||
|     sstr << "\"motd\": \"" << motd << "\", "; | ||||
|     sstr << "\"players\": " << players << ", "; | ||||
|     sstr << "\"max_players\": " << maxPlayers; | ||||
|     sstr << "}"; | ||||
|     mutexData.unlock(); | ||||
| 
 | ||||
|     std::string contentType = "application/json"; | ||||
|     RakNet::RakString createRequest; | ||||
| 
 | ||||
|     if (update) | ||||
|         createRequest = RakNet::RakString::FormatForPUT( | ||||
|                 string("/api/servers/" + serverAddr + ":" + to_string(serverPort)).c_str(), contentType.c_str(), | ||||
|                 sstr.str().c_str()); | ||||
|     else | ||||
|         createRequest = RakNet::RakString::FormatForPOST("/api/servers", contentType.c_str(), | ||||
|                                                          sstr.str().c_str()); | ||||
| 
 | ||||
|     httpConnection->TransmitRequest(createRequest.C_String(), queryAddr.c_str(), queryPort); | ||||
| 
 | ||||
|     RakNet::Packet *packet; | ||||
|     RakNet::SystemAddress sa; | ||||
| 
 | ||||
|     RakNet::RakString transmitted, hostTransmitted; | ||||
|     RakNet::RakString response; | ||||
|     RakNet::SystemAddress hostReceived; | ||||
|     int contentOffset; | ||||
| 
 | ||||
|     while (true) | ||||
|     { | ||||
| 
 | ||||
|         // This is kind of crappy, but for TCP plugins, always do HasCompletedConnectionAttempt,
 | ||||
|         // then Receive(), then HasFailedConnectionAttempt(),HasLostConnection()
 | ||||
|         sa = tcpInterface.HasCompletedConnectionAttempt(); | ||||
|         if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS) | ||||
|             LOG_MESSAGE_SIMPLE(Log::INFO, "Connected to master server: %s", sa.ToString()); | ||||
| 
 | ||||
|         sa = tcpInterface.HasFailedConnectionAttempt(); | ||||
|         if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS) | ||||
|         { | ||||
|             LOG_MESSAGE_SIMPLE(Log::WARNING, "Failed to connect to master server: %s", sa.ToString()); | ||||
|             return "FAIL_CONNECT"; | ||||
|         } | ||||
|         sa = tcpInterface.HasLostConnection(); | ||||
|         if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS) | ||||
|         { | ||||
|             LOG_MESSAGE_SIMPLE(Log::WARNING, "Lost connection to master server: %s", sa.ToString()); | ||||
|             return "LOST_CONNECTION"; | ||||
|         } | ||||
| 
 | ||||
|         for (packet = tcpInterface.Receive(); packet; tcpInterface.DeallocatePacket( | ||||
|                 packet), packet = tcpInterface.Receive()); | ||||
| 
 | ||||
|         if (httpConnection->GetResponse(transmitted, hostTransmitted, response, hostReceived, contentOffset)) | ||||
|         { | ||||
|             if(contentOffset < 0) | ||||
|                 return "NO_CONTENT"; // no content
 | ||||
|             tcpInterface.CloseConnection(sa); | ||||
|             return (response.C_String() + contentOffset); | ||||
|         } | ||||
|         RakSleep(30); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void MasterClient::Update() | ||||
| { | ||||
|     assert(!sRun); | ||||
|     RakNet::RakString response = Send(motd, players, maxPlayers, false); | ||||
|     bool update = true; | ||||
|     sRun = true; | ||||
|     while (sRun) | ||||
|     { | ||||
|         if (response == "Created") | ||||
|             LOG_MESSAGE_SIMPLE(Log::INFO, "Server registered on the master server.", ""); | ||||
|         else if (response == "Accepted") | ||||
|             LOG_MESSAGE_SIMPLE(Log::INFO, "Server updated information about himself on the master server.", ""); | ||||
|         else if (response == "bad request") | ||||
|         { | ||||
|             LOG_MESSAGE_SIMPLE(Log::WARNING, "Update rate is too low, and the master server has deleted information about" | ||||
|                     " the server. Trying low rate...", ""); | ||||
|             SetUpdateRate(timeout - step_rate); | ||||
|             update = false; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             /*cout << "Error: \""<< response << "\"" << endl;
 | ||||
|             cout << response.GetLength() << endl;*/ | ||||
|         } | ||||
| 
 | ||||
|         RakSleep(timeout); | ||||
|         ; | ||||
|         players = mwmp::Networking::Get().NumberOfConnections(); | ||||
|         response = Send(motd, players, maxPlayers, update); | ||||
|         update = true; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void MasterClient::Stop() | ||||
| { | ||||
|     sRun = false; | ||||
| } | ||||
| 
 | ||||
| void MasterClient::SetUpdateRate(unsigned int rate) | ||||
| { | ||||
|     if(timeout < min_rate) | ||||
|         timeout = min_rate; | ||||
|     else if (timeout > max_rate) | ||||
|         timeout = max_rate; | ||||
|     timeout = rate; | ||||
| } | ||||
							
								
								
									
										46
									
								
								apps/openmw-mp/MasterClient.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								apps/openmw-mp/MasterClient.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| //
 | ||||
| // Created by koncord on 14.08.16.
 | ||||
| //
 | ||||
| 
 | ||||
| #ifndef OPENMW_MASTERCLIENT_HPP | ||||
| #define OPENMW_MASTERCLIENT_HPP | ||||
| 
 | ||||
| #include <string> | ||||
| #include <raknet/HTTPConnection2.h> | ||||
| #include <raknet/TCPInterface.h> | ||||
| #include <mutex> | ||||
| 
 | ||||
| class MasterClient | ||||
| { | ||||
| public: | ||||
|     static const unsigned int step_rate = 1000; | ||||
|     static const unsigned int min_rate = 1000; | ||||
|     static const unsigned int max_rate = 30000; | ||||
| public: | ||||
|     MasterClient(std::string queryAddr, unsigned short queryPort, std::string serverAddr, unsigned short serverPort); | ||||
|     void SetPlayers(unsigned pl); | ||||
|     void SetMaxPlayers(unsigned pl); | ||||
|     void SetMOTD(std::string &motd); | ||||
|     void Update(); | ||||
|     void Stop(); | ||||
|     void SetUpdateRate(unsigned int rate); | ||||
| 
 | ||||
| private: | ||||
|     RakNet::RakString Send(std::string motd, unsigned players, unsigned maxPlayers, bool update = true); | ||||
| private: | ||||
|     std::string queryAddr; | ||||
|     unsigned short queryPort; | ||||
|     std::string serverAddr; | ||||
|     unsigned short serverPort; | ||||
|     std::string motd; | ||||
|     unsigned players, maxPlayers; | ||||
|     RakNet::HTTPConnection2 *httpConnection; | ||||
|     RakNet::TCPInterface tcpInterface; | ||||
|     unsigned int timeout; | ||||
|     static bool sRun; | ||||
|     std::mutex mutexData; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif //OPENMW_MASTERCLIENT_HPP
 | ||||
|  | @ -402,3 +402,8 @@ void Networking::KickPlayer(RakNet::RakNetGUID guid) | |||
| { | ||||
|     peer->CloseConnection(guid, true); | ||||
| } | ||||
| 
 | ||||
| unsigned short Networking::NumberOfConnections() const | ||||
| { | ||||
|     return peer->NumberOfConnections(); | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #define OPENMW_NETWORKING_HPP | ||||
| 
 | ||||
| #include <components/openmw-mp/PacketsController.hpp> | ||||
| #include "Player.hpp" | ||||
| 
 | ||||
| namespace  mwmp | ||||
| { | ||||
|  | @ -19,6 +20,7 @@ namespace  mwmp | |||
|         void DisconnectPlayer(RakNet::RakNetGUID guid); | ||||
|         void KickPlayer(RakNet::RakNetGUID guid); | ||||
|         void Update(RakNet::Packet *packet); | ||||
|         unsigned short NumberOfConnections() const; | ||||
| 
 | ||||
|         int MainLoop(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #include <BitStream.h> | ||||
| #include "Player.hpp" | ||||
| #include "Networking.hpp" | ||||
| #include "MasterClient.hpp" | ||||
| #include "Log.hpp" | ||||
| #include <RakPeer.h> | ||||
| #include <MessageIdentifiers.h> | ||||
|  | @ -10,6 +11,7 @@ | |||
| #include <iostream> | ||||
| #include <components/files/configurationmanager.hpp> | ||||
| #include <components/settings/settings.hpp> | ||||
| #include <thread> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace mwmp; | ||||
|  | @ -64,6 +66,11 @@ std::string loadSettings (Settings::Manager & settings) | |||
|     return settingspath; | ||||
| } | ||||
| 
 | ||||
| void queryThread(MasterClient *mclient) | ||||
| { | ||||
|     mclient->Update(); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|     Settings::Manager mgr; | ||||
|  | @ -76,6 +83,7 @@ int main(int argc, char *argv[]) | |||
|     LOG_INIT(logLevel); | ||||
| 
 | ||||
|     int players = mgr.getInt("players", "General"); | ||||
|     string addr = mgr.getString("address", "General"); | ||||
|     int port = mgr.getInt("port", "General"); | ||||
| 
 | ||||
|     string plugin_home = mgr.getString("home", "Plugins"); | ||||
|  | @ -99,7 +107,7 @@ int main(int argc, char *argv[]) | |||
|     const char passw[8] = "1234567"; | ||||
|     peer->SetIncomingPassword(passw, sizeof(passw)); | ||||
| 
 | ||||
|     RakNet::SocketDescriptor sd((unsigned short)port, 0); | ||||
|     RakNet::SocketDescriptor sd((unsigned short)port, addr.c_str()); | ||||
|     if (peer->Startup((unsigned)players, &sd, 1) != RakNet::RAKNET_STARTED) | ||||
|         return 0; | ||||
| 
 | ||||
|  | @ -107,11 +115,33 @@ int main(int argc, char *argv[]) | |||
| 
 | ||||
|     Networking networking(peer); | ||||
| 
 | ||||
|     bool masterEnabled = mgr.getBool("enabled", "MasterServer"); | ||||
|     thread thrQuery; | ||||
|     MasterClient *mclient; | ||||
|     if(masterEnabled) | ||||
|     { | ||||
|         LOG_MESSAGE_SIMPLE(Log::INFO, "%s", "Sharing server query info to master enabled."); | ||||
|         string masterAddr = mgr.getString("address", "MasterServer"); | ||||
|         int masterPort = mgr.getInt("port", "MasterServer"); | ||||
|         mclient = new MasterClient(masterAddr, (unsigned short) masterPort, addr, (unsigned short) port); | ||||
|         mclient->SetMaxPlayers((unsigned)players); | ||||
|         string motd = mgr.getString("motd", "General"); | ||||
|         mclient->SetMOTD(motd); | ||||
|         thrQuery = thread(queryThread, mclient); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     int code = networking.MainLoop(); | ||||
| 
 | ||||
|     RakNet::RakPeerInterface::DestroyInstance(peer); | ||||
| 
 | ||||
|     if(thrQuery.joinable()) | ||||
|     { | ||||
|         mclient->Stop(); | ||||
|         thrQuery.join(); | ||||
|     } | ||||
| 
 | ||||
|     if (code == 0) | ||||
|         printf("Quitting peacefully.\n"); | ||||
|         LOG_MESSAGE_SIMPLE(Log::INFO, "%s", "Quitting peacefully."); | ||||
| 
 | ||||
|     LOG_QUIT(); | ||||
|  |  | |||
|  | @ -1,12 +1,18 @@ | |||
| [General] | ||||
| ;master = master.tes3mp.com:8088 | ||||
| # from 3 to 0. 3 - only errors, 0 - all messages | ||||
| loglevel = 0 | ||||
| motd = My TES3MP server | ||||
| address = server.tes3mp.com | ||||
| port = 25565 | ||||
| ;query = false #enable query server | ||||
| ;query-port = 25566 | ||||
| players = 4 | ||||
| 
 | ||||
| [Plugins] | ||||
| ;home = ~/local/openmw/tes3mp | ||||
| #home = ~/local/openmw/tes3mp | ||||
| home = ~/ClionProjects/PS-dev | ||||
| plugins = tes3mp.lua,chat_parser.lua | ||||
| 
 | ||||
| [MasterServer] | ||||
| enabled = true | ||||
| address = master.tes3mp.com | ||||
| port = 8080 | ||||
| rate = 1000 | ||||
		Loading…
	
		Reference in a new issue