mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-01-30 13:00:54 +00:00
Online splitscreen
It WORKS, including kicking players in splitscreen
This commit is contained in:
parent
005e3ce514
commit
1d6215030e
3 changed files with 136 additions and 100 deletions
112
src/d_clisrv.c
112
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];
|
||||
|
|
114
src/d_netcmd.c
114
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)
|
||||
|
|
10
src/r_main.c
10
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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue