mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-26 05:41:52 +00:00
mvd playback works properly now.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@587 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
2bc22c8e79
commit
0322bdd338
35 changed files with 803 additions and 200 deletions
|
@ -49,7 +49,6 @@ cvar_t cl_chasecam = {"cl_chasecam", "0"};
|
|||
//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
|
||||
//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
|
||||
|
||||
qboolean cam_forceview[MAX_SPLITS];
|
||||
vec3_t cam_viewangles[MAX_SPLITS];
|
||||
double cam_lastviewtime[MAX_SPLITS];
|
||||
|
||||
|
@ -129,12 +128,19 @@ void Cam_Lock(int pnum, int playernum)
|
|||
{
|
||||
char st[40];
|
||||
|
||||
cam_lastviewtime[pnum] = -1000;
|
||||
|
||||
sprintf(st, "ptrack %i", playernum);
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, st);
|
||||
spec_track[pnum] = playernum;
|
||||
cam_forceview[pnum] = true;
|
||||
locked[pnum] = false;
|
||||
|
||||
if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
memcpy(&cl.stats[pnum], cl.players[playernum].stats, sizeof(cl.stats[pnum]));
|
||||
}
|
||||
|
||||
Sbar_Changed();
|
||||
}
|
||||
|
||||
|
@ -351,7 +357,7 @@ void Cam_Track(int pnum, usercmd_t *cmd)
|
|||
vec3_t vec;
|
||||
float len;
|
||||
|
||||
if (!cl.spectator)
|
||||
if (!cl.spectator || !cl.worldmodel) //can happen when the server changes level
|
||||
return;
|
||||
|
||||
if (cl_hightrack.value && !locked[pnum])
|
||||
|
@ -370,11 +376,11 @@ void Cam_Track(int pnum, usercmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
frame = &cl.frames[cl.validsequence & UPDATE_MASK];
|
||||
player = frame->playerstate + spec_track[pnum];
|
||||
self = frame->playerstate + cl.playernum[pnum];
|
||||
|
||||
if (/*locked[pnum] ||*/ !Cam_IsVisible(player, desired_position[pnum]))
|
||||
if (!locked[pnum] || !Cam_IsVisible(player, desired_position[pnum]))
|
||||
{
|
||||
if (!locked[pnum] || realtime - cam_lastviewtime[pnum] > 0.1)
|
||||
{
|
||||
|
|
|
@ -154,7 +154,7 @@ qboolean CL_GetDemoMessage (void)
|
|||
int r, i, j, tracknum;
|
||||
float f;
|
||||
float demotime;
|
||||
qbyte c, msecsadded;
|
||||
qbyte c, msecsadded=0;
|
||||
usercmd_t *pcmd;
|
||||
q1usercmd_t q1cmd;
|
||||
|
||||
|
@ -173,6 +173,7 @@ qboolean CL_GetDemoMessage (void)
|
|||
{
|
||||
cl.gametime = 0;
|
||||
cl.gametimemark = realtime;
|
||||
prevtime = 0;
|
||||
return 0;
|
||||
}
|
||||
if (realtime<= cl.gametime && cl.gametime)// > dem_lasttime+realtime)
|
||||
|
@ -182,6 +183,24 @@ qboolean CL_GetDemoMessage (void)
|
|||
realtime = cl.gametime;
|
||||
cls.netchan.last_received = realtime;
|
||||
}
|
||||
|
||||
{
|
||||
float f = (cl.gametime-realtime)/(cl.gametime-prevtime);
|
||||
float a1;
|
||||
float a2;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
a1 = cl.viewangles[2][i];
|
||||
a2 = cl.viewangles[1][i];
|
||||
if (a1 - a2 > 180)
|
||||
a1 -= 360;
|
||||
if (a1 - a2 < -180)
|
||||
a1 += 360;
|
||||
cl.simangles[0][i] = a2 + f * (a1 - a2);
|
||||
}
|
||||
VectorCopy(cl.simangles[0], cl.viewangles[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -189,13 +208,17 @@ qboolean CL_GetDemoMessage (void)
|
|||
// VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
|
||||
if (cls.demoplayback == DPB_NETQUAKE)
|
||||
{
|
||||
VectorCopy (cl.viewangles[1], cl.viewangles[2]);
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
r = fread (&f, 4, 1, cls.demofile);
|
||||
cl.simangles[0][i] = cl.viewangles[0][i] = LittleFloat (f);
|
||||
cl.simangles[0][i] = cl.viewangles[1][i] = LittleFloat (f);
|
||||
}
|
||||
VectorCopy (cl.viewangles[1], cl.viewangles[0]);
|
||||
}
|
||||
|
||||
prevtime = realtime;
|
||||
|
||||
net_message.cursize = LittleLong (net_message.cursize);
|
||||
if (net_message.cursize > MAX_NQMSGLEN)
|
||||
{
|
||||
|
@ -230,14 +253,6 @@ readnext:
|
|||
|
||||
fread(&msecsadded, sizeof(msecsadded), 1, cls.demofile);
|
||||
demotime = prevtime + msecsadded*(1.0f/1000);
|
||||
|
||||
if (msecsadded)
|
||||
{
|
||||
cls.netchan.incoming_sequence++;
|
||||
cls.netchan.incoming_acknowledged++;
|
||||
cls.netchan.frame_latency = 0;
|
||||
cls.netchan.last_received = demotime; // just to happy timeout check
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -299,6 +314,17 @@ readnext:
|
|||
else
|
||||
realtime = demotime; // we're warping
|
||||
|
||||
if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
if (msecsadded)
|
||||
{
|
||||
cls.netchan.incoming_sequence++;
|
||||
cls.netchan.incoming_acknowledged++;
|
||||
cls.netchan.frame_latency = 0;
|
||||
cls.netchan.last_received = demotime; // just to happy timeout check
|
||||
}
|
||||
}
|
||||
|
||||
prevtime = demotime;
|
||||
|
||||
if (cls.state < ca_demostart)
|
||||
|
@ -1080,7 +1106,7 @@ void CL_PlayDemo_f (void)
|
|||
//
|
||||
// disconnect from server
|
||||
//
|
||||
CL_Disconnect ();
|
||||
CL_Disconnect_f ();
|
||||
|
||||
//
|
||||
// open the demo file
|
||||
|
|
|
@ -406,7 +406,7 @@ void CL_ParsePacketEntities (qboolean delta)
|
|||
int oldindex, newindex;
|
||||
int word, newnum, oldnum;
|
||||
qboolean full;
|
||||
qbyte from;
|
||||
int from;
|
||||
|
||||
newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
|
||||
newp = &cl.frames[newpacket].packet_entities;
|
||||
|
@ -417,37 +417,45 @@ void CL_ParsePacketEntities (qboolean delta)
|
|||
from = MSG_ReadByte ();
|
||||
|
||||
oldpacket = cl.frames[newpacket].delta_sequence;
|
||||
|
||||
if (cls.demoplayback == DPB_MVD)
|
||||
from = oldpacket = cls.netchan.incoming_sequence - 1;
|
||||
|
||||
if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) )
|
||||
Con_DPrintf ("WARNING: from mismatch\n");
|
||||
}
|
||||
else
|
||||
oldpacket = -1;
|
||||
|
||||
full = false;
|
||||
if (oldpacket != -1)
|
||||
{
|
||||
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1)
|
||||
{ // we can't use this, it is too old
|
||||
if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >= UPDATE_BACKUP - 1) {
|
||||
// there are no valid frames left, so drop it
|
||||
FlushEntityPacket ();
|
||||
cl.validsequence = 0;
|
||||
return;
|
||||
}
|
||||
cl.oldvalidsequence = cl.validsequence;
|
||||
cl.validsequence = cls.netchan.incoming_sequence;
|
||||
oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities;
|
||||
|
||||
if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) {
|
||||
Con_DPrintf ("WARNING: from mismatch\n");
|
||||
FlushEntityPacket ();
|
||||
cl.validsequence = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) {
|
||||
// we can't use this, it is too old
|
||||
FlushEntityPacket ();
|
||||
// don't clear cl.validsequence, so that frames can still be rendered;
|
||||
// it is possible that a fresh packet will be received before
|
||||
// (outgoing_sequence - incoming_sequence) exceeds UPDATE_BACKUP - 1
|
||||
return;
|
||||
}
|
||||
|
||||
oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
|
||||
full = false;
|
||||
}
|
||||
else
|
||||
{ // this is a full update that we can start delta compressing from now
|
||||
oldp = &dummy;
|
||||
dummy.num_entities = 0;
|
||||
cl.oldvalidsequence = cl.validsequence;
|
||||
cl.validsequence = cls.netchan.incoming_sequence;
|
||||
full = true;
|
||||
}
|
||||
|
||||
cl.oldvalidsequence = cl.validsequence;
|
||||
cl.validsequence = cls.netchan.incoming_sequence;
|
||||
|
||||
oldindex = 0;
|
||||
newindex = 0;
|
||||
newp->num_entities = 0;
|
||||
|
@ -805,9 +813,7 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o(
|
|||
int oldi;
|
||||
qboolean remove;
|
||||
|
||||
cls.netchan.incoming_sequence++;
|
||||
|
||||
cl.validsequence=1;
|
||||
cl.validsequence = cls.netchan.incoming_sequence++;
|
||||
|
||||
cl_latestframenum = MSG_ReadLong();
|
||||
|
||||
|
@ -926,7 +932,6 @@ void CLNQ_ParseEntity(unsigned int bits)
|
|||
static float lasttime;
|
||||
packet_entities_t *pack;
|
||||
|
||||
cl.validsequence=1;
|
||||
#define NQU_MOREBITS (1<<0)
|
||||
#define NQU_ORIGIN1 (1<<1)
|
||||
#define NQU_ORIGIN2 (1<<2)
|
||||
|
@ -1232,7 +1237,7 @@ void CL_LinkPacketEntities (void)
|
|||
dlight_t *dl;
|
||||
vec3_t angles;
|
||||
|
||||
pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
|
||||
pack = &cl.frames[cl.validsequence&UPDATE_MASK].packet_entities;
|
||||
|
||||
autorotate = anglemod(100*cl.time);
|
||||
|
||||
|
@ -1253,7 +1258,7 @@ void CL_LinkPacketEntities (void)
|
|||
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0, 0);
|
||||
|
||||
// if set to invisible, skip
|
||||
if (s1->modelindex<0)
|
||||
if (s1->modelindex<1)
|
||||
continue;
|
||||
#if 0
|
||||
for (spnum = 0; spnum < cl.splitclients; spnum++)
|
||||
|
@ -1557,7 +1562,7 @@ CL_ParseProjectiles
|
|||
Nails are passed as efficient temporary entities
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseProjectiles (int modelindex)
|
||||
void CL_ParseProjectiles (int modelindex, qboolean nails2)
|
||||
{
|
||||
int i, c, j;
|
||||
qbyte bits[6];
|
||||
|
@ -1566,6 +1571,8 @@ void CL_ParseProjectiles (int modelindex)
|
|||
c = MSG_ReadByte ();
|
||||
for (i=0 ; i<c ; i++)
|
||||
{
|
||||
if (nails2)
|
||||
MSG_ReadByte();
|
||||
for (j=0 ; j<6 ; j++)
|
||||
bits[j] = MSG_ReadByte ();
|
||||
|
||||
|
@ -2080,7 +2087,7 @@ void CL_LinkPlayers (void)
|
|||
CL_NewDlight (j+1, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0)->noppl = (j != cl.playernum[0]);
|
||||
}
|
||||
|
||||
if (!state->modelindex)
|
||||
if (state->modelindex < 1)
|
||||
continue;
|
||||
/*
|
||||
if (!Cam_DrawPlayer(j))
|
||||
|
@ -2442,10 +2449,22 @@ void CL_EmitEntities (void)
|
|||
|
||||
|
||||
|
||||
|
||||
void CL_ParseClientdata (void);
|
||||
|
||||
void MVD_Interpolate(void)
|
||||
{
|
||||
player_state_t *self, *oldself;
|
||||
|
||||
CL_ParseClientdata();
|
||||
|
||||
self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[0]];
|
||||
oldself = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK].playerstate[cl.playernum[0]];
|
||||
self->messagenum = cl.parsecount;
|
||||
VectorCopy(oldself->origin, self->origin);
|
||||
VectorCopy(oldself->velocity, self->velocity);
|
||||
VectorCopy(oldself->viewangles, self->viewangles);
|
||||
|
||||
|
||||
cls.netchan.outgoing_sequence = cl.parsecount+1;
|
||||
}
|
||||
|
||||
|
|
|
@ -847,6 +847,8 @@ void CL_SendCmd (void)
|
|||
if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
|
||||
cl.frames[i].senttime = realtime; // we haven't gotten a reply yet
|
||||
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
|
||||
cmd = &cl.frames[i].cmd[0];
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
@ -867,7 +869,6 @@ void CL_SendCmd (void)
|
|||
|
||||
Cam_FinishMove(0, cmd);
|
||||
|
||||
|
||||
cls.netchan.outgoing_sequence++;
|
||||
}
|
||||
|
||||
|
|
|
@ -1296,8 +1296,8 @@ void CL_Packet_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Cmd_FromServer())
|
||||
{
|
||||
if (Cmd_FromServer()) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from.
|
||||
{ //unfortunatly, 50% of servers are badly configured.
|
||||
if (adr.type == NA_IP)
|
||||
if (adr.ip[0] == 127)
|
||||
if (adr.ip[1] == 0)
|
||||
|
@ -1307,6 +1307,8 @@ void CL_Packet_f (void)
|
|||
Con_Printf ("^b^1Server is broken. Ignoring 'realip' packet request\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf ("Sending realip packet\n");
|
||||
}
|
||||
|
||||
in = Cmd_Argv(2);
|
||||
|
|
|
@ -1258,7 +1258,8 @@ void CL_ParseServerData (void)
|
|||
if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
int i;
|
||||
cls.netchan.last_received = MSG_ReadFloat();
|
||||
extern float nextdemotime;
|
||||
cls.netchan.last_received = nextdemotime = /*olddemotime =*/ MSG_ReadFloat();
|
||||
cl.playernum[0] = MAX_CLIENTS - 1;
|
||||
cl.spectator = true;
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
|
@ -1732,7 +1733,7 @@ void CLNQ_ParseClientdata (int bits)
|
|||
CL_SetStat(0, STAT_ROCKETS, MSG_ReadByte());
|
||||
CL_SetStat(0, STAT_CELLS, MSG_ReadByte());
|
||||
|
||||
CL_SetStat(0, STAT_ACTIVEWEAPON, (unsigned short)MSG_ReadShort());
|
||||
CL_SetStat(0, STAT_ACTIVEWEAPON, MSG_ReadByte());
|
||||
}
|
||||
|
||||
if (bits & DPSU_VIEWZOOM)
|
||||
|
@ -2521,6 +2522,14 @@ void CL_SetStat (int pnum, int stat, int value)
|
|||
return;
|
||||
// Host_EndGame ("CL_SetStat: %i is invalid", stat);
|
||||
|
||||
if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
extern int cls_lastto;
|
||||
cl.players[cls_lastto].stats[stat]=value;
|
||||
if ( spec_track[pnum] != cls_lastto )
|
||||
return;
|
||||
}
|
||||
|
||||
if (cl.stats[pnum][stat] != value)
|
||||
Sbar_Changed ();
|
||||
|
||||
|
@ -3698,7 +3707,10 @@ void CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_nails:
|
||||
CL_ParseProjectiles (cl_spikeindex);
|
||||
CL_ParseProjectiles (cl_spikeindex, false);
|
||||
break;
|
||||
case svc_nails2:
|
||||
CL_ParseProjectiles (cl_spikeindex, true);
|
||||
break;
|
||||
|
||||
case svc_chokecount: // some preceding packets were choked
|
||||
|
@ -4142,7 +4154,7 @@ void CLNQ_ParseServerMessage (void)
|
|||
cl.gametimemark = realtime;
|
||||
if (nq_dp_protocol<5)
|
||||
{
|
||||
cls.netchan.incoming_sequence++;
|
||||
cl.validsequence = cls.netchan.incoming_sequence++;
|
||||
// cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
|
||||
cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0;
|
||||
}
|
||||
|
|
|
@ -579,7 +579,7 @@ void CL_PredictMovePNum (int pnum)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >= UPDATE_BACKUP-1)
|
||||
if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ void CL_PredictMovePNum (int pnum)
|
|||
}
|
||||
|
||||
// this is the last frame received from the server
|
||||
from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
from = &cl.frames[cl.validsequence & UPDATE_MASK];
|
||||
|
||||
if (!cl.intermission)
|
||||
{
|
||||
|
@ -637,13 +637,13 @@ void CL_PredictMovePNum (int pnum)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if ((cl_nopred.value|| cl.fixangle))
|
||||
if (((cl_nopred.value && cls.demoplayback!=DPB_MVD)|| cl.fixangle))
|
||||
{
|
||||
fixedorg:
|
||||
VectorCopy (vel, cl.simvel[pnum]);
|
||||
VectorCopy (org, cl.simorg[pnum]);
|
||||
|
||||
to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
to = &cl.frames[cl.validsequence & UPDATE_MASK];
|
||||
|
||||
|
||||
|
||||
|
@ -655,12 +655,12 @@ fixedorg:
|
|||
oldphysent = pmove.numphysent;
|
||||
CL_SetSolidPlayers (cl.playernum[pnum]);
|
||||
|
||||
to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
|
||||
to = &cl.frames[cl.validsequence & UPDATE_MASK];
|
||||
|
||||
for (i=1 ; i<UPDATE_BACKUP-1 && cls.netchan.incoming_sequence+i <
|
||||
for (i=1 ; i<UPDATE_BACKUP-1 && cl.validsequence+i <
|
||||
cls.netchan.outgoing_sequence; i++)
|
||||
{
|
||||
to = &cl.frames[(cls.netchan.incoming_sequence+i) & UPDATE_MASK];
|
||||
to = &cl.frames[(cl.validsequence+i) & UPDATE_MASK];
|
||||
if (cl.intermission)
|
||||
to->playerstate->pm_type = PM_FLY;
|
||||
CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]]
|
||||
|
|
|
@ -156,6 +156,8 @@ typedef struct player_info_s
|
|||
unsigned short vweapindex;
|
||||
|
||||
int prevcount;
|
||||
|
||||
int stats[MAX_CL_STATS];
|
||||
} player_info_t;
|
||||
|
||||
|
||||
|
@ -703,7 +705,7 @@ void CL_SetSolidPlayers (int playernum);
|
|||
void CL_SetUpPlayerPrediction(qboolean dopred);
|
||||
void CL_EmitEntities (void);
|
||||
void CL_ClearProjectiles (void);
|
||||
void CL_ParseProjectiles (int modelindex);
|
||||
void CL_ParseProjectiles (int modelindex, qboolean nails2);
|
||||
void CL_ParsePacketEntities (qboolean delta);
|
||||
void CL_SetSolidEntities (void);
|
||||
void CL_ParsePlayerinfo (void);
|
||||
|
|
|
@ -322,7 +322,7 @@ static void Stats_LoadFragFile(char *name)
|
|||
if (!*file)
|
||||
break;
|
||||
|
||||
Cmd_TokenizeString(file);
|
||||
Cmd_TokenizeString(file, true, false);
|
||||
file = end+1;
|
||||
if (!Cmd_Argc())
|
||||
continue;
|
||||
|
|
|
@ -869,7 +869,7 @@ void Key_Bind_f (void)
|
|||
|
||||
if (c > 3)
|
||||
{
|
||||
Cmd_ShiftArgs(1);
|
||||
Cmd_ShiftArgs(1, Cmd_ExecLevel==RESTRICT_LOCAL);
|
||||
Key_SetBinding (b, modifier, Cmd_Args(), Cmd_ExecLevel);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,33 @@ void PF_loadfromdata (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
G_FLOAT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
void PF_parseentitydata(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
void *ed = G_EDICT(prinst, OFS_PARM0);
|
||||
char *file = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
|
||||
int size;
|
||||
|
||||
if (!*file)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prinst->restoreent(prinst, file, &size, ed))
|
||||
Con_Printf("parseentitydata: missing opening data\n");
|
||||
else
|
||||
{
|
||||
file += size;
|
||||
while(*file < ' ' && *file)
|
||||
file++;
|
||||
if (*file)
|
||||
Con_Printf("parseentitydata: too much data\n");
|
||||
}
|
||||
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = (float)(((int)G_FLOAT(OFS_PARM0))%((int)G_FLOAT(OFS_PARM1)));
|
||||
|
@ -885,6 +912,18 @@ void PF_etof(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
{
|
||||
G_FLOAT(OFS_RETURN) = G_EDICTNUM(prinst, OFS_PARM0);
|
||||
}
|
||||
void PF_ftoe(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int entnum = G_FLOAT(OFS_PARM0);
|
||||
|
||||
RETURN_EDICT(prinst, EDICT_NUM(prinst, entnum));
|
||||
}
|
||||
|
||||
void PF_IsNull(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int str = G_INT(OFS_PARM0);
|
||||
G_FLOAT(OFS_RETURN) = !str;
|
||||
}
|
||||
|
||||
builtin_t menu_builtins[] = {
|
||||
//0
|
||||
|
@ -977,7 +1016,16 @@ builtin_t menu_builtins[] = {
|
|||
PF_chr2str,//8
|
||||
PF_etof,//9 //float etof(entity ent) = #79;
|
||||
//80
|
||||
skip10
|
||||
PF_ftoe,//10
|
||||
PF_IsNull,
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
skip1
|
||||
//90
|
||||
skip10
|
||||
//100
|
||||
|
@ -1033,7 +1081,7 @@ builtin_t menu_builtins[] = {
|
|||
PF_CL_findkeysforcommand,
|
||||
PF_gethostcachevalue,
|
||||
PF_gethostcachestring,
|
||||
PF_Fixme //void parseentitydata(entity ent, string data) = #613;
|
||||
PF_parseentitydata //void parseentitydata(entity ent, string data) = #613;
|
||||
};
|
||||
int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]);
|
||||
|
||||
|
@ -1084,6 +1132,8 @@ void MP_Shutdown (void)
|
|||
|
||||
mouseusedforgui = false;
|
||||
|
||||
M_Init_Internal();
|
||||
|
||||
if (inmenuprogs) //something in the menu caused the problem, so...
|
||||
{
|
||||
inmenuprogs = 0;
|
||||
|
@ -1108,6 +1158,14 @@ void VARGS Menu_Abort (char *format, ...)
|
|||
|
||||
Con_Printf("Menu_Abort: %s\nShutting down menu.dat\n", string);
|
||||
|
||||
|
||||
{
|
||||
static char buffer[1024*1024*8];
|
||||
int size = sizeof buffer;
|
||||
menuprogs->save_ents(menuprogs, buffer, &size, 3);
|
||||
COM_WriteFile("menucore.txt", buffer, size);
|
||||
}
|
||||
|
||||
MP_Shutdown();
|
||||
}
|
||||
|
||||
|
|
|
@ -368,7 +368,7 @@ void R_ParticleEffect_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
Cmd_TokenizeString(buf);
|
||||
Cmd_TokenizeString(buf, true, true);
|
||||
var = Cmd_Argv(0);
|
||||
value = Cmd_Argv(1);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
|
||||
char *particle_set_spikeset =
|
||||
#if 0
|
||||
"r_part rockettail\n"
|
||||
"{\n"
|
||||
" texture \"particles/rtrail\"\n"
|
||||
|
@ -37,7 +38,47 @@ char *particle_set_spikeset =
|
|||
" blend add\n"
|
||||
" assoc rockettail\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
#else
|
||||
"r_part t_rocket\n"
|
||||
"{\n"
|
||||
" texture \"\"\n"
|
||||
" gravity -200\n"
|
||||
" step 40\n"
|
||||
" scale 10\n"
|
||||
" scaledelta 50\n"
|
||||
" alpha 0.5\n"
|
||||
" die 0.5\n"
|
||||
" red 254\n"
|
||||
" green 128\n"
|
||||
" blue 64\n"
|
||||
" blend add\n"
|
||||
" isbeam\n"
|
||||
" spawnmode spiral\n"
|
||||
" offsetspread 5\n"
|
||||
"}\n"
|
||||
#endif
|
||||
|
||||
//TeamFortress railgun (by model - this is also the effect used with the TE_LIGHTNING1 extension)
|
||||
"r_part t_railtrail\n"
|
||||
"{\n"
|
||||
" texture \"particles/b_rocket3\"\n"
|
||||
" step 15\n"
|
||||
" scale 10\n"
|
||||
" alpha 1\n"
|
||||
" die 1\n"
|
||||
" red 255\n"
|
||||
" green 255\n"
|
||||
" blue 255\n"
|
||||
" blend add\n"
|
||||
" isbeam\n"
|
||||
" spawnmode spiral\n"
|
||||
" offsetspread 100\n"
|
||||
" cliptype t_railtrail\n"
|
||||
" friction 0.7\n"
|
||||
"}\n"
|
||||
"r_trail progs/e_spike1.mdl t_railtrail\n"
|
||||
|
||||
|
||||
"r_part t_grenade\n"
|
||||
"{\n"
|
||||
" texture \"particles/rtrail\"\n"
|
||||
|
@ -245,6 +286,8 @@ char *particle_set_spikeset =
|
|||
" emitintervalrand 0\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
||||
//fixme: 16?!?!
|
||||
"r_part te_explosion\n"
|
||||
"{\n"
|
||||
" texture \"particles/explosion\"\n"
|
||||
|
@ -269,29 +312,7 @@ char *particle_set_spikeset =
|
|||
" scalefactor 1\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"r_part cte_greenexplosion\n"
|
||||
"{\n"
|
||||
" texture \"particles/explosion\"\n"
|
||||
" count 16\n"
|
||||
" scale 100\n"
|
||||
" alpha 0.7\n"
|
||||
" die 4\n"
|
||||
" randomvel 32\n"
|
||||
" veladd 0\n"
|
||||
" red 128\n"
|
||||
" green 255\n"
|
||||
" blue 76\n"
|
||||
" reddelta 0\n"
|
||||
" greendelta 0\n"
|
||||
" reddelta 0\n"
|
||||
" gravity 0\n"
|
||||
"friction 1\n"
|
||||
" stains 0\n"
|
||||
" blend add\n"
|
||||
" assoc shrapnal\n"
|
||||
" scalefactor 1\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
||||
"r_part empcentral\n"
|
||||
"{\n"
|
||||
" texture \"particles/emp\"\n"
|
||||
|
@ -429,7 +450,7 @@ char *particle_set_spikeset =
|
|||
"r_part te_teleportsplash\n"
|
||||
"{\n"
|
||||
" texture \"particles/teleport\"\n"
|
||||
" count 4192\n"
|
||||
" count 4192\n" //EGAD!!!! 4192?!??! What was I thinking?!?!? (it's a very pwetty effect though...)
|
||||
" scale 2\n"
|
||||
" scalefactor 1\n"
|
||||
" alpha 1\n"
|
||||
|
|
|
@ -1099,7 +1099,7 @@ static void TP_LoadLocFile (char *filename, qbool quiet)
|
|||
}
|
||||
line[i] = 0;
|
||||
|
||||
Cmd_TokenizeString (line);
|
||||
Cmd_TokenizeString (line, true, false);
|
||||
|
||||
argc = Cmd_Argc();
|
||||
if (!argc)
|
||||
|
|
|
@ -965,7 +965,7 @@ Cmd_ShiftArgs
|
|||
Shifts Cmd_Argv results down one (killing first param)
|
||||
============
|
||||
*/
|
||||
void Cmd_ShiftArgs (int ammount)
|
||||
void Cmd_ShiftArgs (int ammount, qboolean expandstring)
|
||||
{
|
||||
int arg;
|
||||
while (ammount>0 && cmd_argc)
|
||||
|
@ -984,7 +984,7 @@ void Cmd_ShiftArgs (int ammount)
|
|||
|
||||
if (cmd_args)
|
||||
{
|
||||
cmd_args = COM_StringParse(cmd_args);
|
||||
cmd_args = COM_StringParse(cmd_args, expandstring, false);
|
||||
if (cmd_args)
|
||||
while(*cmd_args == ' ')
|
||||
cmd_args++;
|
||||
|
@ -1114,7 +1114,7 @@ Cmd_TokenizeString
|
|||
Parses the given string into command line tokens.
|
||||
============
|
||||
*/
|
||||
void Cmd_TokenizeString (char *text)
|
||||
void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1145,7 +1145,7 @@ void Cmd_TokenizeString (char *text)
|
|||
if (cmd_argc == 1)
|
||||
cmd_args = text;
|
||||
|
||||
text = COM_StringParse (text);
|
||||
text = COM_StringParse (text, expandmacros, qctokenize);
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
|
@ -1581,7 +1581,7 @@ void Cmd_ExecuteString (char *text, int level)
|
|||
Cmd_ExecLevel = level;
|
||||
|
||||
text = Cmd_ExpandString(text, dest, sizeof(dest), level);
|
||||
Cmd_TokenizeString (text);
|
||||
Cmd_TokenizeString (text, level == RESTRICT_LOCAL, false);
|
||||
|
||||
// execute the command line
|
||||
if (!Cmd_Argc())
|
||||
|
|
|
@ -101,7 +101,7 @@ int Cmd_CheckParm (char *parm);
|
|||
char *Cmd_AliasExist(char *name, int restrictionlevel);
|
||||
void Alias_WipeStuffedAliaes(void);
|
||||
|
||||
void Cmd_TokenizeString (char *text);
|
||||
void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize);
|
||||
// Takes a null terminated string. Does not need to be /n terminated.
|
||||
// breaks the string up into arg tokens.
|
||||
|
||||
|
@ -131,7 +131,7 @@ void Cmd_MessageTrigger (char *message, int type);
|
|||
|
||||
void Cmd_StuffCmds_f (void);
|
||||
|
||||
void Cmd_ShiftArgs (int ammount);
|
||||
void Cmd_ShiftArgs (int ammount, qboolean expandstring);
|
||||
|
||||
char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel);
|
||||
|
||||
|
|
|
@ -1428,7 +1428,7 @@ skipwhite:
|
|||
}
|
||||
|
||||
//same as COM_Parse, but parses two quotes next to each other as a single quote as part of the string
|
||||
char *COM_StringParse (char *data)
|
||||
char *COM_StringParse (char *data, qboolean expandmacros, qboolean qctokenize)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
@ -1442,7 +1442,7 @@ char *COM_StringParse (char *data)
|
|||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
while ( (c = *data), c <= ' ' && c != '\n')
|
||||
{
|
||||
if (c == 0)
|
||||
return NULL; // end of file;
|
||||
|
@ -1501,6 +1501,54 @@ skipwhite:
|
|||
}
|
||||
}
|
||||
|
||||
// handle quoted strings specially
|
||||
if (c == '\'' && qctokenize)
|
||||
{
|
||||
data++;
|
||||
while (1)
|
||||
{
|
||||
if (len >= TOKENSIZE-1)
|
||||
{
|
||||
com_token[len] = '\0';
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
c = *data++;
|
||||
if (c=='\'')
|
||||
{
|
||||
c = *(data);
|
||||
if (c!='\'')
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
while (c=='\'')
|
||||
{
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
data++;
|
||||
c = *(data+1);
|
||||
}
|
||||
}
|
||||
if (!c)
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';'))
|
||||
{
|
||||
// single character
|
||||
com_token[len++] = c;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
|
@ -1514,16 +1562,13 @@ skipwhite:
|
|||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
} while (c>32);
|
||||
} while (c>32 && !(qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';')));
|
||||
|
||||
com_token[len] = 0;
|
||||
#ifndef CLIENTONLY
|
||||
{
|
||||
extern redirect_t sv_redirected;
|
||||
if (sv_redirected) //servers shouldn't give the values of cvars to all clients... Like password...
|
||||
|
||||
if (!expandmacros)
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
//now we check for macros.
|
||||
for (s = com_token, c= 0; c < len; c++, s++) //this isn't a quoted token by the way.
|
||||
{
|
||||
|
|
|
@ -202,7 +202,7 @@ extern qboolean com_eof;
|
|||
|
||||
char *COM_Parse (char *data);
|
||||
char *COM_ParseCString (char *data);
|
||||
char *COM_StringParse (char *data);
|
||||
char *COM_StringParse (char *data, qboolean expandmacros, qboolean qctokenize);
|
||||
char *COM_ParseToken (char *data);
|
||||
char *COM_TrimString(char *str);
|
||||
|
||||
|
|
|
@ -556,6 +556,11 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
|
|||
strcpy(buffer, cl->path+1);
|
||||
else
|
||||
strcpy(buffer, cl->path);
|
||||
|
||||
if (*buffer) //last characture should be a /
|
||||
if (buffer[strlen(buffer)-1] != '/')
|
||||
strcat(buffer, "/");
|
||||
|
||||
strcat(buffer, "*");
|
||||
QueueMessage (cl, "125 Opening FAKE ASCII mode data connection for file.\r\n");
|
||||
|
||||
|
|
|
@ -121,8 +121,14 @@ struct edict_s *ED_Alloc (progfuncs_t *progfuncs)
|
|||
}
|
||||
|
||||
if (i >= maxedicts-1)
|
||||
{
|
||||
int size;
|
||||
char *buf;
|
||||
buf = progfuncs->save_ents(progfuncs, NULL, &size, 0);
|
||||
progfuncs->parms->WriteFile("edalloc.dump", buf, size);
|
||||
Sys_Error ("ED_Alloc: no free edicts");
|
||||
}
|
||||
}
|
||||
|
||||
sv_num_edicts++;
|
||||
e = (edictrun_t*)EDICT_NUM(progfuncs, i);
|
||||
|
@ -1348,6 +1354,99 @@ char *ED_WriteEdict(progfuncs_t *progfuncs, edictrun_t *ed, char *buffer, pbool
|
|||
#undef AddS
|
||||
}
|
||||
|
||||
char *SaveCallStack (progfuncs_t *progfuncs, char *s)
|
||||
{
|
||||
#define AddS(str) strcpy(s, str);s+=strlen(str);
|
||||
char buffer[8192];
|
||||
dfunction_t *f;
|
||||
int i;
|
||||
int progs;
|
||||
|
||||
int arg;
|
||||
int *globalbase;
|
||||
|
||||
progs = -1;
|
||||
|
||||
if (pr_depth == 0)
|
||||
{
|
||||
AddS ("<NO STACK>\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
globalbase = (int *)pr_globals + pr_xfunction->parm_start + pr_xfunction->locals;
|
||||
|
||||
pr_stack[pr_depth].f = pr_xfunction;
|
||||
for (i=pr_depth ; i>0 ; i--)
|
||||
{
|
||||
f = pr_stack[i].f;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
AddS ("<NO FUNCTION>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pr_stack[i].progsnum != progs)
|
||||
{
|
||||
progs = pr_stack[i].progsnum;
|
||||
|
||||
sprintf(buffer, "//%i %s\n", progs, pr_progstate[progs].filename);
|
||||
AddS (buffer);
|
||||
}
|
||||
if (!*f->s_file)
|
||||
sprintf(buffer, "\t\"%i:%s\"\n", progs, f->s_name);
|
||||
else
|
||||
sprintf(buffer, "\t\"%i:%s\" //%s\n", progs, f->s_name, f->s_file);
|
||||
AddS (buffer);
|
||||
|
||||
AddS ("\t{\n");
|
||||
for (arg = 0; arg < f->locals; arg++)
|
||||
{
|
||||
ddef16_t *local;
|
||||
local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
|
||||
if (!local)
|
||||
sprintf(buffer, "\t\tofs%i %i // %f\n", f->parm_start+arg, *(int *)(globalbase - f->locals+arg), *(float *)(globalbase - f->locals+arg) );
|
||||
else
|
||||
{
|
||||
__try
|
||||
{
|
||||
if (local->type == ev_entity)
|
||||
{ //go safly.
|
||||
int n;
|
||||
sprintf(buffer, "\t\t\"%s\"\t\"entity INVALID POINTER\"\n", local->s_name, n);
|
||||
for (n = 0; n < sv_num_edicts; n++)
|
||||
{
|
||||
if (prinst->edicttable[n] == (struct edict_s *)PROG_TO_EDICT(((eval_t*)(globalbase - f->locals+arg))->edict))
|
||||
{
|
||||
sprintf(buffer, "\t\t\"%s\" \"entity %i\"\n", local->s_name, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
sprintf(buffer, "\t\t\"%s\"\t\"%s\"\n", local->s_name, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
sprintf(buffer, "\t\t\"%s\" \"ILLEGAL POINTER\"\n", local->s_name);
|
||||
}
|
||||
if (local->type == ev_vector)
|
||||
arg+=2;
|
||||
}
|
||||
AddS (buffer);
|
||||
}
|
||||
AddS ("\t}\n");
|
||||
|
||||
if (i == pr_depth)
|
||||
globalbase = localstack + localstack_used - f->locals;
|
||||
else
|
||||
globalbase -= f->locals;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
#undef AddS
|
||||
}
|
||||
|
||||
//there are two ways of saving everything.
|
||||
//0 is to save just the entities.
|
||||
//1 is to save the entites, and all the progs info so that all the variables are saved off, and it can be reloaded to exactly how it was (provided no files or data has been changed outside, like the progs.dat for example)
|
||||
|
@ -1413,7 +1512,6 @@ char *SaveEnts(progfuncs_t *progfuncs, char *mem, int *len, int alldata)
|
|||
|
||||
if (alldata)
|
||||
{
|
||||
|
||||
AddS("general {\n");
|
||||
AddS(qcva("\"maxprogs\" \"%i\"\n", maxprogs));
|
||||
// AddS(qcva("\"maxentities\" \"%i\"\n", maxedicts));
|
||||
|
@ -1438,6 +1536,14 @@ char *SaveEnts(progfuncs_t *progfuncs, char *mem, int *len, int alldata)
|
|||
}
|
||||
}
|
||||
|
||||
if (alldata == 3)
|
||||
{
|
||||
//include callstack
|
||||
AddS("stacktrace {\n");
|
||||
s = SaveCallStack(progfuncs, s);
|
||||
AddS("}\n");
|
||||
}
|
||||
|
||||
for (a = 0; a < maxprogs; a++) //I would mix, but external functions rely on other progs being loaded
|
||||
{
|
||||
if (!pr_progstate[a].progs)
|
||||
|
@ -2003,8 +2109,6 @@ struct edict_s *RestoreEnt (progfuncs_t *progfuncs, char *buf, int *size, struct
|
|||
ent = (edictrun_t *)ed;
|
||||
ent->isfree = false;
|
||||
|
||||
ED_ClearEdict(progfuncs, ent);
|
||||
|
||||
buf = ED_ParseEdict(progfuncs, buf, ent);
|
||||
|
||||
*size = buf - start;
|
||||
|
|
|
@ -241,9 +241,14 @@ int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
|
|||
pr_depth++;
|
||||
if (pr_depth == MAX_STACK_DEPTH)
|
||||
{
|
||||
printf ("stack overflow on call to %s", f->s_name);
|
||||
pr_depth--;
|
||||
PR_StackTrace (progfuncs);
|
||||
|
||||
printf ("stack overflow on call to %s\n", f->s_name);
|
||||
|
||||
//comment this out if you want the progs to try to continue anyway (could cause infinate loops)
|
||||
Abort("Stack Overflow\n");
|
||||
|
||||
PR_AbortStack(progfuncs);
|
||||
return pr_xstatement;
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ vars(prstack_t, pr_stack, MAX_STACK_DEPTH);
|
|||
var(int, pr_depth);
|
||||
#define pr_depth prinst->pr_depth
|
||||
|
||||
#define LOCALSTACK_SIZE 16384
|
||||
#define LOCALSTACK_SIZE 4096
|
||||
vars(int, localstack, LOCALSTACK_SIZE);
|
||||
#define localstack prinst->localstack
|
||||
var(int, localstack_used);
|
||||
|
|
|
@ -2704,7 +2704,7 @@ void Draw_CharToDrawable (int num, unsigned int *drawable, int x, int y, int wid
|
|||
|
||||
if (s > e)
|
||||
return;
|
||||
if (y >= height)
|
||||
if (y >= height-e)
|
||||
return;
|
||||
if (y < -8)
|
||||
return;
|
||||
|
@ -2819,13 +2819,13 @@ void XR_PolyText(xclient_t *cl, xReq *request)
|
|||
while(1)
|
||||
{
|
||||
charnum = 0;
|
||||
charnum |= *str++;
|
||||
if (req->reqType == X_ImageText16)
|
||||
charnum |= (*str++)<<8;
|
||||
charnum |= *str++;
|
||||
if (!charnum)
|
||||
return;
|
||||
|
||||
Draw_CharToDrawable(charnum, (unsigned int *)drbuffer, xpos, ypos, drwidth, drheight, gc);
|
||||
Draw_CharToDrawable(charnum&255, (unsigned int *)drbuffer, xpos, ypos, drwidth, drheight, gc);
|
||||
|
||||
xpos += 8;
|
||||
}
|
||||
|
@ -2877,6 +2877,8 @@ void XR_QueryFont(xclient_t *cl, xReq *request) //basically ignored. We only sup
|
|||
{
|
||||
// xResourceReq *req = (xResourceReq *)request;
|
||||
char buffer[8192];
|
||||
int i;
|
||||
xCharInfo *ci;
|
||||
xQueryFontReply *rep = (xQueryFontReply *)buffer;
|
||||
|
||||
rep->type = X_Reply;
|
||||
|
@ -2910,13 +2912,23 @@ void XR_QueryFont(xclient_t *cl, xReq *request) //basically ignored. We only sup
|
|||
rep->drawDirection = 0;
|
||||
rep->minByte1 = 0;
|
||||
rep->maxByte1 = 0;
|
||||
rep->allCharsExist = 1;
|
||||
rep->allCharsExist = 0;
|
||||
rep->fontAscent = 4;
|
||||
rep->fontDescent = 4;
|
||||
rep->nCharInfos = 0; /* followed by this many xCharInfo structures */
|
||||
rep->nCharInfos = 255; /* followed by this many xCharInfo structures */
|
||||
|
||||
rep->length = ((sizeof(xQueryFontReply) - sizeof(xGenericReply)) + rep->nFontProps*sizeof(xFontProp) + rep->nCharInfos*sizeof(xCharInfo))/4;
|
||||
|
||||
ci = (xCharInfo*)(rep+1);
|
||||
for (i = 0; i < rep->nCharInfos; i++)
|
||||
{
|
||||
ci[i].leftSideBearing = 0;
|
||||
ci[i].rightSideBearing = 0;
|
||||
ci[i].characterWidth = 8;
|
||||
ci[i].ascent = 4;
|
||||
ci[i].descent = 4;
|
||||
}
|
||||
|
||||
X_SendData(cl, rep, sizeof(xGenericReply)+rep->length*4);
|
||||
}
|
||||
|
||||
|
|
|
@ -1294,18 +1294,18 @@ void NPP_MVDFlush(void)
|
|||
if (1)
|
||||
{
|
||||
int entnum, i;
|
||||
entity_state_t *ent;
|
||||
|
||||
if (!sv.demostate)
|
||||
sv.demostate = BZ_Malloc(sizeof(entity_state_t)*MAX_EDICTS);
|
||||
mvdentity_state_t *ent;
|
||||
|
||||
if (!sv.demobaselines)
|
||||
{
|
||||
sv.demobaselines = (mvdentity_state_t*)BZ_Malloc(sizeof(mvdentity_state_t)*MAX_EDICTS);
|
||||
sv.demostatevalid = true;
|
||||
}
|
||||
entnum = buffer[1] + (buffer[2]<<8);
|
||||
// if (entnum < MAX_CLIENTS)
|
||||
// break;
|
||||
ent = &sv.demostate[entnum];
|
||||
ent = &sv.demobaselines[entnum];
|
||||
|
||||
ent->number = entnum;
|
||||
ent->modelindex = buffer[3];
|
||||
ent->frame = buffer[4];
|
||||
ent->colormap = buffer[5];
|
||||
|
@ -1314,7 +1314,7 @@ void NPP_MVDFlush(void)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
ent->origin[i] = (short)(buffer[7+i*3] + (buffer[8+i*3]<<8))/8.0f;
|
||||
ent->angles[i] = buffer[9+i*3]*360.0/256;
|
||||
ent->angles[i] = buffer[9+i*3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1412,11 +1412,14 @@ void NPP_MVDFlush(void)
|
|||
ignoreprotocol=true; //a bug exists in that the delta MUST have been reliably recorded.
|
||||
{
|
||||
int i;
|
||||
entity_state_t *ents;
|
||||
int entnum;
|
||||
mvdentity_state_t *ents;
|
||||
unsigned short s;
|
||||
if (!sv.demostate)
|
||||
sv.demostate = BZ_Malloc(sizeof(entity_state_t)*MAX_EDICTS);
|
||||
{
|
||||
sv.demostate = BZ_Malloc(sizeof(mvdentity_state_t)*MAX_EDICTS);
|
||||
sv.demostatevalid = true;
|
||||
}
|
||||
i = majortype-svc_packetentities+1;
|
||||
while (1)
|
||||
{
|
||||
|
@ -1428,12 +1431,23 @@ void NPP_MVDFlush(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
ents = &sv.demostate[s&511];
|
||||
ents->number = s&511;
|
||||
entnum = s&511;
|
||||
s &= ~511;
|
||||
|
||||
if (entnum > sv.demomaxents)
|
||||
sv.demomaxents = entnum;
|
||||
|
||||
ents = &sv.demostate[entnum];
|
||||
if (s & U_REMOVE)
|
||||
{
|
||||
{ //this entity went from the last packet
|
||||
ents->modelindex = 0;
|
||||
ents->effects = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ents->modelindex && !ents->effects && sv.demobaselines)
|
||||
{ //new entity, reset to baseline
|
||||
memcpy(ents, &sv.demobaselines[entnum], sizeof(mvdentity_state_t));
|
||||
}
|
||||
|
||||
if (s & U_MOREBITS)
|
||||
|
@ -1480,7 +1494,7 @@ void NPP_MVDFlush(void)
|
|||
|
||||
if (s & U_ANGLE1)
|
||||
{
|
||||
ents->angles[0] = (unsigned char)(buffer[i]) * (360.0/256);
|
||||
ents->angles[0] = (unsigned char)(buffer[i]);// * (360.0/256);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -1492,7 +1506,7 @@ void NPP_MVDFlush(void)
|
|||
|
||||
if (s & U_ANGLE2)
|
||||
{
|
||||
ents->angles[1] = (unsigned char)(buffer[i]) * (360.0/256);
|
||||
ents->angles[1] = (unsigned char)(buffer[i]);// * (360.0/256);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -1504,7 +1518,7 @@ void NPP_MVDFlush(void)
|
|||
|
||||
if (s & U_ANGLE3)
|
||||
{
|
||||
ents->angles[2] = (unsigned char)(buffer[i]) * (360.0/256);
|
||||
ents->angles[2] = (unsigned char)(buffer[i]);// * (360.0/256);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -1516,7 +1530,7 @@ void NPP_MVDFlush(void)
|
|||
{
|
||||
int i, j;
|
||||
unsigned short flags;
|
||||
entity_state_t *ents;
|
||||
mvdentity_state_t *ents;
|
||||
int wframe, playernum;
|
||||
vec3_t oldorg;
|
||||
vec3_t oldang;
|
||||
|
@ -1549,7 +1563,8 @@ void NPP_MVDFlush(void)
|
|||
for (j=0 ; j<3 ; j++)
|
||||
if (flags & (DF_ANGLES << j))
|
||||
{
|
||||
ents->angles[j] = (int)(buffer[i] + (buffer[i+1]<<8))*360.0f/(256*256);
|
||||
//FIXME: angle truncation here.
|
||||
ents->angles[j] = (int)(buffer[i] + (buffer[i+1]<<8))/256;
|
||||
i+=2;
|
||||
}
|
||||
|
||||
|
@ -1620,7 +1635,7 @@ void NPP_MVDFlush(void)
|
|||
|
||||
case svc_stufftext:
|
||||
ignoreprotocol = true;
|
||||
Cmd_TokenizeString(buffer+1);
|
||||
Cmd_TokenizeString(buffer+1, false, false);
|
||||
if (!stricmp(Cmd_Argv(0), "fullserverinfo"))
|
||||
{
|
||||
Q_strncpyz(sv.demoinfo, Cmd_Argv(1), sizeof(sv.demoinfo));
|
||||
|
|
|
@ -3474,7 +3474,14 @@ void PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
// oldf = pr_xfunction;
|
||||
oldself = pr_global_struct->self;
|
||||
|
||||
if (!SV_TestEntityPosition(ent))
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
|
||||
if (SV_TestEntityPosition(ent))
|
||||
Con_Printf("Entity became stuck\n");
|
||||
}
|
||||
else
|
||||
Con_Printf("Ent is stuck - sorry\n");
|
||||
|
||||
|
||||
// restore program state
|
||||
|
@ -3502,7 +3509,7 @@ void PF_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
end[2] -= 512;
|
||||
|
||||
VectorCopy (ent->v.origin, start);
|
||||
trace = SV_Move (start, ent->v.mins, ent->v.maxs, end, false, ent);
|
||||
trace = SV_Move (start, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
|
||||
|
||||
if (trace.fraction == 1 || trace.allsolid)
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
|
@ -3510,7 +3517,7 @@ void PF_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
{
|
||||
VectorCopy (trace.endpos, ent->v.origin);
|
||||
SV_LinkEdict (ent, false);
|
||||
// ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
|
||||
ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
|
||||
ent->v.groundentity = EDICT_TO_PROG(prinst, trace.ent);
|
||||
G_FLOAT(OFS_RETURN) = 1;
|
||||
}
|
||||
|
@ -5396,9 +5403,9 @@ void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
pf_fopen_files[fnum].ofs = s - pf_fopen_files[fnum].data;
|
||||
|
||||
if (!pr_string_temp[0] && !*s)
|
||||
G_INT(OFS_PARM0) = 0; //EOF
|
||||
G_INT(OFS_RETURN) = 0; //EOF
|
||||
else
|
||||
RETURN_SSTRING(pr_string_temp);
|
||||
G_INT(OFS_RETURN) = (int)pr_string_temp - prinst->stringtable;
|
||||
}
|
||||
|
||||
void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
|
@ -5776,7 +5783,7 @@ void PF_ArgC (progfuncs_t *prinst, struct globalvars_s *pr_globals) //85 /
|
|||
//KRIMZON_SV_PARSECLIENTCOMMAND added these two.
|
||||
void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 //void(string str) tokanize;
|
||||
{
|
||||
Cmd_TokenizeString(PR_GetStringOfs(prinst, OFS_PARM0));
|
||||
Cmd_TokenizeString(PR_GetStringOfs(prinst, OFS_PARM0), false, true);
|
||||
G_FLOAT(OFS_RETURN) = Cmd_Argc();
|
||||
}
|
||||
void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv;
|
||||
|
|
|
@ -80,6 +80,23 @@ typedef struct {
|
|||
#define CTE_CHANNELFADE 16
|
||||
#define CTE_ISBEAM 128
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin;
|
||||
qbyte angles[3];
|
||||
qbyte modelindex;
|
||||
qbyte frame;
|
||||
qbyte colormap;
|
||||
qbyte skinnum;
|
||||
qbyte effects;
|
||||
|
||||
qbyte scale;
|
||||
qbyte trans;
|
||||
qbyte fatness;
|
||||
} mvdentity_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean active; // false when server is going down
|
||||
|
@ -175,7 +192,9 @@ typedef struct
|
|||
|
||||
qboolean mvdrecording;
|
||||
|
||||
//====================================================
|
||||
//this lot is for playback of demos
|
||||
|
||||
qboolean mvdplayback;
|
||||
float realtime;
|
||||
FILE *demofile; //also signifies playing the thing.
|
||||
|
@ -183,6 +202,7 @@ typedef struct
|
|||
int lasttype;
|
||||
int lastto;
|
||||
|
||||
//playback spikes (svc_nails/nails2)
|
||||
int numdemospikes;
|
||||
struct {
|
||||
vec3_t org;
|
||||
|
@ -191,9 +211,14 @@ typedef struct
|
|||
qbyte yaw;
|
||||
qbyte modelindex;
|
||||
} demospikes[255];
|
||||
entity_state_t *demostate;
|
||||
|
||||
//playback of entities (svc_nails/nails2)
|
||||
mvdentity_state_t *demostate;
|
||||
mvdentity_state_t *demobaselines;
|
||||
int demomaxents;
|
||||
qboolean demostatevalid;
|
||||
char demoinfo[MAX_SERVERINFO_STRING];
|
||||
|
||||
//players
|
||||
struct {
|
||||
int stats[MAX_CL_STATS];
|
||||
int pl;
|
||||
|
@ -207,11 +232,14 @@ typedef struct
|
|||
float updatetime;
|
||||
} recordedplayer[MAX_CLIENTS];
|
||||
|
||||
//gamestate
|
||||
char demoinfo[MAX_SERVERINFO_STRING];
|
||||
char demmodel_precache[MAX_MODELS][MAX_QPATH]; // NULL terminated
|
||||
char demsound_precache[MAX_SOUNDS][MAX_QPATH]; // NULL terminated
|
||||
char demgamedir[64];
|
||||
char demname[64]; // map name
|
||||
qboolean democausesreconnect; //make players load the level.
|
||||
|
||||
qboolean democausesreconnect; //this makes current clients go through the connection process (and when the demo ends too)
|
||||
sizebuf_t demosignon;
|
||||
int num_demosignon_buffers;
|
||||
int demosignon_buffer_size[MAX_SIGNON_BUFFERS];
|
||||
|
@ -219,6 +247,7 @@ typedef struct
|
|||
char demfullmapname[64];
|
||||
|
||||
char *demolightstyles[MAX_LIGHTSTYLES];
|
||||
//====================================================
|
||||
|
||||
entity_state_t extendedstatics[MAX_STATIC_ENTITIES];
|
||||
int numextrastatics;
|
||||
|
|
|
@ -751,12 +751,12 @@ void SV_StuffToClient_f(void)
|
|||
char *c;
|
||||
char *key;
|
||||
|
||||
Cmd_ShiftArgs(1);
|
||||
Cmd_ShiftArgs(1, Cmd_ExecLevel==RESTRICT_LOCAL);
|
||||
if (!strcmp(Cmd_Argv(1), "bind"))
|
||||
{
|
||||
key = Z_Malloc(strlen(Cmd_Argv(2))+1);
|
||||
strcpy(key, Cmd_Argv(2));
|
||||
Cmd_ShiftArgs(2);
|
||||
Cmd_ShiftArgs(2, Cmd_ExecLevel==RESTRICT_LOCAL);
|
||||
}
|
||||
else
|
||||
key = NULL;
|
||||
|
@ -1169,7 +1169,7 @@ void SV_SaveInfo(FILE *f, char *info, char *commandname)
|
|||
command = info+1;
|
||||
value = strchr(command, '\\');
|
||||
info = strchr(value+1, '\\');
|
||||
if (!*info) //eot..
|
||||
if (!info) //eot..
|
||||
info = value+strlen(value);
|
||||
|
||||
if (*command == '*') //unsettable, so don't write it for later setting.
|
||||
|
@ -1496,7 +1496,7 @@ void SV_SetTimer_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
Cmd_ShiftArgs(2); //strip the two vars
|
||||
Cmd_ShiftArgs(2, Cmd_ExecLevel==RESTRICT_LOCAL); //strip the two vars
|
||||
command = Cmd_Args();
|
||||
|
||||
timercommand = Cvar_Get("sv_timer", "", CVAR_NOSET, NULL);
|
||||
|
|
|
@ -225,6 +225,14 @@ void SV_LoadClientDemo_f (void)
|
|||
SV_ReadMVD();
|
||||
}
|
||||
|
||||
if (!sv.state)
|
||||
Cmd_ExecuteString("map start\n", Cmd_ExecLevel); //go for the start map
|
||||
if (!sv.state)
|
||||
{
|
||||
Con_Printf("Could not activate server\n");
|
||||
return;
|
||||
}
|
||||
|
||||
demoname = Cmd_Argv(1);
|
||||
com_filesize = COM_FOpenFile(demoname, &svd.demofile);
|
||||
|
||||
|
@ -312,7 +320,7 @@ qboolean SV_RunDemo (void)
|
|||
float demotime;
|
||||
qbyte c;
|
||||
// usercmd_t *pcmd;
|
||||
usercmd_t emptycmd;
|
||||
// usercmd_t emptycmd;
|
||||
static float prevtime = 0.0;
|
||||
qbyte newtime;
|
||||
|
||||
|
@ -376,11 +384,18 @@ readnext:
|
|||
|
||||
switch (c & 7) {
|
||||
case dem_cmd :
|
||||
|
||||
Con_Printf ("dem_cmd not supported\n");
|
||||
fclose(svd.demofile);
|
||||
svd.demofile = NULL;
|
||||
return false;
|
||||
|
||||
|
||||
// user sent input
|
||||
// i = svd.netchan.outgoing_sequence & UPDATE_MASK;
|
||||
// pcmd = &cl.frames[i].cmd;
|
||||
if ((r = fread (&emptycmd, sizeof(emptycmd), 1, svd.demofile)) != 1)
|
||||
SV_Error ("Corrupted demo");
|
||||
// if ((r = fread (&emptycmd, sizeof(emptycmd), 1, svd.demofile)) != 1)
|
||||
// SV_Error ("Corrupted demo");
|
||||
/*
|
||||
// qbyte order stuff
|
||||
for (j = 0; j < 3; j++)
|
||||
|
@ -393,7 +408,7 @@ readnext:
|
|||
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
|
||||
svd.netchan.outgoing_sequence++;
|
||||
*/
|
||||
fread (&emptycmd, 12, 1, svd.demofile);
|
||||
// fread (&emptycmd, 12, 1, svd.demofile);
|
||||
/* for (j = 0; j < 3; j++)
|
||||
cl.viewangles[i] = LittleFloat (cl.viewangles[i]);
|
||||
if (cl.spectator)
|
||||
|
|
|
@ -278,6 +278,10 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb
|
|||
int i;
|
||||
float miss;
|
||||
|
||||
static entity_state_t defaultbaseline;
|
||||
if (from == &((edict_t*)NULL)->baseline)
|
||||
from = &defaultbaseline;
|
||||
|
||||
// send an update
|
||||
bits = 0;
|
||||
|
||||
|
@ -1028,6 +1032,9 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
|
|||
client_t *cl;
|
||||
edict_t *ent, *vent;
|
||||
int pflags;
|
||||
vec3_t lerpedang;
|
||||
|
||||
int splitnum = 0;
|
||||
|
||||
demo_frame_t *demo_frame;
|
||||
demo_client_t *dcl;
|
||||
|
@ -1194,7 +1201,10 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
|
|||
clst.zext = client->zquake_extensions;
|
||||
clst.cl = NULL;
|
||||
|
||||
VectorMA(sv.demostate[i+1].angles, realtime - sv.recordedplayer[i].updatetime, sv.recordedplayer[i].avelocity, ang);
|
||||
ang[0] = sv.demostate[i+1].angles[0]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[0];
|
||||
ang[1] = sv.demostate[i+1].angles[1]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[1];
|
||||
ang[2] = sv.demostate[i+1].angles[2]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[2];
|
||||
|
||||
VectorMA(sv.demostate[i+1].origin, realtime - sv.recordedplayer[i].updatetime, sv.recordedplayer[i].velocity, org);
|
||||
ang[0] *= -3;
|
||||
|
||||
|
@ -1221,7 +1231,19 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
|
|||
|
||||
SV_WritePlayerToClient(msg, &clst);
|
||||
}
|
||||
if (ent != clent)
|
||||
splitnum = 0;
|
||||
if (cl->controlled)
|
||||
{ //hrm. splitscreen.
|
||||
client_t *s;
|
||||
for (s = cl; s; s = s->controlled, splitnum++)
|
||||
{
|
||||
if (s->edict == ent)
|
||||
break;
|
||||
}
|
||||
if (!s)
|
||||
continue;
|
||||
}
|
||||
else if (ent != clent)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1314,7 +1336,7 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
|
|||
clst.health = 100;
|
||||
|
||||
if (sv.demostatevalid)
|
||||
clst.playernum = MAX_CLIENTS-1;
|
||||
clst.playernum = MAX_CLIENTS-1-splitnum;
|
||||
|
||||
clst.isself = false;
|
||||
if ((cl == client || cl->controller == client) && !sv.demostatevalid)
|
||||
|
@ -1343,7 +1365,10 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
|
|||
{
|
||||
clst.origin = sv.demostate[client->spec_track].origin;
|
||||
clst.velocity = sv.recordedplayer[client->spec_track-1].velocity;
|
||||
clst.angles = sv.demostate[client->spec_track].angles;
|
||||
clst.angles = lerpedang;
|
||||
lerpedang[0] = sv.demostate[client->spec_track].angles[0]*360.0/256;
|
||||
lerpedang[1] = sv.demostate[client->spec_track].angles[1]*360.0/256;
|
||||
lerpedang[2] = sv.demostate[client->spec_track].angles[2]*360.0/256;
|
||||
}
|
||||
clst.spectator = 2;
|
||||
}
|
||||
|
@ -1704,7 +1729,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
vec3_t org;
|
||||
edict_t *ent;
|
||||
packet_entities_t *pack;
|
||||
entity_state_t *dement;
|
||||
mvdentity_state_t *dement;
|
||||
edict_t *clent;
|
||||
client_frame_t *frame;
|
||||
entity_state_t *state;
|
||||
|
@ -1779,7 +1804,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
|
||||
if (sv.demostatevalid) //generate info from demo stats
|
||||
{
|
||||
for (e=1, dement=&sv.demostate[e] ; e<sv.num_edicts ; e++, dement++)
|
||||
for (e=1, dement=&sv.demostate[e] ; e<=sv.demomaxents ; e++, dement++)
|
||||
{
|
||||
if (!dement->modelindex)
|
||||
continue;
|
||||
|
@ -1805,7 +1830,9 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
state->number = e;
|
||||
state->flags = EF_DIMLIGHT;
|
||||
VectorCopy (dement->origin, state->origin);
|
||||
VectorCopy (dement->angles, state->angles);
|
||||
state->angles[0] = dement->angles[0]*360.0f/256;
|
||||
state->angles[1] = dement->angles[1]*360.0f/256;
|
||||
state->angles[2] = dement->angles[2]*360.0f/256;
|
||||
state->modelindex = dement->modelindex;
|
||||
state->frame = dement->frame;
|
||||
state->colormap = dement->colormap;
|
||||
|
@ -1817,8 +1844,6 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
#endif
|
||||
#ifdef PEXT_TRANS
|
||||
state->trans = dement->trans;
|
||||
if (!state->trans)
|
||||
state->trans = 1;
|
||||
#endif
|
||||
#ifdef PEXT_FATNESS
|
||||
state->fatness = dement->fatness;
|
||||
|
|
|
@ -649,7 +649,7 @@ void SVC_Status (void)
|
|||
|
||||
int slots=0;
|
||||
|
||||
Cmd_TokenizeString ("status");
|
||||
Cmd_TokenizeString ("status", false, false);
|
||||
SV_BeginRedirect (RD_PACKET);
|
||||
Con_Printf ("%s\n", svs.info);
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
|
@ -1132,7 +1132,7 @@ void SVC_DirectConnect
|
|||
{
|
||||
while(!msg_badread)
|
||||
{
|
||||
Cmd_TokenizeString(MSG_ReadStringLine());
|
||||
Cmd_TokenizeString(MSG_ReadStringLine(), false, false);
|
||||
switch(Q_atoi(Cmd_Argv(0)))
|
||||
{
|
||||
case PROTOCOL_VERSION_FTE:
|
||||
|
@ -1979,7 +1979,7 @@ qboolean SV_ConnectionlessPacket (void)
|
|||
|
||||
s = MSG_ReadStringLine ();
|
||||
|
||||
Cmd_TokenizeString (s);
|
||||
Cmd_TokenizeString (s, false, false);
|
||||
|
||||
c = Cmd_Argv(0);
|
||||
|
||||
|
@ -2020,7 +2020,7 @@ qboolean SV_ConnectionlessPacket (void)
|
|||
{
|
||||
//these messages contain the ip address that it was origionally from (before being farmed out)
|
||||
NET_StringToAdr(Cmd_Argv(1), &net_from);
|
||||
Cmd_ShiftArgs(1); //get rid of the ip address...
|
||||
Cmd_ShiftArgs(1, false); //get rid of the ip address...
|
||||
#ifdef NQPROT
|
||||
SVC_DirectConnect (sock);
|
||||
#else
|
||||
|
@ -2721,6 +2721,11 @@ void SV_Frame (float time)
|
|||
SVM_Think(PORT_MASTER);
|
||||
}
|
||||
|
||||
{
|
||||
void SV_MVDStream_Poll(void);
|
||||
SV_MVDStream_Poll();
|
||||
}
|
||||
|
||||
if (sv.state < ss_active)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
|
|
|
@ -220,6 +220,8 @@ cvar_t sv_demoNoVis = {"sv_demoNoVis", ""};
|
|||
cvar_t sv_demoMaxSize = {"sv_demoMaxSize", ""};
|
||||
cvar_t sv_demoExtraNames = {"sv_demoExtraNames", ""};
|
||||
|
||||
cvar_t mvd_streamport = {"mvd_streamport", "27515"};
|
||||
|
||||
static int demo_max_size;
|
||||
static int demo_size;
|
||||
cvar_t sv_demoPrefix = {"sv_demoPrefix", ""};
|
||||
|
@ -520,6 +522,8 @@ void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
|
|||
demo.size += DWRITE (&len, 4, 1, demo.dest);
|
||||
demo.size += DWRITE (msg->data, msg->cursize, 1, demo.dest);
|
||||
|
||||
if (demo.file)
|
||||
{
|
||||
if (demo.disk)
|
||||
fflush (demo.file);
|
||||
else if (demo.size - demo_size > demo_max_size)
|
||||
|
@ -530,6 +534,9 @@ void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
|
|||
fflush(demo.file);
|
||||
memmove(svs.demomem, svs.demomem + 0x80000, demo.size - 0x80000);
|
||||
}
|
||||
}
|
||||
else
|
||||
demo_size = demo.size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -736,6 +743,17 @@ size_t memwrite ( const void *buffer, size_t size, size_t count, qbyte **mem)
|
|||
return c;
|
||||
}
|
||||
|
||||
size_t streamwrite ( const void *buffer, size_t size, size_t count, qbyte **mem)
|
||||
{
|
||||
int sent;
|
||||
sent = send(demo.tcpsocket, buffer, size*count, 0);
|
||||
|
||||
if (sent <= 0)
|
||||
return 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static char chartbl[256];
|
||||
void CleanName_Init ();
|
||||
|
||||
|
@ -755,7 +773,7 @@ void MVD_Init (void)
|
|||
Cvar_Register (&sv_demoDir, MVDVARGROUP);
|
||||
Cvar_Register (&sv_demoPrefix, MVDVARGROUP);
|
||||
Cvar_Register (&sv_demoSuffix, MVDVARGROUP);
|
||||
Cvar_Register (&sv_demotxt , MVDVARGROUP);
|
||||
Cvar_Register (&sv_demotxt, MVDVARGROUP);
|
||||
Cvar_Register (&sv_demoExtraNames, MVDVARGROUP);
|
||||
|
||||
|
||||
|
@ -765,7 +783,7 @@ void MVD_Init (void)
|
|||
if (p < com_argc-1)
|
||||
size = Q_atoi (com_argv[p+1]) * 1024;
|
||||
else
|
||||
Sys_Error ("Memory_Init: you must specify a size in KB after -democache");
|
||||
Sys_Error ("MVD_Init: you must specify a size in KB after -democache");
|
||||
}
|
||||
|
||||
if (size < MIN_MVD_MEMORY)
|
||||
|
@ -806,6 +824,25 @@ qboolean SV_InitRecord(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
qboolean SV_InitStream(void)
|
||||
{
|
||||
if (!USACACHE)
|
||||
{
|
||||
dwrite = (void *)&streamwrite;
|
||||
demo.dest = &demo.tcpsocket;
|
||||
demo.disk = false;
|
||||
} else
|
||||
{
|
||||
dwrite = (void *)&memwrite;
|
||||
demo.mfile = svs.demomem;
|
||||
demo.dest = &demo.mfile;
|
||||
}
|
||||
|
||||
demo_size = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_Stop
|
||||
|
@ -1031,6 +1068,8 @@ static qboolean SV_MVD_Record (char *name, int tcpsocket)
|
|||
char *gamedir;
|
||||
int seq = 1;
|
||||
|
||||
//okay, this is lame. We're going to allow a new mvd to 'reconnect' if we start recording the other...
|
||||
|
||||
memset(&demo, 0, sizeof(demo));
|
||||
demo.recorder.frames = demo_frames;
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
|
@ -1093,9 +1132,11 @@ static qboolean SV_MVD_Record (char *name, int tcpsocket)
|
|||
}
|
||||
else
|
||||
{
|
||||
SV_InitStream();
|
||||
|
||||
if (demo.tcpsocket)
|
||||
return false;
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording to network client\n");
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording to QWTV\n");
|
||||
demo.tcpsocket = tcpsocket;
|
||||
}
|
||||
|
||||
|
@ -1750,6 +1791,139 @@ void SV_MVDEasyRecord_f (void)
|
|||
SV_MVD_Record (name2, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define ECONNABORTED WSAECONNABORTED
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
||||
|
||||
#define qerrno WSAGetLastError()
|
||||
#else
|
||||
#define qerrno errno
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef sun
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifdef NeXT
|
||||
#include <libc.h>
|
||||
#endif
|
||||
|
||||
#define closesocket close
|
||||
#define ioctlsocket ioctl
|
||||
#endif
|
||||
|
||||
|
||||
int MVD_StreamStartListening(int port)
|
||||
{
|
||||
char name[256];
|
||||
int sock;
|
||||
struct hostent *hent;
|
||||
|
||||
struct sockaddr_in address;
|
||||
// int fromlen;
|
||||
|
||||
unsigned int nonblocking = true;
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
if (gethostname(name, sizeof(name)) == -1)
|
||||
return INVALID_SOCKET;
|
||||
hent = gethostbyname(name);
|
||||
if (!hent)
|
||||
return INVALID_SOCKET;
|
||||
address.sin_addr.s_addr = *(int *)(hent->h_addr_list[0]);
|
||||
address.sin_port = htons((u_short)port);
|
||||
|
||||
|
||||
|
||||
if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
Sys_Error ("MVD_StreamStartListening: socket:", strerror(qerrno));
|
||||
}
|
||||
|
||||
if (ioctlsocket (sock, FIONBIO, &nonblocking) == -1)
|
||||
{
|
||||
Sys_Error ("FTP_TCP_OpenSocket: ioctl FIONBIO:", strerror(qerrno));
|
||||
}
|
||||
|
||||
if( bind (sock, (void *)&address, sizeof(address)) == -1)
|
||||
{
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
listen(sock, 2);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void SV_MVDStream_Poll(void)
|
||||
{
|
||||
static int listensocket=INVALID_SOCKET;
|
||||
static int listenport;
|
||||
int client;
|
||||
netadr_t na;
|
||||
struct sockaddr_qstorage addr;
|
||||
int addrlen;
|
||||
qboolean wanted;
|
||||
if (!sv.state)
|
||||
wanted = false;
|
||||
else if (listenport && (int)mvd_streamport.value != listenport) //easy way to switch... disable for a frame. :)
|
||||
{
|
||||
listenport = mvd_streamport.value;
|
||||
wanted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
listenport = mvd_streamport.value;
|
||||
wanted = true;
|
||||
}
|
||||
|
||||
if (wanted && listensocket==INVALID_SOCKET)
|
||||
listensocket = MVD_StreamStartListening(listenport);
|
||||
else if (!wanted && listensocket!=INVALID_SOCKET)
|
||||
{
|
||||
closesocket(listensocket);
|
||||
listensocket = INVALID_SOCKET;
|
||||
return;
|
||||
}
|
||||
if (listensocket==INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
client = accept(listensocket, (struct sockaddr *)&addr, &addrlen);
|
||||
|
||||
if (client == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
if (sv.mvdrecording)
|
||||
{ //sorry
|
||||
closesocket(client);
|
||||
return;
|
||||
}
|
||||
|
||||
SockadrToNetadr(&addr, &na);
|
||||
Con_Printf("MVD streaming client connected from %s\n", NET_AdrToString(na));
|
||||
|
||||
SV_MVD_Record (NULL, client);
|
||||
}
|
||||
|
||||
void SV_MVDList_f (void)
|
||||
{
|
||||
dir_t dir;
|
||||
|
@ -2122,6 +2296,8 @@ void SV_MVDInit(void)
|
|||
Cmd_AddCommand ("demolist", SV_MVDList_f);
|
||||
Cmd_AddCommand ("rmdemo", SV_MVDRemove_f);
|
||||
Cmd_AddCommand ("rmdemonum", SV_MVDRemoveNum_f);
|
||||
|
||||
Cvar_Register(&mvd_streamport, "MVD Streaming");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -270,7 +270,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
|
|||
|
||||
trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
|
||||
|
||||
if (trace.allsolid)
|
||||
if (trace.startsolid)
|
||||
{ // entity is trapped in another solid
|
||||
VectorCopy (vec3_origin, ent->v.velocity);
|
||||
return 3;
|
||||
|
|
|
@ -109,6 +109,7 @@ void SV_New_f (void)
|
|||
{
|
||||
char *gamedir;
|
||||
int playernum;
|
||||
int splitnum;
|
||||
client_t *split;
|
||||
|
||||
if (host_client->state == cs_spawned)
|
||||
|
@ -166,6 +167,7 @@ void SV_New_f (void)
|
|||
MSG_WriteByte (&host_client->netchan.message, 0);
|
||||
MSG_WriteString (&host_client->netchan.message, gamedir);
|
||||
|
||||
splitnum = 0;
|
||||
for (split = host_client; split; split = split->controlled)
|
||||
{
|
||||
#ifdef Q2SERVER
|
||||
|
@ -175,7 +177,9 @@ void SV_New_f (void)
|
|||
#endif
|
||||
playernum = NUM_FOR_EDICT(svprogfuncs, split->edict)-1;
|
||||
if (sv.demostate)
|
||||
playernum = (MAX_CLIENTS-1)|128;
|
||||
{
|
||||
playernum = (MAX_CLIENTS-1-splitnum)|128;
|
||||
}
|
||||
else if (split->spectator)
|
||||
playernum |= 128;
|
||||
|
||||
|
@ -192,6 +196,7 @@ void SV_New_f (void)
|
|||
#ifdef SVRANKING
|
||||
split->stats_started = realtime;
|
||||
#endif
|
||||
splitnum++;
|
||||
}
|
||||
if (host_client->fteprotocolextensions & PEXT_SPLITSCREEN)
|
||||
MSG_WriteByte (&host_client->netchan.message, 128);
|
||||
|
@ -620,7 +625,7 @@ void SV_Soundlist_f (void)
|
|||
{
|
||||
int i;
|
||||
//char **s;
|
||||
int n;
|
||||
unsigned n;
|
||||
|
||||
if (host_client->state != cs_connected)
|
||||
{
|
||||
|
@ -646,9 +651,10 @@ void SV_Soundlist_f (void)
|
|||
SZ_Clear(&host_client->netchan.message);
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
if (n >= MAX_SOUNDS)
|
||||
{
|
||||
Con_Printf ("SV_Soundlist_f: %s tried to crash us\n", host_client->name);
|
||||
SV_EndRedirect();
|
||||
Con_Printf ("SV_Soundlist_f: %s send an invalid index\n", host_client->name);
|
||||
SV_DropClient(host_client);
|
||||
return;
|
||||
}
|
||||
|
@ -690,7 +696,7 @@ SV_Modellist_f
|
|||
void SV_Modellist_f (void)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
unsigned n;
|
||||
|
||||
if (host_client->state != cs_connected)
|
||||
{
|
||||
|
@ -716,9 +722,10 @@ void SV_Modellist_f (void)
|
|||
SZ_Clear(&host_client->netchan.message);
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
if (n >= MAX_MODELS)
|
||||
{
|
||||
Con_Printf ("SV_Modellist_f: %s tried to crash us\n", host_client->name);
|
||||
SV_EndRedirect();
|
||||
Con_Printf ("SV_Modellist_f: %s send an invalid index\n", host_client->name);
|
||||
SV_DropClient(host_client);
|
||||
return;
|
||||
}
|
||||
|
@ -795,9 +802,12 @@ void SV_PreSpawn_f (void)
|
|||
buf = atoi(Cmd_Argv(2));
|
||||
|
||||
if (buf >= bufs+statics+sv.num_edicts+255)
|
||||
buf = 0;
|
||||
if (buf < 0)
|
||||
buf = 0;
|
||||
{
|
||||
SV_EndRedirect();
|
||||
Con_Printf ("SV_Modellist_f: %s send an invalid index\n", host_client->name);
|
||||
SV_DropClient(host_client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
|
@ -2748,7 +2758,7 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC)
|
|||
|
||||
Con_DPrintf("Client command: %s\n", s);
|
||||
|
||||
Cmd_TokenizeString (s);
|
||||
Cmd_TokenizeString (s, false, false);
|
||||
sv_player = host_client->edict;
|
||||
|
||||
Cmd_ExecLevel=1;
|
||||
|
@ -2766,7 +2776,7 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC)
|
|||
}
|
||||
}
|
||||
sv_player = host_client->edict;
|
||||
Cmd_ShiftArgs(1);
|
||||
Cmd_ShiftArgs(1, false);
|
||||
}
|
||||
|
||||
#ifdef Q2SERVER
|
||||
|
@ -3103,7 +3113,7 @@ void SVNQ_PreSpawn_f (void)
|
|||
}
|
||||
void SVNQ_NQInfo_f (void)
|
||||
{
|
||||
Cmd_TokenizeString(va("setinfo \"%s\" \"%s\"\n", Cmd_Argv(0), Cmd_Argv(1)));
|
||||
Cmd_TokenizeString(va("setinfo \"%s\" \"%s\"\n", Cmd_Argv(0), Cmd_Argv(1)), false, false);
|
||||
SV_SetInfo_f();
|
||||
}
|
||||
|
||||
|
@ -3209,7 +3219,7 @@ void SVNQ_ExecuteUserCommand (char *s)
|
|||
client_t *oldhost = host_client;
|
||||
ucmd_t *u;
|
||||
|
||||
Cmd_TokenizeString (s);
|
||||
Cmd_TokenizeString (s, false, false);
|
||||
sv_player = host_client->edict;
|
||||
|
||||
Cmd_ExecLevel=1;
|
||||
|
|
|
@ -1197,8 +1197,8 @@ void Mod_LoadPlanes (lump_t *l)
|
|||
}
|
||||
|
||||
void Q1BSP_FatPVS (vec3_t org, qboolean add);
|
||||
qboolean Q1BSP_EdictInFatPVS(edict_t *ent);
|
||||
void Q1BSP_FindTouchedLeafs(edict_t *ent);
|
||||
qboolean Q1BSP_EdictInFatPVS(struct edict_s *ent);
|
||||
void Q1BSP_FindTouchedLeafs(struct edict_s *ent);
|
||||
|
||||
/*
|
||||
=================
|
||||
|
|
|
@ -1847,6 +1847,9 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e
|
|||
#endif
|
||||
SV_ClipToLinks ( sv_areanodes, &clip );
|
||||
|
||||
if (clip.trace.startsolid)
|
||||
clip.trace.fraction = 0;
|
||||
|
||||
return clip.trace;
|
||||
}
|
||||
#ifdef Q2SERVER
|
||||
|
|
Loading…
Reference in a new issue