// sv_main.c -- server main program
#include "quakedef.h"
+#include "libcurl.h"
void SV_VM_Init();
void SV_VM_Setup();
cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1", "fixes a bug in Quake that made setmodel always set the entity box to ('-16 -16 -16', '16 16 16') rather than properly checking the model box, breaks some poorly coded mods"};
cvar_t sv_gameplayfix_blowupfallenzombies = {0, "sv_gameplayfix_blowupfallenzombies", "1", "causes findradius to detect SOLID_NOT entities such as zombies and corpses on the floor, allowing splash damage to apply to them"};
cvar_t sv_gameplayfix_findradiusdistancetobox = {0, "sv_gameplayfix_findradiusdistancetobox", "1", "causes findradius to check the distance to the corner of a box rather than the center of the box, makes findradius detect bmodels such as very large doors that would otherwise be unaffected by splash damage"};
+cvar_t sv_gameplayfix_qwplayerphysics = {0, "sv_gameplayfix_qwplayerphysics", "1", "changes water jumping to make it easier to get out of water, and prevents friction on landing when bunnyhopping"};
+cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {0, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"};
cvar_t sv_progs = {0, "sv_progs", "progs.dat", "selects which quakec progs.dat file to run" };
+// TODO: move these cvars here
+extern cvar_t sv_clmovement_enable;
+extern cvar_t sv_clmovement_minping;
+extern cvar_t sv_clmovement_minping_disabletime;
+extern cvar_t sv_clmovement_waitforinput;
+
server_t sv;
server_static_t svs;
*/
void SV_Init (void)
{
+ // init the csqc progs cvars, since they are updated/used by the server code
+ // TODO: fix this since this is a quick hack to make some of [515]'s broken code run ;) [9/13/2006 Black]
+ extern cvar_t csqc_progname;
+ extern cvar_t csqc_progcrc;
+ Cvar_RegisterVariable (&csqc_progname);
+ Cvar_RegisterVariable (&csqc_progcrc);
+
Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f, "save map entities to .ent file (to allow external editing)");
Cvar_RegisterVariable (&sv_maxvelocity);
Cvar_RegisterVariable (&sv_gravity);
Cvar_RegisterVariable (&sv_friction);
+ Cvar_RegisterVariable (&sv_waterfriction);
Cvar_RegisterVariable (&sv_edgefriction);
Cvar_RegisterVariable (&sv_stopspeed);
Cvar_RegisterVariable (&sv_maxspeed);
Cvar_RegisterVariable (&sv_maxairspeed);
Cvar_RegisterVariable (&sv_accelerate);
+ Cvar_RegisterVariable (&sv_airaccelerate);
+ Cvar_RegisterVariable (&sv_wateraccelerate);
+ Cvar_RegisterVariable (&sv_clmovement_enable);
+ Cvar_RegisterVariable (&sv_clmovement_minping);
+ Cvar_RegisterVariable (&sv_clmovement_minping_disabletime);
+ Cvar_RegisterVariable (&sv_clmovement_waitforinput);
Cvar_RegisterVariable (&sv_idealpitchscale);
Cvar_RegisterVariable (&sv_aim);
Cvar_RegisterVariable (&sv_nostep);
Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
Cvar_RegisterVariable (&sv_gameplayfix_blowupfallenzombies);
Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
+ Cvar_RegisterVariable (&sv_gameplayfix_qwplayerphysics);
+ Cvar_RegisterVariable (&sv_gameplayfix_upwardvelocityclearsongroundflag);
Cvar_RegisterVariable (&sv_protocolname);
Cvar_RegisterVariable (&sv_ratelimitlocalplayer);
Cvar_RegisterVariable (&sv_maxrate);
*/
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
{
- int i, v;
+ int i;
if (sv.datagram.cursize > MAX_PACKETFRAGMENT-18)
return;
MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
for (i=0 ; i<3 ; i++)
- {
- v = dir[i]*16;
- if (v > 127)
- v = 127;
- else if (v < -128)
- v = -128;
- MSG_WriteChar (&sv.datagram, v);
- }
+ MSG_WriteChar (&sv.datagram, (int)bound(-128, dir[i]*16, 127));
MSG_WriteByte (&sv.datagram, count);
MSG_WriteByte (&sv.datagram, color);
}
if (field_mask & SND_VOLUME)
MSG_WriteByte (&sv.datagram, volume);
if (field_mask & SND_ATTENUATION)
- MSG_WriteByte (&sv.datagram, attenuation*64);
+ MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
if (field_mask & SND_LARGEENTITY)
{
MSG_WriteShort (&sv.datagram, ent);
==============================================================================
*/
-static const char *SV_InitCmd; //[515]: svprogs able to send cmd to client on connect
-extern qboolean csqc_loaded;
+extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
+extern cvar_t csqc_progcrc;
/*
================
SV_SendServerinfo
SZ_Clear (&client->netconnection->message);
MSG_WriteByte (&client->netconnection->message, svc_print);
- dpsnprintf (message, sizeof (message), "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, prog->filecrc);
+ dpsnprintf (message, sizeof (message), "\nServer: %s build %s (progs %i crc)", gamename, buildstring, prog->filecrc);
MSG_WriteString (&client->netconnection->message,message);
- // FIXME: LordHavoc: this does not work on dedicated servers, needs fixing.
-//[515]: init csprogs according to version of svprogs, check the crc, etc.
- if(csqc_loaded && (cls.state == ca_dedicated || PRVM_NUM_FOR_EDICT(client->edict) != 1))
+ //[515]: init csprogs according to version of svprogs, check the crc, etc.
+ if (FS_FileExists(csqc_progname.string))
{
+ prvm_eval_t *val;
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
- if(SV_InitCmd)
- MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i;%s\n", csqc_progcrc.integer, SV_InitCmd));
+ //[515]: init stufftext string (it is sent before svc_serverinfo)
+ val = PRVM_GETGLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset("SV_InitCmd"));
+ if (val)
+ MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i\n%s\n", csqc_progcrc.integer, PRVM_GetString(val->string)));
else
MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i\n", csqc_progcrc.integer));
}
// send music
MSG_WriteByte (&client->netconnection->message, svc_cdtrack);
- MSG_WriteByte (&client->netconnection->message, prog->edicts->fields.server->sounds);
- MSG_WriteByte (&client->netconnection->message, prog->edicts->fields.server->sounds);
+ MSG_WriteByte (&client->netconnection->message, (int)prog->edicts->fields.server->sounds);
+ MSG_WriteByte (&client->netconnection->message, (int)prog->edicts->fields.server->sounds);
// set view
MSG_WriteByte (&client->netconnection->message, svc_setview);
MSG_WriteByte (&client->netconnection->message, svc_signonnum);
MSG_WriteByte (&client->netconnection->message, 1);
+ {
+ client_t *save;
+ save = host_client;
+ host_client = client;
+ Curl_SendRequirements();
+ host_client = save;
+ }
+
client->spawned = false; // need prespawn, spawn, etc
}
Con_DPrintf("Client %s connected\n", client->netconnection ? client->netconnection->address : "botclient");
- strcpy(client->name, "unconnected");
- strcpy(client->old_name, "unconnected");
+ strlcpy(client->name, "unconnected", sizeof(client->name));
+ strlcpy(client->old_name, "unconnected", sizeof(client->old_name));
client->spawned = false;
client->edict = PRVM_EDICT_NUM(clientnum+1);
if (client->netconnection)
if (effects & 32)
{
effects &= ~32;
- light[0] = 0.2;
- light[1] = 1;
- light[2] = 0.2;
+ light[0] = (int)(0.2*256);
+ light[1] = (int)(1.0*256);
+ light[2] = (int)(0.2*256);
light[3] = 200;
lightpflags |= PFLAGS_FULLDYNAMIC;
}
val = PRVM_GETEDICTFIELDVALUE(ent, eval_colormod);
if (val->vector[0] || val->vector[1] || val->vector[2])
{
- i = val->vector[0] * 32.0f;cs->colormod[0] = bound(0, i, 255);
- i = val->vector[1] * 32.0f;cs->colormod[1] = bound(0, i, 255);
- i = val->vector[2] * 32.0f;cs->colormod[2] = bound(0, i, 255);
+ i = (int)(val->vector[0] * 32.0f);cs->colormod[0] = bound(0, i, 255);
+ i = (int)(val->vector[1] * 32.0f);cs->colormod[1] = bound(0, i, 255);
+ i = (int)(val->vector[2] * 32.0f);cs->colormod[2] = bound(0, i, 255);
}
cs->modelindex = modelindex;
}
else
{
- VectorCopy(cs->origin, cullmins);
- VectorCopy(cs->origin, cullmaxs);
+ // if there is no model (or it could not be loaded), use the physics box
+ VectorAdd(cs->origin, ent->fields.server->mins, cullmins);
+ VectorAdd(cs->origin, ent->fields.server->maxs, cullmaxs);
}
if (specialvisibilityradius)
{
int items;
prvm_eval_t *val;
vec3_t punchvector;
- unsigned char viewzoom;
+ int viewzoom;
const char *s;
//
{
other = PRVM_PROG_TO_EDICT(ent->fields.server->dmg_inflictor);
MSG_WriteByte (msg, svc_damage);
- MSG_WriteByte (msg, ent->fields.server->dmg_save);
- MSG_WriteByte (msg, ent->fields.server->dmg_take);
+ MSG_WriteByte (msg, (int)ent->fields.server->dmg_save);
+ MSG_WriteByte (msg, (int)ent->fields.server->dmg_take);
for (i=0 ; i<3 ; i++)
MSG_WriteCoord (msg, other->fields.server->origin[i] + 0.5*(other->fields.server->mins[i] + other->fields.server->maxs[i]), sv.protocol);
viewzoom = 255;
if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewzoom)))
- viewzoom = val->_float * 255.0f;
+ viewzoom = (int)(val->_float * 255.0f);
if (viewzoom == 0)
viewzoom = 255;
}
memset(stats, 0, sizeof(int[MAX_CL_STATS]));
- stats[STAT_VIEWHEIGHT] = ent->fields.server->view_ofs[2];
+ stats[STAT_VIEWHEIGHT] = (int)ent->fields.server->view_ofs[2];
stats[STAT_ITEMS] = items;
- stats[STAT_WEAPONFRAME] = ent->fields.server->weaponframe;
- stats[STAT_ARMOR] = ent->fields.server->armorvalue;
+ stats[STAT_WEAPONFRAME] = (int)ent->fields.server->weaponframe;
+ stats[STAT_ARMOR] = (int)ent->fields.server->armorvalue;
stats[STAT_WEAPON] = client->weaponmodelindex;
- stats[STAT_HEALTH] = ent->fields.server->health;
- stats[STAT_AMMO] = ent->fields.server->currentammo;
- stats[STAT_SHELLS] = ent->fields.server->ammo_shells;
- stats[STAT_NAILS] = ent->fields.server->ammo_nails;
- stats[STAT_ROCKETS] = ent->fields.server->ammo_rockets;
- stats[STAT_CELLS] = ent->fields.server->ammo_cells;
- stats[STAT_ACTIVEWEAPON] = ent->fields.server->weapon;
+ stats[STAT_HEALTH] = (int)ent->fields.server->health;
+ stats[STAT_AMMO] = (int)ent->fields.server->currentammo;
+ stats[STAT_SHELLS] = (int)ent->fields.server->ammo_shells;
+ stats[STAT_NAILS] = (int)ent->fields.server->ammo_nails;
+ stats[STAT_ROCKETS] = (int)ent->fields.server->ammo_rockets;
+ stats[STAT_CELLS] = (int)ent->fields.server->ammo_cells;
+ stats[STAT_ACTIVEWEAPON] = (int)ent->fields.server->weapon;
stats[STAT_VIEWZOOM] = viewzoom;
// the QC bumps these itself by sending svc_'s, so we have to keep them
// zero or they'll be corrected by the engine
MSG_WriteChar (msg, stats[STAT_VIEWHEIGHT]);
if (bits & SU_IDEALPITCH)
- MSG_WriteChar (msg, ent->fields.server->idealpitch);
+ MSG_WriteChar (msg, (int)ent->fields.server->idealpitch);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
{
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
- MSG_WriteChar(msg, ent->fields.server->punchangle[i]);
+ MSG_WriteChar(msg, (int)ent->fields.server->punchangle[i]);
else
MSG_WriteAngle16i(msg, ent->fields.server->punchangle[i]);
}
if (bits & (SU_VELOCITY1<<i))
{
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
- MSG_WriteChar(msg, ent->fields.server->velocity[i] * (1.0f / 16.0f));
+ MSG_WriteChar(msg, (int)(ent->fields.server->velocity[i] * (1.0f / 16.0f)));
else
MSG_WriteCoord32f(msg, ent->fields.server->velocity[i]);
}
MSG_WriteShort (msg, stats[STAT_CELLS]);
MSG_WriteShort (msg, stats[STAT_ACTIVEWEAPON]);
if (bits & SU_VIEWZOOM)
- MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
+ MSG_WriteShort (msg, bound(0, stats[STAT_VIEWZOOM], 65535));
}
else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
{
if (bits & SU_VIEWZOOM)
{
if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
- MSG_WriteByte (msg, min(stats[STAT_VIEWZOOM], 255));
+ MSG_WriteByte (msg, bound(0, stats[STAT_VIEWZOOM], 255));
else
- MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
+ MSG_WriteShort (msg, bound(0, stats[STAT_VIEWZOOM], 65535));
}
}
}
{
if (host_client->spawned)
SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
- strcpy(host_client->old_name, host_client->name);
+ strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
MSG_WriteByte (&sv.reliable_datagram, i);
// create entity baseline
VectorCopy (svent->fields.server->origin, svent->priv.server->baseline.origin);
VectorCopy (svent->fields.server->angles, svent->priv.server->baseline.angles);
- svent->priv.server->baseline.frame = svent->fields.server->frame;
- svent->priv.server->baseline.skin = svent->fields.server->skin;
+ svent->priv.server->baseline.frame = (int)svent->fields.server->frame;
+ svent->priv.server->baseline.skin = (int)svent->fields.server->skin;
if (entnum > 0 && entnum <= svs.maxclients)
{
svent->priv.server->baseline.colormap = entnum;
else
{
svent->priv.server->baseline.colormap = 0;
- svent->priv.server->baseline.modelindex = svent->fields.server->modelindex;
+ svent->priv.server->baseline.modelindex = (int)svent->fields.server->modelindex;
}
large = false;
{
int i, j;
- svs.serverflags = prog->globals.server->serverflags;
+ svs.serverflags = (int)prog->globals.server->serverflags;
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
{
svs.changelevel_issued = false; // now safe to issue another
+ // make the map a required file for clients
+ Curl_ClearRequirements();
+ Curl_RequireFile(modelname);
+
//
// tell all connected clients that we are going to a new level
//
worldmodel->used = true;
strlcpy (sv.name, server, sizeof (sv.name));
- strcpy(sv.modelname, modelname);
+ strlcpy(sv.modelname, modelname, sizeof(sv.modelname));
sv.worldmodel = worldmodel;
sv.models[1] = sv.worldmodel;
// run two frames to allow everything to settle
for (i = 0;i < 2;i++)
{
- sv.frametime = host_frametime = 0.1;
+ sv.frametime = 0.1;
SV_Physics ();
}
//KrimZon - SERVER COMMANDS IN QUAKEC
mfunction_t *SV_ParseClientCommandQC;
-ddef_t *PRVM_ED_FindGlobal(const char *name);
-
void SV_VM_FindEdictFieldOffsets(void)
{
eval_gravity = PRVM_ED_FindFieldOffset("gravity");
EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
//KrimZon - SERVER COMMANDS IN QUAKEC
SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
-
- //[515]: init stufftext string (it is sent before svc_serverinfo)
- if(PRVM_ED_FindGlobal("SV_InitCmd") && PRVM_ED_FindGlobal("SV_InitCmd")->type & ev_string)
- SV_InitCmd = PRVM_G_STRING(PRVM_ED_FindGlobal("SV_InitCmd")->ofs);
- else
- SV_InitCmd = NULL;
-
gval_trace_dpstartcontents = PRVM_ED_FindGlobalOffset("trace_dpstartcontents");
gval_trace_dphitcontents = PRVM_ED_FindGlobalOffset("trace_dphitcontents");
gval_trace_dphitq3surfaceflags = PRVM_ED_FindGlobalOffset("trace_dphitq3surfaceflags");
void SV_VM_Setup(void)
{
+ unsigned char *csprogsdata;
+ fs_offset_t csprogsdatasize;
+ unsigned int csprogsdatacrc;
PRVM_Begin;
PRVM_InitProg( PRVM_SERVERPROG );
// allocate the mempools
+ // TODO: move the magic numbers/constants into #defines [9/13/2006 Black]
prog->progs_mempool = Mem_AllocPool("Server Progs", 0, NULL);
prog->builtins = vm_sv_builtins;
prog->numbuiltins = vm_sv_numbuiltins;
EntityFrameCSQC_ClearVersions();//[515]: csqc
PRVM_End;
+
+ // see if there is a csprogs.dat installed, and if so, set the csqc_progcrc accordingly, this will be sent to connecting clients to tell them to only load a matching csprogs.dat file
+ csprogsdatacrc = 0;
+ csprogsdata = FS_LoadFile(csqc_progname.string, tempmempool, true, &csprogsdatasize);
+ if (csprogsdata)
+ {
+ csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize);
+ Mem_Free(csprogsdata);
+ }
+ Cvar_SetValueQuick(&csqc_progcrc, csprogsdatacrc);
}
void SV_VM_Begin(void)