// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2018 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file d_clisrv.h /// \brief high level networking stuff #ifndef __D_CLISRV__ #define __D_CLISRV__ #include "d_event.h" #include "d_ticcmd.h" #include "d_netcmd.h" #include "tables.h" #include "d_player.h" #include "md5.h" /* The 'packet version' may be used with packets whose format is expected to change between versions. This version is independent of the mod name, and standard version and subversion. It should only account for the basic fields of the packet, and change infrequently. */ #define PACKETVERSION 0 // Network play related stuff. // There is a data struct that stores network // communication related stuff, and another // one that defines the actual packets to // be transmitted. // SOME numpty changed all the gametype constants and it fell out of sync with vanilla and now we have to pretend to be vanilla when talking to the master server... #define VANILLA_GT_RACE 2 // Woah, what do these numbers mean? 200 refers to SRB2 2.0, 246 refers to // SRB2Riders. Both use the old 2.0 gametype numbers. #if VERSION == 200 || VERSION == 246 #define VANILLA_GT_MATCH 1 #else #define VANILLA_GT_MATCH 3 #endif // Networking and tick handling related. #define BACKUPTICS 32 #define TICQUEUE 512 // more than enough for most timeouts.... #define MAXTEXTCMD 256 // // Packet structure // typedef enum { PT_NOTHING, // To send a nop through the network. ^_~ PT_SERVERCFG, // Server config used in start game // (must stay 1 for backwards compatibility). // This is a positive response to a CLIENTJOIN request. PT_CLIENTCMD, // Ticcmd of the client. PT_CLIENTMIS, // Same as above with but saying resend from. PT_CLIENT2CMD, // 2 cmds in the packet for splitscreen. PT_CLIENT2MIS, // Same as above with but saying resend from PT_NODEKEEPALIVE, // Same but without ticcmd and consistancy PT_NODEKEEPALIVEMIS, PT_SERVERTICS, // All cmds for the tic. PT_SERVERREFUSE, // Server refuses joiner (reason inside). PT_SERVERSHUTDOWN, PT_CLIENTQUIT, // Client closes the connection. PT_ASKINFO, // Anyone can ask info of the server. PT_SERVERINFO, // Send game & server info (gamespy). PT_PLAYERINFO, // Send information for players in game (gamespy). PT_REQUESTFILE, // Client requests a file transfer PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. // If this ID changes, update masterserver definition. PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic PT_RESYNCHGET, // Player got resynch packet // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. // Kart-specific packets PT_CLIENT3CMD, // 3P PT_CLIENT3MIS, PT_CLIENT4CMD, // 4P PT_CLIENT4MIS, PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called PT_JOINCHALLENGE, // You must give a password to joinnnnn PT_DOWNLOADFILESOKAY, // You can download files from the server.... PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL // allows HSendPacket(*, true, *, *) to return false. // In addition, this packet can't occupy all the available slots. PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file. PT_TEXTCMD, // Extra text commands from the client. PT_TEXTCMD2, // Splitscreen text commands. PT_TEXTCMD3, // 3P PT_TEXTCMD4, // 4P PT_CLIENTJOIN, // Client wants to join; used in start game. PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_RESYNCHING, // Packet sent to resync players. // Blocks game advance until synched. PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" PT_PING, // Packet sent to tell clients the other client's latency to server. NUMPACKETTYPE } packettype_t; #ifdef PACKETDROP void Command_Drop(void); void Command_Droprate(void); #endif #ifdef _DEBUG void Command_Numnodes(void); #endif #if defined(_MSC_VER) #pragma pack(1) #endif // Client to server packet typedef struct { UINT8 client_tic; UINT8 resendfrom; INT16 consistancy; ticcmd_t cmd; } ATTRPACK clientcmd_pak; // Splitscreen packet // WARNING: must have the same format of clientcmd_pak, for more easy use typedef struct { UINT8 client_tic; UINT8 resendfrom; INT16 consistancy; ticcmd_t cmd, cmd2; } ATTRPACK client2cmd_pak; // 3P Splitscreen packet // WARNING: must have the same format of clientcmd_pak, for more easy use typedef struct { UINT8 client_tic; UINT8 resendfrom; INT16 consistancy; ticcmd_t cmd, cmd2, cmd3; } ATTRPACK client3cmd_pak; // 4P Splitscreen packet // WARNING: must have the same format of clientcmd_pak, for more easy use typedef struct { UINT8 client_tic; UINT8 resendfrom; INT16 consistancy; ticcmd_t cmd, cmd2, cmd3, cmd4; } ATTRPACK client4cmd_pak; #ifdef _MSC_VER #pragma warning(disable : 4200) #endif // Server to client packet // this packet is too large typedef struct { UINT8 starttic; UINT8 numtics; UINT8 numslots; // "Slots filled": Highest player number in use plus one. ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large } ATTRPACK servertics_pak; // Sent to client when all consistency data // for players has been restored typedef struct { UINT32 randomseed; // CTF flag stuff SINT8 flagplayer[2]; INT32 flagloose[2]; INT32 flagflags[2]; fixed_t flagx[2]; fixed_t flagy[2]; fixed_t flagz[2]; UINT32 ingame; // Spectator bit for each player INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams) // Resynch game scores and the like all at once UINT32 score[MAXPLAYERS]; // Everyone's score UINT32 marescore[MAXPLAYERS]; // SRB2kart: Battle score tic_t realtime[MAXPLAYERS]; UINT8 laps[MAXPLAYERS]; } ATTRPACK resynchend_pak; typedef struct { // Player stuff UINT8 playernum; // Do not send anything visual related. // Only send data that we need to know for physics. UINT8 playerstate; // playerstate_t UINT32 pflags; // pflags_t UINT8 panim; // panim_t angle_t aiming; INT32 currentweapon; INT32 ringweapons; UINT16 powers[NUMPOWERS]; INT32 kartstuff[NUMKARTSTUFF]; // SRB2kart angle_t frameangle; // SRB2kart // Score is resynched in the confirm resync packet INT32 health; SINT8 lives; SINT8 continues; UINT8 scoreadd; SINT8 xtralife; SINT8 pity; UINT8 skincolor; INT32 skin; // Just in case Lua does something like // modify these at runtime // SRB2kart UINT8 kartspeed; UINT8 kartweight; // UINT32 charflags; fixed_t speed; UINT8 jumping; UINT8 secondjump; UINT8 fly1; tic_t glidetime; UINT8 climbing; INT32 deadtimer; tic_t exiting; UINT8 homing; tic_t skidtime; fixed_t cmomx; fixed_t cmomy; fixed_t rmomx; fixed_t rmomy; INT32 weapondelay; INT32 tossdelay; INT16 starpostx; INT16 starposty; INT16 starpostz; INT32 starpostnum; tic_t starposttime; angle_t starpostangle; INT32 maxlink; fixed_t dashspeed; INT32 dashtime; angle_t angle_pos; angle_t old_angle_pos; tic_t bumpertime; INT32 flyangle; tic_t drilltimer; INT32 linkcount; tic_t linktimer; INT32 anotherflyangle; tic_t nightstime; INT32 drillmeter; UINT8 drilldelay; UINT8 bonustime; UINT8 mare; INT16 lastsidehit, lastlinehit; tic_t losstime; UINT8 timeshit; INT32 onconveyor; tic_t jointime; UINT8 splitscreenindex; //player->mo stuff UINT8 hasmo; // Boolean angle_t angle; fixed_t x; fixed_t y; fixed_t z; fixed_t momx; fixed_t momy; fixed_t momz; fixed_t friction; fixed_t movefactor; INT32 tics; statenum_t statenum; UINT32 flags; UINT32 flags2; UINT16 eflags; fixed_t radius; fixed_t height; fixed_t scale; fixed_t destscale; fixed_t scalespeed; } ATTRPACK resynch_pak; typedef struct { UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version // Server launch stuffs UINT8 serverplayer; UINT8 totalslotnum; // "Slots": highest player number in use plus one. tic_t gametic; UINT8 clientnode; UINT8 gamestate; // 0xFF == not in game; else player skin num UINT8 playerskins[MAXPLAYERS]; UINT8 playercolor[MAXPLAYERS]; UINT8 gametype; UINT8 modifiedgame; SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed char server_context[8]; // Unique context id, generated at server startup. UINT8 varlengthinputs[0]; // Playernames and netvars } ATTRPACK serverconfig_pak; typedef struct { UINT8 fileid; UINT32 position; UINT16 size; UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH } ATTRPACK filetx_pak; #ifdef _MSC_VER #pragma warning(default : 4200) #endif #define MAXAPPLICATION 16 typedef struct { UINT8 _255;/* see serverinfo_pak */ UINT8 packetversion; char application[MAXAPPLICATION]; UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version UINT8 localplayers; UINT8 needsdownload; UINT8 challengenum; // Non-zero if trying to join with a password attempt UINT8 challengeanswer[MD5_LEN]; // Join challenge } ATTRPACK clientconfig_pak; typedef struct { UINT8 challengenum; // Number to send back in join attempt UINT8 question[MD5_LEN]; // Challenge data to be manipulated and answered with } ATTRPACK joinchallenge_pak; #define SV_SPEEDMASK 0x03 #define SV_LOTSOFADDONS 0x20 #define SV_DEDICATED 0x40 #define SV_PASSWORD 0x80 #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 #define MAX_MIRROR_LENGTH 256 // This packet is too large typedef struct { /* In the old packet, 'version' is the first field. Now that field is set to 255 always, so older versions won't be confused with the new versions or vice-versa. */ UINT8 _255; UINT8 packetversion; char application[MAXAPPLICATION]; UINT8 version; UINT8 subversion; UINT8 numberofplayer; UINT8 maxplayer; UINT8 gametype; UINT8 modifiedgame; UINT8 cheatsenabled; UINT8 kartvars; // Previously isdedicated, now appropriated for our own nefarious purposes UINT8 fileneedednum; tic_t time; tic_t leveltime; char servername[MAXSERVERNAME]; char mapname[8]; char maptitle[33]; unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; char httpsource[MAX_MIRROR_LENGTH]; // HTTP URL to download from, always defined for compatibility UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; typedef struct { char reason[255]; } ATTRPACK serverrefuse_pak; typedef struct { UINT8 version; tic_t time; // used for ping evaluation } ATTRPACK askinfo_pak; typedef struct { char clientaddr[22]; tic_t time; // used for ping evaluation } ATTRPACK msaskinfo_pak; // Shorter player information for external use. typedef struct { UINT8 node; char name[MAXPLAYERNAME+1]; UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH UINT8 team; UINT8 skin; UINT8 data; // Color is first four bits, hasflag, isit and issuper have one bit each, the last is unused. UINT32 score; UINT16 timeinserver; // In seconds. } ATTRPACK plrinfo; // Shortest player information for join during intermission. typedef struct { char name[MAXPLAYERNAME+1]; UINT8 skin; UINT8 color; UINT32 pflags; UINT32 score; UINT8 ctfteam; } ATTRPACK plrconfig; typedef struct { INT32 first; UINT8 num; UINT8 more; UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK filesneededconfig_pak; typedef struct { char http_source[MAX_MIRROR_LENGTH];/* first byte 0? no die! */ } ATTRPACK fileconfig; // // Network packet data // typedef struct { UINT32 checksum; UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack UINT8 ackreturn; // The return of the ack number UINT8 packettype; UINT8 reserved; // Padding union { clientcmd_pak clientpak; // 145 bytes client2cmd_pak client2pak; // 202 bytes client3cmd_pak client3pak; // 258 bytes(?) client4cmd_pak client4pak; // 316 bytes(?) servertics_pak serverpak; // 132495 bytes (more around 360, no?) serverconfig_pak servercfg; // 773 bytes resynchend_pak resynchend; // resynch_pak resynchpak; // UINT8 resynchgot; // UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 153 bytes joinchallenge_pak joinchallenge; // 17 bytes serverinfo_pak serverinfo; // 1024 bytes serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes fileconfig filecfg; UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; #if defined(_MSC_VER) #pragma pack() #endif #define MAXSERVERLIST 64 // Depends only on the display typedef struct { SINT8 node; serverinfo_pak info; } serverelem_t; extern serverelem_t serverlist[MAXSERVERLIST]; extern UINT32 serverlistcount; extern INT32 mapchangepending; // Points inside doomcom extern doomdata_t *netbuffer; extern consvar_t cv_httpsource; extern consvar_t cv_showjoinaddress; extern consvar_t cv_playbackspeed; #define BASEPACKETSIZE offsetof(doomdata_t, u) #define FILETXHEADER offsetof(filetx_pak, data) #define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0]) #define KICK_MSG_GO_AWAY 1 #define KICK_MSG_CON_FAIL 2 #define KICK_MSG_PLAYER_QUIT 3 #define KICK_MSG_TIMEOUT 4 #define KICK_MSG_BANNED 5 #define KICK_MSG_PING_HIGH 6 #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 typedef enum { KR_KICK = 1, //Kicked by server KR_PINGLIMIT = 2, //Broke Ping Limit KR_SYNCH = 3, //Synch Failure KR_TIMEOUT = 4, //Connection Timeout KR_BAN = 5, //Banned by server KR_LEAVE = 6, //Quit the game } kickreason_t; extern boolean server; #define client (!server) extern boolean dedicated; // For dedicated server extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; extern char connectedservername[MAXSERVERNAME]; void Command_Ping_f(void); extern tic_t connectiontimeout; extern tic_t jointimeout; extern UINT16 pingmeasurecount; extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; extern consvar_t #ifdef VANILLAJOINNEXTROUND cv_joinnextround, #endif cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; // Used in d_net, the only dependence tic_t ExpandTics(INT32 low, tic_t basetic); void D_ClientServerInit(void); // Initialise the other field void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam); // splitsreen3 player void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player // Create any new ticcmds and broadcast to other players. void NetKeepAlive(void); void NetUpdate(void); void SV_StartSinglePlayerServer(void); boolean SV_SpawnServer(void); void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle); void SV_StopServer(void); void SV_ResetServer(void); void CL_AddSplitscreenPlayer(void); void CL_RemoveSplitscreenPlayer(UINT8 p); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, INT32 reason); void CL_UpdateServerList(boolean internetsearch, INT32 room); boolean CL_Responder(event_t *ev); // Is there a game running boolean Playing(void); // Broadcasts special packets to other players // to notify of game exit void D_QuitNetGame(void); //? How many ticks to run? void TryRunTics(tic_t realtic); // extra data for lmps // these functions scare me. they contain magic. /*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum); void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum);*/ #ifndef NONET // translate a playername in a player number return -1 if not found and // print a error message in the console SINT8 nametonum(const char *name); #endif extern char motd[254], server_context[8]; extern UINT8 playernode[MAXPLAYERS]; INT32 D_NumPlayers(void); void D_ResetTiccmds(void); tic_t GetLag(INT32 node); UINT8 GetFreeXCmdSize(void); extern UINT8 hu_resynching; extern UINT8 hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player typedef struct rewind_s { UINT8 savebuffer[(768*1024)]; tic_t leveltime; size_t demopos; ticcmd_t oldcmd[MAXPLAYERS]; mobj_t oldghost[MAXPLAYERS]; struct rewind_s *next; } rewind_t; void CL_ClearRewinds(void); rewind_t *CL_SaveRewindPoint(size_t demopos); rewind_t *CL_RewindToTime(tic_t time); #endif