Tweak splitscreen a little to work around a KTX issue.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5967 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-07-17 15:10:10 +00:00
parent e90a0b3945
commit 9735064a89
11 changed files with 73 additions and 75 deletions

View File

@ -547,7 +547,7 @@ void Cam_Unlock(playerview_t *pv)
{
if (pv->cam_state)
{
CL_SendClientCommand(true, "ptrack");
CL_SendSeatClientCommand(true, pv-cl.playerview, "ptrack");
pv->cam_state = CAM_FREECAM;
pv->viewentity = (cls.demoplayback)?0:(pv->playernum+1); //free floating
SCR_CenterPrint(pv-cl.playerview, NULL, true);
@ -564,7 +564,7 @@ void Cam_Lock(playerview_t *pv, int playernum)
{
pv->cam_lastviewtime = -1000; //allow the wallcam to re-snap as soon as it can
CL_SendClientCommand(true, "ptrack %i", playernum);
CL_SendSeatClientCommand(true, pv-cl.playerview, "ptrack %i", playernum);
if (pv->cam_spec_track != playernum)
{ //flashgrens suck

View File

@ -1563,10 +1563,11 @@ typedef struct clcmdbuf_s {
struct clcmdbuf_s *next;
int len;
qboolean reliable;
unsigned int seat;
char command[4]; //this is dynamically allocated, so this is variably sized.
} clcmdbuf_t;
clcmdbuf_t *clientcmdlist;
void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...)
static clcmdbuf_t *clientcmdlist;
void VARGS CL_SendSeatClientCommand(qboolean reliable, unsigned int seat, char *format, ...)
{
qboolean oldallow;
va_list argptr;
@ -1594,6 +1595,7 @@ void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...)
strcpy(buf->command, string);
buf->len = strlen(buf->command);
buf->reliable = reliable;
buf->seat = seat;
//add to end of the list so that the first of the list is the first to be sent.
if (!clientcmdlist)
@ -1607,6 +1609,17 @@ void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...)
CL_AllowIndependantSendCmd(oldallow);
}
void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...)
{
va_list argptr;
char string[2048];
va_start (argptr, format);
Q_vsnprintfz (string,sizeof(string), format,argptr);
va_end (argptr);
CL_SendSeatClientCommand(reliable, 0, "%s", string);
}
//sometimes a server will quickly restart twice.
//connected clients will then receive TWO 'new' commands - both with the same servercount value.
@ -2090,13 +2103,6 @@ static void CL_SendUserinfoUpdate(void)
qboolean final = true;
char enckey[2048];
char encval[2048];
//handle splitscreen
char pl[64];
if (seat)
Q_snprintfz(pl, sizeof(pl), "%i ", seat);
else
*pl = 0;
#ifdef Q3CLIENT
if (cls.protocol == CP_QUAKE3)
@ -2121,7 +2127,6 @@ static void CL_SendUserinfoUpdate(void)
InfoBuf_ToString(info, userinfo, sizeof(userinfo), NULL, NULL, NULL, NULL, NULL);
MSG_WriteByte (&cls.netchan.message, clcq2_userinfo);
SZ_Write(&cls.netchan.message, pl, strlen(pl));
MSG_WriteString (&cls.netchan.message, userinfo);
}
return;
@ -2145,24 +2150,27 @@ static void CL_SendUserinfoUpdate(void)
if (final && !bloboffset && *encval != '\xff' && *encval != '\xff')
{ //vanilla-compatible info.
s = va("%ssetinfo \"%s\" \"%s\"", pl, enckey, encval);
s = va("setinfo \"%s\" \"%s\"", enckey, encval);
}
else if (cls.fteprotocolextensions2 & PEXT2_INFOBLOBS)
{ //only flood servers that actually support it.
if (final)
s = va("%ssetinfo \"%s\" \"%s\" %u", pl, enckey, encval, (unsigned int)bloboffset);
s = va("setinfo \"%s\" \"%s\" %u", enckey, encval, (unsigned int)bloboffset);
else
s = va("%ssetinfo \"%s\" \"%s\" %u+", pl, enckey, encval, (unsigned int)bloboffset);
s = va("setinfo \"%s\" \"%s\" %u+", enckey, encval, (unsigned int)bloboffset);
}
else
{ //server doesn't support it, just ignore the key
InfoSync_Remove(&cls.userinfosync, 0);
return;
}
if (cls.protocol == CP_QUAKE2)
MSG_WriteByte (&cls.netchan.message, clcq2_stringcmd);
if (seat && (cls.fteprotocolextensions&PEXT_SPLITSCREEN))
{
MSG_WriteByte (&cls.netchan.message, (cls.protocol == CP_QUAKE2)?clcq2_stringcmd_seat:clcfte_stringcmd_seat);
MSG_WriteByte (&cls.netchan.message, seat);
}
else
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteByte (&cls.netchan.message, (cls.protocol == CP_QUAKE2)?clcq2_stringcmd:clc_stringcmd);
MSG_WriteString (&cls.netchan.message, s);
}
@ -2462,14 +2470,26 @@ void CL_SendCmd (double frametime, qboolean mainloop)
break;
if (!strncmp(clientcmdlist->command, "spawn", 5) && cls.userinfosync.numkeys && cl.haveserverinfo)
break; //HACK: don't send the spawn until all pending userinfos have been flushed.
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
if (clientcmdlist->seat && (cls.fteprotocolextensions&PEXT_SPLITSCREEN))
{
MSG_WriteByte (&cls.netchan.message, clcfte_stringcmd_seat);
MSG_WriteByte (&cls.netchan.message, clientcmdlist->seat);
}
else
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, clientcmdlist->command);
}
else
{
if (buf.cursize + 2+strlen(clientcmdlist->command)+100 <= buf.maxsize)
{
MSG_WriteByte (&buf, clc_stringcmd);
if (clientcmdlist->seat && (cls.fteprotocolextensions&PEXT_SPLITSCREEN))
{
MSG_WriteByte (&cls.netchan.message, clcfte_stringcmd_seat);
MSG_WriteByte (&cls.netchan.message, clientcmdlist->seat);
}
else
MSG_WriteByte (&buf, clc_stringcmd);
MSG_WriteString (&buf, clientcmdlist->command);
}
}
@ -2653,7 +2673,7 @@ void CL_SendCvar_f (void)
val = "";
else
val = var->string;
CL_SendClientCommand(true, "sentcvar %s \"%s\"", name, val);
CL_SendSeatClientCommand(true, CL_TargettedSplit(false), "sentcvar %s \"%s\"", name, val);
}
/*

View File

@ -7118,7 +7118,7 @@ void CLQW_ParseServerMessage (void)
for (; i < cl.splitclients; i++)
{ //svcfte_choosesplitclient has a modulo that is also broken, but at least there's no parse errors this way
MSG_ReadByte();
// CL_SendClientCommand(true, va("%i drop", i+1));
// CL_SendSeatClientCommand(true, i, drop");
}
cl.splitclients = MAX_SPLITS;
}

View File

@ -1275,6 +1275,7 @@ qboolean CL_AllowIndependantSendCmd(qboolean allow); //returns previous state.
void CL_FlushClientCommands(void);
void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...) LIKEPRINTF(2);
void VARGS CL_SendSeatClientCommand(qboolean reliable, unsigned int seat, char *format, ...) LIKEPRINTF(3);
float CL_FilterTime (double time, float wantfps, float limit, qboolean ignoreserver);
int CL_RemoveClientCommands(char *command);

View File

@ -811,7 +811,7 @@ static void Sbar_Hexen2InvLeft_f(void)
#endif
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invprev");
CL_SendSeatClientCommand(true, seat, "invprev");
}
else
{
@ -838,7 +838,7 @@ static void Sbar_Hexen2InvRight_f(void)
#endif
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invnext");
CL_SendSeatClientCommand(true, seat, "invnext");
}
else
{
@ -866,7 +866,7 @@ static void Sbar_Hexen2InvUse_f(void)
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invuse");
CL_SendSeatClientCommand(true, seat, "invuse");
}
else
{

View File

@ -3883,10 +3883,10 @@ void CL_Say (qboolean team, char *extra)
//the server is expected to use Cmd_Args and to strip first+last chars if the first is a quote. this is annoying and clumsy for mods to parse.
#ifdef HAVE_LEGACY
if (!dpcompat_console.ival)
CL_SendClientCommand(true, "%s%s \"%s%s\"", split?va("%i ", split+1):"", team ? "say_team" : "say", extra?extra:"", sendtext);
CL_SendSeatClientCommand(true, split, "%s \"%s%s\"", team ? "say_team" : "say", extra?extra:"", sendtext);
else
#endif
CL_SendClientCommand(true, "%s%s %s%s", split?va("%i ", split+1):"", team ? "say_team" : "say", extra?extra:"", sendtext);
CL_SendSeatClientCommand(true, split, "%s %s%s", team ? "say_team" : "say", extra?extra:"", sendtext);
}
}

View File

@ -2638,20 +2638,10 @@ void Cmd_ForwardToServer (void)
#endif
sp = CL_TargettedSplit(false);
if (sp)
{
if (Cmd_Argc() > 1)
CL_SendClientCommand(true, "%i %s %s", sp+1, Cmd_Argv(0), Cmd_Args());
else
CL_SendClientCommand(true, "%i %s", sp+1, Cmd_Argv(0));
}
if (Cmd_Argc() > 1)
CL_SendSeatClientCommand(true, sp, "%s %s", Cmd_Argv(0), Cmd_Args());
else
{
if (Cmd_Argc() > 1)
CL_SendClientCommand(true, "%s %s", Cmd_Argv(0), Cmd_Args());
else
CL_SendClientCommand(true, "%s", Cmd_Argv(0));
}
CL_SendSeatClientCommand(true, sp, "%s", Cmd_Argv(0));
}
// don't forward the first argument
@ -2713,10 +2703,7 @@ static void Cmd_ForwardToServer_f (void)
if (Cmd_Argc() > 1)
{
int split = CL_TargettedSplit(false);
if (split)
CL_SendClientCommand(true, "%i %s", split+1, Cmd_Args());
else
CL_SendClientCommand(true, "%s", Cmd_Args());
CL_SendSeatClientCommand(true, split, "%s", Cmd_Args());
}
}
#else

View File

@ -1497,10 +1497,7 @@ qboolean Cvar_Command (int level)
if (Cmd_FromGamecode() && cls.protocol == CP_QUAKEWORLD)
{ //don't bother even changing the cvar locally, just update the server's version.
//fixme: quake2/quake3 latching.
if (seat)
CL_SendClientCommand(true, "%i setinfo %s %s", seat+1, v->name, COM_QuotedString(str, buffer, sizeof(buffer), false));
else
CL_SendClientCommand(true, "setinfo %s %s", v->name, COM_QuotedString(str, buffer, sizeof(buffer), false));
CL_SendSeatClientCommand(true, seat, "setinfo %s %s", v->name, COM_QuotedString(str, buffer, sizeof(buffer), false));
}
else
CL_SetInfo(seat, v->name, str);

View File

@ -465,6 +465,7 @@ enum clcq2_ops_e
clcr1q2_multimoves = 6, // for crappy clients that can't lerp
//fte-extended
clcq2_stringcmd_seat = 30,
clcq2_voicechat = 31
};
@ -502,6 +503,7 @@ enum {
#define clcfte_voicechat 83
#define clcfte_brushedit 84
#define clcfte_move 85 //part of PEXT2_VRINPUTS. replaces clc_move+clcfte_prydoncursor+clcdp_ackframe
#define clcfte_stringcmd_seat 86
#define VRM_LOSS (1u<<0) //for server packetloss reports
#define VRM_DELAY (1u<<1) //for server to compute lag properly.

View File

@ -1424,10 +1424,10 @@ static void SVC_Log (void)
seq = seq+1; //they will get the next sequence from the one they already have
}
else
seq = 0;
seq = svs.logsequence-1;
if (!fraglog_public.ival)
{ //frag logs are not public (for DoS protection perhaps?.
{ //frag logs are not public (for DoS protection perhaps?)
data[0] = A2A_NACK;
NET_SendPacket (svs.sockets, 1, data, &net_from);
return;
@ -2372,6 +2372,8 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
Q_strncpyz(cl->guid, "", sizeof(cl->guid));
cl->name = cl->namebuf;
cl->team = cl->teambuf;
cl->userinfo.ChangeCB = svs.info.ChangeCB;
cl->userinfo.ChangeCTX = &cl->userinfo;
if (!cl->userid || !loadgame)
cl->userid = ++nextuserid;

View File

@ -6459,31 +6459,6 @@ void SV_ExecuteUserCommand (const char *s, qboolean fromQC)
Cmd_ExecLevel=1;
if (!fromQC && host_client->controlled) //now see if it's meant to be from a slave client
{ //'cmd 2 say hi' should
char *a=Cmd_Argv(0), *e;
int pnum = strtoul(a, &e, 10);
//commands might be in the form of eg '2on2' so make sure that its fully numeric.
//KTX uses eg 'cmd 231', so don't take it if it can't be a seat, but there may be race conditions so we don't want error messages when it might have been a seat.
if (!*e && pnum >= 1 && pnum <= MAX_SPLITS)
{
client_t *sp;
for (sp = host_client; sp; sp = sp->controlled)
{
if (!--pnum)
{
host_client = sp;
break;
}
}
sv_player = host_client->edict;
s = Cmd_Args();
Cmd_ShiftArgs(1, false);
}
}
#ifdef Q2SERVER
if (ISQ2CLIENT(host_client))
u = ucmdsq2;
@ -8330,6 +8305,13 @@ void SV_ExecuteClientMessage (client_t *cl)
break;
#endif
case clcfte_stringcmd_seat:
c = MSG_ReadByte();
host_client = cl;
while (c --> 0 && host_client->controlled)
host_client = host_client->controlled;
sv_player = host_client->edict;
//fall through
case clc_stringcmd:
s = MSG_ReadString ();
SV_ExecuteUserCommand (s, false);
@ -8576,6 +8558,13 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
ge->ClientUserinfoChanged (cl->q2edict, s); //tell the gamecode
break;
case clcq2_stringcmd_seat:
c = MSG_ReadByte();
host_client = cl;
while (c --> 0 && host_client->controlled)
host_client = host_client->controlled;
sv_player = host_client->edict;
//fall through
case clcq2_stringcmd:
s = MSG_ReadString ();
SV_ExecuteUserCommand (s, false);