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

@ -17,7 +17,8 @@
#endif
extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models;
extern cvar_t r_noaliasshadows;
extern cvar_t r_noaliasshadows;
extern cvar_t r_skin_overlays;
extern cvar_t mod_md3flags;
@ -1096,7 +1097,11 @@ void Mod_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber,
texnum->shader = R_RegisterSkin(shadername);
#endif
texnum->base = Mod_LoadHiResTexture(shadername, "models", true, true, true);
texnum->base = Mod_LoadHiResTexture(shadername, "models", true, true, true);
//13/4/08 IMPLEMENTME
texnum->loweroverlay = 0;
texnum->upperoverlay = 0;
}
#endif
@ -1437,7 +1442,19 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha)
texnums->base = texture;
texnums->fullbright = fbtexture;
texnums->bump = bumptexture;
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;
@ -1523,7 +1540,11 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha)
#endif
texnums->base = texture;
texnums->fullbright = fbtexture;
texnums->fullbright = fbtexture;
//13/4/08 IMPLEMENTME
texnums->loweroverlay = 0;
texnums->upperoverlay = 0;
}
pskintype = (daliasskintype_t *)data;
break;
@ -2651,7 +2672,11 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
texnum->fullbright = Mod_LoadBumpmapTexture(name, "models");
}
}
#endif
#endif
//13/4/08 IMPLEMENTME
texnum->loweroverlay = 0;
texnum->upperoverlay = 0;
inshader++;
skin++;

View File

@ -101,7 +101,9 @@ typedef struct {
typedef struct {
int base;
int bump;
int fullbright;
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).

File diff suppressed because it is too large Load Diff

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