diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 2f3440362..a75c455a6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -212,14 +212,9 @@ tic_t firstconnectattempttime = 0; // engine -// Must be a power of two -#define TEXTCMD_HASH_SIZE 4 - typedef struct textcmdtic_s { - tic_t tic; UINT8 *playercmds[MAXPLAYERS]; - struct textcmdtic_s *next; } textcmdtic_t; typedef struct textcmdbuf_s textcmdbuf_t; @@ -234,7 +229,7 @@ static textcmdbuf_t *textcmdbuf[MAXSPLITSCREENPLAYERS] = {NULL}; static ticcmd_t playercmds[MAXPLAYERS]; ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS] = {}; -static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; +static textcmdtic_t *textcmds[BACKUPTICS] = {NULL}; consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -396,20 +391,10 @@ void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_ // Frees all textcmd memory for the specified tic static void D_FreeTextcmd(tic_t tic) { - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t *textcmdtic = *tctprev; - - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } + textcmdtic_t *textcmdtic = textcmds[tic%BACKUPTICS]; if (textcmdtic) { - // Remove this tic from the list. - *tctprev = textcmdtic->next; - // Free all players. for (INT32 i = 0; i < MAXPLAYERS; i++) { @@ -418,14 +403,14 @@ static void D_FreeTextcmd(tic_t tic) // Free this tic's own memory. Z_Free(textcmdtic); + textcmds[tic%BACKUPTICS] = NULL; } } // Gets the buffer for the specified ticcmd, or NULL if there isn't one static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) { - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdtic && textcmdtic->tic != tic) textcmdtic = textcmdtic->next; + textcmdtic_t *textcmdtic = textcmds[tic%BACKUPTICS]; // Do we have an entry for the tic? If so, look for player. if (textcmdtic) @@ -441,22 +426,11 @@ static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) // Gets the buffer for the specified ticcmd, creating one if necessary static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) { - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - - // Look for the tic. - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } + textcmdtic_t *textcmdtic = textcmds[tic%BACKUPTICS]; // If we don't have an entry for the tic, make it. if (!textcmdtic) - { - textcmdtic = *tctprev = (textcmdtic_t*)Z_Calloc(sizeof (textcmdtic_t), PU_STATIC, NULL); - textcmdtic->tic = tic; - } + textcmds[tic%BACKUPTICS] = textcmdtic = (textcmdtic_t*)Z_Calloc(sizeof(textcmdtic_t), PU_STATIC, NULL); // If we don't have an entry for the player, make it. if (!textcmdtic->playercmds[playernum]) @@ -540,9 +514,8 @@ void D_ResetTiccmds(void) } // Reset the net command list - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) - while (textcmds[i]) - D_Clearticcmd(textcmds[i]->tic); + for (i = 0; i < BACKUPTICS; i++) + D_Clearticcmd(i); } void SendKick(UINT8 playernum, UINT8 msg) @@ -1946,16 +1919,17 @@ static boolean SV_SendServerConfig(INT32 node) return waspacketsent; } -#define SAVEGAMESIZE (768*1024) - #ifdef SATURNPAK static boolean SV_ResendingSavegameToAnyone(void) { INT32 i; for (i = 0; i < MAXNETNODES; i++) + { if (nodeingame[i] && resendingsavegame[i]) return true; + } + return false; } #endif @@ -2938,8 +2912,10 @@ static void CL_ConnectToServer(void) { pnumnodes = 0; for (i = 0; i < MAXNETNODES; i++) + { if (nodeingame[i]) pnumnodes++; + } } } while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); @@ -4147,7 +4123,7 @@ static void Command_ResendGamestate(void) } playernum = nametonum(COM_Argv(1)); - if (playernum == -1 || playernum == 0) + if (playernum <= 0) return; doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); @@ -4423,8 +4399,10 @@ void D_QuitNetGame(void) netbuffer->packettype = PT_SERVERSHUTDOWN; for (i = 0; i < MAXNETNODES; i++) + { if (nodeingame[i]) HSendPacket(i, true, 0, 0); + } #ifdef MASTERSERVER if (serverrunning && netgame && cv_advertise.value) // see mserv.c Online() UnregisterServer(); @@ -4468,18 +4446,21 @@ static inline void SV_AddNode(INT32 node) // Xcmd XD_ADDPLAYER static void Got_AddPlayer(const UINT8 **p, INT32 playernum) { + UINT8 i; INT16 node, newplayernum; UINT8 splitscreenplayer = 0; - UINT8 i; + player_t *newplayer; if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { // protect against hacked/buggy client CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); + if (server) { SendKick(playernum, KICK_MSG_CON_FAIL); } + return; } @@ -4488,14 +4469,19 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) splitscreenplayer = newplayernum/MAXPLAYERS; newplayernum %= MAXPLAYERS; + CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum); + // Clear player before joining, lest some things get set incorrectly CL_ClearPlayer(newplayernum); playeringame[newplayernum] = true; G_AddPlayer(newplayernum); + if (newplayernum+1 > doomcom->numslots) doomcom->numslots = (INT16)(newplayernum+1); + newplayer = &players[newplayernum]; + // the server is creating my player if (node == mynode) { @@ -4506,7 +4492,7 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) displayplayers[splitscreenplayer] = newplayernum; DEBFILE(va("spawning one of my sister number %d\n", splitscreenplayer)); if (splitscreenplayer == 1 && botingame) - players[newplayernum].bot = 1; + newplayer->bot = 1; // do we really want this löl } else { @@ -4516,13 +4502,13 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum) DEBFILE("spawning me\n"); } - P_ForceLocalAngle(&players[newplayernum], (angle_t)(players[newplayernum].cmd.angleturn << TICCMD_REDUCE)); + P_ForceLocalAngle(newplayer, (angle_t)(newplayer->cmd.angleturn << TICCMD_REDUCE)); - D_SendPlayerConfig(); + D_SendPlayerConfig(splitscreenplayer); addedtogame = true; } - players[newplayernum].splitscreenindex = splitscreenplayer; + newplayer->splitscreenindex = splitscreenplayer; if (netgame) { @@ -4586,71 +4572,81 @@ static void Got_RemovePlayer(const UINT8 **p, INT32 playernum) #endif } -static boolean SV_AddWaitingPlayers(void) +static boolean SV_AddWaitingPlayers(SINT8 node) { - INT32 node, n, newplayer = false; + INT32 n; UINT8 buf[2]; UINT8 newplayernum = 0; + boolean newplayer = false; - // What is the reason for this? Why can't newplayernum always be 0? - // Sal: Because the dedicated player is stupidly forced into players[0]..... - if (dedicated) - newplayernum = 1; - - for (node = 0; node < MAXNETNODES; node++) + // splitscreen can allow 2+ players in one node + for (; nodewaiting[node] > 0; nodewaiting[node]--) { - // splitscreen can allow 2+ players in one node - for (; nodewaiting[node] > 0; nodewaiting[node]--) - { - newplayer = true; + newplayer = true; - // search for a free playernum - // we can't use playeringame since it is not updated here - for (; newplayernum < MAXPLAYERS; newplayernum++) + // search for a free playernum + // we can't solely use playeringame since it is not updated here + for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) + { + if (playeringame[newplayernum]) + continue; + + for (n = 0; n < MAXNETNODES; n++) { - for (n = 0; n < MAXNETNODES; n++) - if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum - || nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum) - break; - if (n == MAXNETNODES) + if (nodetoplayer[n] == newplayernum || + nodetoplayer2[n] == newplayernum || + nodetoplayer3[n] == newplayernum || + nodetoplayer4[n] == newplayernum) break; } - // should never happen since we check the playernum - // before accepting the join - I_Assert(newplayernum < MAXPLAYERS); - - playernode[newplayernum] = (UINT8)node; - - buf[0] = (UINT8)node; - buf[1] = newplayernum; - if (playerpernode[node] < 1) - { - nodetoplayer[node] = newplayernum; - } - else if (playerpernode[node] < 2) - { - nodetoplayer2[node] = newplayernum; - buf[1] += MAXPLAYERS; - } - else if (playerpernode[node] < 3) - { - nodetoplayer3[node] = newplayernum; - buf[1] += MAXPLAYERS*2; - } - else - { - nodetoplayer4[node] = newplayernum; - buf[1] += MAXPLAYERS*3; - } - playerpernode[node]++; - - SendNetXCmd(XD_ADDPLAYER, &buf, 2); - - DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); - // use the next free slot (we can't put playeringame[newplayernum] = true here) - newplayernum++; + if (n == MAXNETNODES) + break; } + + // should never happen since we check the playernum + // before accepting the join + I_Assert(newplayernum < MAXPLAYERS); + + buf[0] = (UINT8)node; + buf[1] = newplayernum; + + if (playerpernode[node] < 1) + { + nodetoplayer[node] = newplayernum; + } + else if (playerpernode[node] < 2) + { + nodetoplayer2[node] = newplayernum; + buf[1] += MAXPLAYERS; + } + else if (playerpernode[node] < 3) + { + nodetoplayer3[node] = newplayernum; + buf[1] += MAXPLAYERS*2; + } + else if (playerpernode[node] < 4) + { + nodetoplayer4[node] = newplayernum; + buf[1] += MAXPLAYERS*3; + } + else + { + // I don't know if it's safe to assert here, + // but I do know this should not be allowed + // to be reached. + return newplayer; + } + + playernode[newplayernum] = (UINT8)node; + + playerpernode[node]++; + + SendNetXCmd(XD_ADDPLAYER, &buf, 2); + + DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); + // use the next free slot (we can't put playeringame[newplayernum] = true here) + newplayernum++; } return newplayer; @@ -4687,6 +4683,8 @@ boolean Playing(void) boolean SV_SpawnServer(void) { + boolean result = false; + if (demo.playback) G_StopDemo(); // reset engine parameter @@ -4707,7 +4705,15 @@ boolean SV_SpawnServer(void) else doomcom->numslots = 1; } - return SV_AddWaitingPlayers(); + // strictly speaking, i'm not convinced the following is necessary + // but I'm not confident enough to remove it entirely in case it breaks something + { + SINT8 node = 0; + for (; node < MAXNETNODES; node++) + result |= SV_AddWaitingPlayers(node); + } + + return result; } void SV_StopServer(void) @@ -4761,17 +4767,6 @@ void SV_StartSinglePlayerServer(void) multiplayer = true; } -static void SV_SendRefuse(INT32 node, const char *reason) -{ - doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); - - strcpy(netbuffer->u.serverrefuse.reason, reason); - - netbuffer->packettype = PT_SERVERREFUSE; - HSendPacket(node, false, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); - Net_CloseConnection(node); -} - // used at txtcmds received to check packetsize bound static size_t TotalTextCmdPerTic(tic_t tic) { @@ -4788,15 +4783,25 @@ static size_t TotalTextCmdPerTic(tic_t tic) return total; } -/** Called when a PT_CLIENTJOIN packet is received - * - * \param node The packet sender - * - */ -static void HandleConnect(SINT8 node) +static void SV_SendRefuse(INT32 node, const char *reason) { doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + strcpy(netbuffer->u.serverrefuse.reason, reason); + + netbuffer->packettype = PT_SERVERREFUSE; + HSendPacket(node, false, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); + Net_CloseConnection(node); +} + +static const char *GetRefuseMessage(SINT8 node) +{ + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + clientconfig_pak *cc = &netbuffer->u.clientcfg; + + if (!node) /* server connecting to itself */ + return NULL; + // Sal: Dedicated mode is INCREDIBLY hacked together. // If a server filled out, then it'd overwrite the host and turn everyone into weird husks..... // It's too much effort to legimately fix right now. Just prevent it from reaching that state. @@ -4804,11 +4809,19 @@ static void HandleConnect(SINT8 node) UINT8 connectedplayers = 0; for (UINT8 i = dedicated ? 1 : 0; i < MAXPLAYERS; i++) - if (playernode[i] != UINT8_MAX) // We use this to count players because it is affected by SV_AddWaitingPlayers when more than one client joins on the same tic, unlike playeringame and D_NumPlayers. UINT8_MAX denotes no node for that player + { + // We use this to count players because it is affected by SV_AddWaitingPlayers when + // more than one client joins on the same tic, unlike playeringame and D_NumPlayers. + // UINT8_MAX denotes no node for that player. + + if (playernode[i] != UINT8_MAX) + { connectedplayers++; + } + } #ifdef SATURNJOIN - const boolean issaturn = (((doomcom->datalength) == sizeof(clientconfig_pak)) && netbuffer->u.clientcfg.issaturn == ISSATURN); // Check the packet lenght to skip potential garbo data! + const boolean issaturn = (((doomcom->datalength) == sizeof(clientconfig_pak)) && (cc->issaturn == ISSATURN)); // Check the packet length to skip garbo data! #endif if (bannednode && bannednode[node].banid != SIZE_MAX) @@ -4821,47 +4834,44 @@ static void HandleConnect(SINT8 node) if (bannednode[node].timeleft != NO_BAN_TIME) { - // these are fudged a little to allow it to sink in for impatient rejoiners + // these are fudged a little to allow it to sink in for impatient rejoiners int minutes = (bannednode[node].timeleft + 30) / 60; int hours = (minutes + 1) / 60; int days = (hours + 1) / 24; if (days) { - SV_SendRefuse(node, va("K|%s\n(Time remaining: %d day%s)", reason, days, days > 1 ? "s" : "")); + return va("K|%s\n(Time remaining: %d day%s)", reason, days, days > 1 ? "s" : ""); } else if (hours) { - SV_SendRefuse(node, va("K|%s\n(Time remaining: %d hour%s)", reason, hours, hours > 1 ? "s" : "")); + return va("K|%s\n(Time remaining: %d hour%s)", reason, hours, hours > 1 ? "s" : ""); } else if (minutes) { - SV_SendRefuse(node, va("K|%s\n(Time remaining: %d minute%s)", reason, minutes, minutes > 1 ? "s" : "")); + return va("K|%s\n(Time remaining: %d minute%s)", reason, minutes, minutes > 1 ? "s" : ""); } else { - SV_SendRefuse(node, va("K|%s\n(Time remaining: <1 minute)", reason)); + return va("K|%s\n(Time remaining: <1 minute)", reason); } } else { - SV_SendRefuse(node, va("B|%s", reason)); + return va("B|%s", reason); } } - else if (netbuffer->u.clientcfg._255 != 255 || - netbuffer->u.clientcfg.packetversion != PACKETVERSION) + else if (cc->_255 != 255 || cc->packetversion != PACKETVERSION) { - SV_SendRefuse(node, "Incompatible packet formats."); + return "Incompatible packet formats."; } - else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application)) + else if (strncmp(cc->application, SRB2APPLICATION, sizeof(cc->application))) { - SV_SendRefuse(node, "Different SRB2Kart modifications\nare not compatible."); + return "Different SRB2Kart modifications\nare not compatible."; } - else if (netbuffer->u.clientcfg.version != VERSION - || netbuffer->u.clientcfg.subversion != SUBVERSION) + else if (cc->version != VERSION || cc->subversion != SUBVERSION) { - SV_SendRefuse(node, va(M_GetText("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)"), VERSION, SUBVERSION)); + return va("Different SRB2Kart versions cannot\nplay a netgame!\n(server version %d.%d)", VERSION, SUBVERSION); } #ifdef SATURNJOIN else if (((!cv_allownewplayer.value && !issaturn) || (!cv_allownewsaturnplayer.value && issaturn)) && node) @@ -4869,72 +4879,85 @@ static void HandleConnect(SINT8 node) else if (!cv_allownewplayer.value && node) #endif { - SV_SendRefuse(node, M_GetText(cv_joinrefusemessage.string)); + return cv_joinrefusemessage.string; } else if (connectedplayers >= maxplayers) { - SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), maxplayers)); + return va("Maximum players reached: %d", maxplayers); } - else if (netgame && netbuffer->u.clientcfg.localplayers > 4) // Hacked client? + else if (netgame && !cc->localplayers) // Stealth join? { - SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); + return "No players from\nthis node."; } - else if (netgame && connectedplayers + netbuffer->u.clientcfg.localplayers > maxplayers) + else if (netgame && cc->localplayers > 4) // Hacked client? { - SV_SendRefuse(node, va(M_GetText("Number of local players\nwould exceed maximum: %d"), maxplayers)); + return "Too many players from\nthis node."; } - else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? + else if (netgame && connectedplayers + cc->localplayers > maxplayers) { - SV_SendRefuse(node, M_GetText("No players from\nthis node.")); + return va("Number of local players\nwould exceed maximum: %d", maxplayers); } - else - { - boolean newnode = false; - // client authorised to join - nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); + return NULL; +} - if (!nodeingame[node]) +/** Called when a PT_CLIENTJOIN packet is received + * + * \param node The packet sender + * + */ +static void PT_ClientJoin(SINT8 node) +{ + // Ignore duplicate packets + if (client || nodeingame[node] || levelloading) + return; + + const char *refuse = GetRefuseMessage(node); + + if (refuse) + { + SV_SendRefuse(node, refuse); + return; + } + + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + + // client authorised to join + nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); + + gamestate_t backupstate = gamestate; + + SV_AddNode(node); + + /// \note Wait what??? + /// What if the gamestate takes more than one second to get downloaded? + /// Or if a lagspike happens? + // you get a free second before desynch checks. use it wisely. + SV_InitResynchVars(node); + + if (!SV_SendServerConfig(node)) + { + G_SetGamestate(backupstate); + /// \note Shouldn't SV_SendRefuse be called before ResetNode? + SV_SendRefuse(node, "Server couldn't send info, please try again"); + ResetNode(node); // Yeah, lets try it! + /// \todo fix this !!! + return; // restart the while + } + + SV_SendServerInfo(node, 0); // Dunno if 0 time is good idea + G_SetGamestate(backupstate); + DEBFILE("new node joined\n"); + + if (nodewaiting[node]) + { + if (node) { - gamestate_t backupstate = gamestate; - - newnode = true; - - SV_AddNode(node); - - /// \note Wait what??? - /// What if the gamestate takes more than one second to get downloaded? - /// Or if a lagspike happens? - // you get a free second before desynch checks. use it wisely. - SV_InitResynchVars(node); - - if (!SV_SendServerConfig(node)) - { - G_SetGamestate(backupstate); - /// \note Shouldn't SV_SendRefuse be called before ResetNode? - SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); - ResetNode(node); // Yeah, lets try it! - /// \todo fix this !!! - return; // restart the while - } - - SV_SendServerInfo(node, 0); // Dunno if 0 time is good idea - //if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc? - // SV_SendPlayerConfigs(node); // send bare minimum player info - G_SetGamestate(backupstate); - DEBFILE("new node joined\n"); + SV_SendSaveGame(node, false); // send a complete game state + DEBFILE("send savegame\n"); } - if (nodewaiting[node]) - { - if (node && newnode) - { - SV_SendSaveGame(node, false); // send a complete game state - DEBFILE("send savegame\n"); - } - - SV_AddWaitingPlayers(); - } + SV_AddWaitingPlayers(node); } } @@ -4943,8 +4966,11 @@ static void HandleConnect(SINT8 node) * \param node The packet sender (should be the server) * */ -static void HandleShutdown(SINT8 node) +static void PT_ServerShutdown(SINT8 node) { + if (node != servernode || server || cl_mode == CL_SEARCHING) + return; + (void)node; D_QuitNetGame(); CL_Reset(); @@ -4972,7 +4998,7 @@ static void HandleTimeout(SINT8 node) * \note What happens if the packet comes from a client or something like that? * */ -static void HandleServerInfo(SINT8 node) +static void PT_ServerInfo(SINT8 node) { char servername[MAXSERVERNAME]; doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); @@ -4995,7 +5021,7 @@ static void HandleServerInfo(SINT8 node) memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME); } -static void HandlePlayerInfo(void) +static void PT_PlayerInfo(void) { INT32 i; doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); @@ -5393,6 +5419,9 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_ASKINFOVIAMS: Net_CloseConnection(node); break; + case PT_SERVERINFO: + PT_ServerInfo(node); + break; case PT_TELLFILESNEEDED: PT_TellFilesNeeded(node); break; @@ -5423,7 +5452,7 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_CLIENTCMD: break; // This is not an "unknown packet" case PT_PLAYERINFO: - HandlePlayerInfo(); + PT_PlayerInfo(); break; case PT_MAPICON: PT_MapIcon(); @@ -5431,12 +5460,17 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_NEEDMAPICON: PT_NeedMapIcon(node); break; + case PT_SERVERSHUTDOWN: + PT_ServerShutdown(node); + break; + case PT_CLIENTJOIN: + PT_ClientJoin(node); + break; case PT_SERVERTICS: // Do not remove my own server (we have just get a out of order packet) if (node == servernode) break; /* FALLTHRU */ - default: DEBFILE(va("unknown packet received (%d) from unknown host\n", netbuffer->packettype)); Net_CloseConnection(node); @@ -5680,6 +5714,10 @@ static void PT_BasicKeepAlive(INT32 netconsole, SINT8 node) static void PT_TextCmd(INT32 netconsole, SINT8 node) { + size_t j; + tic_t tic; + UINT8 *textcmd; + if (client) return; @@ -5701,79 +5739,84 @@ static void PT_TextCmd(INT32 netconsole, SINT8 node) } if (netconsole < 0 || netconsole >= MAXPLAYERS) - Net_UnAcknowledgePacket(node); - else { - size_t j; - tic_t tic = maketic; - UINT8 *textcmd; - - // ignore if the textcmd has a reported size of zero - // this shouldn't be sent at all - if (!netbuffer->u.textcmd[0]) - { - DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", - node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // ignore if the textcmd size var is actually larger than it should be - // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength - if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-1) - { - DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", - netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-1), - node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // check if tic that we are making isn't too large else we cannot send it :( - // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time - j = (software_MAXPACKETLENGTH - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + (doomcom->numslots+1)*sizeof(ticcmd_t))); - - // search a tic that have enougth space in the ticcmd - while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), - (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) - { - tic++; - } - - if (tic >= firstticstosend + BACKUPTICS) - { - DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " - "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), - maketic, firstticstosend, node, netconsole)); - Net_UnAcknowledgePacket(node); - return; - } - - // Make sure we have a buffer - if (!textcmd) - textcmd = D_GetTextcmd(tic, netconsole); - - DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", - tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); - - memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); - textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; + Net_UnAcknowledgePacket(node); + return; } + + // ignore if the textcmd has a reported size of zero + // this shouldn't be sent at all + if (!netbuffer->u.textcmd[0]) + { + DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // ignore if the textcmd size var is actually larger than it should be + // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-1) + { + DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-1), + node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // check if tic that we are making isn't too large else we cannot send it :( + // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time + j = (software_MAXPACKETLENGTH - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + (doomcom->numslots+1)*sizeof(ticcmd_t))); + + tic = maketic; + + // search a tic that have enougth space in the ticcmd + while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), + (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) + && tic < firstticstosend + BACKUPTICS) + { + tic++; + } + + if (tic >= firstticstosend + BACKUPTICS) + { + DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " + "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), + maketic, firstticstosend, node, netconsole)); + Net_UnAcknowledgePacket(node); + return; + } + + // Make sure we have a buffer + if (!textcmd) + textcmd = D_GetTextcmd(tic, netconsole); + + DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", + tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); + + memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; } static void PT_ClientQuit(INT32 netconsole, SINT8 node) { + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + if (client) + { + if (node == servernode && cl_mode != CL_SEARCHING && netbuffer->packettype == PT_NODETIMEOUT) + HandleTimeout(node); return; + } // nodeingame will be put false in the execution of kick command // this allow to send some packets to the quitting client to have their ack back nodewaiting[node] = 0; if (netconsole != -1 && playeringame[netconsole]) { - doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); - SendKick(netconsole, (netbuffer->packettype == PT_NODETIMEOUT) ? KICK_MSG_TIMEOUT : KICK_MSG_PLAYER_QUIT); + const int quitreason = ((netbuffer->packettype == PT_NODETIMEOUT) ? KICK_MSG_TIMEOUT : KICK_MSG_PLAYER_QUIT); + SendKick(netconsole, quitreason); } Net_CloseConnection(node); nodeingame[node] = false; @@ -5959,9 +6002,6 @@ static void HandlePacketFromPlayer(SINT8 node) switch (netbuffer->packettype) { // -------------------------------------------- SERVER RECEIVE ---------- - case PT_RESYNCHGET: - SV_AcknowledgeResynchAck(node, netbuffer->u.resynchgot); - break; case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENT3CMD: @@ -5987,24 +6027,6 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_CLIENTQUIT: PT_ClientQuit(netconsole, node); break; -// -------------------------------------------- CLIENT RECEIVE ---------- - case PT_RESYNCHEND: - PT_Resynched(node); - break; - case PT_SERVERTICS: - PT_ServerTics(node); - break; - case PT_RESYNCHING: - PT_Resynching(node); - break; - case PT_PING: - PT_Ping(node); - break; - case PT_SERVERCFG: - break; - case PT_FILEFRAGMENT: - PT_FileFragmentFromPlayer(node); - break; #ifdef SATURNPAK case PT_CANRECEIVEGAMESTATE: PT_CanReceiveGamestate(node); @@ -6012,6 +6034,25 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_RECEIVEDGAMESTATE: PT_ReceivedGamestate(node); break; +#endif + case PT_SERVERINFO: + PT_ServerInfo(node); + break; + case PT_RESYNCHGET: + SV_AcknowledgeResynchAck(node, netbuffer->u.resynchgot); + break; +// -------------------------------------------- CLIENT RECEIVE ---------- + case PT_SERVERTICS: + PT_ServerTics(node); + break; + case PT_PING: + PT_Ping(node); + break; + + case PT_FILEFRAGMENT: + PT_FileFragmentFromPlayer(node); + break; +#ifdef SATURNPAK case PT_WILLRESENDGAMESTATE: PT_WillResendGamestate(); break; @@ -6020,6 +6061,20 @@ static void HandlePacketFromPlayer(SINT8 node) is_client_saturn[node] = true; break; #endif + case PT_SERVERSHUTDOWN: + PT_ServerShutdown(node); + break; + case PT_SERVERCFG: + break; + case PT_CLIENTJOIN: + PT_ClientJoin(node); + break; + case PT_RESYNCHING: + PT_Resynching(node); + break; + case PT_RESYNCHEND: + PT_Resynched(node); + break; default: DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", netbuffer->packettype, node)); } @@ -6040,36 +6095,6 @@ static void GetPackets(void) { node = (SINT8)doomcom->remotenode; - if (server && netbuffer->packettype == PT_CLIENTJOIN) - { - if (!levelloading) // Otherwise just ignore - { - HandleConnect(node); - } - - continue; - } - - if (client && node == servernode && cl_mode != CL_SEARCHING) - { - if (netbuffer->packettype == PT_SERVERSHUTDOWN) - { - HandleShutdown(node); - continue; - } - if (netbuffer->packettype == PT_NODETIMEOUT) - { - HandleTimeout(node); - continue; - } - } - - if (netbuffer->packettype == PT_SERVERINFO) - { - HandleServerInfo(node); - continue; - } - /*if (netbuffer->packettype == PT_PLAYERINFO) continue; // We do nothing with PLAYERINFO, that's for the MS browser. Not quite true anymore :p*/ @@ -6388,21 +6413,7 @@ static void CL_SendClientCmd(void) { if (localtextcmd[i][0]) { - switch (i) - { - case 3: - netbuffer->packettype = PT_TEXTCMD4; - break; - case 2: - netbuffer->packettype = PT_TEXTCMD3; - break; - case 1: - netbuffer->packettype = PT_TEXTCMD2; - break; - default: - netbuffer->packettype = PT_TEXTCMD; - break; - } + netbuffer->packettype = PT_TEXTCMD + i; memcpy(netbuffer->u.textcmd, localtextcmd[i], localtextcmd[i][0]+1); @@ -6446,7 +6457,7 @@ static void SV_SendTics(void) continue; // assert supposedtics[n]>=nettics[n] - realfirsttic = max(supposedtics[n], firstticstosend); + realfirsttic = supposedtics[n]; lasttictosend = min(maketic, nettics[n] + CLIENTBACKUPTICS); if (realfirsttic >= lasttictosend) @@ -6620,7 +6631,7 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle) // create missed tic static void SV_Maketic(void) { - G_MoveTiccmd(netcmds[maketic % BACKUPTICS], playercmds, MAXPLAYERS); + G_CopyTiccmd(netcmds[maketic % BACKUPTICS], playercmds, MAXPLAYERS); maketic++; } @@ -6837,8 +6848,10 @@ static inline void PingUpdate(void) //send out our ping packets for (i = 0; i < MAXNETNODES; i++) + { if (nodeingame[i]) HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); + } pingmeasurecount = 0; //Reset count } @@ -6941,10 +6954,15 @@ static void RenewHolePunch(void) static void HandleNodeTimeouts(void) { INT32 i; + if (server) + { for (i = 1; i < MAXNETNODES; i++) + { if (nodeingame[i] && freezetimeout[i] < I_GetTime()) Net_ConnectionTimeout(i); + } + } } // Keep the network alive while not advancing tics! @@ -7154,11 +7172,13 @@ void NetUpdate(void) } for (i = 0; i < MAXNETNODES; ++i) + { if (resynch_inprogress[i]) { SV_SendResynch(i); counts = -666; } + } // Do not make tics while resynching if (counts != -666) @@ -7185,6 +7205,8 @@ void NetUpdate(void) Net_AckTicker(); HandleNodeTimeouts(); + nowtime /= NEWTICRATERATIO; + if (nowtime > resptime) { resptime = nowtime; @@ -7210,9 +7232,15 @@ void NetUpdate(void) INT32 D_NumPlayers(void) { INT32 num = 0, ix; + for (ix = 0; ix < MAXPLAYERS; ix++) + { if (playeringame[ix]) + { num++; + } + } + return num; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 430729bc2..08bccf845 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -660,9 +660,11 @@ extern UINT8 hu_redownloadinggamestate; #endif extern boolean hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player +#define SAVEGAMESIZE (768*1024) + typedef struct rewind_s { - UINT8 savebuffer[(768*1024)]; + UINT8 savebuffer[SAVEGAMESIZE]; tic_t leveltime; size_t demopos; diff --git a/src/d_net.c b/src/d_net.c index c0d8c667b..f7e7ffecd 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -612,12 +612,8 @@ void Net_WaitAllAckReceived(UINT32 timeout) static void InitNode(node_t *node) { - node->acktosend_head = node->acktosend_tail = 0; - memset(node->acktosend, 0, sizeof(node->acktosend)); - node->firstacktosend = 0; + memset(node, 0, sizeof(node_t)); node->nextacknum = 1; - node->remotefirstack = 0; - node->flags = 0; } static void InitAck(void) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6ecc670d1..d16b54be9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1208,11 +1208,11 @@ static boolean AllowedPlayerNameChar(char ch) static boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) { - INT32 ix; + size_t ix, len = strlen(name); - if (strlen(name) == 0 || strlen(name) > MAXPLAYERNAME) + if (len == 0 || len > MAXPLAYERNAME) return false; // Empty or too long. - if (name[0] == ' ' || name[strlen(name)-1] == ' ') + if (name[0] == ' ' || name[len-1] == ' ') return false; // Starts or ends with a space. if (isdigit(name[0])) return false; // Starts with a digit. @@ -1226,20 +1226,19 @@ static boolean EnsurePlayerNameIsGood(char *name, INT32 playernum) // Also, anything over 0x80 is disallowed too, since compilers love to // differ on whether they're printable characters or not. - for (ix = 0; name[ix] != '\0'; ix++) + for (ix = 0; ix < len; ix++) if (!AllowedPlayerNameChar(name[ix])) return false; // Check if a player is currently using the name, case-insensitively. for (ix = 0; ix < MAXPLAYERS; ix++) { - if (ix != playernum && playeringame[ix] + if (ix != (size_t)playernum && playeringame[ix] && fasticmp(name, player_names[ix])) { // We shouldn't kick people out just because // they joined the game with the same name // as someone else -- modify the name instead. - size_t len = strlen(name); // Recursion! // Slowly strip characters off the end of the @@ -1458,7 +1457,9 @@ UINT8 CanChangeSkin(INT32 playernum) return true; } - if (players[playernum].spectator || players[playernum].playerstate == PST_DEAD || players[playernum].playerstate == PST_REBORN) + if (players[playernum].spectator || + players[playernum].playerstate == PST_DEAD || + players[playernum].playerstate == PST_REBORN) return true; return false; @@ -1492,445 +1493,144 @@ static void ForceAllSkins(INT32 forcedskin) } } -static INT32 snacpending = 0, snac2pending = 0, snac3pending = 0, snac4pending = 0, chmappending = 0; +static INT32 chmappending; +static INT32 snacpending[MAXSPLITSCREENPLAYERS]; + +// wonky compat, idk if anything uses this.... +#define playerisbot (splitplayer == 1 && botingame) // name, color, or skin has changed // -static void SendNameAndColor(void) +static void SendNameAndColor(UINT8 splitplayer) { char buf[MAXPLAYERNAME+2]; char *p; p = buf; + // splitscreen + if (splitscreen < splitplayer && !playerisbot) + return; + + const INT32 pnum = P_GetLocalPlayerNumForNum(splitplayer); + + player_t *player = &players[pnum]; + + // TODO: make those cvars arrays + consvar_t *playercolor, *playername, *playerskin; + consvar_t *colorvars[] = {&cv_playercolor, &cv_playercolor2, &cv_playercolor3, &cv_playercolor4}; + consvar_t *namevars[] = {&cv_playername, &cv_playername2, &cv_playername3, &cv_playername4}; + consvar_t *skinvars[] = {&cv_skin, &cv_skin2, &cv_skin3, &cv_skin4}; + + playercolor = colorvars[splitplayer]; + playername = namevars[splitplayer]; + playerskin = skinvars[splitplayer]; + // normal player colors if (G_GametypeHasTeams()) { - if (players[consoleplayer].ctfteam == 1 && cv_playercolor.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor, skincolor_redteam); - else if (players[consoleplayer].ctfteam == 2 && cv_playercolor.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor, skincolor_blueteam); + if (player->ctfteam == 1 && playercolor->value != skincolor_redteam) + CV_StealthSetValue(playercolor, skincolor_redteam); + else if (player->ctfteam == 2 && playercolor->value != skincolor_blueteam) + CV_StealthSetValue(playercolor, skincolor_blueteam); } // never allow the color "none" - if (!cv_playercolor.value) + if (!playercolor->value) { - if (players[consoleplayer].skincolor) - CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor); - else if (skins[players[consoleplayer].skin].prefcolor) - CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor); + if (player->skincolor) + CV_StealthSetValue(playercolor, player->skincolor); + else if (skins[player->skin].prefcolor) + CV_StealthSetValue(playercolor, skins[player->skin].prefcolor); else - CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue); + CV_StealthSet(playercolor, playercolor->defaultvalue); } - if (fastcmp(cv_playername.string, player_names[consoleplayer]) - && cv_playercolor.value == players[consoleplayer].skincolor - && fastcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) - return; - // We'll handle it later if we're not playing. if (!Playing()) return; + if (fastcmp(playername->string, player_names[pnum]) + && playercolor->value == player->skincolor + && fastcmp(playerskin->string, skins[player->skin].name)) + return; + + if (playerisbot) + { + players[pnum].skincolor = botcolor; + if (players[pnum].mo) + players[pnum].mo->color = players[pnum].skincolor; + SetPlayerSkinByNum(pnum, botskin-1); + return; + } + // If you're not in a netgame, merely update the skin, color, and name. if (!netgame) { INT32 foundskin; - CleanupPlayerName(consoleplayer, cv_playername.zstring); - strcpy(player_names[consoleplayer], cv_playername.zstring); + CleanupPlayerName(pnum, playername->zstring); + strcpy(player_names[pnum], playername->zstring); - players[consoleplayer].skincolor = cv_playercolor.value; + player->skincolor = playercolor->value; - if (players[consoleplayer].mo) - players[consoleplayer].mo->color = players[consoleplayer].skincolor; + if (player->mo) + player->mo->color = player->skincolor; - if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1) + if ((foundskin = R_SkinAvailable(playerskin->string)) != -1) { - cv_skin.value = foundskin; - SetPlayerSkin(consoleplayer, cv_skin.string); - CV_StealthSet(&cv_skin, skins[cv_skin.value].name); + playerskin->value = foundskin; + SetPlayerSkin(pnum, playerskin->string); + CV_StealthSet(playerskin, skins[playerskin->value].name); } else { - cv_skin.value = players[consoleplayer].skin; - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + playerskin->value = player->skin; + CV_StealthSet(playerskin, skins[player->skin].name); // will always be same as current - SetPlayerSkin(consoleplayer, cv_skin.string); + SetPlayerSkin(pnum, playerskin->string); } return; } - snacpending++; + snacpending[splitplayer]++; // Don't change name if muted - if (player_name_changes[consoleplayer] >= MAXNAMECHANGES) + if (player_name_changes[pnum] >= MAXNAMECHANGES) { - CV_StealthSet(&cv_playername, player_names[consoleplayer]); + CV_StealthSet(playername, player_names[pnum]); HU_AddChatText("\x85*You must wait to change your name again", false); } - else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) - CV_StealthSet(&cv_playername, player_names[consoleplayer]); + else if (cv_mute.value && !(server || IsPlayerAdmin(pnum))) + CV_StealthSet(playername, player_names[pnum]); else // Cleanup name if changing it - CleanupPlayerName(consoleplayer, cv_playername.zstring); + CleanupPlayerName(pnum, playername->zstring); // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(consoleplayer)) - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + if (!CanChangeSkin(pnum)) + CV_StealthSet(playerskin, skins[player->skin].name); // check if player has the skin loaded (cv_skin may have // the name of a skin that was available in the previous game) - cv_skin.value = R_SkinAvailable(cv_skin.string); - if (cv_skin.value < 0) + playerskin->value = R_SkinAvailable(playerskin->string); + if (playerskin->value < 0) { - INT32 skinnum = players[consoleplayer].skin; - CV_StealthSet(&cv_skin, skins[skinnum].name); - cv_skin.value = skinnum; + INT32 skinnum = player->skin; + CV_StealthSet(playerskin, skins[skinnum].name); + playerskin->value = skinnum; } // Finally write out the complete packet and send it off. - WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME); - WRITEUINT8(p, (UINT8)cv_playercolor.value); - WRITEUINT8(p, (UINT8)cv_skin.value); - SendNetXCmdForPlayer(0, XD_NAMEANDCOLOR, buf, p - buf); -} - -// splitscreen -static void SendNameAndColor2(void) -{ - INT32 secondplaya = -1; - char buf[MAXPLAYERNAME+2]; - char *p; - - if (splitscreen < 1 && !botingame) - return; // can happen if skin2/color2/name2 changed - - if (displayplayers[1] != consoleplayer) - secondplaya = displayplayers[1]; - else if (!netgame) // HACK - secondplaya = 1; - - if (secondplaya == -1) - return; - - p = buf; - - // normal player colors - if (G_GametypeHasTeams()) - { - if (players[secondplaya].ctfteam == 1 && cv_playercolor2.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor2, skincolor_redteam); - else if (players[secondplaya].ctfteam == 2 && cv_playercolor2.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam); - } - - // never allow the color "none" - if (!cv_playercolor2.value) - { - if (players[secondplaya].skincolor) - CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor); - else if (skins[players[secondplaya].skin].prefcolor) - CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); - else - CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue); - } - - // We'll handle it later if we're not playing. - if (!Playing()) - return; - - // If you're not in a netgame, merely update the skin, color, and name. - if (botingame) - { - players[secondplaya].skincolor = botcolor; - if (players[secondplaya].mo) - players[secondplaya].mo->color = players[secondplaya].skincolor; - SetPlayerSkinByNum(secondplaya, botskin-1); - return; - } - else if (!netgame) - { - INT32 foundskin; - - CleanupPlayerName(secondplaya, cv_playername2.zstring); - strcpy(player_names[secondplaya], cv_playername2.zstring); - - // don't use displayplayers[1]: the second player must be 1 - players[secondplaya].skincolor = cv_playercolor2.value; - if (players[secondplaya].mo) - players[secondplaya].mo->color = players[secondplaya].skincolor; - - if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1) - { - cv_skin2.value = foundskin; - SetPlayerSkin(secondplaya, cv_skin2.string); - } - else - { - cv_skin2.value = players[secondplaya].skin; - CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name); - // will always be same as current - SetPlayerSkin(secondplaya, cv_skin2.string); - } - return; - } - - snac2pending++; - - // Don't change name if muted - if (player_name_changes[displayplayers[1]] >= MAXNAMECHANGES) - { - CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]); - HU_AddChatText("\x85*You must wait to change your name again", false); - } - else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[1]))) - CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]); - else // Cleanup name if changing it - CleanupPlayerName(displayplayers[1], cv_playername2.zstring); - - // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(displayplayers[1])) - CV_StealthSet(&cv_skin2, skins[players[displayplayers[1]].skin].name); - - // check if player has the skin loaded (cv_skin2 may have - // the name of a skin that was available in the previous game) - cv_skin2.value = R_SkinAvailable(cv_skin2.string); - if (cv_skin2.value < 0) - { - INT32 skinnum = players[displayplayers[1]].skin; - CV_StealthSet(&cv_skin2, skins[skinnum].name); - cv_skin2.value = skinnum; - } - - // Finally write out the complete packet and send it off. - WRITESTRINGN(p, cv_playername2.zstring, MAXPLAYERNAME); - WRITEUINT8(p, (UINT8)cv_playercolor2.value); - WRITEUINT8(p, (UINT8)cv_skin2.value); - SendNetXCmdForPlayer(1, XD_NAMEANDCOLOR, buf, p - buf); -} - -static void SendNameAndColor3(void) -{ - INT32 thirdplaya = -1; - char buf[MAXPLAYERNAME+2]; - char *p; - - if (splitscreen < 2) - return; // can happen if skin3/color3/name3 changed - - if (displayplayers[2] != consoleplayer) - thirdplaya = displayplayers[2]; - else if (!netgame) // HACK - thirdplaya = 2; - - if (thirdplaya == -1) - return; - - p = buf; - - // normal player colors - if (G_GametypeHasTeams()) - { - if (players[thirdplaya].ctfteam == 1 && cv_playercolor3.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor3, skincolor_redteam); - else if (players[thirdplaya].ctfteam == 2 && cv_playercolor3.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor3, skincolor_blueteam); - } - - // never allow the color "none" - if (!cv_playercolor3.value) - { - if (players[thirdplaya].skincolor) - CV_StealthSetValue(&cv_playercolor3, players[thirdplaya].skincolor); - else if (skins[players[thirdplaya].skin].prefcolor) - CV_StealthSetValue(&cv_playercolor3, skins[players[thirdplaya].skin].prefcolor); - else - CV_StealthSet(&cv_playercolor3, cv_playercolor3.defaultvalue); - } - - // We'll handle it later if we're not playing. - if (!Playing()) - return; - - // If you're not in a netgame, merely update the skin, color, and name. - if (!netgame) - { - INT32 foundskin; - - CleanupPlayerName(thirdplaya, cv_playername3.zstring); - strcpy(player_names[thirdplaya], cv_playername3.zstring); - - // don't use displayplayers[2]: the third player must be 2 - players[thirdplaya].skincolor = cv_playercolor3.value; - if (players[thirdplaya].mo) - players[thirdplaya].mo->color = players[thirdplaya].skincolor; - - if ((foundskin = R_SkinAvailable(cv_skin3.string)) != -1) - { - cv_skin3.value = foundskin; - SetPlayerSkin(thirdplaya, cv_skin3.string); - } - else - { - cv_skin3.value = players[thirdplaya].skin; - CV_StealthSet(&cv_skin3, skins[players[thirdplaya].skin].name); - // will always be same as current - SetPlayerSkin(thirdplaya, cv_skin3.string); - } - return; - } - - snac3pending++; - - // Don't change name if muted - if (player_name_changes[displayplayers[2]] >= MAXNAMECHANGES) - { - CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]); - HU_AddChatText("\x85*You must wait to change your name again", false); - } - else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[2]))) - CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]); - else // Cleanup name if changing it - CleanupPlayerName(displayplayers[2], cv_playername3.zstring); - - // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(displayplayers[2])) - CV_StealthSet(&cv_skin3, skins[players[displayplayers[2]].skin].name); - - // check if player has the skin loaded (cv_skin3 may have - // the name of a skin that was available in the previous game) - cv_skin3.value = R_SkinAvailable(cv_skin3.string); - if (cv_skin3.value < 0) - { - INT32 skinnum = players[displayplayers[2]].skin; - CV_StealthSet(&cv_skin3, skins[skinnum].name); - cv_skin3.value = skinnum; - } - - // Finally write out the complete packet and send it off. - WRITESTRINGN(p, cv_playername3.zstring, MAXPLAYERNAME); - WRITEUINT8(p, (UINT8)cv_playercolor3.value); - WRITEUINT8(p, (UINT8)cv_skin3.value); - SendNetXCmdForPlayer(2, XD_NAMEANDCOLOR, buf, p - buf); -} - -static void SendNameAndColor4(void) -{ - INT32 fourthplaya = -1; - char buf[MAXPLAYERNAME+2]; - char *p; - - if (splitscreen < 3) - return; // can happen if skin4/color4/name4 changed - - if (displayplayers[3] != consoleplayer) - fourthplaya = displayplayers[3]; - else if (!netgame) // HACK - fourthplaya = 3; - - if (fourthplaya == -1) - return; - - p = buf; - - // normal player colors - if (G_GametypeHasTeams()) - { - if (players[fourthplaya].ctfteam == 1 && cv_playercolor4.value != skincolor_redteam) - CV_StealthSetValue(&cv_playercolor4, skincolor_redteam); - else if (players[fourthplaya].ctfteam == 2 && cv_playercolor4.value != skincolor_blueteam) - CV_StealthSetValue(&cv_playercolor4, skincolor_blueteam); - } - - // never allow the color "none" - if (!cv_playercolor4.value) - { - if (players[fourthplaya].skincolor) - CV_StealthSetValue(&cv_playercolor4, players[fourthplaya].skincolor); - else if (skins[players[fourthplaya].skin].prefcolor) - CV_StealthSetValue(&cv_playercolor4, skins[players[fourthplaya].skin].prefcolor); - else - CV_StealthSet(&cv_playercolor4, cv_playercolor4.defaultvalue); - } - - // We'll handle it later if we're not playing. - if (!Playing()) - return; - - // If you're not in a netgame, merely update the skin, color, and name. - if (botingame) - { - players[fourthplaya].skincolor = botcolor; - if (players[fourthplaya].mo) - players[fourthplaya].mo->color = players[fourthplaya].skincolor; - SetPlayerSkinByNum(fourthplaya, botskin-1); - return; - } - else if (!netgame) - { - INT32 foundskin; - - CleanupPlayerName(fourthplaya, cv_playername4.zstring); - strcpy(player_names[fourthplaya], cv_playername4.zstring); - - // don't use displayplayers[3]: the second player must be 4 - players[fourthplaya].skincolor = cv_playercolor4.value; - if (players[fourthplaya].mo) - players[fourthplaya].mo->color = players[fourthplaya].skincolor; - - if ((foundskin = R_SkinAvailable(cv_skin4.string)) != -1) - { - cv_skin4.value = foundskin; - SetPlayerSkin(fourthplaya, cv_skin4.string); - } - else - { - cv_skin4.value = players[fourthplaya].skin; - CV_StealthSet(&cv_skin4, skins[players[fourthplaya].skin].name); - // will always be same as current - SetPlayerSkin(fourthplaya, cv_skin4.string); - } - return; - } - - snac4pending++; - - // Don't change name if muted - if (player_name_changes[displayplayers[3]] >= MAXNAMECHANGES) - { - CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]); - HU_AddChatText("\x85*You must wait to change your name again", false); - } - else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[3]))) - CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]); - else // Cleanup name if changing it - CleanupPlayerName(displayplayers[3], cv_playername4.zstring); - - // Don't change skin if the server doesn't want you to. - if (!CanChangeSkin(displayplayers[3])) - CV_StealthSet(&cv_skin4, skins[players[displayplayers[3]].skin].name); - - // check if player has the skin loaded (cv_skin4 may have - // the name of a skin that was available in the previous game) - cv_skin4.value = R_SkinAvailable(cv_skin4.string); - if (cv_skin4.value < 0) - { - INT32 skinnum = players[displayplayers[3]].skin; - CV_StealthSet(&cv_skin4, skins[skinnum].name); - cv_skin4.value = skinnum; - } - - // Finally write out the complete packet and send it off. - WRITESTRINGN(p, cv_playername4.zstring, MAXPLAYERNAME); - WRITEUINT8(p, (UINT8)cv_playercolor4.value); - WRITEUINT8(p, (UINT8)cv_skin4.value); - SendNetXCmdForPlayer(3, XD_NAMEANDCOLOR, buf, p - buf); + WRITESTRINGN(p, playername->zstring, MAXPLAYERNAME); + WRITEUINT8(p, (UINT8)playercolor->value); + WRITEUINT8(p, (UINT8)playerskin->value); + SendNetXCmdForPlayer(splitplayer, XD_NAMEANDCOLOR, buf, p - buf); } static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) { - player_t *p = &players[playernum]; + player_t *player = &players[playernum]; char name[MAXPLAYERNAME+1]; UINT8 color, skin; @@ -1939,19 +1639,14 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) I_Error("There is no player %d!", playernum); #endif - if (playernum == consoleplayer) - snacpending--; // TODO: make snacpending an array instead of 4 separate vars? - else if (playernum == displayplayers[1]) - snac2pending--; - else if (playernum == displayplayers[2]) - snac3pending--; - else if (playernum == displayplayers[3]) - snac4pending--; - + if (P_IsLocalPlayer(player)) + { + snacpending[playernum]--; #ifdef PARANOIA - if (snacpending < 0 || snac2pending < 0 || snac3pending < 0 || snac4pending < 0) - I_Error("snacpending negative!"); + if (snacpending[playernum] < 0) + I_Error("snacpending negative!"); #endif + } READSTRINGN(*cp, name, MAXPLAYERNAME); color = READUINT8(*cp); @@ -1965,33 +1660,32 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) } // set color - p->skincolor = color % MAXSKINCOLORS; - if (p->mo) - p->mo->color = (UINT8)p->skincolor; + player->skincolor = color % MAXSKINCOLORS; + if (player->mo) + player->mo->color = (UINT8)player->skincolor; demo_extradata[playernum] |= DXD_COLOR; // normal player colors - if (server && (p != &players[consoleplayer] && p != &players[displayplayers[1]] - && p != &players[displayplayers[2]] && p != &players[displayplayers[3]])) + if (server && !P_IsLocalPlayer(player)) { boolean kick = false; // team colors if (G_GametypeHasTeams()) { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) + if (player->ctfteam == 1 && player->skincolor != skincolor_redteam) kick = true; - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) + else if (player->ctfteam == 2 && player->skincolor != skincolor_blueteam) kick = true; } // don't allow color "none" - if (!p->skincolor) + if (!player->skincolor) kick = true; if (kick) { - CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor); + CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], player->ctfteam, player->skincolor); SendKick(playernum, KICK_MSG_CON_FAIL); return; } @@ -2003,6 +1697,7 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) const INT32 forcedskin = cv_forceskin.value; SetPlayerSkinByNum(playernum, forcedskin); + // TODO: make cv_skin an array if (playernum == consoleplayer) CV_StealthSet(&cv_skin, skins[forcedskin].name); else if (playernum == displayplayers[1]) @@ -2016,44 +1711,16 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) SetPlayerSkinByNum(playernum, skin); } -void SendWeaponPref(void) +void SendWeaponPref(UINT8 splitplayer) { UINT8 buf[1]; buf[0] = 0; - if (cv_flipcam[0].value) + + if (cv_flipcam[splitplayer].value) buf[0] |= 1; - SendNetXCmdForPlayer(0, XD_WEAPONPREF, buf, 1); -} -void SendWeaponPref2(void) -{ - UINT8 buf[1]; - - buf[0] = 0; - if (cv_flipcam[1].value) - buf[0] |= 1; - SendNetXCmdForPlayer(1, XD_WEAPONPREF, buf, 1); -} - -void SendWeaponPref3(void) -{ - UINT8 buf[1]; - - buf[0] = 0; - if (cv_flipcam[2].value) - buf[0] |= 1; - SendNetXCmdForPlayer(2, XD_WEAPONPREF, buf, 1); -} - -void SendWeaponPref4(void) -{ - UINT8 buf[1]; - - buf[0] = 0; - if (cv_flipcam[3].value) - buf[0] |= 1; - SendNetXCmdForPlayer(3, XD_WEAPONPREF, buf, 1); + SendNetXCmdForPlayer(splitplayer, XD_WEAPONPREF, buf, 1); } static void Got_WeaponPref(const UINT8 **cp, INT32 playernum) @@ -2069,23 +1736,10 @@ static void Got_WeaponPref(const UINT8 **cp, INT32 playernum) player->pflags |= PF_ANALOGMODE; } -void D_SendPlayerConfig(void) +void D_SendPlayerConfig(UINT8 splitplayer) { - SendNameAndColor(); - if (splitscreen || botingame) - SendNameAndColor2(); - if (splitscreen > 1) - SendNameAndColor3(); - if (splitscreen > 2) - SendNameAndColor4(); - - SendWeaponPref(); - if (splitscreen) - SendWeaponPref2(); - if (splitscreen > 1) - SendWeaponPref3(); - if (splitscreen > 2) - SendWeaponPref4(); + SendNameAndColor(splitplayer); + SendWeaponPref(splitplayer); } // Only works for displayplayer, sorry! @@ -2108,10 +1762,12 @@ INT32 D_LookupPlayer(const char *s) return playernum; } + const size_t len = strlen(s); + for (playernum = 0; playernum < MAXPLAYERS; ++playernum) { /* Match name case-insensitively: fully, or partially the start. */ - if (playeringame[playernum] && (strnicmp(player_names[playernum], s, strlen(s)) == 0)) + if (playeringame[playernum] && (strnicmp(player_names[playernum], s, len) == 0)) { return playernum; } @@ -2151,13 +1807,15 @@ static void GetViewablePlayerPlaceRange(INT32 *first, INT32 *last) (*last) = 0; for (i = 0; i < MAXPLAYERS; ++i) - if (G_CouldView(i)) { - place = players[i].kartstuff[k_position]; - if (place < (*first)) - (*first) = place; - if (place > (*last)) - (*last) = place; + if (G_CouldView(i)) + { + place = players[i].kartstuff[k_position]; + if (place < (*first)) + (*first) = place; + if (place > (*last)) + (*last) = place; + } } } @@ -2491,7 +2149,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r displayplayers[1] = 1; playeringame[1] = true; players[1].bot = 1; - SendNameAndColor2(); + SendNameAndColor(1); } } @@ -5768,50 +5426,54 @@ static void ForceSkin_OnChange(void) } } -//Allows the player's name to be changed if cv_mute is off. +// Allows the player's name to be changed if cv_mute is off. static void Name_OnChange(void) { if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername, player_names[consoleplayer]); + return; } - else - SendNameAndColor(); + + SendNameAndColor(0); } static void Name2_OnChange(void) { - if (cv_mute.value) //Secondary player can't be admin. + if (cv_mute.value) // Secondary player can't be admin. { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]); + return; } - else - SendNameAndColor2(); + + SendNameAndColor(1); } static void Name3_OnChange(void) { - if (cv_mute.value) //Third player can't be admin. + if (cv_mute.value) // Third player can't be admin. { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]); + return; } - else - SendNameAndColor3(); + + SendNameAndColor(2); } static void Name4_OnChange(void) { - if (cv_mute.value) //Secondary player can't be admin. + if (cv_mute.value) // Secondary player can't be admin. { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]); + return; } - else - SendNameAndColor4(); + + SendNameAndColor(3); } /** Sends a skin change for the console player, unless that player is moving. @@ -5833,7 +5495,7 @@ static void Skin_OnChange(void) } if (CanChangeSkin(consoleplayer) && !P_PlayerMoving(consoleplayer)) - SendNameAndColor(); + SendNameAndColor(0); else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); @@ -5854,7 +5516,7 @@ static void Skin2_OnChange(void) return; // do whatever you want if (CanChangeSkin(displayplayers[1]) && !P_PlayerMoving(displayplayers[1])) - SendNameAndColor2(); + SendNameAndColor(1); else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); @@ -5870,7 +5532,7 @@ static void Skin3_OnChange(void) return; // do whatever you want if (CanChangeSkin(displayplayers[2]) && !P_PlayerMoving(displayplayers[2])) - SendNameAndColor3(); + SendNameAndColor(2); else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); @@ -5886,7 +5548,7 @@ static void Skin4_OnChange(void) return; // do whatever you want if (CanChangeSkin(displayplayers[3]) && !P_PlayerMoving(displayplayers[3])) - SendNameAndColor4(); + SendNameAndColor(3); else { CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n")); @@ -5999,7 +5661,7 @@ static void Color_OnChange(void) if (!P_PlayerMoving(consoleplayer)) { // Color change menu scrolling fix is no longer necessary - SendNameAndColor(); + SendNameAndColor(0); } else { @@ -6021,7 +5683,7 @@ static void Color2_OnChange(void) if (!P_PlayerMoving(displayplayers[1])) { // Color change menu scrolling fix is no longer necessary - SendNameAndColor2(); + SendNameAndColor(1); } else { @@ -6038,7 +5700,7 @@ static void Color3_OnChange(void) if (!P_PlayerMoving(displayplayers[2])) { // Color change menu scrolling fix is no longer necessary - SendNameAndColor3(); + SendNameAndColor(2); } else { @@ -6055,7 +5717,7 @@ static void Color4_OnChange(void) if (!P_PlayerMoving(displayplayers[3])) { // Color change menu scrolling fix is no longer necessary - SendNameAndColor4(); + SendNameAndColor(3); } else { diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 6b7382403..f22fe33a8 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -21,10 +21,7 @@ extern "C" { #include "command.h" -void SendWeaponPref(void); -void SendWeaponPref2(void); -void SendWeaponPref3(void); -void SendWeaponPref4(void); +void SendWeaponPref(UINT8 splitplayer); // console vars extern consvar_t cv_playername; @@ -295,7 +292,7 @@ typedef union { // add game commands, needs cleanup void D_RegisterServerCommands(void); void D_RegisterClientCommands(void); -void D_SendPlayerConfig(void); +void D_SendPlayerConfig(UINT8 splitplayer); void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore diff --git a/src/d_netfil.c b/src/d_netfil.c index ed186bba5..67fd28a82 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -960,7 +960,7 @@ void Got_Filetxpak(void) || fastcmp(filename, "music.kart") || fastcmp(filename, "patch.kart") )) - I_Error("Tried to download \"%s\"", filename); + I_Error("Tried to download base-game file: \"%s\"", filename); if (filenum >= fileneedednum) { @@ -1019,21 +1019,21 @@ void Got_Filetxpak(void) switch(file->status) { - case FS_NOTFOUND: - s = "FS_NOTFOUND"; - break; - case FS_FOUND: - s = "FS_FOUND"; - break; - case FS_OPEN: - s = "FS_OPEN"; - break; - case FS_MD5SUMBAD: - s = "FS_MD5SUMBAD"; - break; - default: - s = "unknown"; - break; + case FS_NOTFOUND: + s = "FS_NOTFOUND"; + break; + case FS_FOUND: + s = "FS_FOUND"; + break; + case FS_OPEN: + s = "FS_OPEN"; + break; + case FS_MD5SUMBAD: + s = "FS_MD5SUMBAD"; + break; + default: + s = "unknown"; + break; } I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s); diff --git a/src/g_game.c b/src/g_game.c index a79a957ef..196b2ec68 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -69,9 +69,6 @@ UINT8 botcolor = 0; JoyType_t Joystick[MAXSPLITSCREENPLAYERS] = {}; -// 1024 bytes is plenty for a savegame -#define SAVEGAMESIZE (1024) - // SRB2kart char gamedatafilename[64] = "kartdata.dat"; char timeattackfolder[64] = "kart"; @@ -3902,7 +3899,7 @@ void G_SaveGame(UINT32 savegameslot) char name[VERSIONSIZE]; size_t length; - save.p = save.buffer = (UINT8 *)Z_Malloc(SAVEGAMESIZE, PU_STATIC, NULL); + save.p = save.buffer = (UINT8 *)Z_Malloc(1024, PU_STATIC, NULL); // 1024 bytes is plenty for a savegame if (!save.p) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); diff --git a/src/i_tcp.c b/src/i_tcp.c index 5b9b0237d..9723d5b2d 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -496,8 +496,10 @@ static void cleanupnodes(void) // Why can't I start at zero? for (j = 1; j < MAXNETNODES; j++) + { if (!(nodeingame[j] || SV_SendingFile(j))) nodeconnected[j] = false; + } } static SINT8 getfreenode(void) @@ -507,11 +509,13 @@ static SINT8 getfreenode(void) cleanupnodes(); for (j = 0; j < MAXNETNODES; j++) + { if (!nodeconnected[j]) { nodeconnected[j] = true; return j; } + } /** \warning No free node? Just in case a node might not have been freed properly, * look if there are connected nodes that aren't in game, and forget them. @@ -812,7 +816,7 @@ static void SOCK_Send(void) static void SOCK_FreeNodenum(INT32 numnode) { // can't disconnect from self :) - if (!numnode || numnode > MAXNETNODES) + if (numnode <= 0 || numnode > MAXNETNODES) return; DEBFILE(va("Free node %d (%s)\n", numnode, SOCK_GetNodeAddress(numnode))); @@ -1432,14 +1436,12 @@ static void SOCK_RegisterHolePunch(void) static boolean SOCK_OpenSocket(void) { - size_t i; - - memset(clientaddress, 0, sizeof (clientaddress)); + memset(clientaddress, 0, sizeof(clientaddress)); + memset(nodeconnected, false, sizeof(nodeconnected)); nodeconnected[0] = true; // always connected to self - for (i = 1; i < MAXNETNODES; i++) - nodeconnected[i] = false; nodeconnected[BROADCASTADDR] = true; + I_NetSend = SOCK_Send; I_NetGet = SOCK_Get; I_NetCloseSocket = SOCK_CloseSocket; @@ -1479,7 +1481,7 @@ static boolean SOCK_Ban(INT32 node) { INT32 ban; - if (node > MAXNETNODES) + if (node < 0 || node > MAXNETNODES) return false; ban = numbans; diff --git a/src/r_main.cpp b/src/r_main.cpp index 430a7cd32..2b318858a 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -280,22 +280,22 @@ static void Fov_OnChange(void) static void FlipCam_OnChange(void) { - SendWeaponPref(); + SendWeaponPref(0); } static void FlipCam2_OnChange(void) { - SendWeaponPref2(); + SendWeaponPref(1); } static void FlipCam3_OnChange(void) { - SendWeaponPref3(); + SendWeaponPref(2); } static void FlipCam4_OnChange(void) { - SendWeaponPref4(); + SendWeaponPref(3); } static void Precipstuff_OnChange(void)