Track areas properly, so we don't bug out when a client has multiple cameras in different areas.

Fix up r_ignoreentpvs 0 to check areas properly.
checkpvs builtin can no longer mess up area checks elsewhere.
Write out foo.db files for release builds, in the hopes of at least getting function names from release-build crashes.
Implement _skyroom worldspawn field, still needs a few tweaks though.
Try to fix android surface-related crashes, AGAIN.
Separate parsing of connect requests, in preparation for formal logins (and removal of the old ranking code).
A few tweaks to try to improve compatibility with q3 mods.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5484 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-07-02 04:12:20 +00:00
parent 6c7220324e
commit 8197e0875f
64 changed files with 1336 additions and 959 deletions

View file

@ -852,10 +852,6 @@ void PR_Deinit(void)
World_Destroy(&sv.world);
#ifdef SQL
SQL_KillServers();
#endif
//clear out function pointers (so changing game modes cannot lead to confusions)
memset(&gfuncs, 0, sizeof(gfuncs));
SpectatorConnect = 0;
@ -863,14 +859,6 @@ void PR_Deinit(void)
SpectatorDisconnect = 0;
}
void PR_Shutdown(void)
{
PR_Deinit();
#ifdef SQL
SQL_DeInit();
#endif
}
void PR_LoadGlabalStruct(qboolean muted)
{
static float svphysicsmode = 2;
@ -1989,10 +1977,6 @@ void Q_InitProgs(qboolean cinematic)
Con_Printf(CON_ERROR"Running without gamecode\n");
}
#ifdef SQL
SQL_KillServers(); // TODO: is this the best placement for this?
#endif
if (oldprnum >= 0)
f = PR_FindFunction (svprogfuncs, "AddAddonProgs", oldprnum);
else
@ -3901,7 +3885,7 @@ void PF_newcheckclient (pubprogfuncs_t *prinst, world_t *w)
w->lastcheckpvs = NULL;
else
{
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, checkorg);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, checkorg, NULL);
w->lastcheckpvs = sv.world.worldmodel->funcs.ClusterPVS (sv.world.worldmodel, cluster, &checkpvsbuffer, PVM_FAST);
}
@ -3956,7 +3940,7 @@ int PF_checkclient_Internal (pubprogfuncs_t *prinst)
if (w->lastcheckpvs)
{
clust = w->worldmodel->funcs.ClusterForPoint(w->worldmodel, view);
clust = w->worldmodel->funcs.ClusterForPoint(w->worldmodel, view, NULL);
if ( (clust<0) || !(w->lastcheckpvs[clust>>3] & (1<<(clust&7)) ) )
{
return 0;
@ -6488,7 +6472,7 @@ void QCBUILTIN PF_sqlconnect (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
if (!driver[0])
driver = sql_driver.string;
G_FLOAT(OFS_RETURN) = SQL_NewServer(driver, paramstr);
G_FLOAT(OFS_RETURN) = SQL_NewServer(prinst, driver, paramstr);
}
void QCBUILTIN PF_sqldisconnect (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -6497,7 +6481,7 @@ void QCBUILTIN PF_sqldisconnect (pubprogfuncs_t *prinst, struct globalvars_s *pr
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
SQL_Disconnect(server);
@ -6555,7 +6539,7 @@ void QCBUILTIN PF_sqlopenquery (pubprogfuncs_t *prinst, struct globalvars_s *pr_
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
queryrequest_t *qreq;
@ -6597,7 +6581,7 @@ void QCBUILTIN PF_sqlclosequery (pubprogfuncs_t *prinst, struct globalvars_s *pr
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
qreq = SQL_GetQueryRequest(server, G_FLOAT(OFS_PARM1));
@ -6621,7 +6605,7 @@ void QCBUILTIN PF_sqlreadfield (pubprogfuncs_t *prinst, struct globalvars_s *pr_
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
@ -6653,7 +6637,7 @@ void QCBUILTIN PF_sqlreadfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
if (G_FLOAT(OFS_PARM2) < 0)
@ -6729,7 +6713,7 @@ void QCBUILTIN PF_sqlreadblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (SQL_Available())
{
server = SQL_GetServer(serveridx, false);
server = SQL_GetServer(prinst, serveridx, false);
if (server)
{
qres = SQL_GetQueryResult(server, queryidx, row);
@ -6791,7 +6775,7 @@ void QCBUILTIN PF_sqlerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), true);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), true);
if (server)
{
if (svprogfuncs->callargc == 2)
@ -6825,7 +6809,7 @@ void QCBUILTIN PF_sqlescape (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
toescape = PR_GetStringOfs(prinst, OFS_PARM1);
@ -6847,7 +6831,7 @@ void QCBUILTIN PF_sqlversion (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
server = SQL_GetServer(prinst, G_FLOAT(OFS_PARM0), false);
if (server)
{
RETURN_TSTRING(SQL_Info(server));

View file

@ -28,7 +28,6 @@ void SVQ1_CvarChanged(cvar_t *var);
#define NewGetEdictFieldValue GetEdictFieldValue
void Q_SetProgsParms(qboolean forcompiler);
void PR_Deinit(void); //server shutting down
void PR_Shutdown(void); //server quitting
void PR_LoadGlabalStruct(qboolean muted);
void Q_InitProgs(qboolean cinematic);
void PR_SpawnInitialEntities(const char *file);

View file

@ -400,7 +400,9 @@ typedef enum {
BOTLIB_PC_LOAD_SOURCE,
BOTLIB_PC_FREE_SOURCE,
BOTLIB_PC_READ_TOKEN,
BOTLIB_PC_SOURCE_FILE_AND_LINE
BOTLIB_PC_SOURCE_FILE_AND_LINE,
G_DEFAULTCASEWARNINGDISABLE //note: not an allowed index, just exists to prevent clang from warning about the default case.
} q3ggameImport_t;

View file

@ -448,6 +448,23 @@ enum
#define STUFFCMD_BROADCAST ( 1<<2) // everyone sees it.
#define STUFFCMD_UNRELIABLE ( 1<<3) // someone might not see it. oh well.
enum serverprotocols_e
{
SCP_BAD, //don't send (a bot)
SCP_QUAKEWORLD,
SCP_QUAKE2,
SCP_QUAKE3,
//all the below are considered netquake clients.
SCP_NETQUAKE,
//bjp1, bjp2
SCP_BJP3, //16bit angles,model+sound indexes. nothing else (assume raised ent limits too).
SCP_FITZ666,
//dp5
SCP_DARKPLACES6,
SCP_DARKPLACES7 //extra prediction stuff
//note, nq is nq+
};
typedef struct client_s
{
client_conn_state_t state;
@ -660,21 +677,7 @@ typedef struct client_s
unsigned int max_net_clients; /*max number of player slots supported by the client */
unsigned int maxmodels; /*max models supported by whatever the protocol is*/
enum {
SCP_BAD, //don't send (a bot)
SCP_QUAKEWORLD,
SCP_QUAKE2,
SCP_QUAKE3,
//all the below are considered netquake clients.
SCP_NETQUAKE,
//bjp1, bjp2
SCP_BJP3, //16bit angles,model+sound indexes. nothing else (assume raised ent limits too).
SCP_FITZ666,
//dp5
SCP_DARKPLACES6,
SCP_DARKPLACES7 //extra prediction stuff
//note, nq is nq+
} protocol;
enum serverprotocols_e protocol;
unsigned int supportedprotocols;
qboolean proquake_angles_hack; //expect 16bit client->server angles .
@ -1145,7 +1148,29 @@ char *SV_PlayerPublicAddress(client_t *cl);
qboolean SVC_GetChallenge (qboolean respond_dp);
int SV_NewChallenge (void);
client_t *SVC_DirectConnect(void);
void SVC_DirectConnect(int expectedreliablesequence);
typedef struct
{
enum serverprotocols_e protocol; //protocol used to talk to this client.
#ifdef NQPROT
qboolean proquakeanglehack; //specifies that the client will expect proquake angles if we give a proquake CCREP_ACCEPT response.
unsigned int expectedreliablesequence; //required for nq connection cookies (like tcp's syn cookies).
unsigned int supportedprotocols; //1<<SCP_* bitmask
#endif
unsigned int ftepext1;
unsigned int ftepext2;
// unsigned int ezpext1;
int qport; //part of the qw protocol to avoid issues with buggy routers that periodically renumber cl2sv ports.
#ifdef HUFFNETWORK
int huffcrc; //network compression stuff
#endif
int challenge; //the challenge used at connect. remembered to make life harder for proxies.
int mtu; //allowed fragment size (also signifies that it supports fragmented qw packets)
char userinfo[2048]; //random userinfo data. no blobs, obviously.
char guid[128]; //user's guid data
netadr_t adr; //the address the connect request came from (so we can check passwords before accepting)
} svconnectinfo_t;
void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info);
int SV_ModelIndex (const char *name);
@ -1213,13 +1238,15 @@ void MSV_SubServerCommand_f(void);
void MSV_SubServerCommand_f(void);
void MSV_MapCluster_f(void);
void SSV_Send(const char *dest, const char *src, const char *cmd, const char *msg);
qboolean MSV_ClusterLogin(char *guid, char *userinfo, size_t userinfosize);
qboolean MSV_ClusterLogin(svconnectinfo_t *info);
void MSV_PollSlaves(void);
void MSV_Status(void);
void MSV_OpenUserDatabase(void);
#else
#define SSV_UpdateAddresses() ((void)0)
#define MSV_ClusterLogin(guid,info,infosize) false
#define MSV_ClusterLogin(info) false
#define SSV_IsSubServer() false
#define MSV_OpenUserDatabase()
#endif
//

View file

@ -14,6 +14,24 @@
//FIXME: deadlocks when both gw and ss both fill their pipe buffers.
//FIXME: no networking for remote nodes.
//The servers are arranged as a 'tree'.
//There is only one root server, the one that used the 'mapcluster [startmap]' command.
// This is treated as a gateway, that clients connect to and then get redirected to one of the other servers.
// It may be a 'listen' server, with the server component offloaded to another process/thread.
// It may be a dedicated server started with the 'map' command (but not a listen server).
//Additional 'leaf' servers are automatically started on the same host.
// Will be started automatically when a player tries to transfer to a new/unknown map.
// leaf sends a ccmd_serveraddress at init+mapchanges
// root sends a ccmd_acceptserver to tell the new leaf what it should be.
//Transferring a player from one leaf to another:
// ccmd_transferplayer is sent to the root (which includes the player's parms)
// the root finds/creates the target server and sends it the ccmd_takeplayer message.
// destination tries to create a loadzombie and replies with ccmd_tookplayer (to accept or reject), which root forwards to the source
// source tells client to connect to the destination's address
// destination receives connection from client (or times out) and sends a ccmd_saveplayer(0) to the root, root sees the server change and sends ccmd_transferedplayer to the source.
// source knows that the player is no longer present (or aborts the transfer if it was a timeout, reenabling other transfers/retries).
#ifdef SUBSERVERS
#ifdef SQL
@ -22,7 +40,7 @@
extern cvar_t sv_serverip;
void VARGS SV_RejectMessage(int protocol, char *format, ...);
void VARGS SV_RejectMessage(enum serverprotocols_e protocol, char *format, ...);
void MSV_UpdatePlayerStats(unsigned int playerid, unsigned int serverid, int numstats, float *stats);
@ -43,7 +61,7 @@ typedef struct {
static pubsubserver_t *subservers;
static link_t clusterplayers;
qboolean isClusterSlave;
unsigned int nextserverid;
static unsigned int nextserverid;
static clusterplayer_t *MSV_FindPlayerId(unsigned int playerid)
{
@ -104,8 +122,8 @@ pubsubserver_t *MSV_FindSubServer(unsigned int id)
return NULL;
}
vfsfile_t *msv_loop_to_ss;
vfsfile_t *msv_loop_from_ss;
static vfsfile_t *msv_loop_to_ss;
static vfsfile_t *msv_loop_from_ss;
static void MSV_Loop_Instruct(pubsubserver_t *ps, sizebuf_t *cmd)
{
unsigned short size = cmd->cursize;
@ -289,7 +307,7 @@ void MSV_MapCluster_f(void)
};
Con_Printf("Opening database \"%s\"\n", sqlparams[3]);
sv.logindatabase = SQL_NewServer("sqlite", sqlparams);
sv.logindatabase = SQL_NewServer(&sv, "sqlite", sqlparams);
if (sv.logindatabase == -1)
#endif
{
@ -1097,7 +1115,7 @@ void SSV_InitiatePlayerTransfer(client_t *cl, const char *newserver)
#ifdef SQL
#include "sv_sql.h"
int pendinglookups = 0;
static int pendinglookups = 0;
struct logininfo_s
{
netadr_t clientaddr;
@ -1113,11 +1131,11 @@ void MSV_UpdatePlayerStats(unsigned int playerid, unsigned int serverid, int num
{
#ifdef SQL
queryrequest_t *req;
sqlserver_t *srv;
sqlserver_t *srv = SQL_GetServer(&sv, sv.logindatabase, false);
static char hex[16] = "0123456789abcdef";
char sql[2048], *sqle;
union{float *f;qbyte *b;} blob;
if (sv.logindatabase != -1)
if (srv)
{
Q_snprintfz(sql, sizeof(sql), "UPDATE accounts SET stats=x'");
sqle = sql+strlen(sql);
@ -1128,9 +1146,7 @@ void MSV_UpdatePlayerStats(unsigned int playerid, unsigned int serverid, int num
}
Q_snprintfz(sqle, sizeof(sql)-(sqle-sql), "', serverid=%u WHERE playerid = %u;", serverid, playerid);
srv = SQL_GetServer(sv.logindatabase, false);
if (srv)
SQL_NewQuery(srv, SV_IgnoreSQLResult, sql, &req);
SQL_NewQuery(srv, SV_IgnoreSQLResult, sql, &req);
}
#endif
}
@ -1199,81 +1215,121 @@ qboolean MSV_ClusterLoginReply(netadr_t *legacyclientredirect, unsigned int serv
#ifdef SQL
qboolean MSV_ClusterLoginSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof)
{
sqlserver_t *sql = SQL_GetServer(req->srvid, true);
sqlserver_t *sql = SQL_GetServer(&sv, req->srvid, true);
queryresult_t *res = SQL_GetQueryResult(sql, req->num, 0);
struct logininfo_s *info = req->user.thread;
svconnectinfo_t *info = req->user.thread;
char *s;
int playerid, serverid;
char *statsblob;
size_t blobsize;
res = SQL_GetQueryResult(sql, req->num, 0);
if (!res)
//we only expect one row. if its a continuation then don't bug out
if (!firstrow)
{
playerid = 0;
statsblob = NULL;
blobsize = 0;
serverid = 0;
res = SQL_GetQueryResult(sql, req->num, 0);
if (!res)
{
playerid = 0;
statsblob = NULL;
blobsize = 0;
serverid = 0;
}
else
{
s = SQL_ReadField(sql, res, 0, 0, true, NULL);
playerid = atoi(s);
statsblob = SQL_ReadField(sql, res, 0, 2, true, &blobsize);
s = SQL_ReadField(sql, res, 0, 1, true, NULL);
serverid = s?atoi(s):0;
}
net_from = info->adr; //okay, that's a bit stupid, rewrite rejectmessage to accept an arg?
if (!playerid)
SV_RejectMessage(info->protocol, "Bad username or password.\n");
else if (sv.state == ss_clustermode)
MSV_ClusterLoginReply(NULL, serverid, playerid, Info_ValueForKey(info->userinfo, "name"), info->guid, &info->adr, statsblob, blobsize);
else
SV_DoDirectConnect(info);
Z_Free(info);
req->user.thread = NULL;
pendinglookups--;
}
else
{
s = SQL_ReadField(sql, res, 0, 0, true, NULL);
playerid = atoi(s);
statsblob = SQL_ReadField(sql, res, 0, 2, true, &blobsize);
s = SQL_ReadField(sql, res, 0, 1, true, NULL);
serverid = s?atoi(s):0;
}
net_from = info->clientaddr; //okay, that's a bit stupid, rewrite rejectmessage to accept an arg?
if (!playerid)
SV_RejectMessage(SCP_QUAKEWORLD, "Bad username or password.\n");
else
MSV_ClusterLoginReply(NULL, serverid, playerid, info->name, info->guid, &info->clientaddr, statsblob, blobsize);
Z_Free(info);
pendinglookups--;
return false;
}
#endif
qboolean MSV_IgnoreSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof)
{
return false;
}
void MSV_OpenUserDatabase(void)
{
#if 0
sqlserver_t *sql;
const char *sqlparams[] =
{
"",
"",
"",
"login",
};
Con_Printf("Opening database \"%s\"\n", sqlparams[3]);
sv.logindatabase = SQL_NewServer(&sv, "sqlite", sqlparams);
//create a the accounts table, so we don't end up with unusable databases.
sql = SQL_GetServer(&sv, sv.logindatabase, false);
if (sql)
{
SQL_NewQuery(sql, MSV_IgnoreSQLResult,
"CREATE TABLE IF NOT EXISTS accounts("
"playerid INTEGER PRIMARY KEY,"
"name TEXT NOT NULL UNIQUE,"
"password TEXT,"
"serverid INTEGER,"
"parms BLOB,"
"parmstring TEXT"
");", NULL);
}
#endif
}
//returns true to block entry to this server.
extern int nextuserid;
qboolean MSV_ClusterLogin(char *guid, char *userinfo, size_t userinfosize)
qboolean MSV_ClusterLogin(svconnectinfo_t *info)
{
if (sv.state != ss_clustermode)
return false;
/*if (!*guid)
{
SV_RejectMessage(SCP_QUAKEWORLD, "No guid info, please set cl_sendguid to 1.\n");
return false;
}*/
#ifdef SQL
if (sv.logindatabase != -1)
{
char escname[64], escpasswd[64];
struct logininfo_s *info;
sqlserver_t *sql;
queryrequest_t *req;
if (pendinglookups > 10)
return true;
sql = SQL_GetServer(sv.logindatabase, false);
return true; //don't spam requests if we're getting dos-spammed.
sql = SQL_GetServer(&sv, sv.logindatabase, false);
if (!sql)
return true;
SQL_Escape(sql, Info_ValueForKey(userinfo, "name"), escname, sizeof(escname));
SQL_Escape(sql, Info_ValueForKey(userinfo, "password"), escpasswd, sizeof(escpasswd));
if (SQL_NewQuery(sql, MSV_ClusterLoginSQLResult, va("SELECT playerid,serverid,stats FROM accounts WHERE name='%s' AND password='%s';", escname, escpasswd), &req) != -1)
return true; //connection was killed? o.O
SQL_Escape(sql, Info_ValueForKey(info->userinfo, "name"), escname, sizeof(escname));
SQL_Escape(sql, Info_ValueForKey(info->userinfo, "password"), escpasswd, sizeof(escpasswd));
if (SQL_NewQuery(sql, MSV_ClusterLoginSQLResult, va("SELECT playerid,serverid,parms,parmstring FROM accounts WHERE name='%s' AND password='%s';", escname, escpasswd), &req) != -1)
{
pendinglookups++;
req->user.thread = info = Z_Malloc(sizeof(*info));
Q_strncpyz(info->guid, guid, sizeof(info->guid));
info->clientaddr = net_from;
req->user.thread = Z_Malloc(sizeof(*info));
memcpy(req->user.thread, info, sizeof(*info));
}
}
else
#endif
if (sv.state != ss_clustermode)
return false;
else
/* if (0)
{
char tmpbuf[256];
@ -1286,7 +1342,7 @@ qboolean MSV_ClusterLogin(char *guid, char *userinfo, size_t userinfosize)
return true;
}
else*/
MSV_ClusterLoginReply(NULL, 0, ++nextuserid, Info_ValueForKey(userinfo, "name"), guid, &net_from, NULL, 0);
MSV_ClusterLoginReply(NULL, 0, ++nextuserid, Info_ValueForKey(info->userinfo, "name"), info->guid, &net_from, NULL, 0);
return true;
}
#endif

View file

@ -33,6 +33,7 @@ typedef struct
int numents;
edict_t *ent[SV_PVS_CAMERAS]; //ents in this list are always sent, even if the server thinks that they are invisible.
vec3_t org[SV_PVS_CAMERAS];
int area[1+SV_PVS_CAMERAS];
pvsbuffer_t pvs;
} pvscamera_t;
@ -2695,7 +2696,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
continue;
// ignore if not touching a PV leaf
if (cameras && !sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &ent->pvsinfo, cameras->pvs.buffer))
if (cameras && !sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &ent->pvsinfo, cameras->pvs.buffer, &cameras->numents))
continue;
if (!((int)clent->xv->dimension_see & ((int)ent->xv->dimension_seen | (int)ent->xv->dimension_ghost)))
@ -3690,13 +3691,13 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
}
else
{
if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)tracecullent)->pvsinfo, cameras->pvs.buffer))
if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)tracecullent)->pvsinfo, cameras->pvs.buffer, cameras->area))
continue;
}
}
else
{
if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)ent)->pvsinfo, cameras->pvs.buffer))
if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)ent)->pvsinfo, cameras->pvs.buffer, cameras->area))
continue;
tracecullent = ent;
}
@ -3710,14 +3711,14 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
{
//FIXME: this lookup should be cachable or something.
if (client->edict)
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, client->edict->v->origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, client->edict->v->origin, NULL); //ignore areas, can hear through doors.
else
cluster = -1; //mvd
if (cluster >= 0)
{
mask = phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, ent->v->origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, ent->v->origin, NULL);
if (cluster >= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) )
{
continue;
@ -3859,6 +3860,7 @@ void SV_AddCameraEntity(pvscamera_t *cameras, edict_t *ent, vec3_t viewofs)
{
int i;
vec3_t org;
int area;
for (i = 0; i < cameras->numents; i++)
{
@ -3871,6 +3873,17 @@ void SV_AddCameraEntity(pvscamera_t *cameras, edict_t *ent, vec3_t viewofs)
else
VectorCopy (ent->v->origin, org);
sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, org, &area);
for (i = 1; ; i++)
{
if (i > cameras->area[0])
{ //reached the end of the known count. add it now.
cameras->area[++cameras->area[0]] = area;
break;
}
if (cameras->area[i] == area)
break; //already have a camera in this area, don't make stuff slow with dupes.
}
sv.world.worldmodel->funcs.FatPVS(sv.world.worldmodel, org, &cameras->pvs, cameras->numents!=0);
if (cameras->numents < SV_PVS_CAMERAS)
{
@ -3882,6 +3895,7 @@ void SV_AddCameraEntity(pvscamera_t *cameras, edict_t *ent, vec3_t viewofs)
void SV_Snapshot_SetupPVS(client_t *client, pvscamera_t *camera)
{
camera->area[0] = 0;
camera->numents = 0;
for (; client; client = client->controlled)
{

View file

@ -20,6 +20,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "pr_common.h"
#ifdef SQL
#include "sv_sql.h"
#endif
#ifndef CLIENTONLY
extern int total_loading_size, current_loading_size, loading_stage;
char *T_GetString(int num);
@ -798,6 +801,9 @@ void SV_WipeServerState(void)
for (i = 0; i < sizeof(sv.strings) / sizeof(sv.strings.ptrs[0]); i++)
Z_Free(ptrs[i]);
}
#ifdef SQL
SQL_KillServers(&sv);
#endif
memset (&sv, 0, sizeof(sv));
sv.logindatabase = -1;
}
@ -1103,6 +1109,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
sv.state = ss_loading;
MSV_OpenUserDatabase();
sv.world.max_edicts = pr_maxedicts.value;
if (sv.world.max_edicts > MAX_EDICTS)
sv.world.max_edicts = MAX_EDICTS;

File diff suppressed because it is too large Load diff

View file

@ -781,7 +781,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
mask = NULL;
else
{
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin, NULL);
if (cluster >= 0)
mask = sv.world.worldmodel->phs + cluster*sv.world.worldmodel->pvsbytes;
else
@ -792,7 +792,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
case MULTICAST_PVS_R:
reliable = true; // intentional fallthrough
case MULTICAST_PVS:
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin, NULL);
if (cluster >= 0)
mask = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, cluster, NULL, PVM_FAST);
else
@ -877,7 +877,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
{
vec3_t pos;
VectorAdd(split->edict->v->origin, split->edict->v->view_ofs, pos);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos, NULL);
if (cluster>= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) )
{
// Con_Printf ("PVS supressed multicast\n");
@ -1042,7 +1042,7 @@ void SV_MulticastCB(vec3_t origin, multicast_t to, const char *reliableinfokey,
mask = NULL;
else
{
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin, NULL);
if (cluster >= 0)
mask = sv.world.worldmodel->phs + cluster * sv.world.worldmodel->pvsbytes;
else
@ -1053,7 +1053,7 @@ void SV_MulticastCB(vec3_t origin, multicast_t to, const char *reliableinfokey,
case MULTICAST_PVS_R:
reliable = true; // intentional fallthrough
case MULTICAST_PVS:
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin);
cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin, NULL);
if (cluster >= 0)
mask = sv.world.worldmodel->funcs.ClusterPVS(sv.world.worldmodel, cluster, NULL, PVM_FAST);
else
@ -1127,7 +1127,7 @@ void SV_MulticastCB(vec3_t origin, multicast_t to, const char *reliableinfokey,
{
vec3_t pos;
VectorAdd(split->edict->v->origin, split->edict->v->view_ofs, pos);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos);
cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, pos, NULL);
if (cluster>= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) )
{
// Con_Printf ("PVS supressed multicast\n");

View file

@ -166,10 +166,14 @@ queryrequest_t *SQL_PullRequest(sqlserver_t *server, qboolean lock)
return qreq;
}
sqlserver_t **sqlservers;
int sqlservercount;
int sqlavailable;
int sqlinited;
struct
{
void *owner;
sqlserver_t *handle;
} *sqlservers;
static int sqlservercount;
static int sqlavailable;
static int sqlinited;
#ifdef USE_SQLITE
//this is to try to sandbox sqlite so it can only edit the file its originally opened with.
@ -506,15 +510,17 @@ int sql_serverworker(void *sref)
return 0;
}
sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives)
sqlserver_t *SQL_GetServer (void *owner, int serveridx, qboolean inactives)
{
if (serveridx < 0 || serveridx >= sqlservercount)
return NULL;
if (!sqlservers[serveridx])
if (owner && sqlservers[serveridx].owner != owner)
return NULL;
if (!inactives && sqlservers[serveridx]->active == false)
if (!sqlservers[serveridx].handle)
return NULL;
return sqlservers[serveridx];
if (!inactives && sqlservers[serveridx].handle->active == false)
return NULL;
return sqlservers[serveridx].handle;
}
queryrequest_t *SQL_GetQueryRequest (sqlserver_t *server, int queryidx)
@ -801,7 +807,7 @@ void SQL_CleanupServer(sqlserver_t *server)
Z_Free(server);
}
int SQL_NewServer(const char *driver, const char **paramstr)
int SQL_NewServer(void *owner, const char *driver, const char **paramstr)
{
sqlserver_t *server;
int serverref;
@ -851,13 +857,13 @@ int SQL_NewServer(const char *driver, const char **paramstr)
{
serverref = 0;
sqlservercount = 1;
sqlservers = (sqlserver_t **)BZ_Malloc(sizeof(sqlserver_t *));
sqlservers = BZ_Malloc(sizeof(*sqlservers));
}
else
{
serverref = sqlservercount;
sqlservercount++;
sqlservers = (sqlserver_t **)BZ_Realloc(sqlservers, sizeof(sqlserver_t *) * sqlservercount);
sqlservers = BZ_Realloc(sqlservers, sizeof(*sqlservers) * sqlservercount);
}
// assemble server structure
@ -883,7 +889,8 @@ int SQL_NewServer(const char *driver, const char **paramstr)
// string should be null-terminated due to Z_Malloc
}
sqlservers[serverref] = server;
sqlservers[serverref].owner = owner;
sqlservers[serverref].handle = server;
server->driver = (sqldrv_t)drvchoice;
server->querynum = 1;
@ -944,11 +951,13 @@ int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req,
SQL_PushRequest(server, qreq);
Sys_ConditionSignal(server->requestcondv);
*reqout = qreq;
if (reqout)
*reqout = qreq;
return querynum;
}
*reqout = NULL;
if (reqout)
*reqout = NULL;
return -1;
}
@ -1079,7 +1088,7 @@ void SQL_Status_f(void)
queryrequest_t *qreq;
queryresult_t *qres;
sqlserver_t *server = sqlservers[i];
sqlserver_t *server = sqlservers[i].handle;
if (!server)
continue;
@ -1168,7 +1177,7 @@ void SQL_Kill_f (void)
return;
}
server = SQL_GetServer(atoi(Cmd_Argv(1)), false);
server = SQL_GetServer(NULL, atoi(Cmd_Argv(1)), false);
if (server)
{
server->active = false;
@ -1179,7 +1188,7 @@ void SQL_Kill_f (void)
void SQL_Killall_f (void)
{
SQL_KillServers();
SQL_KillServers(NULL);
}
void SQL_ServerCycle (void)
@ -1188,7 +1197,7 @@ void SQL_ServerCycle (void)
for (i = 0; i < sqlservercount; i++)
{
sqlserver_t *server = sqlservers[i];
sqlserver_t *server = sqlservers[i].handle;
queryresult_t *qres;
queryrequest_t *qreq;
@ -1244,7 +1253,7 @@ void SQL_ServerCycle (void)
if (server->terminated)
{
sqlservers[i] = NULL;
sqlservers[i].handle = NULL;
SQL_CleanupServer(server);
continue;
}
@ -1294,28 +1303,36 @@ void SQL_Init(void)
Cvar_Register(&sql_defaultdb, SQLCVAROPTIONS);
}
void SQL_KillServers(void)
void SQL_KillServers(void *owner)
{
int i;
for (i = 0; i < sqlservercount; i++)
for (i = sqlservercount; i-- > 0; )
{
sqlserver_t *server = sqlservers[i];
sqlservers[i] = NULL;
if (!server)
continue;
SQL_CleanupServer(server);
if (!owner || sqlservers[i].owner == owner)
{
sqlserver_t *server = sqlservers[i].handle;
sqlservers[i].handle = NULL;
sqlservers[i].owner = NULL;
if (server)
SQL_CleanupServer(server);
if (sqlservercount == i+1)
sqlservercount--;
}
}
if (!sqlservercount)
{
if (sqlservers)
Z_Free(sqlservers);
sqlservers = NULL;
}
if (sqlservers)
Z_Free(sqlservers);
sqlservers = NULL;
sqlservercount = 0;
}
void SQL_DeInit(void)
{
sqlavailable = 0;
SQL_KillServers();
SQL_KillServers(NULL);
sqlinited = false;
#ifdef USE_MYSQL

View file

@ -95,10 +95,10 @@ typedef struct sqlserver_s
/* prototypes */
void SQL_Init(void);
void SQL_KillServers(void);
void SQL_KillServers(void *owner);
void SQL_DeInit(void);
sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives);
sqlserver_t *SQL_GetServer (void *owner, int serveridx, qboolean inactives);
queryrequest_t *SQL_GetQueryRequest (sqlserver_t *server, int queryidx);
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx, int row);
//void SQL_DeallocResult(sqlserver_t *server, queryresult_t *qres);
@ -107,7 +107,7 @@ void SQL_CloseResult(sqlserver_t *server, queryresult_t *qres);
void SQL_CloseRequest(sqlserver_t *server, queryrequest_t *qres, qboolean force);
void SQL_CloseAllResults(sqlserver_t *server);
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields, size_t *resultsize);
int SQL_NewServer(const char *driver, const char **paramstr);
int SQL_NewServer(void *owner, const char *driver, const char **paramstr);
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), const char *str, queryrequest_t **reqout); //callback will be called on the main thread once the result is back
void SQL_Disconnect(sqlserver_t *server);
void SQL_Escape(sqlserver_t *server, const char *src, char *dst, int dstlen);

View file

@ -723,14 +723,6 @@ static qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_
maxs1[0] >= mins2[0] && maxs1[1] >= mins2[1] && maxs1[2] >= mins2[2]);
}
typedef struct {
int serverTime;
int angles[3];
int buttons;
qbyte weapon; // weapon
signed char forwardmove, rightmove, upmove;
} q3usercmd_t;
#define CMD_MASK Q3UPDATE_MASK
static qboolean SVQ3_GetUserCmd(int clientnumber, q3usercmd_t *ucmd)
{
usercmd_t *cmd;
@ -768,7 +760,7 @@ void SVQ3_SendServerCommand(client_t *cl, char *str)
}
cl->server_command_sequence++;
Q_strncpyz(cl->server_commands[cl->server_command_sequence & TEXTCMD_MASK], str, sizeof(cl->server_commands[0]));
Q_strncpyz(cl->server_commands[cl->server_command_sequence & Q3TEXTCMD_MASK], str, sizeof(cl->server_commands[0]));
}
void SVQ3_SendConfigString(client_t *dest, int num, char *string)
@ -839,7 +831,7 @@ static int SVQ3_BotGetConsoleMessage( int client, char *buf, int size )
return false;
cl->server_command_ack++;
index = cl->server_command_ack & TEXTCMD_MASK;
index = cl->server_command_ack & Q3TEXTCMD_MASK;
if ( !cl->server_commands[index][0] )
return false;
@ -861,11 +853,55 @@ static void SVQ3_Adjust_Area_Portal_State(q3sharedEntity_t *ge, qboolean open)
CMQ3_SetAreaPortalState(sv.world.worldmodel, se->areanum, se->areanum2, open);
}
static qboolean SV_InPVS(vec3_t p1, vec3_t p2)
{
model_t *worldmodel = sv.world.worldmodel;
if (!worldmodel || worldmodel->loadstate != MLS_LOADED)
return false; //still loading, don't give bad results.
else if (!worldmodel->funcs.FatPVS)
return true; //no pvs info, assume everything is visible
else
{
#if 1
int l1 = CM_PointLeafnum(worldmodel, p1);
int l2 = CM_PointLeafnum(worldmodel, p2);
int c1 = CM_LeafCluster(worldmodel, l1);
int c2 = CM_LeafCluster(worldmodel, l2);
qbyte *pvs;
if (c1 < 0 || c2 < 0)
return (c1<0); //outside can see in, inside cannot (normally) see out.
pvs = CM_ClusterPVS(worldmodel, c1, NULL, PVM_FAST);
if (pvs[c2>>3] & (1<<(c2&7)))
{
int a1 = CM_LeafArea(worldmodel, l1);
int a2 = CM_LeafArea(worldmodel, l2);
if (CM_AreasConnected(worldmodel, a1, a2))
return true;
}
return false;
#else
const qbyte *mask;
int c1 = worldmodel->funcs.ClusterForPoint(worldmodel, p1);
int c2 = worldmodel->funcs.ClusterForPoint(worldmodel, p2);
if (c1 < 0 || c2 < 0)
return true; //one is outside of the world, so can see inside.
mask = worldmodel->funcs.ClusterPVS(worldmodel, c1, NULL, PVM_FAST);
if (mask[c2>>3] & (1<<(c2&7)))
{
//FIXME: check areas/portals too
return true; //visible
}
return false; //nope. :(
#endif
}
}
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to game trap %u passes invalid pointer\n", (unsigned int)fn); //out of bounds.
static qintptr_t Q3G_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
{
int ret = 0;
switch(fn)
switch((q3ggameImport_t)fn)
{
case G_PRINT: // ( const char *string );
Con_Printf("%s", (char*)VM_POINTER(arg[0]));
@ -946,16 +982,17 @@ static qintptr_t Q3G_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, co
case G_FS_FOPEN_FILE: //fopen
if ((int)arg[1] + 4 >= mask || VM_POINTER(arg[1]) < offset)
break; //out of bounds.
VM_LONG(ret) = VM_fopen(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), 0);
ret = VM_fopen(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), 0);
break;
case G_FS_READ: //fread
if ((int)arg[0] + VM_LONG(arg[1]) >= mask || VM_POINTER(arg[0]) < offset)
break; //out of bounds.
VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 0);
ret = VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 0);
break;
case G_FS_WRITE: //fwrite
ret = VM_FWrite(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 0);
break;
case G_FS_FCLOSE_FILE: //fclose
VM_fclose(VM_LONG(arg[0]), 0);
@ -1081,8 +1118,8 @@ static qintptr_t Q3G_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, co
return !!mapentspointer;
case G_REAL_TIME: // 41
VM_FLOAT(ret) = realtime;
return ret;
VALIDATEPOINTER(arg[0], sizeof(q3time_t));
return Q3VM_GetRealtime(VM_POINTER(arg[0]));
case G_SNAPVECTOR:
{
float *fp = (float *)VM_POINTER( arg[0] );
@ -1566,9 +1603,30 @@ static qintptr_t Q3G_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, co
#endif
case G_IN_PVS:
return SV_InPVS(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
case G_AREAS_CONNECTED: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_AREAS_CONNECTED"); return ret;
case G_DEBUG_POLYGON_CREATE: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_DEBUG_POLYGON_CREATE"); return ret;
case G_DEBUG_POLYGON_DELETE: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_DEBUG_POLYGON_DELETE"); return ret;
case G_IN_PVS_IGNORE_PORTALS: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_IN_PVS_IGNORE_PORTALS"); return ret;
case G_MATRIXMULTIPLY: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_MATRIXMULTIPLY"); return ret;
case G_ANGLEVECTORS:
VALIDATEPOINTER(arg[1], sizeof(vec3_t));
VALIDATEPOINTER(arg[2], sizeof(vec3_t));
VALIDATEPOINTER(arg[3], sizeof(vec3_t));
AngleVectors(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_POINTER(arg[3]));
break;
case G_PERPENDICULARVECTOR: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_PERPENDICULARVECTOR"); return ret;
VALIDATEPOINTER(arg[1], sizeof(vec3_t));
PerpendicularVector(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
break;
case G_FS_SEEK: Con_Printf("Q3Game: builtin %s is not implemented\n", "G_FS_SEEK"); return ret;
return VM_FSeek(arg[0], arg[1], arg[2], 0);
//case G_DEFAULTCASEWARNINGDISABLE: NOT A REAL VALUE
// notimplemented:
default:
Con_Printf("builtin %i is not implemented\n", (int)fn);
Con_Printf("Q3Game: builtin %i is not known\n", (int)fn);
}
return ret;
}
@ -2709,7 +2767,7 @@ static void SVQ3_WriteServerCommandsToClient(client_t *client, sizebuf_t *msg)
{
MSG_WriteBits(msg, svcq3_serverCommand, 8);
MSG_WriteBits(msg, i, 32);
str = client->server_commands[i & TEXTCMD_MASK];
str = client->server_commands[i & Q3TEXTCMD_MASK];
len = strlen(str);
for (j = 0; j <= len; j++)
MSG_WriteBits(msg, str[j], 8);
@ -2905,7 +2963,7 @@ static qboolean SVQ3_Netchan_Process(client_t *client)
// calculate bitmask
bitmask = (serverid ^ lastSequence ^ client->challenge) & 0xff;
string = client->server_commands[lastServerCommandNum & TEXTCMD_MASK];
string = client->server_commands[lastServerCommandNum & Q3TEXTCMD_MASK];
#ifndef Q3_NOENCRYPT
// decrypt the packet
@ -3003,7 +3061,7 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
return; // was dropped
// calculate key for usercmd decryption
string = client->server_commands[client->server_command_ack & TEXTCMD_MASK];
string = client->server_commands[client->server_command_ack & Q3TEXTCMD_MASK];
key = client->last_sequence ^ fs_key ^ StringKey(string, 32);
// read delta sequenced usercmds
@ -3219,8 +3277,8 @@ void SVQ3_ParseClientMessage(client_t *client)
// read last server command number client received
client->server_command_ack = MSG_ReadBits(32);
if( client->server_command_ack <= client->server_command_sequence - TEXTCMD_BACKUP )
client->server_command_ack = client->server_command_sequence - TEXTCMD_BACKUP + 1; //too old
if( client->server_command_ack <= client->server_command_sequence - Q3TEXTCMD_BACKUP )
client->server_command_ack = client->server_command_sequence - Q3TEXTCMD_BACKUP + 1; //too old
else if( client->server_command_ack > client->server_command_sequence )
client->server_command_ack = client->server_command_sequence; //client is from the future? o.O make fatal?
@ -3341,8 +3399,11 @@ void SVQ3_NewMapConnects(void)
if (svs.clients[i].state < cs_connected)
continue;
ret = VM_Call(q3gamevm, GAME_CLIENT_CONNECT, i, false, svs.clients[i].protocol == SCP_BAD);
if (ret || (gametype->value == 2 && svs.clients[i].protocol == SCP_BAD))
if (gametype->value == 2 && svs.clients[i].protocol == SCP_BAD)
ret = true;
else
ret = VM_Call(q3gamevm, GAME_CLIENT_CONNECT, i, false, svs.clients[i].protocol == SCP_BAD);
if (ret)
{
SV_DropClient(&svs.clients[i]);
}
@ -3461,6 +3522,7 @@ int SVQ3_AddBot(void)
cl->state = cs_spawned;
memset(&cl->netchan.remote_address, 0, sizeof(cl->netchan.remote_address));
GENTITY_FOR_NUM(cl-svs.clients)->s.number = cl-svs.clients;
return cl - svs.clients;
}

View file

@ -138,7 +138,7 @@ qboolean World_BoxTrace(struct model_s *model, int hulloverride, int frame, vec3
VectorCopy (p2, trace->endpos);
return Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, p1, p2, against, trace);
}
qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, const framestate_t *framestate, const vec3_t axis[3], const vec3_t p1, const vec3_t p2, const vec3_t mins, const vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
{
//bbox vs capsule (NYI)
//capsule vs capsule (NYI)
@ -196,7 +196,7 @@ qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, framestate_
}
return false;
}
model_t *World_CapsuleForBox(vec3_t mins, vec3_t maxs)
model_t *World_CapsuleForBox(const vec3_t mins, const vec3_t maxs)
{
VectorCopy(mins, mod_capsule.mins);
VectorCopy(maxs, mod_capsule.maxs);
@ -1068,7 +1068,7 @@ void WorldQ2_Q1BSP_LinkEdict(world_t *w, q2edict_t *ent)
#if defined(Q2BSPS) || defined(Q3BSPS)
void Q23BSP_FindTouchedLeafs(model_t *model, struct pvscache_s *ent, float *mins, float *maxs)
void Q23BSP_FindTouchedLeafs(model_t *model, struct pvscache_s *ent, const float *mins, const float *maxs)
{
#define MAX_TOTAL_ENT_LEAFS 128
int leafs[MAX_TOTAL_ENT_LEAFS];
@ -1536,7 +1536,7 @@ int World_AreaEdicts (world_t *w, vec3_t mins, vec3_t maxs, wedict_t **list, int
#endif
#ifdef Q2SERVER
float *area_mins, *area_maxs;
const float *area_mins, *area_maxs;
q2edict_t **area_q2list;
int area_count, area_maxcount;
int area_type;
@ -1598,7 +1598,7 @@ static void WorldQ2_AreaEdicts_r (areanode_t *node)
WorldQ2_AreaEdicts_r ( node->children[1] );
}
int VARGS WorldQ2_AreaEdicts (world_t *w, vec3_t mins, vec3_t maxs, q2edict_t **list,
int VARGS WorldQ2_AreaEdicts (world_t *w, const vec3_t mins, const vec3_t maxs, q2edict_t **list,
int maxcount, int areatype)
{
area_mins = mins;