Reworked stats for csqc to match LH's suggestion. CSQC can read the 'delta' entities (experimental). Fixed up sv_getrealip, made banning work based on realip too. Added a ban command to easily ban a single client. Renamed some svcs for clarification. Added pvsflags to ssqc for greater control over how ents are sent to csqc. Broke some stuff.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2977 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2008-05-25 22:23:43 +00:00
parent 40952dabf4
commit 654eabc4c2
27 changed files with 2601 additions and 1954 deletions

View File

@ -1381,6 +1381,9 @@ void CL_SendCmd (double frametime)
cl.frames[i].senttime = realtime;
cl.frames[i].receivedtime = 0; // nq doesn't allow us to find our own packetloss
#ifdef CSQC_DAT
CSQC_Input_Frame(cmd);
#endif
CLNQ_SendCmd ();
memset(&independantphysics[0], 0, sizeof(independantphysics[plnum]));
return;
@ -1422,7 +1425,6 @@ void CL_SendCmd (double frametime)
cls.resendinfo = false;
}
MSG_WriteByte (&buf, clcq2_move);
// save the position for a checksum qbyte
@ -1461,6 +1463,12 @@ void CL_SendCmd (double frametime)
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.frames[i].cmd[plnum];
*cmd = independantphysics[plnum];
cmd->lightlevel = lightlev;
#ifdef CSQC_DAT
CSQC_Input_Frame(cmd);
#endif
cl.frames[i].senttime = realtime;
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
memset(&independantphysics[plnum], 0, sizeof(independantphysics[plnum]));
@ -1475,7 +1483,6 @@ void CL_SendCmd (double frametime)
i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
cmd = &cl.frames[i].cmd[plnum];
cmd->lightlevel = lightlev;
if (cl_c2sImpulseBackup.value >= 2)
dontdrop = dontdrop || cmd->impulse;
MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
@ -1485,7 +1492,6 @@ void CL_SendCmd (double frametime)
if (cl_c2sImpulseBackup.value >= 3)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.frames[i].cmd[plnum];
cmd->lightlevel = lightlev;
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
oldcmd = cmd;
@ -1493,7 +1499,6 @@ void CL_SendCmd (double frametime)
if (cl_c2sImpulseBackup.value >= 1)
dontdrop = dontdrop || cmd->impulse;
cmd = &cl.frames[i].cmd[plnum];
cmd->lightlevel = lightlev;
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
if (!firstsize)
@ -1576,6 +1581,8 @@ void CL_SendCmd (double frametime)
dropcount = 0;
}
if (cl.sendprespawn)
buf.cursize = 0; //tastyspleen.net is alergic.
//
// deliver the message
//

View File

@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void CL_GetNumberedEntityInfo (int num, float *org, float *ang);
void CLNQ_ParseDarkPlaces5Entities(void);
void CL_SetStat (int pnum, int stat, int value);
void CL_SetStatInt (int pnum, int stat, int value);
int nq_dp_protocol;
int msgflags;
@ -725,6 +725,21 @@ int CL_LoadModels(int stage)
}
}
if (atstage())
{
cl.worldmodel = cl.model_precache[1];
if (!cl.worldmodel || cl.worldmodel->type == mod_dummy)
Host_EndGame("Worldmodel wasn't sent\n");
R_CheckSky();
CSQC_WorldLoaded();
endstage();
}
for (i=1 ; i<MAX_CSQCMODELS ; i++)
{
if (!cl.model_csqcname[i][0])
@ -740,16 +755,6 @@ int CL_LoadModels(int stage)
}
}
if (atstage())
{
cl.worldmodel = cl.model_precache[1];
if (!cl.worldmodel || cl.worldmodel->type == mod_dummy)
Host_EndGame("Worldmodel wasn't sent\n");
R_CheckSky();
endstage();
}
if (atstage())
{
Wad_NextDownload();
@ -2180,9 +2185,9 @@ void CLNQ_ParseClientdata (void)
bits |= (MSG_ReadByte() << 24);
if (bits & SU_VIEWHEIGHT)
CL_SetStat(0, STAT_VIEWHEIGHT, MSG_ReadChar ());
CL_SetStatInt(0, STAT_VIEWHEIGHT, MSG_ReadChar ());
else if (nq_dp_protocol < 6)
CL_SetStat(0, STAT_VIEWHEIGHT, DEFAULT_VIEWHEIGHT);
CL_SetStatInt(0, STAT_VIEWHEIGHT, DEFAULT_VIEWHEIGHT);
if (bits & SU_IDEALPITCH)
/*cl.idealpitch =*/ MSG_ReadChar ();
@ -2216,7 +2221,7 @@ void CLNQ_ParseClientdata (void)
}
if (bits & SU_ITEMS)
CL_SetStat(0, STAT_ITEMS, MSG_ReadLong());
CL_SetStatInt(0, STAT_ITEMS, MSG_ReadLong());
// cl.onground = (bits & SU_ONGROUND) != 0;
// cl.inwater = (bits & SU_INWATER) != 0;
@ -2226,37 +2231,37 @@ void CLNQ_ParseClientdata (void)
}
else if (nq_dp_protocol == 5)
{
CL_SetStat(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned short)MSG_ReadShort():0);
CL_SetStat(0, STAT_ARMOR, (bits & SU_ARMOR)?MSG_ReadShort():0);
CL_SetStat(0, STAT_WEAPON, (bits & SU_WEAPON)?MSG_ReadShort():0);
CL_SetStatInt(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned short)MSG_ReadShort():0);
CL_SetStatInt(0, STAT_ARMOR, (bits & SU_ARMOR)?MSG_ReadShort():0);
CL_SetStatInt(0, STAT_WEAPON, (bits & SU_WEAPON)?MSG_ReadShort():0);
CL_SetStat(0, STAT_HEALTH, MSG_ReadShort());
CL_SetStatInt(0, STAT_HEALTH, MSG_ReadShort());
CL_SetStat(0, STAT_AMMO, MSG_ReadShort());
CL_SetStatInt(0, STAT_AMMO, MSG_ReadShort());
CL_SetStat(0, STAT_SHELLS, MSG_ReadShort());
CL_SetStat(0, STAT_NAILS, MSG_ReadShort());
CL_SetStat(0, STAT_ROCKETS, MSG_ReadShort());
CL_SetStat(0, STAT_CELLS, MSG_ReadShort());
CL_SetStatInt(0, STAT_SHELLS, MSG_ReadShort());
CL_SetStatInt(0, STAT_NAILS, MSG_ReadShort());
CL_SetStatInt(0, STAT_ROCKETS, MSG_ReadShort());
CL_SetStatInt(0, STAT_CELLS, MSG_ReadShort());
CL_SetStat(0, STAT_ACTIVEWEAPON, (unsigned short)MSG_ReadShort());
CL_SetStatInt(0, STAT_ACTIVEWEAPON, (unsigned short)MSG_ReadShort());
}
else
{
CL_SetStat(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned char)MSG_ReadByte():0);
CL_SetStat(0, STAT_ARMOR, (bits & SU_ARMOR)?MSG_ReadByte():0);
CL_SetStat(0, STAT_WEAPON, (bits & SU_WEAPON)?MSG_ReadByte():0);
CL_SetStatInt(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned char)MSG_ReadByte():0);
CL_SetStatInt(0, STAT_ARMOR, (bits & SU_ARMOR)?MSG_ReadByte():0);
CL_SetStatInt(0, STAT_WEAPON, (bits & SU_WEAPON)?MSG_ReadByte():0);
CL_SetStat(0, STAT_HEALTH, MSG_ReadShort());
CL_SetStatInt(0, STAT_HEALTH, MSG_ReadShort());
CL_SetStat(0, STAT_AMMO, MSG_ReadByte());
CL_SetStatInt(0, STAT_AMMO, MSG_ReadByte());
CL_SetStat(0, STAT_SHELLS, MSG_ReadByte());
CL_SetStat(0, STAT_NAILS, MSG_ReadByte());
CL_SetStat(0, STAT_ROCKETS, MSG_ReadByte());
CL_SetStat(0, STAT_CELLS, MSG_ReadByte());
CL_SetStatInt(0, STAT_SHELLS, MSG_ReadByte());
CL_SetStatInt(0, STAT_NAILS, MSG_ReadByte());
CL_SetStatInt(0, STAT_ROCKETS, MSG_ReadByte());
CL_SetStatInt(0, STAT_CELLS, MSG_ReadByte());
CL_SetStat(0, STAT_ACTIVEWEAPON, MSG_ReadByte());
CL_SetStatInt(0, STAT_ACTIVEWEAPON, MSG_ReadByte());
}
if (bits & DPSU_VIEWZOOM)
@ -2267,10 +2272,10 @@ void CLNQ_ParseClientdata (void)
i = MSG_ReadByte();
if (i < 2)
i = 2;
CL_SetStat(0, STAT_VIEWZOOM, i);
CL_SetStatInt(0, STAT_VIEWZOOM, i);
}
else if (nq_dp_protocol < 6)
CL_SetStat(0, STAT_VIEWZOOM, 255);
CL_SetStatInt(0, STAT_VIEWZOOM, 255);
}
#endif
/*
@ -2613,11 +2618,10 @@ void CL_ParseBaseline2 (void)
void CLQ2_Precache_f (void)
{
cl.sendprespawn = true;
Sound_NextDownload();
#ifdef VM_CG
CG_Start();
#endif
CL_RequestNextDownload();
}
@ -3186,7 +3190,7 @@ static void CL_SetStat_Internal (int pnum, int stat, int value)
TP_StatChanged(stat, value);
}
void CL_SetStat (int pnum, int stat, int value)
void CL_SetStatInt (int pnum, int stat, int value)
{
if (stat < 0 || stat >= MAX_CL_STATS)
return;
@ -3213,7 +3217,46 @@ void CL_SetStat (int pnum, int stat, int value)
else
CL_SetStat_Internal(pnum, stat, value);
}
void CL_SetStatFloat (int pnum, int stat, float value)
{
if (stat < 0 || stat >= MAX_CL_STATS)
return;
// Host_EndGame ("CL_SetStat: %i is invalid", stat);
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
extern int cls_lastto;
cl.players[cls_lastto].statsf[stat]=value;
for (pnum = 0; pnum < cl.splitclients; pnum++)
if (spec_track[pnum] == cls_lastto)
cl.statsf[pnum][stat] = value;
}
else
cl.statsf[pnum][stat] = value;
}
void CL_SetStatString (int pnum, int stat, char *value)
{
if (stat < 0 || stat >= MAX_CL_STATS)
return;
// Host_EndGame ("CL_SetStat: %i is invalid", stat);
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
/* extern int cls_lastto;
cl.players[cls_lastto].statsstr[stat]=value;
for (pnum = 0; pnum < cl.splitclients; pnum++)
if (spec_track[pnum] == cls_lastto)
cl.statsstr[pnum][stat] = value;*/
}
else
{
if (cl.statsstr[pnum][stat])
Z_Free(cl.statsstr[pnum][stat]);
cl.statsstr[pnum][stat] = Z_Malloc(strlen(value));
}
}
/*
==============
CL_MuzzleFlash
@ -4059,6 +4102,7 @@ void CL_ParseServerMessage (void)
char *s;
int i, j;
int destsplit;
float f;
received_framecount = host_framecount;
cl.last_servermessage = realtime;
@ -4092,7 +4136,7 @@ void CL_ParseServerMessage (void)
cmd = MSG_ReadByte ();
if (cmd == svc_choosesplitclient)
if (cmd == svcfte_choosesplitclient)
{
SHOWNET(svc_strings[cmd]);
@ -4234,7 +4278,7 @@ void CL_ParseServerMessage (void)
cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
break;
#ifdef PEXT_LIGHTSTYLECOL
case svc_lightstylecol:
case svcfte_lightstylecol:
if (!(cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL))
Host_EndGame("PEXT_LIGHTSTYLECOL is meant to be disabled\n");
i = MSG_ReadByte ();
@ -4291,7 +4335,7 @@ void CL_ParseServerMessage (void)
Host_EndGame("CL_ParseServerMessage: svc_spawnbaseline failed with size %i", i);
CL_ParseBaseline (cl_baselines + i);
break;
case svc_spawnbaseline2:
case svcfte_spawnbaseline2:
CL_ParseBaseline2 ();
break;
case svc_spawnstatic:
@ -4307,20 +4351,20 @@ void CL_ParseServerMessage (void)
CL_ParseTEnt ();
#endif
break;
case svc_customtempent:
case svcfte_customtempent:
CL_ParseCustomTEnt();
break;
case svc_particle:
CLNQ_ParseParticleEffect ();
break;
case svc_particle2:
case svcfte_particle2:
CL_ParseParticleEffect2 ();
break;
case svc_particle3:
case svcfte_particle3:
CL_ParseParticleEffect3 ();
break;
case svc_particle4:
case svcfte_particle4:
CL_ParseParticleEffect4 ();
break;
@ -4335,12 +4379,26 @@ void CL_ParseServerMessage (void)
case svc_updatestat:
i = MSG_ReadByte ();
j = MSG_ReadByte ();
CL_SetStat (destsplit, i, j);
CL_SetStatInt (destsplit, i, j);
CL_SetStatFloat (destsplit, i, j);
break;
case svc_updatestatlong:
i = MSG_ReadByte ();
j = MSG_ReadLong (); //make qbyte if nq compatability?
CL_SetStat (destsplit, i, j);
CL_SetStatInt (destsplit, i, j);
CL_SetStatFloat (destsplit, i, j);
break;
case svcfte_updatestatstring:
i = MSG_ReadByte();
s = MSG_ReadString();
CL_SetStatString (destsplit, i, s);
break;
case svcfte_updatestatfloat:
i = MSG_ReadByte();
f = MSG_ReadFloat();
CL_SetStatInt (destsplit, i, f);
CL_SetStatFloat (destsplit, i, f);
break;
case svc_spawnstaticsound:
@ -4427,7 +4485,7 @@ void CL_ParseServerMessage (void)
case svc_modellist:
CL_ParseModellist (false);
break;
case svc_modellistshort:
case svcfte_modellistshort:
CL_ParseModellist (true);
break;
@ -4462,7 +4520,7 @@ void CL_ParseServerMessage (void)
break;
#ifdef PEXT_BULLETENS
case svc_bulletentext:
case svcfte_bulletentext:
if (!(cls.fteprotocolextensions & PEXT_BULLETENS))
Host_EndGame("PEXT_BULLETENS is meant to be disabled\n");
Bul_ParseMessage();
@ -4489,32 +4547,32 @@ void CL_ParseServerMessage (void)
break;
#endif
case svc_showpic:
case svcfte_showpic:
SCR_ShowPic_Create();
break;
case svc_hidepic:
case svcfte_hidepic:
SCR_ShowPic_Hide();
break;
case svc_movepic:
case svcfte_movepic:
SCR_ShowPic_Move();
break;
case svc_updatepic:
case svcfte_updatepic:
SCR_ShowPic_Update();
break;
case svcqw_effect:
case svcfte_effect:
CL_ParseEffect(false);
break;
case svcqw_effect2:
case svcfte_effect2:
CL_ParseEffect(true);
break;
#ifdef PEXT_CSQC
case svc_csqcentities:
case svcfte_csqcentities:
CSQC_ParseEntities();
break;
#endif
case svc_precache:
case svcfte_precache:
CL_ParsePrecache();
break;
}
@ -5062,12 +5120,14 @@ void CLNQ_ParseServerMessage (void)
case svc_updatestat:
i = MSG_ReadByte ();
j = MSG_ReadLong ();
CL_SetStat (0, i, j);
CL_SetStatInt (0, i, j);
CL_SetStatFloat (0, i, j);
break;
case svcdp_updatestatbyte:
i = MSG_ReadByte ();
j = MSG_ReadByte ();
CL_SetStat (0, i, j);
CL_SetStatInt (0, i, j);
CL_SetStatFloat (0, i, j);
break;
case svc_setangle:
for (i=0 ; i<3 ; i++)

View File

@ -164,6 +164,7 @@ typedef struct player_info_s
int prevcount;
int stats[MAX_CL_STATS];
int statsf[MAX_CL_STATS];
} player_info_t;
@ -456,6 +457,8 @@ typedef struct
// information for local display
int stats[MAX_SPLITS][MAX_CL_STATS]; // health, etc
float statsf[MAX_SPLITS][MAX_CL_STATS]; // health, etc
char *statsstr[MAX_SPLITS][MAX_CL_STATS]; // health, etc
float item_gettime[MAX_SPLITS][32]; // cl.time of aquiring item, for blinking
float faceanimtime[MAX_SPLITS]; // use anim frame if cl.time < this

View File

@ -1,5 +1,19 @@
#include "quakedef.h"
/*
EXT_CSQC is the 'root' extension
EXT_CSQC_1 are a collection of additional features to cover omissions in the original spec
note the CHEAT_PARANOID define disables certain EXT_CSQC_1 features,
in an attempt to prevent the player from finding out where he/she is, thus preventing aimbots.
This is specifically targetted towards deathmatch mods where each player is a single player.
In reality, this paranoia provides nothing which could not be done with a cheat proxy.
Seeing as the client ensures hashes match in the first place, this paranoia gives nothing in the long run.
Unfortunatly EXT_CSQC was designed around this paranoia.
*/
#ifdef CSQC_DAT
#ifdef RGLQUAKE
@ -7,8 +21,12 @@
#include "shader.h"
#endif
//#define CHEAT_PARANOID
#include "pr_common.h"
#define ANGLE2SHORT(x) ((x/360.0)*65535)
static progfuncs_t *csqcprogs;
typedef struct csqctreadstate_s {
@ -34,8 +52,8 @@ cvar_t cl_nocsqc = SCVAR("cl_nocsqc", "0");
cvar_t pr_csqc_coreonerror = SCVAR("pr_csqc_coreonerror", "1");
#define MASK_ENGINE 1
#define MASK_ENGINEVIEWMODEL 2
#define MASK_DELTA 1
#define MASK_STDVIEWMODEL 2
// standard effect cvars/sounds
@ -51,20 +69,25 @@ extern sfx_t *cl_sfx_r_exp3;
//If I do it like this, I'll never forget to register something...
#define csqcglobals \
globalfunction(init_function, "CSQC_Init"); \
globalfunction(worldloaded, "CSQC_WorldLoaded"); \
globalfunction(shutdown_function, "CSQC_Shutdown"); \
globalfunction(draw_function, "CSQC_UpdateView"); \
globalfunction(parse_stuffcmd, "CSQC_Parse_StuffCmd"); \
globalfunction(parse_centerprint, "CSQC_Parse_CenterPrint"); \
globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(console_command, "CSQC_ConsoleCommand"); \
\
globalfunction(ent_update, "CSQC_Ent_Update"); \
globalfunction(ent_remove, "CSQC_Ent_Remove"); \
globalfunction(delta_update, "CSQC_Delta_Update");/*EXT_CSQC_1*/ \
globalfunction(delta_remove, "CSQC_Delta_Remove");/*EXT_CSQC_1*/ \
\
globalfunction(serversound, "CSQC_ServerSound"); \
\
/*These are pointers to the csqc's globals.*/ \
globalfloat(time, "time"); /*float Written before entering most qc functions*/ \
globalfloat(simtime, "simtime"); /*float Written before entering most qc functions*/ \
globalentity(self, "self"); /*entity Written before entering most qc functions*/ \
globalentity(other, "other"); /*entity Written before entering most qc functions*/ \
\
@ -84,14 +107,15 @@ extern sfx_t *cl_sfx_r_exp3;
globalfloat(trace_plane_dist, "trace_plane_dist"); /*float written by traceline*/ \
globalentity(trace_ent, "trace_ent"); /*entity written by traceline*/ \
globalfloat(trace_surfaceflags, "trace_surfaceflags"); /*float written by traceline*/ \
globalfloat(trace_endcontents, "trace_endcontents"); /*float written by traceline*/ \
globalfloat(trace_endcontents, "trace_endcontents"); /*float written by traceline EXT_CSQC_1*/ \
\
globalfloat(clientcommandframe, "clientcommandframe"); /*float the next frame that will be sent*/ \
globalfloat(servercommandframe, "servercommandframe"); /*float the most recent frame received from the server*/ \
\
globalfloat(player_localentnum, "player_localentnum"); /*float the entity number of the local player*/ \
globalfloat(player_localnum, "player_localnum"); /*float the entity number of the local player*/ \
globalfloat(intermission, "intermission"); /*float set when the client receives svc_intermission*/ \
globalvector(view_angles, "view_angles"); /*float set to the view angles at the start of each new frame */ \
globalvector(view_angles, "view_angles"); /*float set to the view angles at the start of each new frame (EXT_CSQC_1)*/ \
\
globalvector(pmove_org, "pmove_org"); /*read/written by runplayerphysics*/ \
globalvector(pmove_vel, "pmove_vel"); /*read/written by runplayerphysics*/ \
@ -104,6 +128,10 @@ extern sfx_t *cl_sfx_r_exp3;
globalvector(input_angles, "input_angles"); /*vector filled by getinputstate, read by runplayerphysics*/ \
globalvector(input_movevalues, "input_movevalues"); /*vector filled by getinputstate, read by runplayerphysics*/ \
globalfloat(input_buttons, "input_buttons"); /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat(input_impulse, "input_impulse"); /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat(input_lightlevel, "input_lightlevel"); /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat(input_weapon, "input_weapon"); /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat(input_servertime, "input_servertime"); /*float filled by getinputstate, read by runplayerphysics*/ \
\
globalfloat(movevar_gravity, "movevar_gravity"); /*float obtained from the server*/ \
globalfloat(movevar_stopspeed, "movevar_stopspeed"); /*float obtained from the server*/ \
@ -156,9 +184,13 @@ static void CSQC_FindGlobals(void)
if (csqcg.time)
*csqcg.time = Sys_DoubleTime();
if (csqcg.simtime)
*csqcg.simtime = cl.servertime;
if (csqcg.player_localentnum)
*csqcg.player_localentnum = cl.playernum[plnum]+1;
if (csqcg.player_localnum)
*csqcg.player_localnum = cl.playernum[plnum];
if (csqcg.maxclients)
*csqcg.maxclients = MAX_CLIENTS;
@ -181,12 +213,12 @@ static void CSQC_FindGlobals(void)
fieldfloat(colormap); \
fieldfloat(flags); \
fieldfloat(frame); \
fieldfloat(frame2); \
fieldfloat(frame1time); \
fieldfloat(frame2time); \
fieldfloat(lerpfrac); \
fieldfloat(frame2); /*EXT_CSQC_1*/\
fieldfloat(frame1time); /*EXT_CSQC_1*/\
fieldfloat(frame2time); /*EXT_CSQC_1*/\
fieldfloat(lerpfrac); /*EXT_CSQC_1*/\
fieldfloat(renderflags);\
fieldfloat(forceshader);\
fieldfloat(forceshader);/*FTE_CSQC_SHADERS*/\
fieldfloat(dimension_hit); \
fieldfloat(dimension_solid); \
\
@ -264,6 +296,9 @@ static int maxcsqcentities;
static int csqcentsize;
static char *csqcmapentitydata;
static qboolean csqcmapentitydataloaded;
static model_t *CSQC_GetModelForIndex(int index);
static void CS_LinkEdict(csqcedict_t *ent, qboolean touchtriggers);
@ -844,14 +879,19 @@ static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_glob
}
}
if (mask & MASK_ENGINE && cl.worldmodel)
if (cl.worldmodel)
{
if (mask & MASK_ENGINEVIEWMODEL)
if (mask & MASK_STDVIEWMODEL)
{
CL_LinkViewModel ();
CL_LinkPlayers ();
CL_LinkPacketEntities ();
CL_LinkProjectiles ();
CL_UpdateTEnts ();
}
if (mask & MASK_DELTA)
{
CL_LinkPlayers ();
CL_LinkPacketEntities ();
CL_LinkProjectiles ();
CL_UpdateTEnts ();
}
}
}
@ -1107,6 +1147,108 @@ static void PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_global
}
}
static void PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
viewflags parametertype = G_FLOAT(OFS_PARM0);
float *r = G_VECTOR(OFS_RETURN);
r[0] = 0;
r[1] = 0;
r[2] = 0;
switch(parametertype)
{
case VF_FOV:
r[0] = r_refdef.fov_x;
r[1] = r_refdef.fov_y;
break;
case VF_FOVX:
*r = r_refdef.fov_x;
break;
case VF_FOVY:
*r = r_refdef.fov_y;
break;
case VF_ORIGIN:
#ifdef CHEAT_PARANOID
VectorClear(r);
#else
VectorCopy(r_refdef.vieworg, r);
#endif
break;
case VF_ORIGIN_Z:
case VF_ORIGIN_X:
case VF_ORIGIN_Y:
#ifdef CHEAT_PARANOID
*r = 0;
#else
*r = r_refdef.vieworg[parametertype-VF_ORIGIN_X];
#endif
break;
case VF_ANGLES:
VectorCopy(r_refdef.viewangles, r);
break;
case VF_ANGLES_X:
case VF_ANGLES_Y:
case VF_ANGLES_Z:
*r = r_refdef.viewangles[parametertype-VF_ANGLES_X];
break;
case VF_CARTESIAN_ANGLES:
Con_Printf(CON_WARNING "WARNING: CARTESIAN ANGLES ARE NOT YET SUPPORTED!\n");
break;
case VF_VIEWPORT:
r[0] = r_refdef.vrect.width;
r[1] = r_refdef.vrect.height;
break;
case VF_SIZE_X:
*r = r_refdef.vrect.width;
break;
case VF_SIZE_Y:
*r = r_refdef.vrect.height;
break;
case VF_SIZE:
r[0] = r_refdef.vrect.width;
r[1] = r_refdef.vrect.height;
break;
case VF_MIN_X:
*r = r_refdef.vrect.x;
break;
case VF_MIN_Y:
*r = r_refdef.vrect.y;
break;
case VF_MIN:
r[0] = r_refdef.vrect.x;
r[1] = r_refdef.vrect.y;
break;
case VF_DRAWWORLD:
*r = !(r_refdef.flags&Q2RDF_NOWORLDMODEL);;
break;
case VF_ENGINESBAR:
*r = csqc_drawsbar;
break;
case VF_DRAWCROSSHAIR:
*r = csqc_addcrosshair;
break;
case VF_PERSPECTIVE:
*r = r_refdef.useperspective;
break;
default:
Con_DPrintf("GetViewFlag: %i not recognised\n", parametertype);
break;
}
}
static void PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (cl.worldmodel)
@ -1441,11 +1583,17 @@ static void csqc_setmodel(progfuncs_t *prinst, csqcedict_t *ent, int modelindex)
ent->v->modelindex = modelindex;
if (modelindex < 0)
{
if (modelindex <= -MAX_MODELS)
return;
ent->v->model = PR_SetString(prinst, cl.model_csqcname[-modelindex]);
if (!cl.model_csqcprecache[-modelindex])
cl.model_csqcprecache[-modelindex] = Mod_ForName(cl.model_csqcname[-modelindex], false);
model = cl.model_csqcprecache[-modelindex];
}
else
{
if (modelindex >= MAX_MODELS)
return;
ent->v->model = PR_SetString(prinst, cl.model_name[modelindex]);
model = cl.model_precache[modelindex];
}
@ -1476,7 +1624,7 @@ static void PF_cs_SetModel(progfuncs_t *prinst, struct globalvars_s *pr_globals)
Q_strncpyz(cl.model_csqcname[-freei], modelname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now
modelindex = freei;
cl.model_csqcprecache[-freei] = Mod_ForName(cl.model_csqcname[-freei], false);
cl.model_csqcprecache[-freei] = NULL;
}
csqc_setmodel(prinst, ent, modelindex);
@ -1514,7 +1662,8 @@ static void PF_cs_PrecacheModel(progfuncs_t *prinst, struct globalvars_s *pr_glo
Q_strncpyz(cl.model_csqcname[-freei], modelname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now
modelindex = freei;
cl.model_csqcprecache[-freei] = Mod_ForName(cl.model_csqcname[-freei], false);
CL_CheckOrEnqueDownloadFile(modelname, modelname);
cl.model_csqcprecache[-freei] = NULL;
}
G_FLOAT(OFS_RETURN) = modelindex;
@ -1550,6 +1699,20 @@ static void PF_ReadShort(progfuncs_t *prinst, struct globalvars_s *pr_globals)
G_FLOAT(OFS_RETURN) = MSG_ReadShort();
}
static void PF_ReadEntityNum(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned short val;
val = MSG_ReadShort();
if (val & 0x8000)
{ //our protocol only supports 15bits of revelent entity number (16th bit is used as 'remove').
//so warn with badly coded mods.
Con_Printf("ReadEntityNumber read bad entity number\n");
G_FLOAT(OFS_RETURN) = 0;
}
else
G_FLOAT(OFS_RETURN) = val;
}
static void PF_ReadLong(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
G_FLOAT(OFS_RETURN) = MSG_ReadLong();
@ -1645,6 +1808,64 @@ static void PF_cs_particlesloaded (progfuncs_t *prinst, struct globalvars_s *pr_
G_FLOAT(OFS_RETURN) = P_DescriptionIsLoaded(effectname);
}
static void cs_set_input_state (usercmd_t *cmd)
{
if (csqcg.input_timelength)
*csqcg.input_timelength = cmd->msec/1000.0f;
if (csqcg.input_angles)
{
csqcg.input_angles[0] = SHORT2ANGLE(cmd->angles[0]+0.5);
csqcg.input_angles[1] = SHORT2ANGLE(cmd->angles[1]+0.5);
csqcg.input_angles[2] = SHORT2ANGLE(cmd->angles[2]+0.5);
}
if (csqcg.input_movevalues)
{
csqcg.input_movevalues[0] = cmd->forwardmove;
csqcg.input_movevalues[1] = cmd->sidemove;
csqcg.input_movevalues[2] = cmd->upmove;
}
if (csqcg.input_buttons)
*csqcg.input_buttons = cmd->buttons;
if (csqcg.input_impulse)
*csqcg.input_impulse = cmd->impulse;
if (csqcg.input_lightlevel)
*csqcg.input_lightlevel = cmd->lightlevel;
if (csqcg.input_weapon)
*csqcg.input_weapon = cmd->weapon;
if (csqcg.input_servertime)
*csqcg.input_servertime = cmd->servertime/1000.0f;
}
static void cs_get_input_state (usercmd_t *cmd)
{
if (csqcg.input_timelength)
cmd->msec = *csqcg.input_timelength*1000;
if (csqcg.input_angles)
{
cmd->angles[0] = ANGLE2SHORT(csqcg.input_angles[0]);
cmd->angles[1] = ANGLE2SHORT(csqcg.input_angles[1]);
cmd->angles[2] = ANGLE2SHORT(csqcg.input_angles[2]);
}
if (csqcg.input_movevalues)
{
cmd->forwardmove = csqcg.input_movevalues[0];
cmd->sidemove = csqcg.input_movevalues[1];
cmd->upmove = csqcg.input_movevalues[2];
}
if (csqcg.input_buttons)
cmd->buttons = *csqcg.input_buttons;
if (csqcg.input_impulse)
cmd->impulse = *csqcg.input_impulse;
if (csqcg.input_lightlevel)
cmd->lightlevel = *csqcg.input_lightlevel;
if (csqcg.input_weapon)
cmd->weapon = *csqcg.input_weapon;
if (csqcg.input_servertime)
cmd->servertime = *csqcg.input_servertime*1000;
}
//get the input commands, and stuff them into some globals.
static void PF_cs_getinputstate (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -1666,26 +1887,11 @@ static void PF_cs_getinputstate (progfuncs_t *prinst, struct globalvars_s *pr_gl
// save this command off for prediction
cmd = &cl.frames[f&UPDATE_MASK].cmd[plnum];
if (csqcg.input_timelength)
*csqcg.input_timelength = cmd->msec/1000.0f;
if (csqcg.input_angles)
{
csqcg.input_angles[0] = SHORT2ANGLE(cmd->angles[0]+0.5);
csqcg.input_angles[1] = SHORT2ANGLE(cmd->angles[1]+0.5);
csqcg.input_angles[2] = SHORT2ANGLE(cmd->angles[2]+0.5);
}
if (csqcg.input_movevalues)
{
csqcg.input_movevalues[0] = cmd->forwardmove;
csqcg.input_movevalues[1] = cmd->sidemove;
csqcg.input_movevalues[2] = cmd->upmove;
}
if (csqcg.input_buttons)
*csqcg.input_buttons = cmd->buttons;
cs_set_input_state(cmd);
G_FLOAT(OFS_RETURN) = true;
}
#define ANGLE2SHORT(x) ((x/360.0)*65535)
//read lots of globals, run the default player physics, write lots of globals.
static void PF_cs_runplayerphysics (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -1796,6 +2002,20 @@ typedef struct {
VectorCopy(pmove.velocity, csqcg.pmove_vel);
}
static void PF_cs_getentitytoken (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (!csqcmapentitydata)
{
//nothing more to parse
G_INT(OFS_RETURN) = 0;
}
else
{
csqcmapentitydata = COM_ParseToken(csqcmapentitydata, "{}()\'\":,");
RETURN_TSTRING(com_token);
}
}
static void CheckSendPings(void)
{ //quakeworld sends a 'pings' client command to retrieve the frequently updating stuff
if (realtime - cl.last_ping_request > 2)
@ -2991,6 +3211,188 @@ static void PF_cs_setlistener (progfuncs_t *prinst, struct globalvars_s *pr_glob
S_Update(origin, forward, right, up);
}
typedef struct oldcsqcpack_s
{
unsigned int numents;
unsigned int maxents;
unsigned short *entnum;
csqcedict_t **entptr;
} oldcsqcpack_t;
static oldcsqcpack_t loadedcsqcpack[2];
static int loadedcsqcpacknum;
#define RSES_NOLERP 1
#define RSES_AUTOROTATE 2
packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp);
static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//read the arguments the csqc gave us
unsigned int flags = G_FLOAT(OFS_PARM0);
float servertime = G_FLOAT(OFS_PARM1);
//locals
packet_entities_t *pack;
csqcedict_t *ent;
entity_state_t *src;
unsigned int i;
lerpents_t *le;
csqcedict_t *oldent;
oldcsqcpack_t *oldlist, *newlist;
int oldidx = 0, newidx = 0;
model_t *model;
//setup
servertime += cl.servertime;
pack = CL_ProcessPacketEntities(&servertime, (flags & RSES_NOLERP));
if (!pack)
return; //can't do anything, just don't update
oldlist = &loadedcsqcpack[loadedcsqcpacknum];
loadedcsqcpacknum ^= 1;
newlist = &loadedcsqcpack[loadedcsqcpacknum];
newlist->numents = 0;
for (i = 0; i < pack->num_entities; i++)
{
src = &pack->entities[i];
// CL_LinkPacketEntities
#ifndef _MSC_VER
#warning what to do here?
#endif
// if (csqcent[src->number])
// continue; //don't add the entity if we have one sent specially via csqc protocols.
if (oldidx == oldlist->numents)
{ //reached the end of the old frame's ents
oldent = NULL;
}
else
{
while (oldidx < oldlist->numents && oldlist->entnum[oldidx] < src->number)
{
//this entity is stale, remove it.
oldent = oldlist->entptr[oldidx];
*csqcg.self = EDICT_TO_PROG(prinst, (void*)oldent);
PR_ExecuteProgram(prinst, csqcg.delta_remove);
oldidx++;
}
if (src->number < oldlist->entnum[oldidx])
oldent = NULL;
else
{
oldent = oldlist->entptr[oldidx];
oldidx++;
}
}
//note: we don't delta the state here. we just replace the old.
//its already lerped
if (oldent)
ent = oldent;
else
ent = (csqcedict_t *)ED_Alloc(prinst);
le = &cl.lerpents[src->number];
//frames needs special handling
ent->v->frame = src->frame;
ent->v->frame2 = le->frame;
if (le->framechange == le->oldframechange)
ent->v->lerpfrac = 0;
else
{
ent->v->lerpfrac = 1-(servertime - le->framechange) / (le->framechange - le->oldframechange);
if (ent->v->lerpfrac > 1)
ent->v->lerpfrac = 1;
else if (ent->v->lerpfrac < 0)
{
ent->v->lerpfrac = 0;
}
}
ent->v->entnum = src->number;
ent->v->modelindex = src->modelindex;
model = cl.model_precache[src->modelindex];
// ent->v->bitmask = src->bitmask;
ent->v->flags = src->flags;
// ent->v->effects = src->effects;
ent->v->origin[0] = src->origin[0];
ent->v->origin[1] = src->origin[1];
ent->v->origin[2] = src->origin[2];
ent->v->angles[0] = src->angles[0];
ent->v->angles[1] = src->angles[1];
ent->v->angles[2] = src->angles[2];
//we ignore the q2 state fields
ent->v->colormap = src->colormap;
ent->v->skin = src->skinnum;
// ent->v->glowsize = src->glowsize;
// ent->v->glowcolor = src->glowcolour;
ent->v->scale = src->scale/16.0f;
ent->v->fatness = src->fatness/16.0f;
// ent->v->hexen2flags = src->hexen2flags;
// ent->v->abslight = src->abslight;
// ent->v->dpflags = src->dpflags;
// ent->v->colormod[0] = (src->colormod[0]/255.0f)*8;
// ent->v->colormod[1] = (src->colormod[1]/255.0f)*8;
// ent->v->colormod[2] = (src->colormod[2]/255.0f)*8;
ent->v->alpha = src->trans/255.0f;
// ent->v->lightstyle = src->lightstyle;
// ent->v->lightpflags = src->lightpflags;
// ent->v->solid = src->solid;
// ent->v->light[0] = src->light[0];
// ent->v->light[1] = src->light[1];
// ent->v->light[2] = src->light[2];
// ent->v->light[3] = src->light[3];
// ent->v->tagentity = src->tagentity;
// ent->v->tagindex = src->tagindex;
if (model)
{
if (model->flags & EF_ROTATE)
{
ent->v->angles[0] = 0;
ent->v->angles[1] = 100*servertime;
ent->v->angles[2] = 0;
}
}
if (csqcg.delta_update)
{
*csqcg.self = EDICT_TO_PROG(prinst, (void*)ent);
G_FLOAT(OFS_PARM0) = !oldent;
PR_ExecuteProgram(prinst, csqcg.delta_update);
}
if (newlist->maxents <= newidx)
{
newlist->maxents = newidx + 64;
newlist->entptr = BZ_Realloc(newlist->entptr, sizeof(*newlist->entptr)*newlist->maxents);
newlist->entnum = BZ_Realloc(newlist->entnum, sizeof(*newlist->entnum)*newlist->maxents);
}
newlist->entptr[newidx] = ent;
newlist->entnum[newidx] = src->number;
newidx++;
}
//remove any unreferenced ents stuck on the end
while (oldidx < oldlist->numents)
{
oldent = oldlist->entptr[oldidx];
*csqcg.self = EDICT_TO_PROG(prinst, (void*)oldent);
PR_ExecuteProgram(prinst, csqcg.delta_remove);
oldidx++;
}
newlist->numents = newidx;
}
#define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme
//prefixes:
@ -3271,7 +3673,7 @@ PF_R_PolygonBegin, // #306 void(string texturename) R_BeginPolygon (EXT_CSQC_
PF_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex (EXT_CSQC_???)
PF_R_PolygonEnd, // #308 void() R_EndPolygon (EXT_CSQC_???)
PF_Fixme, // #309
PF_R_GetViewFlag, // #309 vector/float(float property) getproperty (EXT_CSQC_1)
//310
//maths stuff that uses the current view settings.
@ -3339,7 +3741,7 @@ PF_cs_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC)
PF_WasFreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
PF_cs_serverkey, // #354 string(string key) serverkey;
PF_Fixme, // #355
PF_cs_getentitytoken, // #355 string() getentitytoken;
PF_Fixme, // #356
PF_Fixme, // #357
PF_Fixme, // #358
@ -3357,8 +3759,8 @@ PF_ReadAngle, // #365 float() readangle (EXT_CSQC)
PF_ReadString, // #366 string() readstring (EXT_CSQC)
PF_ReadFloat, // #367 string() readfloat (EXT_CSQC)
PF_Fixme, // #368
PF_Fixme, // #369
PF_ReadEntityNum, // #368 float() readentitynum (EXT_CSQC)
PF_ReadServerEntityState, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1)
//370
PF_FixTen,
@ -3622,6 +4024,8 @@ int CSQC_PRFileSize (char *path)
double csqctime;
qboolean CSQC_Init (unsigned int checksum)
{
int i;
csqcedict_t *worldent;
csqcchecksum = checksum;
CSQC_Shutdown();
@ -3677,6 +4081,7 @@ qboolean CSQC_Init (unsigned int checksum)
if (!csqcprogs)
{
in_sensitivityscale = 1;
csqcmapentitydataloaded = true;
csqcprogs = InitProgs(&csqcprogparms);
PR_Configure(csqcprogs, -1, 16);
@ -3707,11 +4112,32 @@ qboolean CSQC_Init (unsigned int checksum)
ED_Alloc(csqcprogs); //we need a word entity.
//world edict becomes readonly
EDICT_NUM(csqcprogs, 0)->readonly = true;
EDICT_NUM(csqcprogs, 0)->isfree = false;
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->readonly = true;
worldent->isfree = false;
worldent->v->model = PR_SetString(csqcprogs, cl.model_name[1]);
for (i = 0; i < 2; i++)
{
loadedcsqcpack[i].numents = 0;
loadedcsqcpack[i].maxents = 0;
Z_Free(loadedcsqcpack[i].entptr);
loadedcsqcpack[i].entptr = NULL;
Z_Free(loadedcsqcpack[i].entnum);
loadedcsqcpack[i].entnum = NULL;
}
csqcmapentitydata = NULL;
csqcmapentitydataloaded = false;
if (csqcg.init_function)
{
void *pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = 1.0; //api version
(((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, FULLENGINENAME));
G_FLOAT(OFS_PARM2) = build_number();
PR_ExecuteProgram(csqcprogs, csqcg.init_function);
}
Con_Printf("Loaded csqc\n");
}
@ -3719,6 +4145,19 @@ qboolean CSQC_Init (unsigned int checksum)
return true; //success!
}
void CSQC_WorldLoaded(void)
{
if (!csqcprogs)
return;
if (csqcmapentitydataloaded)
return;
csqcmapentitydataloaded = true;
csqcmapentitydata = cl.worldmodel->entities;
if (csqcg.worldloaded)
PR_ExecuteProgram(csqcprogs, csqcg.worldloaded);
csqcmapentitydata = NULL;
}
void CSQC_CoreDump(void)
{
if (!csqcprogs)
@ -3781,6 +4220,13 @@ qboolean CSQC_DrawView(void)
CSQC_RunThreads(); //wake up any qc threads
//EXT_CSQC_1
{
void *pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = vid.width;
G_FLOAT(OFS_PARM1) = vid.height;
}
//end EXT_CSQC_1
PR_ExecuteProgram(csqcprogs, csqcg.draw_function);
return true;
@ -3857,6 +4303,21 @@ qboolean CSQC_CenterPrint(char *cmd)
return G_FLOAT(OFS_RETURN);
}
void CSQC_Input_Frame(usercmd_t *cmd)
{
if (!csqcprogs || !csqcg.input_frame)
return;
if (csqcg.time)
*csqcg.time = Sys_DoubleTime();
if (csqcg.clientcommandframe)
*csqcg.clientcommandframe = cls.netchan.outgoing_sequence;
cs_set_input_state(cmd);
PR_ExecuteProgram (csqcprogs, csqcg.input_frame);
cs_get_input_state(cmd);
}
//this protocol allows up to 32767 edicts.
#ifdef PEXT_CSQC
void CSQC_EntityCheck(int entnum)
@ -3867,7 +4328,7 @@ void CSQC_EntityCheck(int entnum)
{
newmax = entnum+64;
csqcent = BZ_Realloc(csqcent, sizeof(*csqcent)*newmax);
memset(csqcent + maxcsqcentities, 0, newmax - maxcsqcentities);
memset(csqcent + maxcsqcentities, 0, (newmax - maxcsqcentities)*sizeof(csqcent));
maxcsqcentities = newmax;
}
}

View File

@ -615,3 +615,4 @@ int i;
}
}

View File

@ -1526,7 +1526,7 @@ char *TP_LocationName (vec3_t location)
}
recursive = true;
Cmd_ExpandString (locdata[minnum].name, buf, sizeof(buf), Cmd_ExecLevel, false);
Cmd_ExpandString (locdata[minnum].name, buf, sizeof(buf), Cmd_ExecLevel, true, false);
recursive = false;
return buf;
@ -3217,7 +3217,7 @@ void CL_Say (qboolean team, char *extra)
!strchr(s, '\x0d') /* explicit $\ in message overrides cl_fakename */)
{
char buf[1024];
Cmd_ExpandString (cl_fakename.string, buf, sizeof(buf), Cmd_ExecLevel, true);
Cmd_ExpandString (cl_fakename.string, buf, sizeof(buf), Cmd_ExecLevel, true, true);
strcpy (buf, TP_ParseMacroString (buf));
Q_snprintfz (sendtext, sizeof(sendtext), "\x0d%s: ", TP_ParseFunChars(buf, true));
}

View File

@ -1150,7 +1150,7 @@ If not SERVERONLY, also expands $macro expressions
Note: dest must point to a 1024 byte buffer
================
*/
char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel, qboolean expandmacros)
char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel, qboolean expandcvars, qboolean expandmacros)
{
unsigned int c;
char buf[255];
@ -1341,7 +1341,7 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
while (1)
{
// skip whitespace up to a /n
// skip whitespace up to a \n
while (*text && (unsigned)*text <= ' ' && *text != '\n')
{
text++;
@ -1838,7 +1838,7 @@ void Cmd_ExecuteString (char *text, int level)
Cmd_ExecLevel = level;
text = Cmd_ExpandString(text, dest, sizeof(dest), level, !Cmd_IsInsecure()?true:false);
text = Cmd_ExpandString(text, dest, sizeof(dest), level, !Cmd_IsInsecure()?true:false, true);
Cmd_TokenizeString (text, level == RESTRICT_LOCAL?true:false, false);
// execute the command line

View File

@ -141,7 +141,7 @@ void Cmd_MessageTrigger (char *message, int type);
void Cmd_ShiftArgs (int ammount, qboolean expandstring);
char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel, qboolean expandmacros);
char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel, qboolean expandcvars, qboolean expandmacros);
extern cvar_t rcon_level;

View File

@ -18,6 +18,7 @@
extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models;
extern cvar_t r_noaliasshadows;
extern cvar_t r_skin_overlays;
extern cvar_t mod_md3flags;
@ -1097,6 +1098,10 @@ void Mod_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber,
#endif
texnum->base = Mod_LoadHiResTexture(shadername, "models", true, true, true);
//13/4/08 IMPLEMENTME
texnum->loweroverlay = 0;
texnum->upperoverlay = 0;
}
#endif
@ -1439,6 +1444,18 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha)
texnums->fullbright = fbtexture;
texnums->bump = bumptexture;
//13/4/08 IMPLEMENTME
if (r_skin_overlays.value)
{
snprintf(skinname, sizeof(skinname), "%s_%i", loadname, i);
texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha);
}
else
{
texnums->loweroverlay = 0;
texnums->upperoverlay = 0;
}
pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s);
break;
@ -1524,6 +1541,10 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha)
texnums->base = texture;
texnums->fullbright = fbtexture;
//13/4/08 IMPLEMENTME
texnums->loweroverlay = 0;
texnums->upperoverlay = 0;
}
pskintype = (daliasskintype_t *)data;
break;
@ -2653,6 +2674,10 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
}
#endif
//13/4/08 IMPLEMENTME
texnum->loweroverlay = 0;
texnum->upperoverlay = 0;
inshader++;
skin++;
texnum++;

View File

@ -102,6 +102,8 @@ typedef struct {
int base;
int bump;
int fullbright;
int upperoverlay;
int loweroverlay;
#ifdef Q3SHADERS
shader_t *shader;

View File

@ -1046,6 +1046,9 @@ void *Mod_LoadWall(char *name)
COM_FileBase(name, ln, sizeof(ln));
if (!CL_CheckOrEnqueDownloadFile(name, NULL))
return NULL;
wal = (void *)COM_LoadMallocFile (name);
if (!wal)
return NULL;

View File

@ -207,49 +207,52 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//FTE extended svcs
#ifdef PEXT_VIEW2
#define svc_view2 56
//#define svcfte_view2 56
#endif
#ifdef PEXT_LIGHTSTYLECOL
#define svc_lightstylecol 57
#define svcfte_lightstylecol 57
#endif
#ifdef PEXT_BULLETENS
#define svc_bulletentext 58
#define svcfte_bulletentext 58
#endif
#ifdef PEXT_LIGHTUPDATES
#define svc_lightnings 59
#define svcfte_lightnings 59
#endif
#ifdef PEXT_MODELDBL
#define svc_modellistshort 60 // [strings]
#define svcfte_modellistshort 60 // [strings]
#endif
#define svc_ftesetclientpersist 61 //ushort DATA
#define svc_setportalstate 62
#define svc_particle2 63
#define svc_particle3 64
#define svc_particle4 65
#define svc_spawnbaseline2 66
#define svcfte_particle2 63
#define svcfte_particle3 64
#define svcfte_particle4 65
#define svcfte_spawnbaseline2 66
#define svc_customtempent 67
#define svcfte_customtempent 67
#define svc_choosesplitclient 68
#define svc_showpic 69
#define svc_hidepic 70
#define svc_movepic 71
#define svc_updatepic 72
#define svcfte_choosesplitclient 68
#define svcfte_showpic 69
#define svcfte_hidepic 70
#define svcfte_movepic 71
#define svcfte_updatepic 72
#define svcqw_effect 74 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
#define svcqw_effect2 75 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
#define svcfte_effect 74 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
#define svcfte_effect2 75 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
#ifdef PEXT_CSQC
#define svc_csqcentities 76 //entity lump for csqc
#define svcfte_csqcentities 76 //entity lump for csqc
#endif
#define svc_precache 77
#define svcfte_precache 77
#define svcfte_updatestatstring 78
#define svcfte_updatestatfloat 79
//DP extended svcs

View File

@ -162,6 +162,13 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
while (Q1_HullPointContents (hull, hull->firstclipnode, mid)
== Q1CONTENTS_SOLID)
{ // shouldn't really happen, but does occasionally
if (!(frac < 10000000) && !(frac > -10000000))
{
trace->fraction = 0;
VectorClear (trace->endpos);
Con_Printf ("nan in traceline\n");
return false;
}
frac -= 0.1;
if (frac < 0)
{

View File

@ -421,6 +421,7 @@ qvm_t *QVM_Load(const char *name, sys_callqvm_t syscall)
// check file
if(header->vmMagic!=VM_MAGIC || header->instructionCount<=0 || header->codeLength<=0)
{
Con_Printf("%s: invalid qvm file\n", name);
BZ_Free(raw);
return NULL;
}

View File

@ -15,30 +15,24 @@
#include "quakedef.h"
#ifdef RGLQUAKE
#include "glquake.h"
#include "glquake.h"
#endif
#if defined(RGLQUAKE) || defined(SERVERONLY)
#include "shader.h"
#include "hash.h"
#if defined(ZYMOTICMODELS) || defined(MD5MODELS)
#define SKELETALMODELS
#include <stdlib.h>
#endif
#ifdef _WIN32
#include <malloc.h>
#include <malloc.h>
#else
#include <alloca.h>
#include <alloca.h>
#endif
#define MAX_BONES 256
#ifndef SERVERONLY
static model_t *loadmodel;
static model_t *loadmodel;
#endif
#include "com_mesh.h"
//FIXME
typedef struct
{
@ -97,113 +91,7 @@ vec3_t *tempNormals;
extern cvar_t gl_ati_truform;
extern cvar_t r_vertexdlights;
extern cvar_t mod_md3flags;
typedef struct {
int ofs_indexes;
int numindexes;
int ofs_trineighbours;
int numskins;
#ifndef SERVERONLY
int ofsskins;
#endif
qboolean sharesverts; //used with models with two shaders using the same vertex - use last mesh's verts
qboolean sharesbones; //use last mesh's bones (please, never set this on the first mesh!)
int numverts;
#ifndef SERVERONLY
int ofs_st_array;
#endif
int groups;
int groupofs;
int nextsurf;
#ifdef SKELETALMODELS
int numbones;
int ofsbones;
int numtransforms;
int ofstransforms;
#endif
//these exist only in the root mesh.
int numtagframes;
int numtags;
int ofstags;
} galiasinfo_t;
//frame is an index into this
typedef struct {
#ifdef SKELETALMODELS
qboolean isheirachical; //for models with transforms, states that bones need to be transformed from their parent.
//this is actually bad, and can result in bones shortening as they interpolate.
#endif
qboolean loop;
int numposes;
float rate;
int poseofs;
char name[64];
} galiasgroup_t;
typedef struct {
int ofsverts;
#ifndef SERVERONLY
int ofsnormals;
#endif
vec3_t scale;
vec3_t scale_origin;
} galiaspose_t;
#ifdef SKELETALMODELS
typedef struct {
char name[32];
int parent;
} galiasbone_t;
typedef struct {
//skeletal poses refer to this.
int vertexindex;
int boneindex;
vec4_t org;
} galisskeletaltransforms_t;
#endif
//we can't be bothered with animating skins.
//We'll load up to four of them but after that you're on your own
#ifndef SERVERONLY
typedef struct {
int skinwidth;
int skinheight;
int ofstexels; //this is 8bit for frame 0 only. only valid in q1 models without replacement textures, used for colourising player skins.
float skinspeed;
int texnums;
int ofstexnums;
char name [MAX_QPATH];
} galiasskin_t;
typedef struct {
int base;
int bump;
int fullbright;
#ifdef Q3SHADERS
shader_t *shader;
#endif
} galiastexnum_t;
typedef struct {
char name[MAX_QPATH];
galiastexnum_t texnum;
int colour;
int skinnum;
bucket_t bucket;
} galiascolourmapped_t;
#endif
extern cvar_t r_skin_overlays;
#ifdef SKELETALMODELS
static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, float bonepose[MAX_BONES][12]);
@ -1039,7 +927,9 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur
char hashname[512];
cc = (tc<<4)|bc;
if (forced)
// if (e->scoreboard->skin->cachedbpp
/* if (cls.protocol == CP_QUAKE2)
{
if (e->scoreboard && e->scoreboard->skin)
snprintf(hashname, sizeof(hashname), "%s$%s$%i", modelname, e->scoreboard->skin->name, surfnum);
@ -1047,7 +937,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur
snprintf(hashname, sizeof(hashname), "%s$%i", modelname, surfnum);
skinname = hashname;
}
else
else */
{
if (e->scoreboard && e->scoreboard->skin)
{
@ -2090,6 +1980,20 @@ void R_DrawGAliasModel (entity_t *e)
// else
GL_DrawAliasMesh(&mesh, skin->base);
if (skin->loweroverlay && r_skin_overlays.value)
{
qglEnable(GL_BLEND);
qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]);
c_alias_polys += mesh.numindexes/3;
GL_DrawAliasMesh(&mesh, skin->loweroverlay);
}
if (skin->upperoverlay && r_skin_overlays.value)
{
qglEnable(GL_BLEND);
qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]);
c_alias_polys += mesh.numindexes/3;
GL_DrawAliasMesh(&mesh, skin->upperoverlay);
}
if (skin->fullbright && r_fb_models.value && cls.allow_luma)
{
mesh.colors_array = NULL;

View File

@ -1222,6 +1222,7 @@ BOOL bSetupPixelFormat(HDC hDC)
if (SetPixelFormat(hDC, pixelformat, &pfd))
{
TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n"));
DescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd);
FixPaletteInDescriptor(hDC, &pfd);
gl_canstencil = pfd.cStencilBits;
return TRUE;

View File

@ -136,13 +136,13 @@ void NPP_NQFlush(void)
break;
case svcdp_hidelmp:
requireextension = PEXT_SHOWPIC;
buffer[0] = svc_hidepic;
buffer[0] = svcfte_hidepic;
break;
case svcdp_showlmp:
requireextension = PEXT_SHOWPIC;
memmove(buffer+2, buffer+1, bufferlen-1);
bufferlen++;
buffer[0] = svc_showpic;
buffer[0] = svcfte_showpic;
buffer[1] = 0; //top left
//pad the bytes to shorts.
buffer[bufferlen] = buffer[bufferlen-1];

View File

@ -2001,7 +2001,7 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m)
if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, m);
#ifdef NQPROT
@ -2264,7 +2264,7 @@ void PF_centerprint (progfuncs_t *prinst, struct globalvars_s *pr_globals)
}
sp = cl->controller;
ClientReliableWrite_Begin (sp, svc_choosesplitclient, 4 + slen);
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 4 + slen);
ClientReliableWrite_Byte (sp, pnum);
ClientReliableWrite_Byte (sp, svc_centerprint);
ClientReliableWrite_String (sp, s);
@ -2620,7 +2620,7 @@ static void PF_particle2 (progfuncs_t *prinst, globalvars_t *pr_globals)
effect = G_FLOAT(OFS_PARM4);
count = G_FLOAT(OFS_PARM5);
MSG_WriteByte (&sv.multicast, svc_particle2);
MSG_WriteByte (&sv.multicast, svcfte_particle2);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
@ -2659,7 +2659,7 @@ static void PF_particle3 (progfuncs_t *prinst, globalvars_t *pr_globals)
effect = G_FLOAT(OFS_PARM3);
count = G_FLOAT(OFS_PARM4);
MSG_WriteByte (&sv.multicast, svc_particle3);
MSG_WriteByte (&sv.multicast, svcfte_particle3);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
@ -2695,7 +2695,7 @@ static void PF_particle4 (progfuncs_t *prinst, globalvars_t *pr_globals)
effect = G_FLOAT(OFS_PARM3);
count = G_FLOAT(OFS_PARM4);
MSG_WriteByte (&sv.multicast, svc_particle4);
MSG_WriteByte (&sv.multicast, svcfte_particle4);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
@ -3247,7 +3247,7 @@ void PF_stuffcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals)
}
sp = cl->controller;
ClientReliableWrite_Begin (sp, svc_choosesplitclient, 4 + slen);
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 4 + slen);
ClientReliableWrite_Byte (sp, pnum);
ClientReliableWrite_Byte (sp, svc_stufftext);
ClientReliableWrite_String (sp, str);
@ -3744,7 +3744,7 @@ void PF_precache_sound_Internal (progfuncs_t *prinst, char *s)
if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i+32768);
MSG_WriteString(&sv.reliable_datagram, s);
#ifdef NQPROT
@ -3802,7 +3802,7 @@ void PF_precache_model_Internal (progfuncs_t *prinst, char *s)
if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, s);
#ifdef NQPROT
@ -4049,7 +4049,7 @@ void PF_applylightstyle(int style, char *val, int col)
#ifdef PEXT_LIGHTSTYLECOL
if ((client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && col!=7)
{
ClientReliableWrite_Begin (client, svc_lightstylecol, strlen(val)+4);
ClientReliableWrite_Begin (client, svcfte_lightstylecol, strlen(val)+4);
ClientReliableWrite_Byte (client, style);
ClientReliableWrite_Char (client, col);
ClientReliableWrite_String (client, val);
@ -5537,7 +5537,7 @@ void PF_bulleten (progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (client->fteprotocolextensions & PEXT_BULLETENS)
{
ClientReliableCheckBlock(client, msglen+1);
ClientReliableWrite_Byte(client, svc_bulletentext);
ClientReliableWrite_Byte(client, svcfte_bulletentext);
ClientReliableWrite_Byte(client, board);
ClientReliableWrite_String(client, msg);
}
@ -8501,7 +8501,7 @@ void PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (type < 0 || type >= 255)
return;
MSG_WriteByte(&sv.multicast, svc_customtempent);
MSG_WriteByte(&sv.multicast, svcfte_customtempent);
MSG_WriteByte(&sv.multicast, type);
MSG_WriteCoord(&sv.multicast, org[0]);
MSG_WriteCoord(&sv.multicast, org[1]);
@ -9148,7 +9148,7 @@ static void PF_effect(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (startframe>255 || index>255)
{
MSG_WriteByte (&sv.multicast, svcqw_effect2);
MSG_WriteByte (&sv.multicast, svcfte_effect2);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
@ -9170,7 +9170,7 @@ static void PF_effect(progfuncs_t *prinst, struct globalvars_s *pr_globals)
}
else
{
MSG_WriteByte (&sv.multicast, svcqw_effect);
MSG_WriteByte (&sv.multicast, svcfte_effect);
MSG_WriteCoord (&sv.multicast, org[0]);
MSG_WriteCoord (&sv.multicast, org[1]);
MSG_WriteCoord (&sv.multicast, org[2]);
@ -9314,7 +9314,7 @@ static client_t *DirectSplit(client_t *cl, int svc, int svclen)
}
sp = cl->controller;
ClientReliableWrite_Begin (sp, svc_choosesplitclient, 2+svclen);
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 2+svclen);
ClientReliableWrite_Byte (sp, pnum);
ClientReliableWrite_Byte (sp, svc);
return sp;
@ -9362,7 +9362,7 @@ void PF_ShowPic(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh.
cl = DirectSplit(&svs.clients[entnum], svc_showpic, 8 + strlen(slot)+strlen(picname));
cl = DirectSplit(&svs.clients[entnum], svcfte_showpic, 8 + strlen(slot)+strlen(picname));
ClientReliableWrite_Byte(cl, zone);
ClientReliableWrite_String(cl, slot);
ClientReliableWrite_String(cl, picname);
@ -9395,7 +9395,7 @@ void PF_HidePic(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh.
cl = DirectSplit(&svs.clients[entnum], svc_hidepic, 2 + strlen(slot));
cl = DirectSplit(&svs.clients[entnum], svcfte_hidepic, 2 + strlen(slot));
ClientReliableWrite_String(cl, slot);
}
else
@ -9430,7 +9430,7 @@ void PF_MovePic(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh.
cl = DirectSplit(&svs.clients[entnum], svc_movepic, 6 + strlen(slot));
cl = DirectSplit(&svs.clients[entnum], svcfte_movepic, 6 + strlen(slot));
ClientReliableWrite_String(cl, slot);
ClientReliableWrite_Byte(cl, zone);
ClientReliableWrite_Short(cl, x);
@ -9463,7 +9463,7 @@ void PF_ChangePic(progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh.
cl = DirectSplit(&svs.clients[entnum], svc_updatepic, 3 + strlen(slot)+strlen(newpic));
cl = DirectSplit(&svs.clients[entnum], svcfte_updatepic, 3 + strlen(slot)+strlen(newpic));
ClientReliableWrite_String(cl, slot);
ClientReliableWrite_String(cl, newpic);
}
@ -10766,6 +10766,7 @@ void PR_RegisterFields(void) //it's just easier to do it this way.
fieldxfunction(SendEntity);
fieldxfloat(Version);
fieldxfloat(pvsflags);
//Tell the qc library to split the entity fields each side.
//the fields above become < 0, the remaining fields specified by the qc stay where the mod specified, as far as possible (with addons at least).

View File

@ -137,6 +137,10 @@ typedef enum
G_MAKEVECTORS,
G_NEXTCLIENT,
G_PRECAHCE_VWEP_MODEL,
G_SETPAUSE,
G_SETUSERINFO,
G_MAX
} gameImport_t;
@ -496,6 +500,7 @@ void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_ExecuteCommand (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_setspawnparms (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_ForceInfoKey(progfuncs_t *prinst, struct globalvars_s *pr_globals);
int PF_checkclient_Internal (progfuncs_t *prinst);
@ -1086,11 +1091,20 @@ Con_DPrintf("PF_readcmd: %s\n%s", s, output);
/*
case G_Remove_Bot:
break;
case G_SetBotUserInfo:
break;
case G_SetBotCMD:
break;
*/
case G_SETUSERINFO:
{
char *key = VM_POINTER(arg[1]);
if (*key == '*' && (VM_LONG(arg[3])&1))
return -1; //denied!
}
//fallthrough
case G_SetBotUserInfo:
WrapQCBuiltin(PF_ForceInfoKey, offset, mask, arg, "ess");
return 0;
case G_strftime:
{
char *out = VM_POINTER(arg[0]);
@ -1193,14 +1207,16 @@ static int EXPORT_FN syscallnative (int arg, ...)
void Q1QVM_Shutdown(void)
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
{
if (svs.clients[i].name)
Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf));
svs.clients[i].name = svs.clients[i].namebuf;
}
if (q1qvm)
{
for (i = 0; i < MAX_CLIENTS; i++)
{
if (svs.clients[i].name)
Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf));
svs.clients[i].name = svs.clients[i].namebuf;
}
VM_Destroy(q1qvm);
}
q1qvm = NULL;
VM_fcloseall(VMFSID_Q1QVM);
if (svprogfuncs == &q1qvmprogfuncs)
@ -1480,4 +1496,3 @@ void Q1QVM_EndFrame(void)
}
#endif

View File

@ -237,6 +237,7 @@ typedef struct extentvars_s
//csqc stuph.
func_t SendEntity;
float Version;
float pvsflags;
#ifdef VM_Q1
} extentvars_t;

View File

@ -110,6 +110,7 @@ typedef struct
float gamespeed; //time progression multiplier, fixed per-level.
qboolean csqcdebug;
unsigned int csqcchecksum;
qboolean mapchangelocked;
double time;
@ -405,7 +406,9 @@ typedef struct client_s
// client known data for deltas
int old_frags;
int stats[MAX_CL_STATS];
int statsi[MAX_CL_STATS];
float statsf[MAX_CL_STATS];
char *statss[MAX_CL_STATS];
union{ //save space
client_frame_t *frames; // updates can be deltad from here
@ -821,6 +824,13 @@ typedef struct
#define FF_CROUCHING 1 //fte flags. seperate from flags
#define FF_LADDER 2 //fte flags. seperate from flags
#define PVSF_NORMALPVS 0x0
#define PVSF_NOTRACECHECK 0x1
#define PVSF_USEPHS 0x2
#define PVSF_IGNOREPVS 0x3
#define PVSF_MODE_MASK 0x3
#define PVSF_NOREMOVE 0x80
// entity effects
//define EF_BRIGHTFIELD 1

View File

@ -701,13 +701,59 @@ void SV_BanName_f (void)
Con_TPrintf (STL_USERDOESNTEXIST, Cmd_Argv(1));
}
void SV_KickBanIP(netadr_t banadr, netadr_t banmask, char *reason)
{
qboolean shouldkick;
client_t *cl;
int i;
unsigned int reasonsize;
bannedips_t *nb;
if (reason)
reasonsize = strlen(reason);
else
reasonsize = 0;
// loop through clients and kick the ones that match
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state<=cs_zombie)
continue;
shouldkick = false;
if (NET_CompareAdrMasked(cl->netchan.remote_address, banadr, banmask))
shouldkick = true;
else if (cl->realip_status >= 1)
if (NET_CompareAdrMasked(cl->realip, banadr, banmask))
shouldkick = true;
if (shouldkick)
{
// match, so kick
SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTWASBANNED, cl->name);
// print directly, because the dropped client won't get the
// SV_BroadcastPrintf message
SV_ClientTPrintf (cl, PRINT_HIGH, STL_YOUWEREBANNED);
SV_LogPlayer(cl, "banned ip");
SV_DropClient (cl);
}
}
// add IP and mask to ban list
nb = Z_Malloc(sizeof(bannedips_t)+reasonsize);
nb->next = svs.bannedips;
nb->adr = banadr;
nb->adrmask = banmask;
svs.bannedips = nb;
if (reasonsize)
Q_strcpy(nb->reason, reason);
}
void SV_BanIP_f (void)
{
netadr_t banadr;
netadr_t banmask;
int i;
client_t *cl;
bannedips_t *nb;
char *reason = NULL;
int reasonsize = 0;
@ -730,37 +776,39 @@ void SV_BanIP_f (void)
}
if (Cmd_Argc() > 2)
{
reason = Cmd_Argv(2);
reasonsize = strlen(reason);
}
// loop through clients and kick the ones that match
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
SV_KickBanIP(banadr, banmask, reason);
}
void SV_BanClientIP_f (void)
{
netadr_t banmask;
client_t *cl;
char *reason = NULL;
int clnum=-1;
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
{
if (cl->state<=cs_zombie)
continue;
if (NET_CompareAdrMasked(cl->netchan.remote_address, banadr, banmask))
if (NET_IsLoopBackAddress(cl->netchan.remote_address))
{
// match, so kick
SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTWASBANNED, cl->name);
// print directly, because the dropped client won't get the
// SV_BroadcastPrintf message
SV_ClientTPrintf (cl, PRINT_HIGH, STL_YOUWEREBANNED);
SV_LogPlayer(cl, "banned ip");
SV_DropClient (cl);
Con_Printf("You're not allowed to ban loopback!\n");
continue;
}
if (cl->realip_status>0)
{
memset(&banmask.address, 0xff, sizeof(banmask.address));
banmask.type = cl->netchan.remote_address.type;
SV_KickBanIP(cl->realip, banmask, reason);
}
else
{
memset(&banmask.address, 0xff, sizeof(banmask.address));
banmask.type = cl->netchan.remote_address.type;
SV_KickBanIP(cl->netchan.remote_address, banmask, reason);
}
}
// add IP and mask to ban list
nb = Z_Malloc(sizeof(bannedips_t)+reasonsize);
nb->next = svs.bannedips;
nb->adr = banadr;
nb->adrmask = banmask;
svs.bannedips = nb;
if (reasonsize)
Q_strcpy(nb->reason, reason);
}
void SV_FilterIP_f (void)
@ -1245,6 +1293,8 @@ void SV_Status_f (void)
{
if (net_local_sv_ipadr.type != NA_LOOPBACK)
Con_Printf ("ip address : %s\n",NET_AdrToString (net_local_sv_ipadr));
if (net_local_sv_ip6adr.type != NA_LOOPBACK)
Con_Printf ("ipv6 address : %s\n",NET_AdrToString (net_local_sv_ip6adr));
Con_Printf("Server is not running\n");
return;
@ -1262,7 +1312,7 @@ void SV_Status_f (void)
if (svs.socketip != INVALID_SOCKET && net_local_sv_ipadr.type != NA_LOOPBACK)
{
extern cvar_t pr_imitatemvdsv;
if (pr_imitatemvdsv.value)
if (pr_imitatemvdsv.value) //ktpro requires 'net address' for some reason that I don't remember
Con_Printf ("net address : %s\n",NET_AdrToString (net_local_sv_ipadr));
else
Con_Printf ("ip address : %s\n",NET_AdrToString (net_local_sv_ipadr));
@ -1973,6 +2023,7 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("banname", SV_BanName_f);
Cmd_AddCommand ("banlist", SV_BanList_f);
Cmd_AddCommand ("banip", SV_BanIP_f);
Cmd_AddCommand ("ban", SV_BanClientIP_f);
Cmd_AddCommand ("unban", SV_Unban_f);
// Cmd_AddCommand ("ban", SV_BanName_f);
Cmd_AddCommand ("status", SV_Status_f);

View File

@ -115,6 +115,8 @@ extern int sv_lightningmodel;
static edict_t *csqcent[MAX_EDICTS];
static int csqcnuments;
static edict_t *ssqcent[MAX_EDICTS];
qboolean SV_AddNailUpdate (edict_t *ent)
{
if (ent->v->modelindex != sv_nailmodel
@ -348,7 +350,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg)
if (client->protocol != SCP_QUAKEWORLD)
MSG_WriteByte(msg, svcdp_csqcentities);
else
MSG_WriteByte(msg, svc_csqcentities);
MSG_WriteByte(msg, svcfte_csqcentities);
}
MSG_WriteShort(msg, ent->entnum);
if (sv.csqcdebug) //optional extra.
@ -362,12 +364,12 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg)
// Con_Printf("Sending update packet %i\n", ent->entnum);
}
else if (sv.csqcentversion[ent->entnum])
else if (sv.csqcentversion[ent->entnum] && !((int)ent->xv->pvsflags & PVSF_NOREMOVE))
{ //Don't want to send.
if (!writtenheader)
{
writtenheader=true;
MSG_WriteByte(msg, svc_csqcentities);
MSG_WriteByte(msg, svcfte_csqcentities);
}
mask = (unsigned)ent->entnum | 0x8000;
@ -379,9 +381,9 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg)
}
for (en = 1; en < sv.num_edicts; en++)
{
if (client->csqcentversions[en] > 0 && (client->csqcentversions[en] != sv.csqcentversion[en]))
ent = EDICT_NUM(svprogfuncs, en);
if (client->csqcentversions[en] > 0 && (client->csqcentversions[en] != sv.csqcentversion[en]) && !((int)ent->xv->pvsflags & PVSF_NOREMOVE))
{
ent = EDICT_NUM(svprogfuncs, en);
// if (!ent->isfree)
// continue;
@ -393,7 +395,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg)
if (!writtenheader)
{
writtenheader=true;
MSG_WriteByte(msg, svc_csqcentities);
MSG_WriteByte(msg, svcfte_csqcentities);
}
// Con_Printf("Sending remove packet %i\n", en);
@ -2163,6 +2165,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
edict_t *clent;
client_frame_t *frame;
entity_state_t *state;
int pvsflags;
client_t *split;
@ -2184,33 +2187,6 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
#endif
for (split = client->controlled; split; split = split->controlled)
sv.worldmodel->funcs.FatPVS(sv.worldmodel, split->edict->v->origin, true);
/*
if (sv.worldmodel->fromgame == fg_doom)
{
}
else
#ifdef Q2BSPS
if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3)
{
leafnum = CM_PointLeafnum (org);
clientarea = CM_LeafArea (leafnum);
clientcluster = CM_LeafCluster (leafnum);
SV_Q2BSP_FatPVS (org);
}
else
#endif
{
SV_Q1BSP_FatPVS (org);
#ifdef PEXT_VIEW2
if (clent->xv->view2)
SV_Q1BSP_AddToFatPVS (PROG_TO_EDICT(svprogfuncs, clent->xv->view2)->v->origin, sv.worldmodel->nodes); //add a little more...
#endif
for (split = client->controlled; split; split = split->controlled)
SV_Q1BSP_AddToFatPVS (split->edict->v->origin, sv.worldmodel->nodes); //add a little more...
}
*/
}
else
clent = NULL;
@ -2369,6 +2345,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC))
continue;
pvsflags = ent->xv->pvsflags;
if (progstype != PROG_QW)
{
// if (progstype == PROG_H2)
@ -2388,26 +2365,43 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
if (!ignorepvs && ent != clent)
{
//branch out to the pvs testing.
if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, client->edict))
if ((pvsflags & PVSF_MODE_MASK) < PVSF_USEPHS)
{
//unconditional
}
else if (ent->xv->tag_entity)
{
edict_t *p = ent;
int c = 10;
while(p->xv->tag_entity&&c-->0)
//branch out to the pvs testing.
if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, client->edict))
{
p = EDICT_NUM(svprogfuncs, p->xv->tag_entity);
//unconditional
}
else if (ent->xv->tag_entity)
{
edict_t *p = ent;
int c = 10;
while(p->xv->tag_entity&&c-->0)
{
p = EDICT_NUM(svprogfuncs, p->xv->tag_entity);
}
if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, p))
continue;
}
else
{
if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, ent))
continue;
}
if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, p))
continue;
}
else
else if ((pvsflags & PVSF_MODE_MASK) == PVSF_USEPHS && sv.worldmodel->fromgame == fg_quake)
{
if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, ent))
int leafnum;
unsigned char *mask;
leafnum = sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, host_client->edict->v->origin);
mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
leafnum = sv.worldmodel->funcs.LeafnumForPoint (sv.worldmodel, ent->v->origin)-1;
if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
{
Con_Printf ("PHS supressed entity\n");
continue;
}
}
}
@ -2444,7 +2438,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
continue; //not in this dimension - sorry...
if (!ignorepvs && ent != clent)
if (!ignorepvs && ent != clent && (pvsflags & PVSF_MODE_MASK)==PVSF_NORMALPVS)
{ //more expensive culling
if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value)
if (Cull_Traceline(clent, ent))

View File

@ -831,11 +831,15 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
if (file)
{
char text[64];
sprintf(text, "0x%x", Com_BlockChecksum(file, com_filesize));
sv.csqcchecksum = Com_BlockChecksum(file, com_filesize);
sprintf(text, "0x%x", sv.csqcchecksum);
Info_SetValueForStarKey(svs.info, "*csprogs", text, MAX_SERVERINFO_STRING);
}
else
{
sv.csqcchecksum = 0;
Info_SetValueForStarKey(svs.info, "*csprogs", "", MAX_SERVERINFO_STRING);
}
sv.csqcdebug = sv_csqcdebug.value;
if (sv.csqcdebug)

View File

@ -2279,6 +2279,8 @@ void SVC_RealIP (void)
{
unsigned int slotnum;
int cookie;
bannedips_t *banip;
slotnum = atoi(Cmd_Argv(1));
cookie = atoi(Cmd_Argv(2));
@ -2298,6 +2300,24 @@ void SVC_RealIP (void)
if (svs.clients[slotnum].realip_status)
return;
if (NET_AddressSmellsFunny(net_from))
{
Con_Printf("funny realip address: %s, ", NET_AdrToString(net_from));
Con_Printf("proxy address: %s\n", NET_AdrToString(svs.clients[slotnum].netchan.remote_address));
return;
}
banip = SV_BannedAddress(&net_from);
if (banip)
{
Con_Printf("%s has a banned realip\n", svs.clients[slotnum].name);
if (banip->reason)
SV_ClientPrintf(&svs.clients[slotnum], PRINT_CHAT, "You were banned.\nReason: %s\n", banip->reason);
else
SV_ClientPrintf(&svs.clients[slotnum], PRINT_CHAT, "You were banned.\n");
SV_DropClient(&svs.clients[slotnum]);
return;
}
svs.clients[slotnum].realip_status = 1;
svs.clients[slotnum].realip = net_from;

View File

@ -938,7 +938,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
other = PROG_TO_EDICT(svprogfuncs, ent->v->dmg_inflictor);
if (pnum)
{
MSG_WriteByte(msg, svc_choosesplitclient);
MSG_WriteByte(msg, svcfte_choosesplitclient);
MSG_WriteByte(msg, pnum);
}
MSG_WriteByte (msg, svc_damage);
@ -956,7 +956,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
{
if (pnum)
{
MSG_WriteByte(msg, svc_choosesplitclient);
MSG_WriteByte(msg, svcfte_choosesplitclient);
MSG_WriteByte(msg, pnum);
}
MSG_WriteByte (msg, svc_setangle);
@ -1237,7 +1237,7 @@ void SV_ClearQCStats(void)
numqcstats = 0;
}
void SV_UpdateQCStats(edict_t *ent, int *stats)
void SV_UpdateQCStats(edict_t *ent, int *statsi, char **statss, float *statsf)
{
char *s;
int i;
@ -1252,20 +1252,21 @@ void SV_UpdateQCStats(edict_t *ent, int *stats)
switch(qcstats[i].type)
{
case ev_float:
stats[qcstats[i].statnum] = eval->_float;
statsf[qcstats[i].statnum] = eval->_float;
break;
case ev_integer:
stats[qcstats[i].statnum] = eval->_int;
statsi[qcstats[i].statnum] = eval->_int;
break;
case ev_entity:
stats[qcstats[i].statnum] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, eval->edict));
statsi[qcstats[i].statnum] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, eval->edict));
break;
case ev_string:
s = PR_GetString(svprogfuncs, eval->string);
stats[qcstats[i].statnum+0] = LittleLong(((int*)s)[0]); //so the network is sent out correctly as a string.
stats[qcstats[i].statnum+1] = LittleLong(((int*)s)[1]);
stats[qcstats[i].statnum+2] = LittleLong(((int*)s)[2]);
stats[qcstats[i].statnum+3] = LittleLong(((int*)s)[3]);
statss[qcstats[i].statnum] = s;
// statsi[qcstats[i].statnum+0] = LittleLong(((int*)s)[0]); //so the network is sent out correctly as a string.
// statsi[qcstats[i].statnum+1] = LittleLong(((int*)s)[1]);
// statsi[qcstats[i].statnum+2] = LittleLong(((int*)s)[2]);
// statsi[qcstats[i].statnum+3] = LittleLong(((int*)s)[3]);
break;
}
}
@ -1282,88 +1283,92 @@ when a reliable message can be delivered this frame.
void SV_UpdateClientStats (client_t *client, int pnum)
{
edict_t *ent;
int stats[MAX_CL_STATS];
int statsi[MAX_CL_STATS];
float statsf[MAX_CL_STATS];
char *statss[MAX_CL_STATS];
int i, m;
globalvars_t *pr_globals;
extern qboolean pr_items2;
ent = client->edict;
memset (stats, 0, sizeof(stats));
memset (statsi, 0, sizeof(statsi));
memset (statsf, 0, sizeof(statsf));
memset (statss, 0, sizeof(statss));
// if we are a spectator and we are tracking a player, we get his stats
// so our status bar reflects his
if (client->spectator && client->spec_track > 0)
ent = svs.clients[client->spec_track - 1].edict;
stats[STAT_HEALTH] = ent->v->health;
stats[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel));
statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh
statsi[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel));
if (host_client->fteprotocolextensions & PEXT_MODELDBL)
{
if ((unsigned)stats[STAT_WEAPON] >= 512)
stats[STAT_WEAPON] = 0;
if ((unsigned)statsi[STAT_WEAPON] >= 512)
statsi[STAT_WEAPON] = 0;
}
else
{
if ((unsigned)stats[STAT_WEAPON] >= 256)
stats[STAT_WEAPON] = 0;
if ((unsigned)statsi[STAT_WEAPON] >= 256)
statsi[STAT_WEAPON] = 0;
}
stats[STAT_AMMO] = ent->v->currentammo;
stats[STAT_ARMOR] = ent->v->armorvalue;
stats[STAT_SHELLS] = ent->v->ammo_shells;
stats[STAT_NAILS] = ent->v->ammo_nails;
stats[STAT_ROCKETS] = ent->v->ammo_rockets;
stats[STAT_CELLS] = ent->v->ammo_cells;
statsf[STAT_AMMO] = ent->v->currentammo;
statsf[STAT_ARMOR] = ent->v->armorvalue;
statsf[STAT_SHELLS] = ent->v->ammo_shells;
statsf[STAT_NAILS] = ent->v->ammo_nails;
statsf[STAT_ROCKETS] = ent->v->ammo_rockets;
statsf[STAT_CELLS] = ent->v->ammo_cells;
if (!client->spectator)
{
stats[STAT_ACTIVEWEAPON] = ent->v->weapon;
statsi[STAT_ACTIVEWEAPON] = ent->v->weapon;
if (client->csqcactive)
stats[STAT_WEAPONFRAME] = ent->v->weaponframe;
statsi[STAT_WEAPONFRAME] = ent->v->weaponframe;
}
// stuff the sigil bits into the high bits of items for sbar
if (pr_items2)
stats[STAT_ITEMS] = (int)ent->v->items | ((int)ent->xv->items2 << 23);
statsi[STAT_ITEMS] = (int)ent->v->items | ((int)ent->xv->items2 << 23);
else
stats[STAT_ITEMS] = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
statsi[STAT_ITEMS] = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
stats[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
statsf[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
#ifdef PEXT_VIEW2
if (ent->xv->view2)
stats[STAT_VIEW2] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, ent->xv->view2));
statsi[STAT_VIEW2] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, ent->xv->view2));
else
stats[STAT_VIEW2] = 0;
statsi[STAT_VIEW2] = 0;
#endif
if (!ent->xv->viewzoom)
stats[STAT_VIEWZOOM] = 255;
statsf[STAT_VIEWZOOM] = 255;
else
stats[STAT_VIEWZOOM] = ent->xv->viewzoom*255;
statsf[STAT_VIEWZOOM] = ent->xv->viewzoom*255;
if (host_client->protocol == SCP_DARKPLACES7)
{
float *statsf = (float*)stats;
// statsf[STAT_MOVEVARS_WALLFRICTION] = sv_wall
statsf[STAT_MOVEVARS_FRICTION] = sv_friction.value;
statsf[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value;
statsf[STAT_MOVEVARS_TICRATE] = 72;
statsf[STAT_MOVEVARS_TIMESCALE] = sv_gamespeed.value;
statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
statsf[STAT_MOVEVARS_STOPSPEED] = sv_stopspeed.value;
statsf[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed;
statsf[STAT_MOVEVARS_SPECTATORMAXSPEED] = sv_spectatormaxspeed.value;
statsf[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value;
statsf[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value;
statsf[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value;
statsf[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsf[STAT_MOVEVARS_JUMPVELOCITY] = 280;//sv_jumpvelocity.value; //bah
statsf[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsf[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed;
statsf[STAT_MOVEVARS_STEPHEIGHT] = 18;
statsf[STAT_MOVEVARS_AIRACCEL_QW] = 1;
statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_gravity.value;
float *statsfi = (float*)statsi;
// statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall
statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value;
statsfi[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value;
statsfi[STAT_MOVEVARS_TICRATE] = 72;
statsfi[STAT_MOVEVARS_TIMESCALE] = sv_gamespeed.value;
statsfi[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
statsfi[STAT_MOVEVARS_STOPSPEED] = sv_stopspeed.value;
statsfi[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed;
statsfi[STAT_MOVEVARS_SPECTATORMAXSPEED] = sv_spectatormaxspeed.value;
statsfi[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value;
statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value;
statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value;
statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 280;//sv_jumpvelocity.value; //bah
statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed;
statsfi[STAT_MOVEVARS_STEPHEIGHT] = 18;
statsfi[STAT_MOVEVARS_AIRACCEL_QW] = 1;
statsfi[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_gravity.value;
}
SV_UpdateQCStats(ent, stats);
SV_UpdateQCStats(ent, statsi, statss, statsf);
//dmw tweek for stats
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
@ -1378,71 +1383,106 @@ void SV_UpdateClientStats (client_t *client, int pnum)
//dmw tweek for stats
if (getplayerstati[i])
{
G_INT(OFS_PARM0) = stats[i];
G_INT(OFS_PARM0) = statsf[i];
PR_ExecuteProgram(svprogfuncs, getplayerstati[i]);
stats[i] = G_INT(OFS_RETURN);
statsf[i] = G_INT(OFS_RETURN);
}
else if (getplayerstat[i])
{
G_FLOAT(OFS_PARM0) = stats[i];
G_FLOAT(OFS_PARM0) = statsf[i];
PR_ExecuteProgram(svprogfuncs, getplayerstat[i]);
stats[i] = G_FLOAT(OFS_RETURN);
statsf[i] = G_FLOAT(OFS_RETURN);
}
if (sv.demofile)
{
if (!client->spec_track)
{
stats[i] = 0;
statsf[i] = 0;
if (i == STAT_HEALTH)
stats[i] = 100;
statsf[i] = 100;
}
else
stats[i] = sv.recordedplayer[client->spec_track - 1].stats[i];
}
if (stats[i] != client->stats[i])
{
client->stats[i] = stats[i];
#ifdef NQPROT
if (!ISQWCLIENT(client))
{
statsf[i] = sv.recordedplayer[client->spec_track - 1].stats[i];
statsi[i] = sv.recordedplayer[client->spec_track - 1].stats[i];
}
}
if (!ISQWCLIENT(client))
{
if (!statsi[i])
statsi[i] = *(int*)&statsf[i];
if (statsi[i] != client->statsi[i])
{
client->statsi[i] = statsi[i];
ClientReliableWrite_Begin(client, svc_updatestat, 3);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Long(client, stats[i]);
ClientReliableWrite_Long(client, statsi[i]);
}
else
#endif
if (pnum)
}
else
{
if ((client->fteprotocolextensions & PEXT_CSQC) && sv.csqcchecksum)
{
if (stats[i] >=0 && stats[i] <= 255)
if (statsf[i] && statsf[i] - (float)(int)statsf[i] == 0)
{
ClientReliableWrite_Begin(client->controller, svc_choosesplitclient, 5);
statsi[i] = statsf[i];
statsf[i] = 0;
}
else if (statsf[i] != client->statsf[i])
{
client->statsf[i] = statsf[i];
// client->statsi[i] = statsi[i];
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 8);
ClientReliableWrite_Byte(client->controller, pnum);
}
ClientReliableWrite_Begin(client, svcfte_updatestatfloat, 6);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Float(client, statsf[i]);
}
if (statss[i] || client->statss[i])
if (strcmp(statss[i]?statss[i]:"", client->statss[i]?client->statss[i]:""))
{
client->statss[i] = statss[i];
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 5+strlen(statss[i]));
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svcfte_updatestatstring);
}
else
ClientReliableWrite_Begin(client, svcfte_updatestatstring, 3+strlen(statss[i]));
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_String(client, statss[i]);
}
}
else if (!statsi[i])
statsi[i] = statsf[i];
if (statsi[i] != client->statsi[i])
{
client->statsi[i] = statsi[i];
client->statsf[i] = 0;
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 8);
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svc_updatestat);
ClientReliableWrite_Byte(client->controller, i);
ClientReliableWrite_Byte(client->controller, stats[i]);
}
if (statsi[i] >=0 && statsi[i] <= 255)
{
ClientReliableWrite_Begin(client, svc_updatestat, 3);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Byte(client, statsi[i]);
}
else
{
ClientReliableWrite_Begin(client->controller, svc_choosesplitclient, 8);
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svc_updatestatlong);
ClientReliableWrite_Byte(client->controller, i);
ClientReliableWrite_Long(client->controller, stats[i]);
ClientReliableWrite_Begin(client, svc_updatestatlong, 6);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Long(client, statsi[i]);
}
}
else if (stats[i] >=0 && stats[i] <= 255)
{
ClientReliableWrite_Begin(client, svc_updatestat, 3);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Byte(client, stats[i]);
}
else
{
ClientReliableWrite_Begin(client, svc_updatestatlong, 6);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Long(client, stats[i]);
}
}
}
}
@ -1534,7 +1574,7 @@ client_t *SV_SplitClientDest(client_t *client, qbyte first, int size)
}
sp = client->controller;
ClientReliableWrite_Begin (sp, svc_choosesplitclient, size+2);
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, size+2);
ClientReliableWrite_Byte (sp, pnum);
ClientReliableWrite_Byte (sp, first);
return sp;
@ -1711,7 +1751,7 @@ void SV_UpdateToReliableMessages (void)
}
sp = host_client->controller;
ClientReliableWrite_Begin (sp, svc_choosesplitclient, 7);
ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 7);
ClientReliableWrite_Byte (sp, pnum);
ClientReliableWrite_Byte (sp, svc_maxspeed);
ClientReliableWrite_Float(sp, newval);

View File

@ -82,6 +82,12 @@ extern cvar_t pm_airstep;
extern cvar_t pm_walljump;
cvar_t sv_pushplayers = SCVAR("sv_pushplayers", "0");
//yes, realip cvars need to be fully initialised or realip will be disabled
cvar_t sv_getrealip = SCVAR("sv_getrealip", "0");
cvar_t sv_realiphostname_ipv4 = SCVAR("sv_realiphostname_ipv4", "");
cvar_t sv_realiphostname_ipv6 = SCVAR("sv_realiphostname_ipv4", "");
cvar_t sv_realip_timeout = SCVAR("sv_realip_timeout", "10");
char sv_votinggroup[] = "server voting";
@ -108,16 +114,13 @@ host_client and sv_player will be valid.
============================================================
*/
qboolean SV_CheakRealIP(client_t *client, qboolean force)
qboolean SV_CheckRealIP(client_t *client, qboolean force)
{
//returns true if they have a real ip
cvar_t *sv_getrealip;
char *serverip;
char *msg;
sv_getrealip = Cvar_Get("sv_getrealip", "0", 0, "Experimental cvars");
if (!sv_getrealip || !sv_getrealip->value)
if (!sv_getrealip.value)
return true;
if (client->netchan.remote_address.type == NA_LOOPBACK)
@ -128,7 +131,6 @@ qboolean SV_CheakRealIP(client_t *client, qboolean force)
if (client->realip_status == 2)
{
ClientReliableWrite_Begin(client, svc_print, 256);
ClientReliableWrite_Byte(client, svc_print);
ClientReliableWrite_Byte(client, PRINT_HIGH);
ClientReliableWrite_String(client, "Couldn't verify your real ip\n");
return true; //client doesn't support certainty.
@ -136,13 +138,17 @@ qboolean SV_CheakRealIP(client_t *client, qboolean force)
if (client->realip_status == -1)
return true; //can't get a better answer
if (realtime - host_client->connection_started > 10)
if (realtime - host_client->connection_started > sv_realip_timeout.value)
{
client->realip_status = -1;
ClientReliableWrite_Begin(client, svc_print, 256);
ClientReliableWrite_Byte(client, svc_print);
ClientReliableWrite_Byte(client, PRINT_HIGH);
ClientReliableWrite_String(client, "Couldn't determine your real ip\n");
if (sv_getrealip.value == 2)
{
SV_DropClient(client);
return false;
}
return true;
}
@ -154,9 +160,25 @@ qboolean SV_CheakRealIP(client_t *client, qboolean force)
}
else
{
serverip = NET_AdrToString (net_local_sv_ipadr);
if (client->netchan.remote_address.type == NA_IPV6)
{
serverip = sv_realiphostname_ipv6.string;
// serverip = NET_AdrToString (net_local_sv_ip6adr);
}
else
{
serverip = sv_realiphostname_ipv4.string;
// serverip = NET_AdrToString (net_local_sv_ipadr);
}
ClientReliableWrite_Byte(client, svc_stufftext);
if (!*serverip)
{
Con_Printf("realip not fully configured\n");
client->realip_status = -2;
return true;
}
ClientReliableWrite_Begin(client, svc_stufftext, 256);
ClientReliableWrite_String(client, va("packet %s \"realip %i %i\"\n", serverip, client-svs.clients, client->realip_num));
}
return false;
@ -180,8 +202,6 @@ void SV_New_f (void)
if (host_client->state == cs_spawned)
return;
SV_CheakRealIP(host_client, false);
/* splitt delay
host_client->state = cs_connected;
host_client->connection_started = realtime;
@ -264,6 +284,7 @@ void SV_New_f (void)
#endif
splitnum++;
}
if (host_client->fteprotocolextensions & PEXT_SPLITSCREEN)
ClientReliableWrite_Byte (host_client, 128);
@ -319,6 +340,9 @@ void SV_New_f (void)
host_client->csqcactive = false;
host_client->realip_num = rand()+(host_client->challenge<<16);
SV_CheckRealIP(host_client, false);
// send music
ClientReliableCheckBlock(host_client, 2);
@ -873,7 +897,7 @@ void SV_Modellist_f (void)
if (n >= 255)
{
MSG_WriteByte (&host_client->netchan.message, svc_modellistshort);
MSG_WriteByte (&host_client->netchan.message, svcfte_modellistshort);
MSG_WriteShort (&host_client->netchan.message, n);
}
else
@ -1062,7 +1086,7 @@ void SV_PreSpawn_f (void)
}
else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2)
{
MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline2);
MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2);
SV_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions);
}
else if (state->modelindex < 256)
@ -1101,7 +1125,7 @@ void SV_PreSpawn_f (void)
if (host_client->fteprotocolextensions & PEXT_CUSTOMTEMPEFFECTS)
{
MSG_WriteByte(&host_client->netchan.message, svc_customtempent);
MSG_WriteByte(&host_client->netchan.message, svcfte_customtempent);
MSG_WriteByte(&host_client->netchan.message, 255);
MSG_WriteByte(&host_client->netchan.message, i);
MSG_WriteByte(&host_client->netchan.message, ctent->netstyle);
@ -1219,7 +1243,7 @@ void SV_Spawn_f (void)
#ifdef PEXT_LIGHTSTYLECOL
if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7)
{
ClientReliableWrite_Begin (host_client, svc_lightstylecol,
ClientReliableWrite_Begin (host_client, svcfte_lightstylecol,
3 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1));
ClientReliableWrite_Byte (host_client, (char)i);
ClientReliableWrite_Char (host_client, sv.strings.lightstylecolours[i]);
@ -1254,7 +1278,9 @@ void SV_Spawn_f (void)
//
// force stats to be updated
//
memset (host_client->stats, 0, sizeof(host_client->stats));
memset (host_client->statsi, 0, sizeof(host_client->statsi));
memset (host_client->statsf, 0, sizeof(host_client->statsf));
memset (host_client->statss, 0, sizeof(host_client->statss));
}
ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
@ -1322,7 +1348,7 @@ void SV_Begin_f (void)
int i;
qboolean sendangles=false;
if (!SV_CheakRealIP(host_client, true))
if (!SV_CheckRealIP(host_client, true))
{
if (host_client->protocol == SCP_QUAKE2)
ClientReliableWrite_Begin (host_client, svcq2_stufftext, 13+strlen(Cmd_Args()));
@ -3749,7 +3775,9 @@ void SVNQ_Spawn_f (void)
//
// force stats to be updated
//
memset (host_client->stats, 0, sizeof(host_client->stats));
memset (host_client->statsi, 0, sizeof(host_client->statsi));
memset (host_client->statsf, 0, sizeof(host_client->statsf));
memset (host_client->statss, 0, sizeof(host_client->statss));
ClientReliableWrite_Begin (host_client, svc_updatestat, 6);
ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
@ -5583,6 +5611,11 @@ void SV_UserInit (void)
Cvar_Register (&sv_cheatspeedchecktime, cvargroup_servercontrol);
Cvar_Register (&sv_playermodelchecks, cvargroup_servercontrol);
Cvar_Register (&sv_getrealip, cvargroup_servercontrol);
Cvar_Register (&sv_realiphostname_ipv4, cvargroup_servercontrol);
Cvar_Register (&sv_realiphostname_ipv6, cvargroup_servercontrol);
Cvar_Register (&sv_realip_timeout, cvargroup_servercontrol);
Cvar_Register (&sv_pushplayers, cvargroup_servercontrol);
Cvar_Register (&sv_floodprotect, cvargroup_servercontrol);