diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 63393690..3c934e3b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2419,14 +2419,15 @@ static void CL_RemovePlayer(INT32 playernum) if (server && !demoplayback) { INT32 node = playernode[playernum]; + //playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one playerpernode[node]--; if (playerpernode[node] <= 0) { // If a resynch was in progress, well, it no longer needs to be. SV_InitResynchVars(playernode[playernum]); - nodeingame[playernode[playernum]] = false; - Net_CloseConnection(playernode[playernum]); + nodeingame[node] = false; + Net_CloseConnection(node); ResetNode(node); } } @@ -2761,11 +2762,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) } // Is playernum authorized to make this kick? - if (playernum != serverplayer && !IsPlayerAdmin(playernum) - && !(playerpernode[playernode[playernum]] >= 2 - && (nodetoplayer2[playernode[playernum]] == pnum - || nodetoplayer3[playernode[playernum]] == pnum - || nodetoplayer4[playernode[playernum]] == pnum))) + if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { // We received a kick command from someone who isn't the // server or admin, and who isn't in splitscreen removing @@ -2777,12 +2774,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) // "consistency failure" and kicking the offending user // instead. - // Note: Splitscreen in netgames is broken because of - // this. Only the server has any idea of which players - // are using splitscreen on the same computer, so - // clients cannot always determine if a kick is - // legitimate. - CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum); // In debug, print a longer message with more details. @@ -2892,7 +2883,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) break; } - if (pnum == consoleplayer) + if (playernode[pnum] == playernode[consoleplayer]) { #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); @@ -2916,7 +2907,18 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); } else - CL_RemovePlayer(pnum); + { + UINT8 splitnode = playernode[pnum]; + // Can't tell which player pnum is on the node from a glance, so we have to convert to node, then check each player on the node + if (nodetoplayer[splitnode] != -1) + CL_RemovePlayer(nodetoplayer[splitnode]); + if (nodetoplayer2[splitnode] != -1) + CL_RemovePlayer(nodetoplayer2[splitnode]); + if (nodetoplayer3[splitnode] != -1) + CL_RemovePlayer(nodetoplayer3[splitnode]); + if (nodetoplayer4[splitnode] != -1) + CL_RemovePlayer(nodetoplayer4[splitnode]); + } } consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; @@ -3156,7 +3158,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) // Clear player before joining, lest some things get set incorrectly // HACK: don't do this for splitscreen, it relies on preset values - if (!splitscreen && !botingame) + //if (!splitscreen && !botingame) CL_ClearPlayer(newplayernum); playeringame[newplayernum] = true; G_AddPlayer(newplayernum); @@ -3256,69 +3258,17 @@ static boolean SV_AddWaitingPlayers(void) { newplayer = true; - if (netgame) - // !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!! - // - // The line just after that comment is an awful, horrible, terrible, TERRIBLE hack. - // - // Basically, the fix I did in order to fix the download freezes happens - // to cause situations in which a player number does not match - // the node number associated to that player. - // That is totally normal, there is absolutely *nothing* wrong with that. - // Really. Player 7 being tied to node 29, for instance, is totally fine. - // - // HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake - // of mixing up the concepts of node and player, resulting in - // incorrect handling of cases where a player is tied to a node that has - // a different number (which is a totally normal case, or at least should be). - // This incorrect handling can go as far as literally - // anyone from joining your server at all, forever. - // - // Given those two facts, there are two options available - // in order to let this download freeze fix be: - // 1) Fix the broken parts that assume a node is a player or similar bullshit. - // 2) Change the part this comment is located at, so that any player who joins - // is given the same number as their associated node. - // - // No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack. - // Unfortunately, after trying 1), I most likely didn't manage to find all - // of those broken parts, and thus 2) has become the only safe option that remains. - // - // So I did this hack. - // - // If it isn't clear enough, in order to get rid of this ugly hack, - // you will have to fix all parts of the netcode that - // make a confusion between nodes and players. - // - // And if it STILL isn't clear enough, a node and a player - // is NOT the same thing. Never. NEVER. *NEVER*. - // - // And if someday you make the terrible mistake of - // daring to have the unforgivable idea to try thinking - // that a node might possibly be the same as a player, - // or that a player should have the same number as its node, - // be sure that I will somehow know about it and - // hunt you down tirelessly and make you regret it, - // even if you live on the other side of the world. - // - // TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - // \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<< - // TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - // - // !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!! - newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1! - else // Don't use the hack if we don't have to - // search for a free playernum - // we can't use playeringame since it is not updated here - for (; newplayernum < MAXPLAYERS; newplayernum++) - { - for (n = 0; n < MAXNETNODES; n++) - if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum - || nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum) - break; - if (n == MAXNETNODES) + // search for a free playernum + // we can't use playeringame since it is not updated here + for (; newplayernum < MAXPLAYERS; newplayernum++) + { + for (n = 0; n < MAXNETNODES; n++) + if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum + || nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum) break; - } + if (n == MAXNETNODES) + break; + } // should never happen since we check the playernum // before accepting the join @@ -3493,7 +3443,7 @@ static void HandleConnect(SINT8 node) SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment")); else if (D_NumPlayers() >= cv_maxplayers.value) SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value)); - else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client? + else if (netgame && netbuffer->u.clientcfg.localplayers > 4) // Hacked client? SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? SV_SendRefuse(node, M_GetText("No players from\nthis node.")); @@ -3979,10 +3929,10 @@ FILESTAMP --resynch_score[node]; break; case PT_TEXTCMD: - case PT_TEXTCMD2: // splitscreen special + case PT_TEXTCMD2: case PT_TEXTCMD3: case PT_TEXTCMD4: - if (netbuffer->packettype == PT_TEXTCMD2) + if (netbuffer->packettype == PT_TEXTCMD2) // splitscreen special netconsole = nodetoplayer2[node]; else if (netbuffer->packettype == PT_TEXTCMD3) netconsole = nodetoplayer3[node]; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 144e4bf9..ea913b06 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1350,16 +1350,23 @@ static void SendNameAndColor(void) // splitscreen static void SendNameAndColor2(void) { - INT32 secondplaya; + INT32 secondplaya = -1; + XBOXSTATIC char buf[MAXPLAYERNAME+2]; + char *p; if (splitscreen < 1 && !botingame) return; // can happen if skin2/color2/name2 changed if (secondarydisplayplayer != consoleplayer) secondplaya = secondarydisplayplayer; - else // HACK + else if (!netgame) // HACK secondplaya = 1; + if (secondplaya == -1) + return; + + p = buf; + // normal player colors if (G_GametypeHasTeams()) { @@ -1436,21 +1443,53 @@ static void SendNameAndColor2(void) return; } - // Don't actually send anything because splitscreen isn't actually allowed in netgames anyway! + snac2pending++; + + // Don't change name if muted + if (cv_mute.value && !(server || IsPlayerAdmin(secondarydisplayplayer))) + CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]); + else // Cleanup name if changing it + CleanupPlayerName(secondarydisplayplayer, cv_playername2.zstring); + + // Don't change skin if the server doesn't want you to. + if (!CanChangeSkin(secondarydisplayplayer)) + CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].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) + { + CV_StealthSet(&cv_skin2, DEFAULTSKIN); + cv_skin2.value = 0; + } + + // 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); + SendNetXCmd2(XD_NAMEANDCOLOR, buf, p - buf); } static void SendNameAndColor3(void) { - INT32 thirdplaya; + INT32 thirdplaya = -1; + XBOXSTATIC char buf[MAXPLAYERNAME+2]; + char *p; if (splitscreen < 2) return; // can happen if skin3/color3/name3 changed if (thirddisplayplayer != consoleplayer) thirdplaya = thirddisplayplayer; - else // HACK + else if (!netgame) // HACK thirdplaya = 2; + if (thirdplaya == -1) + return; + + p = buf; + // normal player colors if (G_GametypeHasTeams()) { @@ -1519,21 +1558,53 @@ static void SendNameAndColor3(void) return; } - // Don't actually send anything because splitscreen isn't actually allowed in netgames anyway! + snac3pending++; + + // Don't change name if muted + if (cv_mute.value && !(server || IsPlayerAdmin(thirddisplayplayer))) + CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]); + else // Cleanup name if changing it + CleanupPlayerName(thirddisplayplayer, cv_playername3.zstring); + + // Don't change skin if the server doesn't want you to. + if (!CanChangeSkin(thirddisplayplayer)) + CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].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) + { + CV_StealthSet(&cv_skin3, DEFAULTSKIN); + cv_skin3.value = 0; + } + + // 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); + SendNetXCmd3(XD_NAMEANDCOLOR, buf, p - buf); } static void SendNameAndColor4(void) { - INT32 fourthplaya; + INT32 fourthplaya = -1; + XBOXSTATIC char buf[MAXPLAYERNAME+2]; + char *p; if (splitscreen < 3) return; // can happen if skin4/color4/name4 changed if (fourthdisplayplayer != consoleplayer) fourthplaya = fourthdisplayplayer; - else // HACK + else if (!netgame) // HACK fourthplaya = 3; + if (fourthplaya == -1) + return; + + p = buf; + // normal player colors if (G_GametypeHasTeams()) { @@ -1610,7 +1681,32 @@ static void SendNameAndColor4(void) return; } - // Don't actually send anything because splitscreen isn't actually allowed in netgames anyway! + snac4pending++; + + // Don't change name if muted + if (cv_mute.value && !(server || IsPlayerAdmin(fourthdisplayplayer))) + CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]); + else // Cleanup name if changing it + CleanupPlayerName(fourthdisplayplayer, cv_playername4.zstring); + + // Don't change skin if the server doesn't want you to. + if (!CanChangeSkin(fourthdisplayplayer)) + CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].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) + { + CV_StealthSet(&cv_skin4, DEFAULTSKIN); + cv_skin4.value = 0; + } + + // 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); + SendNetXCmd4(XD_NAMEANDCOLOR, buf, p - buf); } static void Got_NameAndColor(UINT8 **cp, INT32 playernum) diff --git a/src/r_main.c b/src/r_main.c index 5990224c..11213a27 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -178,16 +178,6 @@ void SplitScreen_OnChange(void) { UINT8 i; - if (!cv_debug && netgame) - { - if (splitscreen) - { - CONS_Alert(CONS_NOTICE, M_GetText("Splitscreen not supported in netplay, sorry!\n")); - splitscreen = 0; - } - return; - } - // recompute screen size R_ExecuteSetViewSize();