Online splitscreen

It WORKS, including kicking players in splitscreen
This commit is contained in:
TehRealSalt 2018-09-30 00:51:03 -04:00
parent 005e3ce514
commit 1d6215030e
3 changed files with 136 additions and 100 deletions

View file

@ -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];

View file

@ -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)

View file

@ -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();