#pragma once #include #include "Config.h" #include #include #include #include #include namespace NetQuake { struct NetworkGenericPacket { // generic packet straight from server char type[2]; char length[2]; std::string remainder; }; enum PacketType { NQ_CONTROL_PACKET = 0x8000, NQ_MESSAGE_BLOCK_CHUNK = 0x0001, NQ_MESSAGE_BLOCK_END = 0x0009, NQ_ACK = 0x0002, NQ_UNRELIABLE = 0x0010, NQ_UNKNOWN_PACKET }; struct SerializedGenericPacket { PacketType type; int length; std::string remainder; }; SerializedGenericPacket Serialize(NetworkGenericPacket ngp); enum ClientMessageType { CLIENT_MESSAGE_NOOP = 0x00, CLIENT_MESSAGE_KEEPALIVE = 0x01, CLIENT_MESSAGE_DISCONNECT = 0x02, CLIENT_MESSAGE_MOVEMENT = 0x03, CLIENT_MESSAGE_CONSOLE = 0x04, CLIENT_MESSAGE_UNKNOWN }; struct ClientMessage { ClientMessageType type; std::string data; }; struct ClientMessageBlock { std::vector messages; }; struct GenericGamePacket { PacketType type; int length; long packetNumber; ClientMessageBlock messageBlock; bool valid = false; }; GenericGamePacket toGenericGamePacket(SerializedGenericPacket sgp); enum DemoMessageType { DEM_BAD = 0x00, DEM_NOP = 0x01, DEM_DISCONNECT = 0x02, DEM_UPDATESTAT = 0x03, DEM_VERSION = 0x04, DEM_SETVIEW = 0x05, DEM_SOUND = 0x06, DEM_TIME = 0x07, DEM_PRINT = 0x08, DEM_STUFFTEXT = 0x09, DEM_SETANGLE = 0x0A, DEM_SERVERINFO = 0x0B, DEM_LIGHTSTYLE = 0x0C, DEM_UPDATENAME = 0x0D, DEM_UPDATEFRAGS = 0x0E, DEM_CLIENTDATA = 0x0F, DEM_STOPSOUND = 0x10, DEM_UPDATECOLORS = 0x11, DEM_PARTICLE = 0x12, DEM_DAMAGE = 0x13, DEM_SPAWNSTATIC = 0x14, DEM_SPAWNBINARY = 0x15, DEM_SPAWNBASELINE = 0x16, DEM_TEMP_ENTITY = 0x17, DEM_SETPAUSE = 0x18, DEM_SIGNONUM = 0x19, DEM_CENTERPRINT = 0x1A, DEM_KILLEDMONSTER = 0x1B, DEM_FOUNDSECRET = 0x1C, DEM_SPAWNSTATICSOUND = 0x1D, DEM_INTERMISSION = 0x1E, DEM_FINALE = 0x1F, DEM_CDTRACK = 0x20, DEM_SELLSCREEN = 0x21, DEM_CUTSCENE = 0x22, DEM_UPDATEENTITY = 0x80 }; class GenericServerMessage { public: DemoMessageType type; virtual std::string Serialize() = 0; }; namespace ServerMessages { class Print : public GenericServerMessage { // 0x08 public: std::string text = ""; Print() { this->type = DEM_PRINT; } std::string Serialize(); }; class ServerInfo : public GenericServerMessage { // 0x0B public: long serverVersion = 15; long maxClients; long multi; std::string mapName; std::vector precacheModels; long numModels; std::vector precacheSounds; long numSounds; ServerInfo() { this->type = DEM_SERVERINFO; precacheModels = std::vector(256); precacheSounds = std::vector(256); } std::string Serialize(); }; class SignOn : public GenericServerMessage { public: long signon; SignOn() { type = DEM_SIGNONUM; } std::string Serialize(); }; } class ServerMessageBlock{ public: PacketType type; int order; std::vector serverMessages; std::string Serialize(); }; enum Control_OpCode { CONTROL_CONNECTION_REQUEST = 0x01, CONTROL_SERVER_INFO_REQUEST = 0x02, CONTROL_PLAYER_INFO_REQUEST = 0x03, CONTROL_RULE_INFO_REQUEST = 0x04, CONTROL_SERVER_INFO_REPLY = 0x83 }; struct GenericControlPacket { Control_OpCode opcode; std::string remainder; GenericControlPacket(SerializedGenericPacket sgp); }; enum NetProtocolVersion { QTEST1 = 0x01, QUNKNOWN = 0x02, QGOLD = 0x03 }; struct ServerInfoRequest { std::string gameName; NetProtocolVersion netVersion; ServerInfoRequest(GenericControlPacket gcp); }; struct Address { std::string ip; int port; }; struct ServerInfoReply { Address address; std::string hostname; std::string levelname; char currentPlayers; char maxPlayers; NetProtocolVersion netVersion; }; std::string Serialize(ServerInfoReply sirp); struct ConnectionRequest { std::string gameName; NetProtocolVersion netVersion; ConnectionRequest(GenericControlPacket gcp); }; struct ConnectionRequestReply { bool reject; short port; // LITTLE-ENDIAN (!)(!)(!)(!)(!) char unknown[2]; // [ have fun :) ] std::string reason; }; ::std::string Serialize(ConnectionRequestReply crr); class GameEndpoint { std::thread internalThread; public: GameEndpoint(); GameEndpoint(Config::Config* config, int port, asio::ip::udp::endpoint startRemote); ~GameEndpoint(); }; namespace Internal { struct NewEndpointRequestReply { bool ready = false; bool error = false; std::string reason; int port; asio::ip::udp::endpoint startRemote; }; class InternalRequestConsole { std::vector newEndpointRequests; int lastEndpointRequestTreated = 0; public: InternalRequestConsole(); int newEndpointRequest(asio::ip::udp::endpoint ep); NewEndpointRequestReply getEndpointRequest(int id); void Update(Config::Config *config, std::vector* gameEndpointsVector); ~InternalRequestConsole(); }; } std::string AcknowledgePacket(int packet); void NetQuake_ControlServer(Internal::InternalRequestConsole* internalRequestConsole, Config::Config* config, bool* serverRunning); void NetQuake_EndpointServer(Config::Config* config, int port, asio::ip::udp::endpoint startRemote); }