misc fixes, tweaks, and hacks.

qc rt target api now uses names instead of numbers. shaders can name such rendertargets in advance.
added timing info to qc profiling, instead of just opcodes executed.
added sv_showconnectionlessmessages, to show all messages that don't relate to a client, so omc can see if he's getting DDOSed easily.
try to show proper error messages with the xmpp plugin, at least for certain things.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4714 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-08-03 14:47:47 +00:00
parent d63b8cefd6
commit 402aa52362
38 changed files with 502 additions and 269 deletions

View file

@ -3510,6 +3510,13 @@ void CL_LinkPacketEntities (void)
CL_RotateAroundTag(ent, state->number, state->tagentity, state->tagindex); CL_RotateAroundTag(ent, state->number, state->tagentity, state->tagindex);
} }
#ifdef RAGDOLL
if (model && model->dollinfo)
rag_updatedeltaent(ent, le);
ent->framestate.g[FS_REG].frame[0] &= ~0x8000;
ent->framestate.g[FS_REG].frame[1] &= ~0x8000;
#endif
CLQ1_AddShadow(ent); CLQ1_AddShadow(ent);
CLQ1_AddPowerupShell(ent, false, state->effects); CLQ1_AddPowerupShell(ent, false, state->effects);
@ -3527,11 +3534,6 @@ void CL_LinkPacketEntities (void)
VectorMA(dl->origin, 16, dl->axis[0], dl->origin); VectorMA(dl->origin, 16, dl->axis[0], dl->origin);
} }
#ifdef RAGDOLL
if (model && model->dollinfo)
rag_updatedeltaent(ent, le);
#endif
if (model2) if (model2)
CL_AddVWeapModel (ent, model2); CL_AddVWeapModel (ent, model2);

View file

@ -1511,6 +1511,8 @@ void CL_Disconnect_f (void)
CL_Disconnect (); CL_Disconnect ();
connectinfo.trying = false; connectinfo.trying = false;
CSQC_UnconnectedInit();
} }
/* /*

View file

@ -2424,10 +2424,10 @@ void CLDP_ParseDownloadBegin(char *s)
{ {
qdownload_t *dl = cls.download; qdownload_t *dl = cls.download;
char buffer[8192]; char buffer[8192];
unsigned int size, pos, chunk; qofs_t size, pos, chunk;
char *fname; char *fname;
Cmd_TokenizeString(s+1, false, false); Cmd_TokenizeString(s+1, false, false);
size = (unsigned int)atoi(Cmd_Argv(1)); size = (qofs_t)strtoull(Cmd_Argv(1), NULL, 0);
fname = Cmd_Argv(2); fname = Cmd_Argv(2);
if (!dl || strcmp(fname, dl->remotename)) if (!dl || strcmp(fname, dl->remotename))

View file

@ -4226,7 +4226,7 @@ typedef struct
qbyte srcdata[1]; qbyte srcdata[1];
} mp3decoder_t; } mp3decoder_t;
void S_MP3_Abort(sfx_t *sfx) static void S_MP3_Abort(sfx_t *sfx)
{ {
mp3decoder_t *dec = sfx->decoder.buf; mp3decoder_t *dec = sfx->decoder.buf;

View file

@ -312,7 +312,7 @@ typedef struct rendererinfo_s {
texid_tf (*IMG_LoadCompressed) (const char *name); texid_tf (*IMG_LoadCompressed) (const char *name);
texid_tf (*IMG_FindTexture) (const char *identifier, unsigned int flags); texid_tf (*IMG_FindTexture) (const char *identifier, unsigned int flags);
texid_tf (*IMG_AllocNewTexture) (const char *identifier, int w, int h, unsigned int flags); texid_tf (*IMG_AllocNewTexture) (const char *identifier, int w, int h, unsigned int flags);
void (*IMG_Upload) (texid_t tex, char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags); void (*IMG_Upload) (texid_t tex, const char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags);
void (*IMG_DestroyTexture) (texid_t tex); void (*IMG_DestroyTexture) (texid_t tex);
void (*R_Init) (void); //FIXME - merge implementations void (*R_Init) (void); //FIXME - merge implementations
@ -398,7 +398,7 @@ typedef struct rendererinfo_s {
#define BE_RenderToTextureUpdate2d rf->BE_RenderToTextureUpdate2d #define BE_RenderToTextureUpdate2d rf->BE_RenderToTextureUpdate2d
texid_t R2D_RT_Configure(unsigned int id, int width, int height, uploadfmt_t rtfmt); texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfmt);
texid_t R2D_RT_GetTexture(unsigned int id, unsigned int *width, unsigned int *height); texid_t R2D_RT_GetTexture(const char *id, unsigned int *width, unsigned int *height);
texid_t R2D_RT_DetachTexture(unsigned int id);

View file

@ -1557,44 +1557,47 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
r_refdef.useperspective = *p; r_refdef.useperspective = *p;
break; break;
case VF_RT_DESTCOLOUR: case VF_RT_DESTCOLOUR0:
if (prinst->callargc >= 4)
{ {
float fmt = G_FLOAT(OFS_PARM2); int i = parametertype - VF_RT_DESTCOLOUR0;
float *size = G_VECTOR(OFS_PARM3); Q_strncpyz(r_refdef.rt_destcolour[i].texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.rt_destcolour[i].texname));
R2D_RT_Configure(*p, size[0], size[1], fmt); if (prinst->callargc >= 4 && *r_refdef.rt_destcolour[i].texname)
{
float fmt = G_FLOAT(OFS_PARM2);
float *size = G_VECTOR(OFS_PARM3);
R2D_RT_Configure(r_refdef.rt_destcolour[i].texname, size[0], size[1], fmt);
}
BE_RenderToTextureUpdate2d(true);
} }
r_refdef.rt_destcolour = *p;
BE_RenderToTextureUpdate2d(true);
break; break;
case VF_RT_SOURCECOLOUR: case VF_RT_SOURCECOLOUR:
if (prinst->callargc >= 4) Q_strncpyz(r_refdef.rt_sourcecolour.texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.rt_sourcecolour));
if (prinst->callargc >= 4 && *r_refdef.rt_sourcecolour.texname)
{ {
float fmt = G_FLOAT(OFS_PARM2); float fmt = G_FLOAT(OFS_PARM2);
float *size = G_VECTOR(OFS_PARM3); float *size = G_VECTOR(OFS_PARM3);
R2D_RT_Configure(*p, size[0], size[1], fmt); R2D_RT_Configure(r_refdef.rt_sourcecolour.texname, size[0], size[1], fmt);
} }
r_refdef.rt_sourcecolour = *p;
BE_RenderToTextureUpdate2d(false); BE_RenderToTextureUpdate2d(false);
break; break;
case VF_RT_DEPTH: case VF_RT_DEPTH:
if (prinst->callargc >= 4) Q_strncpyz(r_refdef.rt_depth.texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.rt_depth.texname));
if (prinst->callargc >= 4 && *r_refdef.rt_depth.texname)
{ {
float fmt = G_FLOAT(OFS_PARM2); float fmt = G_FLOAT(OFS_PARM2);
float *size = G_VECTOR(OFS_PARM3); float *size = G_VECTOR(OFS_PARM3);
R2D_RT_Configure(*p, size[0], size[1], fmt); R2D_RT_Configure(r_refdef.rt_depth.texname, size[0], size[1], fmt);
} }
r_refdef.rt_depth = *p;
BE_RenderToTextureUpdate2d(false); BE_RenderToTextureUpdate2d(false);
break; break;
case VF_RT_RIPPLE: case VF_RT_RIPPLE:
if (prinst->callargc >= 4) Q_strncpyz(r_refdef.rt_ripplemap.texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.rt_ripplemap.texname));
if (prinst->callargc >= 4 && *r_refdef.rt_ripplemap.texname)
{ {
float fmt = G_FLOAT(OFS_PARM2); float fmt = G_FLOAT(OFS_PARM2);
float *size = G_VECTOR(OFS_PARM3); float *size = G_VECTOR(OFS_PARM3);
R2D_RT_Configure(*p, size[0], size[1], fmt); R2D_RT_Configure(r_refdef.rt_ripplemap.texname, size[0], size[1], fmt);
} }
r_refdef.rt_ripplemap = *p;
BE_RenderToTextureUpdate2d(false); BE_RenderToTextureUpdate2d(false);
break; break;
@ -2452,16 +2455,19 @@ static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct global
/*outgoing_sequence says how many packets have actually been sent, but there's an extra pending packet which has not been sent yet - be warned though, its data will change in the coming frames*/ /*outgoing_sequence says how many packets have actually been sent, but there's an extra pending packet which has not been sent yet - be warned though, its data will change in the coming frames*/
if (f == cl.movesequence) if (f == cl.movesequence)
{ {
int i;
cmd = &independantphysics[seat]; cmd = &independantphysics[seat];
for (f=0 ; f<3 ; f++)
cmd->angles[f] = ((int)(csqc_playerview->viewangles[f]*65536.0/360)&65535);
tmp = *cmd;
cmd = &tmp;
for (i=0 ; i<3 ; i++)
cmd->angles[i] = ((int)(csqc_playerview->viewangles[i]*65536.0/360)&65535);
if (!cmd->msec) if (!cmd->msec)
{ {
tmp = *cmd; // *cmd = cl.outframes[(f-1)&UPDATE_MASK].cmd[seat];
cmd = &tmp; CL_BaseMove (cmd, seat, 0, 72);
CL_BaseMove (&tmp, seat, 0, 72);
} }
cmd->msec = (realtime - cl.outframes[(f-1)&UPDATE_MASK].senttime)*1000;
} }
else else
{ {

View file

@ -34,14 +34,6 @@ static avec4_t draw_mesh_colors[4];
index_t r_quad_indexes[6] = {0, 1, 2, 2, 3, 0}; index_t r_quad_indexes[6] = {0, 1, 2, 2, 3, 0};
unsigned int r2d_be_flags; unsigned int r2d_be_flags;
static struct
{
texid_t id;
int width;
int height;
uploadfmt_t fmt;
} *rendertargets;
static unsigned int numrendertargets;
extern cvar_t scr_conalpha; extern cvar_t scr_conalpha;
extern cvar_t gl_conback; extern cvar_t gl_conback;
@ -125,10 +117,6 @@ void R2D_Shutdown(void)
cl_numstris = 0; cl_numstris = 0;
cl_maxstris = 0; cl_maxstris = 0;
while (numrendertargets>0)
R_DestroyTexture(rendertargets[--numrendertargets].id);
free(rendertargets);
rendertargets = NULL;
if (font_console == font_default) if (font_console == font_default)
font_console = NULL; font_console = NULL;
@ -1301,30 +1289,22 @@ void R2D_DrawCrosshair(void)
R2D_ImageColours(1, 1, 1, 1); R2D_ImageColours(1, 1, 1, 1);
} }
static texid_t internalrt;
//resize a texture for a render target and specify the format of it. //resize a texture for a render target and specify the format of it.
//pass TF_INVALID and sizes=0 to get without configuring (shaders that hardcode an $rt1 etc). //pass TF_INVALID and sizes=0 to get without configuring (shaders that hardcode an $rt1 etc).
texid_t R2D_RT_Configure(unsigned int id, int width, int height, uploadfmt_t rtfmt) texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfmt)
{ {
id--; //0 is invalid. texid_t tid;
if (id < 0 || id > 255) //sanity limit if (!strcmp(id, "-"))
return r_nulltex;
//extend the array if needed. these should be fairly light.
if (id >= numrendertargets)
{ {
rendertargets = realloc(rendertargets, (id+1) * sizeof(*rendertargets)); internalrt = tid = R_AllocNewTexture("", 0, 0, IF_NOMIPMAP);
while(numrendertargets <= id) }
{ else
rendertargets[numrendertargets].id = r_nulltex; {
rendertargets[numrendertargets].width = 0; tid = R_FindTexture(id, IF_NOMIPMAP);
rendertargets[numrendertargets].height = 0; if (!TEXVALID(tid))
rendertargets[numrendertargets].fmt = TF_INVALID; tid = R_AllocNewTexture(id, 0, 0, IF_NOMIPMAP);
numrendertargets++;
}
} }
if (!TEXVALID(rendertargets[id].id))
rendertargets[id].id = R_AllocNewTexture(va("", id+1), 0, 0, IF_NOMIPMAP);
if (rtfmt) if (rtfmt)
{ {
switch(rtfmt) switch(rtfmt)
@ -1337,55 +1317,31 @@ texid_t R2D_RT_Configure(unsigned int id, int width, int height, uploadfmt_t rtf
case 6: rtfmt = TF_DEPTH32; break; case 6: rtfmt = TF_DEPTH32; break;
default:rtfmt = TF_INVALID; break; default:rtfmt = TF_INVALID; break;
} }
R_Upload(tid, id, rtfmt, NULL, NULL, width, height, IF_NOMIPMAP);
// if (rendertargets[id].fmt != rtfmt || rendertargets[id].width != width || rendertargets[id].height != height) tid.ref->width = width;
{ tid.ref->height = height;
rendertargets[id].fmt = rtfmt;
rendertargets[id].width = width;
rendertargets[id].height = height;
R_Upload(rendertargets[id].id, "", rtfmt, NULL, NULL, width, height, IF_NOMIPMAP);
}
} }
return rendertargets[id].id; return tid;
} }
texid_t R2D_RT_GetTexture(unsigned int id, unsigned int *width, unsigned int *height) texid_t R2D_RT_GetTexture(const char *id, unsigned int *width, unsigned int *height)
{ {
if (!id) texid_t tid;
if (!strcmp(id, "-"))
tid = internalrt;
else
tid = R_FindTexture(id, IF_NOMIPMAP);
if (tid.ref)
{
*width = tid.ref->width;
*height = tid.ref->height;
}
else
{ {
*width = 0; *width = 0;
*height = 0; *height = 0;
return r_nulltex;
} }
id--; return tid;
if (id >= numrendertargets)
{
Con_Printf("Render target %u is not configured\n", id);
R2D_RT_Configure(id, 0, 0, TF_INVALID);
if (id >= numrendertargets)
{
*width = 0;
*height = 0;
return r_nulltex;
}
}
*width = rendertargets[id].width;
*height = rendertargets[id].height;
return rendertargets[id].id;
}
texid_t R2D_RT_DetachTexture(unsigned int id)
{
texid_t r;
id--;
if (id >= numrendertargets)
return r_nulltex;
r = rendertargets[id].id;
rendertargets[id].id = r_nulltex;
rendertargets[id].fmt = TF_INVALID;
rendertargets[id].width = 0;
rendertargets[id].height = 0;
return r;
} }
#endif #endif

View file

@ -215,7 +215,7 @@ void Surf_AddStain(vec3_t org, float red, float green, float blue, float radius)
for (i=1 ; i< pmove.numphysent ; i++) //0 is world... for (i=1 ; i< pmove.numphysent ; i++) //0 is world...
{ {
pe = &pmove.physents[i]; pe = &pmove.physents[i];
if (pe->model && pe->model->surfaces == cl.worldmodel->surfaces) if (pe->model && pe->model->surfaces == cl.worldmodel->surfaces && !pe->model->needload)
{ {
parms[1] = org[0] - pe->origin[0]; parms[1] = org[0] - pe->origin[0];
parms[2] = org[1] - pe->origin[1]; parms[2] = org[1] - pe->origin[1];

View file

@ -189,6 +189,11 @@ typedef struct
void CL_BlendFog(fogstate_t *result, fogstate_t *oldf, float time, fogstate_t *newf); void CL_BlendFog(fogstate_t *result, fogstate_t *oldf, float time, fogstate_t *newf);
void CL_ResetFog(void); void CL_ResetFog(void);
typedef struct {
char texname[MAX_QPATH];
} rtname_t;
#define R_MAX_RENDERTARGETS 8
#define R_MAX_RECURSE 6 #define R_MAX_RECURSE 6
#define R_POSTPROC_PASSES 6 #define R_POSTPROC_PASSES 6
#define RDFD_FOV 1 #define RDFD_FOV 1
@ -230,10 +235,10 @@ typedef struct
unsigned int flipcull; /*reflected/flipped view, requires inverted culling (should be set to SHADER_CULL_FLIPPED or 0)*/ unsigned int flipcull; /*reflected/flipped view, requires inverted culling (should be set to SHADER_CULL_FLIPPED or 0)*/
qboolean useperspective; /*not orthographic*/ qboolean useperspective; /*not orthographic*/
int rt_destcolour; /*used for 2d. written by 3d*/ rtname_t rt_destcolour[R_MAX_RENDERTARGETS]; /*used for 2d. written by 3d*/
int rt_sourcecolour; /*read by 2d. not used for 3d. */ rtname_t rt_sourcecolour; /*read by 2d. not used for 3d. */
int rt_depth; /*read by 2d. used by 3d (renderbuffer used if not set)*/ rtname_t rt_depth; /*read by 2d. used by 3d (renderbuffer used if not set)*/
int rt_ripplemap; /*read by 2d. used by 3d (internal ripplemap buffer used if not set)*/ rtname_t rt_ripplemap; /*read by 2d. used by 3d (internal ripplemap buffer used if not set)*/
qbyte *forcedvis; qbyte *forcedvis;
qboolean areabitsknown; qboolean areabitsknown;
@ -357,6 +362,8 @@ enum imageflags
IF_UIPIC = 1<<10, //subject to texturemode2d IF_UIPIC = 1<<10, //subject to texturemode2d
IF_LINEAR = 1<<11, IF_LINEAR = 1<<11,
IF_PREMULTIPLYALPHA = 1<<12, //rgb *= alpha IF_PREMULTIPLYALPHA = 1<<12, //rgb *= alpha
IF_RENDERTARGET = 1<<28, /*never loaded from disk, loading can't fail*/
IF_EXACTEXTENSION = 1<<29, IF_EXACTEXTENSION = 1<<29,
IF_REPLACE = 1<<30, IF_REPLACE = 1<<30,
IF_SUBDIRONLY = 1<<31 IF_SUBDIRONLY = 1<<31

View file

@ -149,7 +149,17 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
Con_Printf("Initing OSS sound device %s\n", snddev); Con_Printf("Initing OSS sound device %s\n", snddev);
#ifdef __linux__
//linux is a pile of shit.
//nonblock is needed to get around issues with the old/buggy linux oss3 clone implementation, as well as because this code is too lame to thread audio.
sc->audio_fd = open(snddev, O_RDWR | O_NONBLOCK); //try the primary device
//fixme: the following is desired once threading is supported.
//int flags = fcntl(fd, F_GETFL, 0);
//fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
#else
//FIXME: remove non-block if we're using threads.
sc->audio_fd = open(snddev, O_WRONLY | O_NONBLOCK); //try the primary device sc->audio_fd = open(snddev, O_WRONLY | O_NONBLOCK); //try the primary device
#endif
if (sc->audio_fd < 0) if (sc->audio_fd < 0)
{ {
perror(snddev); perror(snddev);

View file

@ -1536,7 +1536,7 @@ void Sys_Quit (void)
} }
#if 1 #if 0
/* /*
================ ================
Sys_DoubleTime Sys_DoubleTime

View file

@ -49,7 +49,7 @@ static texid_tf Headless_IMG_AllocNewTexture (const char *identifier, int w, int
{ {
return dummytex; return dummytex;
} }
static void Headless_IMG_Upload (texid_t tex, char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags) static void Headless_IMG_Upload (texid_t tex, const char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags)
{ {
} }
static void Headless_IMG_DestroyTexture (texid_t tex) static void Headless_IMG_DestroyTexture (texid_t tex)

View file

@ -235,7 +235,7 @@ qboolean NET_CompareAdr (netadr_t *a, netadr_t *b)
if (b->address.ip6[i] != 0) if (b->address.ip6[i] != 0)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++) for (; i < 12; i++)
if (b->address.ip6[i] != 0xff && b->address.ip6[i] != 0x00) //0x00 is depricated if (b->address.ip6[i] != 0xff)// && b->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
@ -251,7 +251,7 @@ qboolean NET_CompareAdr (netadr_t *a, netadr_t *b)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++) for (; i < 12; i++)
if (a->address.ip6[i] != 0xff && a->address.ip6[i] != 0x00) //0x00 is depricated if (a->address.ip6[i] != 0xff)// && a->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@ -1297,6 +1297,8 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
// NET_CompareAdrMasked: given 3 addresses, 2 to compare with a complimentary mask, // NET_CompareAdrMasked: given 3 addresses, 2 to compare with a complimentary mask,
// returns true or false if they match // returns true or false if they match
//WARNING: a is typically an ipv6 address, even if its an ipv4-mapped address.
//so ipv4ify first.
qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask) qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask)
{ {
int i; int i;
@ -1318,7 +1320,7 @@ qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask)
if (b->address.ip6[i] != 0) if (b->address.ip6[i] != 0)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++) for (; i < 12; i++)
if (b->address.ip6[i] != 0xff && b->address.ip6[i] != 0x00) //0x00 is depricated if (b->address.ip6[i] != 0xff)// && b->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
@ -1334,7 +1336,7 @@ qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask)
return false; //only matches if they're 0s, otherwise its not an ipv4 address there return false; //only matches if they're 0s, otherwise its not an ipv4 address there
for (; i < 12; i++) for (; i < 12; i++)
if (a->address.ip6[i] != 0xff && a->address.ip6[i] != 0x00) //0x00 is depricated if (a->address.ip6[i] != 0xff)// && a->address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)

View file

@ -1324,15 +1324,15 @@ void Plug_Initialise(qboolean fromgamedir)
Plug_Client_Init(); Plug_Client_Init();
} }
if (!fromgamedir) if (plug_loaddefault.value)
{ {
FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat)); if (!fromgamedir)
Con_DPrintf("Loading plugins from \"%s\"\n", nat); {
Sys_EnumerateFiles(nat, "fteplug_*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat));
} Con_DPrintf("Loading plugins from \"%s\"\n", nat);
if (fromgamedir) Sys_EnumerateFiles(nat, "fteplug_*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL);
{ }
if (plug_loaddefault.value) if (fromgamedir)
{ {
COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm");
} }

View file

@ -1218,8 +1218,8 @@ were contacted during the move.
*/ */
void PM_PlayerMove (float gamespeed) void PM_PlayerMove (float gamespeed)
{ {
int i; // int i;
int tmp; //for rounding // int tmp; //for rounding
frametime = pmove.cmd.msec * 0.001*gamespeed; frametime = pmove.cmd.msec * 0.001*gamespeed;
pmove.numtouch = 0; pmove.numtouch = 0;

View file

@ -577,10 +577,17 @@ typedef enum
VF_STATSENTITIY = 207, //the player number for the stats. VF_STATSENTITIY = 207, //the player number for the stats.
VF_SCREENVOFFSET = 208, VF_SCREENVOFFSET = 208,
VF_RT_DESTCOLOUR = 209, VF_RT_SOURCECOLOUR = 209,
VF_RT_SOURCECOLOUR = 210, VF_RT_DEPTH = 210,
VF_RT_DEPTH = 211, VF_RT_RIPPLE = 211, /**/
VF_RT_RIPPLE = 212, /**/ VF_RT_DESTCOLOUR0 = 212,
VF_RT_DESTCOLOUR1 = 213,
VF_RT_DESTCOLOUR2 = 214,
VF_RT_DESTCOLOUR3 = 215,
VF_RT_DESTCOLOUR4 = 216,
VF_RT_DESTCOLOUR5 = 217,
VF_RT_DESTCOLOUR6 = 218,
VF_RT_DESTCOLOUR7 = 219,
} viewflags; } viewflags;
/*FIXME: this should be changed*/ /*FIXME: this should be changed*/

View file

@ -125,6 +125,10 @@ void TL_InitLanguages(void)
*lang = 0; *lang = 0;
//we don't understand codesets sadly. //we don't understand codesets sadly.
lang = strrchr(sys_language, '.'); lang = strrchr(sys_language, '.');
if (lang)
*lang = 0;
//we also only support the single primary locale (no fallbacks, we're just using the language[+territory])
lang = strrchr(sys_language, ':');
if (lang) if (lang)
*lang = 0; *lang = 0;
//but we do support territories. //but we do support territories.

View file

@ -8853,6 +8853,14 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
/> />
</FileConfiguration> </FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath="..\client\in_win.c" RelativePath="..\client\in_win.c"
@ -11207,6 +11215,14 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
/> />
</FileConfiguration> </FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath="..\client\pr_csqc.c" RelativePath="..\client\pr_csqc.c"
@ -16872,6 +16888,7 @@
</FileConfiguration> </FileConfiguration>
<FileConfiguration <FileConfiguration
Name="Debug Dedicated Server|x64" Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
> >
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
@ -21383,7 +21400,6 @@
</FileConfiguration> </FileConfiguration>
<FileConfiguration <FileConfiguration
Name="Debug Dedicated Server|x64" Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
> >
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"

View file

@ -63,6 +63,12 @@ static hashtable_t skincolourmapped;
//q3 .skin support //q3 .skin support
static skinfile_t **registeredskins; static skinfile_t **registeredskins;
static skinid_t numregisteredskins; static skinid_t numregisteredskins;
struct cctx_s
{
texid_t diffuse;
int width;
int height;
};
void Mod_WipeSkin(skinid_t id) void Mod_WipeSkin(skinid_t id)
{ {
skinfile_t *sk; skinfile_t *sk;
@ -99,7 +105,7 @@ skinfile_t *Mod_LookupSkin(skinid_t id)
return registeredskins[id]; return registeredskins[id];
return NULL; return NULL;
} }
static void Mod_ComposeSkin(char *texture) static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
{ {
float x=0, y=0; float x=0, y=0;
float w, h; float w, h;
@ -121,19 +127,13 @@ static void Mod_ComposeSkin(char *texture)
//load the image and set some default sizes, etc. //load the image and set some default sizes, etc.
sourceimg = R2D_SafeCachePic(tname); sourceimg = R2D_SafeCachePic(tname);
if (!sourceimg) //no shader? no point in doing anything. if (sourceimg) //no shader? no point in doing anything.
return;
w = sourceimg->width;
h = sourceimg->height;
//create a render target if one is not already selected
if (!r_refdef.rt_destcolour)
{ {
r_refdef.rt_destcolour = 1; //fixme: this 1 here is a technicality. it will destroy this render target slot. we should find/make a free one instead. w = sourceimg->width;
R2D_RT_Configure(r_refdef.rt_destcolour, x+w, y+h, TF_RGBA32); h = sourceimg->height;
BE_RenderToTextureUpdate2d(true);
} }
else
w = h = 0;
while(*s) while(*s)
{ {
@ -171,6 +171,21 @@ static void Mod_ComposeSkin(char *texture)
} }
} }
if (!w || !h)
return;
//create a render target if one is not already selected
if (!TEXVALID(cctx->diffuse))
{
strcpy(r_refdef.rt_destcolour[0].texname, "-");
cctx->width = x+w;
cctx->height = y+h;
cctx->diffuse = R2D_RT_Configure(r_refdef.rt_destcolour[0].texname, cctx->width, cctx->height, TF_RGBA32);
BE_RenderToTextureUpdate2d(true);
}
if (!sourceimg)
return;
R2D_ImageColours(r,g,b,a); R2D_ImageColours(r,g,b,a);
R2D_Image(x, 512-(y+h), w, h, 0, 1, 1, 0, sourceimg); R2D_Image(x, 512-(y+h), w, h, 0, 1, 1, 0, sourceimg);
@ -233,6 +248,9 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
//body //body
if (com_tokentype != TTP_LINEENDING) if (com_tokentype != TTP_LINEENDING)
{ {
struct cctx_s cctx;
memset(&cctx, 0, sizeof(cctx));
Q_strncpyz(skin->mappings[skin->nummappings].surface, com_token, sizeof(skin->mappings[skin->nummappings].surface)); Q_strncpyz(skin->mappings[skin->nummappings].surface, com_token, sizeof(skin->mappings[skin->nummappings].surface));
skintext = COM_ParseToken(skintext, NULL); skintext = COM_ParseToken(skintext, NULL);
Q_strncpyz(shadername, com_token, sizeof(shadername)); Q_strncpyz(shadername, com_token, sizeof(shadername));
@ -249,14 +267,14 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
else else
break; break;
skintext = COM_Parse(skintext); skintext = COM_Parse(skintext);
Mod_ComposeSkin(com_token); Mod_ComposeSkin(com_token, &cctx);
} }
skin->mappings[skin->nummappings].needsfree = 1; skin->mappings[skin->nummappings].needsfree = 1;
skin->mappings[skin->nummappings].texnums.base = R2D_RT_DetachTexture(r_refdef.rt_destcolour); skin->mappings[skin->nummappings].texnums.base = cctx.diffuse;
skin->nummappings++; skin->nummappings++;
r_refdef.rt_destcolour = 0; *r_refdef.rt_destcolour[0].texname = 0;
BE_RenderToTextureUpdate2d(true); BE_RenderToTextureUpdate2d(true);
} }
} }

View file

@ -4523,9 +4523,9 @@ void GLBE_RenderToTextureUpdate2d(qboolean destchanged)
unsigned int width = 0, height = 0; unsigned int width = 0, height = 0;
if (destchanged) if (destchanged)
{ {
if (r_refdef.rt_destcolour) if (*r_refdef.rt_destcolour[0].texname)
{ {
texid_t tex = R2D_RT_GetTexture(r_refdef.rt_destcolour, &width, &height); texid_t tex = R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, &width, &height);
GLBE_FBO_Update(&shaderstate.fbo_2dfbo, true, FBO_TEX_COLOUR, tex, r_nulltex, width, height); GLBE_FBO_Update(&shaderstate.fbo_2dfbo, true, FBO_TEX_COLOUR, tex, r_nulltex, width, height);
} }
else else
@ -4535,8 +4535,8 @@ void GLBE_RenderToTextureUpdate2d(qboolean destchanged)
} }
else else
{ {
shaderstate.tex_sourcecol = R2D_RT_GetTexture(r_refdef.rt_sourcecolour, &width, &height); shaderstate.tex_sourcecol = R2D_RT_GetTexture(r_refdef.rt_sourcecolour.texname, &width, &height);
shaderstate.tex_sourcedepth = R2D_RT_GetTexture(r_refdef.rt_depth, &width, &height); shaderstate.tex_sourcedepth = R2D_RT_GetTexture(r_refdef.rt_depth.texname, &width, &height);
} }
} }
void GLBE_FBO_Sources(texid_t sourcecolour, texid_t sourcedepth) void GLBE_FBO_Sources(texid_t sourcecolour, texid_t sourcedepth)

View file

@ -93,10 +93,10 @@ void GL_UploadFmt(texid_t tex, const char *name, enum uploadfmt fmt, void *data,
GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP, GL_DEPTH_COMPONENT32_ARB); GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP, GL_DEPTH_COMPONENT32_ARB);
break; break;
case TF_RGBA16F: case TF_RGBA16F:
GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP, GL_RGBA16F_ARB); GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP|IF_CLAMP, GL_RGBA16F_ARB);
break; break;
case TF_RGBA32F: case TF_RGBA32F:
GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP, GL_RGBA32F_ARB); GL_Upload32_Int(name, NULL, width, height, flags|IF_NOMIPMAP|IF_CLAMP, GL_RGBA32F_ARB);
break; break;
default: default:
@ -590,11 +590,11 @@ void GL_Set2D (qboolean flipped)
float rad, ang; float rad, ang;
float tmp[16], tmp2[16]; float tmp[16], tmp2[16];
float w = vid.width, h = vid.height; float w = vid.width, h = vid.height;
qboolean fbo = !!r_refdef.rt_destcolour; qboolean fbo = !!*r_refdef.rt_destcolour[0].texname;
if (fbo) if (fbo)
{ {
R2D_RT_GetTexture(r_refdef.rt_destcolour, &vid.fbpwidth, &vid.fbpheight); R2D_RT_GetTexture(r_refdef.rt_destcolour[0].texname, &vid.fbpwidth, &vid.fbpheight);
vid.fbvwidth = vid.fbpwidth; vid.fbvwidth = vid.fbpwidth;
vid.fbvheight = vid.fbpheight; vid.fbvheight = vid.fbpheight;
} }
@ -1241,6 +1241,12 @@ static void GL_Upload32_Int (const char *name, unsigned *data, int width, int he
glcolormode = GL_DEPTH_COMPONENT; glcolormode = GL_DEPTH_COMPONENT;
type = GL_UNSIGNED_BYTE; type = GL_UNSIGNED_BYTE;
} }
else if (glcolormode == GL_RGBA16F_ARB || glcolormode == GL_RGBA32F_ARB)
{
samples = glcolormode;
glcolormode = GL_RGBA;
type = GL_FLOAT;
}
else if (gl_config.gles) else if (gl_config.gles)
{ {
glcolormode = GL_RGBA; /*our input is RGBA or RGBX, with the internal format restriction, we must therefore always have an alpha value*/ glcolormode = GL_RGBA; /*our input is RGBA or RGBX, with the internal format restriction, we must therefore always have an alpha value*/
@ -1319,7 +1325,8 @@ static void GL_Upload32_Int (const char *name, unsigned *data, int width, int he
GL_Texturemode_Apply(targ, flags); GL_Texturemode_Apply(targ, flags);
if (!data) if (!data)
qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data); scaled = NULL;
// qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data);
else if (scaled_width == width && scaled_height == height) else if (scaled_width == width && scaled_height == height)
{ {
if (((flags&IF_NOMIPMAP)||gl_config.sgis_generate_mipmap) && !(flags & IF_PREMULTIPLYALPHA)) //gotta love this with NPOT textures... :) if (((flags&IF_NOMIPMAP)||gl_config.sgis_generate_mipmap) && !(flags & IF_PREMULTIPLYALPHA)) //gotta love this with NPOT textures... :)
@ -1330,7 +1337,7 @@ static void GL_Upload32_Int (const char *name, unsigned *data, int width, int he
else if (type == GL_UNSIGNED_SHORT_4_4_4_4) else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
GL_8888to4444(targface, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height); GL_8888to4444(targface, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
else else
qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data); qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, type, data);
goto done; goto done;
} }
memcpy (scaled, data, width*height*4); memcpy (scaled, data, width*height*4);
@ -1367,7 +1374,7 @@ static void GL_Upload32_Int (const char *name, unsigned *data, int width, int he
else if (type == GL_UNSIGNED_SHORT_4_4_4_4) else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
GL_8888to4444(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height); GL_8888to4444(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
else else
qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled); qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, type, scaled);
if (!(flags&IF_NOMIPMAP) && !gl_config.sgis_generate_mipmap) if (!(flags&IF_NOMIPMAP) && !gl_config.sgis_generate_mipmap)
{ {
miplevel = 0; miplevel = 0;

View file

@ -1499,7 +1499,7 @@ r_refdef must be set before the first call
*/ */
void GLR_RenderView (void) void GLR_RenderView (void)
{ {
int dofbo = r_refdef.rt_destcolour || r_refdef.rt_depth; int dofbo = *r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname;
double time1 = 0, time2; double time1 = 0, time2;
checkglerror(); checkglerror();
@ -1525,18 +1525,27 @@ void GLR_RenderView (void)
if (dofbo) if (dofbo)
{ {
unsigned int flags = 0; unsigned int flags = 0;
texid_t col = r_nulltex, depth = r_nulltex; texid_t col[R_MAX_RENDERTARGETS], depth = r_nulltex;
unsigned int cw=0, ch=0, dw=0, dh=0; unsigned int cw=0, ch=0, dw=0, dh=0;
int mrt;
//3d views generally ignore source colour+depth. //3d views generally ignore source colour+depth.
//FIXME: support depth with no colour //FIXME: support depth with no colour
if (r_refdef.rt_destcolour) for (mrt = 0; mrt < R_MAX_RENDERTARGETS; mrt++)
col = R2D_RT_GetTexture(r_refdef.rt_destcolour, &cw, &ch); {
if (r_refdef.rt_depth) if (*r_refdef.rt_destcolour[mrt].texname)
depth = R2D_RT_GetTexture(r_refdef.rt_depth, &dw, &dh); col[mrt] = R2D_RT_GetTexture(r_refdef.rt_destcolour[mrt].texname, &cw, &ch);
else
{
col[mrt] = r_nulltex;
break;
}
}
if (*r_refdef.rt_depth.texname)
depth = R2D_RT_GetTexture(r_refdef.rt_depth.texname, &dw, &dh);
if (r_refdef.rt_destcolour) if (mrt)
{ //colour (with or without depth) { //colour (with or without depth)
if (r_refdef.rt_depth && (dw != cw || dh != dh)) if (*r_refdef.rt_depth.texname && (dw != cw || dh != dh))
{ {
Con_Printf("RT: destcolour and depth render targets are of different sizes\n"); //should check rgb/depth modes too I guess. Con_Printf("RT: destcolour and depth render targets are of different sizes\n"); //should check rgb/depth modes too I guess.
depth = r_nulltex; depth = r_nulltex;
@ -1549,13 +1558,13 @@ void GLR_RenderView (void)
vid.fbvwidth = vid.fbpwidth = dw; vid.fbvwidth = vid.fbpwidth = dw;
vid.fbvheight = vid.fbpheight = dh; vid.fbvheight = vid.fbpheight = dh;
} }
if (TEXVALID(col)) if (TEXVALID(col[0]))
flags |= FBO_TEX_COLOUR; flags |= FBO_TEX_COLOUR;
if (TEXVALID(depth)) if (TEXVALID(depth))
flags |= FBO_TEX_DEPTH; flags |= FBO_TEX_DEPTH;
else else
flags |= FBO_RB_DEPTH; flags |= FBO_RB_DEPTH;
GLBE_FBO_Update(&fbo_gameview, true, flags, col, depth, vid.fbpwidth, vid.fbpheight); GLBE_FBO_Update(&fbo_gameview, true, flags, col[0], depth, vid.fbpwidth, vid.fbpheight);
} }
else else
{ {

View file

@ -594,7 +594,17 @@ static int Shader_SetImageFlags(shader_t *shader, shaderpass_t *pass, char **nam
while (name) while (name)
{ {
if (!Q_strnicmp(*name, "$3d:", 4)) if (!Q_strnicmp(*name, "$rt:", 4))
{
*name += 4;
flags |= IF_RENDERTARGET;
}
else if (!Q_strnicmp(*name, "$clamp:", 7))
{
*name += 7;
flags |= IF_CLAMP;
}
else if (!Q_strnicmp(*name, "$3d:", 4))
{ {
*name+=4; *name+=4;
flags = (flags&~IF_TEXTYPE) | IF_3DMAP; flags = (flags&~IF_TEXTYPE) | IF_3DMAP;
@ -643,6 +653,13 @@ static texid_t Shader_FindImage ( char *name, int flags )
if (!Q_stricmp (name, "$whiteimage")) if (!Q_stricmp (name, "$whiteimage"))
return r_whiteimage; return r_whiteimage;
} }
if (flags & IF_RENDERTARGET)
{
texid_t tid = R_FindTexture(name, (flags&~IF_RENDERTARGET)|IF_NOMIPMAP);
if (!TEXVALID(tid))
tid = R_AllocNewTexture(name, 0, 0, (flags&~IF_RENDERTARGET)|IF_NOMIPMAP);
return tid;
}
return R_LoadHiResTexture(name, NULL, flags); return R_LoadHiResTexture(name, NULL, flags);
} }

View file

@ -697,7 +697,7 @@ reeval:
#endif #endif
} }
newf = &pr_functions[fnum & ~0xff000000]; newf = &pr_cp_functions[fnum & ~0xff000000];
if (newf->first_statement < 0) if (newf->first_statement < 0)
{ // negative statements are built in functions { // negative statements are built in functions
@ -968,11 +968,11 @@ reeval:
break; break;
case OP_CSTATE: case OP_CSTATE:
externs->cstateop(&progfuncs->funcs, OPA->_float, OPB->_float, pr_xfunction - pr_functions); externs->cstateop(&progfuncs->funcs, OPA->_float, OPB->_float, pr_xfunction - pr_cp_functions);
break; break;
case OP_CWSTATE: case OP_CWSTATE:
externs->cwstateop(&progfuncs->funcs, OPA->_float, OPB->_float, pr_xfunction - pr_functions); externs->cwstateop(&progfuncs->funcs, OPA->_float, OPB->_float, pr_xfunction - pr_cp_functions);
break; break;
case OP_THINKTIME: case OP_THINKTIME:

View file

@ -547,7 +547,7 @@ int PDECL PR_GetFuncArgCount(pubprogfuncs_t *ppf, func_t func)
unsigned int pnum; unsigned int pnum;
unsigned int fnum; unsigned int fnum;
dfunction_t *f; mfunction_t *f;
pnum = (func & 0xff000000)>>24; pnum = (func & 0xff000000)>>24;
fnum = (func & 0x00ffffff); fnum = (func & 0x00ffffff);
@ -566,7 +566,7 @@ int PDECL PR_GetFuncArgCount(pubprogfuncs_t *ppf, func_t func)
func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, const char *funcname, progsnum_t pnum) func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, const char *funcname, progsnum_t pnum)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
dfunction_t *f=NULL; mfunction_t *f=NULL;
if (pnum == PR_ANY) if (pnum == PR_ANY)
{ {
for (pnum = 0; (unsigned)pnum < maxprogs; pnum++) for (pnum = 0; (unsigned)pnum < maxprogs; pnum++)
@ -1041,10 +1041,12 @@ pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf)
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
struct progstate_s *ps; struct progstate_s *ps;
unsigned int i, f, j, s; unsigned int i, f, j, s;
unsigned long long cpufrequency;
struct struct
{ {
char *fname; char *fname;
int profile; int profile;
unsigned long long profiletime;
} *sorted, t; } *sorted, t;
if (!prinst.profiling) if (!prinst.profiling)
{ {
@ -1053,6 +1055,8 @@ pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf)
return true; return true;
} }
cpufrequency = Sys_GetClockRate();
for (i = 0; i < maxprogs; i++) for (i = 0; i < maxprogs; i++)
{ {
ps = &pr_progstate[i]; ps = &pr_progstate[i];
@ -1068,14 +1072,16 @@ pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf)
continue; continue;
sorted[s].fname = ps->functions[f].s_name+progfuncs->funcs.stringtable; sorted[s].fname = ps->functions[f].s_name+progfuncs->funcs.stringtable;
sorted[s].profile = ps->functions[f].profile; sorted[s].profile = ps->functions[f].profile;
sorted[s].profiletime = ps->functions[f].profiletime - ps->functions[f].profilechildtime;
ps->functions[f].profile = 0; ps->functions[f].profile = 0;
ps->functions[f].profiletime = 0;
s++; s++;
} }
// good 'ol bubble sort // good 'ol bubble sort
for (f = 0; f < s; f++) for (f = 0; f < s; f++)
for (j = f; j < s; j++) for (j = f; j < s; j++)
if (sorted[f].profile > sorted[j].profile) if (sorted[f].profiletime > sorted[j].profiletime)
{ {
t = sorted[f]; t = sorted[f];
sorted[f] = sorted[j]; sorted[f] = sorted[j];
@ -1084,7 +1090,7 @@ pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf)
//print it out //print it out
for (f = 0; f < s; f++) for (f = 0; f < s; f++)
printf("%s: %u\n", sorted[f].fname, sorted[f].profile); printf("%s: %u %g\n", sorted[f].fname, sorted[f].profile, (float)(((double)sorted[f].profiletime) / cpufrequency));
free(sorted); free(sorted);
} }
return true; return true;

View file

@ -512,6 +512,23 @@ typedef struct
qbyte parm_size[MAX_PARMS]; qbyte parm_size[MAX_PARMS];
} QCC_dfunction_t; } QCC_dfunction_t;
typedef struct
{
int first_statement; // negative numbers are builtins
int parm_start;
int locals; // total ints of parms + locals
int profile; //number of qc instructions executed.
unsigned long long profiletime; //total time inside (cpu cycles)
unsigned long long profilechildtime; //time inside children (excluding builtins, cpu cycles)
string_t s_name;
string_t s_file; // source file defined in
int numparms;
qbyte parm_size[MAX_PARMS];
} mfunction_t;
#define PROG_QTESTVERSION 3 #define PROG_QTESTVERSION 3
#define PROG_VERSION 6 #define PROG_VERSION 6
#define PROG_KKQWSVVERSION 7 #define PROG_KKQWSVVERSION 7

View file

@ -436,9 +436,9 @@ unsigned int *ED_FindGlobalOfsFromProgs (progfuncs_t *progfuncs, char *name, pro
ED_FindFunction ED_FindFunction
============ ============
*/ */
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *prnum, progsnum_t fromprogs) mfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *prnum, progsnum_t fromprogs)
{ {
dfunction_t *func; mfunction_t *func;
unsigned int i; unsigned int i;
char *sep; char *sep;
@ -507,7 +507,7 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val, pbool v
{ {
static char line[4096]; static char line[4096];
fdef_t *fielddef; fdef_t *fielddef;
dfunction_t *f; mfunction_t *f;
#ifdef DEF_SAVEGLOBAL #ifdef DEF_SAVEGLOBAL
type &= ~DEF_SAVEGLOBAL; type &= ~DEF_SAVEGLOBAL;
@ -620,7 +620,7 @@ char *PDECL PR_UglyValueString (pubprogfuncs_t *ppf, etype_t type, eval_t *val)
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
static char line[4096]; static char line[4096];
fdef_t *fielddef; fdef_t *fielddef;
dfunction_t *f; mfunction_t *f;
int i, j; int i, j;
#ifdef DEF_SAVEGLOBAL #ifdef DEF_SAVEGLOBAL
@ -732,7 +732,7 @@ char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
{ {
static char line[4096]; static char line[4096];
fdef_t *fielddef; fdef_t *fielddef;
dfunction_t *f; mfunction_t *f;
#ifdef DEF_SAVEGLOBAL #ifdef DEF_SAVEGLOBAL
type &= ~DEF_SAVEGLOBAL; type &= ~DEF_SAVEGLOBAL;
@ -1107,7 +1107,7 @@ pbool PDECL ED_ParseEval (pubprogfuncs_t *ppf, eval_t *eval, int type, const cha
fdef_t *def; fdef_t *def;
char *v, *w; char *v, *w;
string_t st; string_t st;
dfunction_t *func; mfunction_t *func;
switch (type & ~DEF_SAVEGLOBAL) switch (type & ~DEF_SAVEGLOBAL)
{ {
@ -1189,7 +1189,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int
fdef_t *def; fdef_t *def;
char *v, *w; char *v, *w;
string_t st; string_t st;
dfunction_t *func; mfunction_t *func;
int type = fldtype & ~DEF_SAVEGLOBAL; int type = fldtype & ~DEF_SAVEGLOBAL;
qcptr += fldofs*sizeof(int); qcptr += fldofs*sizeof(int);
@ -1596,7 +1596,7 @@ char *SaveCallStack (progfuncs_t *progfuncs, char *buf, int *bufofs, int bufmax)
{ {
#define AddS(str) PR_Cat(buf, str, bufofs, bufmax) #define AddS(str) PR_Cat(buf, str, bufofs, bufmax)
char buffer[8192]; char buffer[8192];
const dfunction_t *f; const mfunction_t *f;
int i; int i;
int progs; int progs;
@ -1915,7 +1915,7 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, float killonspawnfl
if (!resethunk) if (!resethunk)
{ {
dfunction_t *f; mfunction_t *f;
if ((var = QC_GetEdictFieldValue (&progfuncs->funcs, (struct edict_s *)ed, "classname", NULL))) if ((var = QC_GetEdictFieldValue (&progfuncs->funcs, (struct edict_s *)ed, "classname", NULL)))
{ {
f = ED_FindFunction(progfuncs, var->string + progfuncs->funcs.stringtable, NULL, -1); f = ED_FindFunction(progfuncs, var->string + progfuncs->funcs.stringtable, NULL, -1);
@ -1923,7 +1923,7 @@ int PDECL PR_LoadEnts(pubprogfuncs_t *ppf, const char *file, float killonspawnfl
{ {
var = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self")); var = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self"));
var->edict = EDICT_TO_PROG(progfuncs, ed); var->edict = EDICT_TO_PROG(progfuncs, ed);
PR_ExecuteProgram(&progfuncs->funcs, f-pr_functions); PR_ExecuteProgram(&progfuncs->funcs, f-pr_cp_functions);
} }
} }
} }
@ -2502,7 +2502,7 @@ PR_LoadProgs
*/ */
int PR_ReallyLoadProgs (progfuncs_t *progfuncs, const char *filename, int headercrc, progstate_t *progstate, pbool complain) int PR_ReallyLoadProgs (progfuncs_t *progfuncs, const char *filename, int headercrc, progstate_t *progstate, pbool complain)
{ {
unsigned int i, type; unsigned int i, j, type;
// extensionbuiltin_t *eb; // extensionbuiltin_t *eb;
// float fl; // float fl;
int len; int len;
@ -2521,6 +2521,7 @@ int PR_ReallyLoadProgs (progfuncs_t *progfuncs, const char *filename, int header
ddef16_t *gd16, *fld16; ddef16_t *gd16, *fld16;
float *glob; float *glob;
dfunction_t *fnc; dfunction_t *fnc;
mfunction_t *fnc2;
dstatement16_t *st16; dstatement16_t *st16;
int hmark=0xffffffff; int hmark=0xffffffff;
@ -2676,7 +2677,7 @@ retry:
return false; return false;
} }
fnc = pr_functions = (dfunction_t *)((qbyte *)pr_progs + pr_progs->ofs_functions); fnc = (dfunction_t *)((qbyte *)pr_progs + pr_progs->ofs_functions);
pr_strings = ((char *)pr_progs + pr_progs->ofs_strings); pr_strings = ((char *)pr_progs + pr_progs->ofs_strings);
current_progstate->globaldefs = *(void**)&gd16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs); current_progstate->globaldefs = *(void**)&gd16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs);
current_progstate->fielddefs = *(void**)&fld16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs); current_progstate->fielddefs = *(void**)&fld16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs);
@ -2753,9 +2754,9 @@ retry:
{ {
len=sizeof(dfunction_t)*pr_progs->numfunctions; len=sizeof(dfunction_t)*pr_progs->numfunctions;
s = PRHunkAlloc(progfuncs, len, "dfunctiontable"); s = PRHunkAlloc(progfuncs, len, "dfunctiontable");
QC_decode(progfuncs, PRLittleLong(*(int *)pr_functions), len, 2, (char *)(((int *)pr_functions)+1), s); QC_decode(progfuncs, PRLittleLong(*(int *)fnc), len, 2, (char *)(((int *)fnc)+1), s);
fnc = pr_functions = (dfunction_t *)s; fnc = (dfunction_t *)s;
} }
if (pr_progs->blockscompressed & 16) //string table if (pr_progs->blockscompressed & 16) //string table
{ {
@ -2839,7 +2840,7 @@ retry:
} }
} }
pr_functions = fnc; pr_cp_functions = NULL;
// pr_strings = ((char *)pr_progs + pr_progs->ofs_strings); // pr_strings = ((char *)pr_progs + pr_progs->ofs_strings);
gd16 = *(ddef16_t**)&current_progstate->globaldefs = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs); gd16 = *(ddef16_t**)&current_progstate->globaldefs = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs);
fld16 = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs); fld16 = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs);
@ -2855,45 +2856,50 @@ retry:
current_progstate->edict_size = pr_progs->entityfields * 4 + externs->edictsize; current_progstate->edict_size = pr_progs->entityfields * 4 + externs->edictsize;
if (sizeof(mfunction_t) > sizeof(qtest_function_t))
Sys_Error("assumption no longer works");
// byte swap the lumps // byte swap the lumps
switch(current_progstate->structtype) switch(current_progstate->structtype)
{ {
case PST_QTEST: case PST_QTEST:
// qtest needs a struct remap // qtest needs a struct remap
pr_cp_functions = (mfunction_t*)fnc;
fnc2 = pr_cp_functions;
for (i=0 ; i<pr_progs->numfunctions; i++) for (i=0 ; i<pr_progs->numfunctions; i++)
{ {
int j; //qtest functions are bigger, so we can just do this in-place
qtest_function_t qtfunc = ((qtest_function_t*)fnc)[i]; qtest_function_t qtfunc = ((qtest_function_t*)fnc)[i];
fnc[i].first_statement = PRLittleLong (qtfunc.first_statement); fnc2[i].first_statement = PRLittleLong (qtfunc.first_statement);
fnc[i].parm_start = PRLittleLong (qtfunc.parm_start); fnc2[i].parm_start = PRLittleLong (qtfunc.parm_start);
fnc[i].s_name = (string_t)PRLittleLong (qtfunc.s_name); fnc2[i].s_name = (string_t)PRLittleLong (qtfunc.s_name);
fnc[i].s_file = (string_t)PRLittleLong (qtfunc.s_file); fnc2[i].s_file = (string_t)PRLittleLong (qtfunc.s_file);
fnc[i].numparms = PRLittleLong (qtfunc.numparms); fnc2[i].numparms = PRLittleLong (qtfunc.numparms);
fnc[i].locals = PRLittleLong (qtfunc.locals); fnc2[i].locals = PRLittleLong (qtfunc.locals);
for (j=0; j<MAX_PARMS;j++) for (j=0; j<MAX_PARMS;j++)
fnc[i].parm_size[j] = PRLittleLong (qtfunc.parm_size[j]); fnc2[i].parm_size[j] = PRLittleLong (qtfunc.parm_size[j]);
fnc[i].s_name += stringadjust; fnc2[i].s_name += stringadjust;
fnc[i].s_file += stringadjust; fnc2[i].s_file += stringadjust;
} }
break; break;
case PST_KKQWSV: case PST_KKQWSV:
case PST_DEFAULT: case PST_DEFAULT:
case PST_FTE32: case PST_FTE32:
for (i=0 ; i<pr_progs->numfunctions; i++) pr_cp_functions = PRHunkAlloc(progfuncs, sizeof(*pr_cp_functions)*pr_progs->numfunctions, "mfunctions");
for (i=0,fnc2=pr_cp_functions; i<pr_progs->numfunctions; i++, fnc2++)
{ {
#ifndef NOENDIAN fnc2->first_statement = PRLittleLong (fnc[i].first_statement);
fnc[i].first_statement = PRLittleLong (fnc[i].first_statement); fnc2->parm_start = PRLittleLong (fnc[i].parm_start);
fnc[i].parm_start = PRLittleLong (fnc[i].parm_start); fnc2->s_name = (string_t)PRLittleLong ((long)fnc[i].s_name) + stringadjust;
fnc[i].s_name = (string_t)PRLittleLong ((long)fnc[i].s_name); fnc2->s_file = (string_t)PRLittleLong ((long)fnc[i].s_file) + stringadjust;
fnc[i].s_file = (string_t)PRLittleLong ((long)fnc[i].s_file); fnc2->numparms = PRLittleLong (fnc[i].numparms);
fnc[i].numparms = PRLittleLong (fnc[i].numparms); fnc2->locals = PRLittleLong (fnc[i].locals);
fnc[i].locals = PRLittleLong (fnc[i].locals);
#endif for (j=0; j<MAX_PARMS;j++)
fnc[i].s_name += stringadjust; fnc2->parm_size[j] = fnc[i].parm_size[j];
fnc[i].s_file += stringadjust;
} }
break; break;
default: default:

View file

@ -31,7 +31,6 @@
#endif #endif
#endif #endif
//============================================================================= //=============================================================================
/* /*
@ -307,7 +306,7 @@ static void PDECL PR_PrintRelevantLocals(progfuncs_t *progfuncs)
void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals) void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
{ {
progfuncs_t *progfuncs = (progfuncs_t *)ppf; progfuncs_t *progfuncs = (progfuncs_t *)ppf;
const dfunction_t *f; const mfunction_t *f;
int i; int i;
int progs; int progs;
int arg; int arg;
@ -488,7 +487,7 @@ PR_EnterFunction
Returns the new program statement counter Returns the new program statement counter
==================== ====================
*/ */
int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum) int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, mfunction_t *f, int progsnum)
{ {
int i, j, c, o; int i, j, c, o;
@ -496,6 +495,10 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsn
pr_stack[pr_depth].f = pr_xfunction; pr_stack[pr_depth].f = pr_xfunction;
pr_stack[pr_depth].progsnum = progsnum; pr_stack[pr_depth].progsnum = progsnum;
pr_stack[pr_depth].pushed = pr_spushed; pr_stack[pr_depth].pushed = pr_spushed;
if (prinst.profiling)
{
pr_stack[pr_depth].timestamp = Sys_GetClock();
}
pr_depth++; pr_depth++;
if (pr_depth == MAX_STACK_DEPTH) if (pr_depth == MAX_STACK_DEPTH)
{ {
@ -563,10 +566,22 @@ int ASMCALL PR_LeaveFunction (progfuncs_t *progfuncs)
// up stack // up stack
pr_depth--; pr_depth--;
PR_SwitchProgsParms(progfuncs, pr_stack[pr_depth].progsnum); PR_SwitchProgsParms(progfuncs, pr_stack[pr_depth].progsnum);
pr_xfunction = pr_stack[pr_depth].f;
pr_spushed = pr_stack[pr_depth].pushed; pr_spushed = pr_stack[pr_depth].pushed;
if (prinst.profiling)
{
unsigned long long cycles;
cycles = Sys_GetClock() - pr_stack[pr_depth].timestamp;
pr_xfunction->profiletime += cycles;
pr_xfunction = pr_stack[pr_depth].f;
if (pr_depth)
pr_xfunction->profilechildtime += cycles;
}
else
pr_xfunction = pr_stack[pr_depth].f;
localstack_used -= pr_spushed; localstack_used -= pr_spushed;
return pr_stack[pr_depth].s; return pr_stack[pr_depth].s;
} }
@ -911,7 +926,7 @@ char *PDECL PR_EvaluateDebugString(pubprogfuncs_t *ppf, char *key)
case ev_function: case ev_function:
{ {
dfunction_t *func; mfunction_t *func;
int i; int i;
int progsnum = -1; int progsnum = -1;
char *s = assignment; char *s = assignment;
@ -962,7 +977,7 @@ void SetExecutionToLine(progfuncs_t *progfuncs, int linenum)
{ {
int pn = pr_typecurrent; int pn = pr_typecurrent;
int snum; int snum;
const dfunction_t *f = pr_xfunction; const mfunction_t *f = pr_xfunction;
switch(current_progstate->structtype) switch(current_progstate->structtype)
{ {
@ -998,7 +1013,7 @@ int PDECL PR_ToggleBreakpoint(pubprogfuncs_t *ppf, char *filename, int linenum,
unsigned int fl; unsigned int fl;
unsigned int i; unsigned int i;
int pn = pr_typecurrent; int pn = pr_typecurrent;
dfunction_t *f; mfunction_t *f;
int op = 0; //warning about not being initialized before use int op = 0; //warning about not being initialized before use
for (pn = 0; (unsigned)pn < maxprogs; pn++) for (pn = 0; (unsigned)pn < maxprogs; pn++)
@ -1170,7 +1185,7 @@ static char *lastfile = 0;
int pn = pr_typecurrent; int pn = pr_typecurrent;
int i; int i;
const dfunction_t *f = pr_xfunction; const mfunction_t *f = pr_xfunction;
pr_xstatement = statement; pr_xstatement = statement;
if (!externs->useeditor) if (!externs->useeditor)
@ -1244,7 +1259,7 @@ static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
int swtchtype = 0; //warning about not being initialized before use int swtchtype = 0; //warning about not being initialized before use
const dstatement16_t *fte_restrict st; const dstatement16_t *fte_restrict st;
dfunction_t *fte_restrict newf; mfunction_t *fte_restrict newf;
int i; int i;
edictrun_t *ed; edictrun_t *ed;
eval_t *ptr; eval_t *ptr;
@ -1291,7 +1306,7 @@ static int PR_ExecuteCode32 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
int swtchtype = 0; //warning about not being initialized before use int swtchtype = 0; //warning about not being initialized before use
const dstatement32_t *fte_restrict st; const dstatement32_t *fte_restrict st;
dfunction_t *fte_restrict newf; mfunction_t *fte_restrict newf;
int i; int i;
edictrun_t *ed; edictrun_t *ed;
eval_t *ptr; eval_t *ptr;
@ -1406,7 +1421,7 @@ static void PR_ExecuteCode (progfuncs_t *progfuncs, int s)
void PDECL PR_ExecuteProgram (pubprogfuncs_t *ppf, func_t fnum) void PDECL PR_ExecuteProgram (pubprogfuncs_t *ppf, func_t fnum)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
dfunction_t *f; mfunction_t *f;
int i; int i;
unsigned int initial_progs; unsigned int initial_progs;
int oldexitdepth; int oldexitdepth;
@ -1446,7 +1461,7 @@ void PDECL PR_ExecuteProgram (pubprogfuncs_t *ppf, func_t fnum)
oldexitdepth = prinst.exitdepth; oldexitdepth = prinst.exitdepth;
f = &pr_functions[fnum & ~0xff000000]; f = &pr_cp_functions[fnum & ~0xff000000];
if (f->first_statement < 0) if (f->first_statement < 0)
{ // negative statements are built in functions { // negative statements are built in functions
@ -1519,7 +1534,7 @@ struct qcthread_s *PDECL PR_ForkStack(pubprogfuncs_t *ppf)
int ed = prinst.exitdepth; int ed = prinst.exitdepth;
int localsoffset, baselocalsoffset; int localsoffset, baselocalsoffset;
qcthread_t *thread = externs->memalloc(sizeof(qcthread_t)); qcthread_t *thread = externs->memalloc(sizeof(qcthread_t));
const dfunction_t *f; const mfunction_t *f;
//copy out the functions stack. //copy out the functions stack.
for (i = 0,localsoffset=0; i < ed; i++) for (i = 0,localsoffset=0; i < ed; i++)
@ -1584,7 +1599,7 @@ struct qcthread_s *PDECL PR_ForkStack(pubprogfuncs_t *ppf)
void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread) void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
dfunction_t *f, *oldf; mfunction_t *f, *oldf;
int i,l,ls; int i,l,ls;
progsnum_t initial_progs; progsnum_t initial_progs;
int oldexitdepth; int oldexitdepth;
@ -1628,7 +1643,7 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
} }
if (i+1 == thread->fstackdepth) if (i+1 == thread->fstackdepth)
f = &pr_functions[fnum]; f = &pr_cp_functions[fnum];
else else
f = pr_progstate[thread->fstack[i+1].progsnum].functions + thread->fstack[i+1].fnum; f = pr_progstate[thread->fstack[i+1].progsnum].functions + thread->fstack[i+1].fnum;
for (l = 0; l < f->locals; l++) for (l = 0; l < f->locals; l++)
@ -1644,7 +1659,7 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
PR_RunError(&progfuncs->funcs, "Thread stores incorrect locals count\n"); PR_RunError(&progfuncs->funcs, "Thread stores incorrect locals count\n");
f = &pr_functions[fnum]; f = &pr_cp_functions[fnum];
// thread->lstackused -= f->locals; //the current function is the odd one out. // thread->lstackused -= f->locals; //the current function is the odd one out.

View file

@ -61,9 +61,10 @@ typedef struct sharedvar_s
typedef struct typedef struct
{ {
int s; int s;
dfunction_t *f; mfunction_t *f;
int progsnum; int progsnum;
int pushed; int pushed;
unsigned long long timestamp;
} prstack_t; } prstack_t;
typedef struct prinst_s typedef struct prinst_s
@ -130,7 +131,7 @@ int reorganisefields;
int exitdepth; int exitdepth;
pbool profiling; pbool profiling;
dfunction_t *pr_xfunction; mfunction_t *pr_xfunction;
#define pr_xfunction prinst.pr_xfunction #define pr_xfunction prinst.pr_xfunction
int pr_xstatement; int pr_xstatement;
#define pr_xstatement prinst.pr_xstatement #define pr_xstatement prinst.pr_xstatement
@ -297,7 +298,7 @@ typedef enum
typedef struct progstate_s typedef struct progstate_s
{ {
dprograms_t *progs; dprograms_t *progs;
dfunction_t *functions; mfunction_t *functions;
char *strings; char *strings;
union { union {
ddefXX_t *globaldefs; ddefXX_t *globaldefs;
@ -342,7 +343,7 @@ typedef struct extensionbuiltin_s {
#define pr_progs current_progstate->progs #define pr_progs current_progstate->progs
#define pr_functions current_progstate->functions #define pr_cp_functions current_progstate->functions
#define pr_strings current_progstate->strings #define pr_strings current_progstate->strings
#define pr_globaldefs16 ((ddef16_t*)current_progstate->globaldefs) #define pr_globaldefs16 ((ddef16_t*)current_progstate->globaldefs)
#define pr_globaldefs32 ((ddef32_t*)current_progstate->globaldefs) #define pr_globaldefs32 ((ddef32_t*)current_progstate->globaldefs)
@ -443,6 +444,49 @@ fdef_t *PDECL ED_FieldInfo (pubprogfuncs_t *progfuncs, unsigned int *count);
char *PDECL PR_UglyValueString (pubprogfuncs_t *progfuncs, etype_t type, eval_t *val); char *PDECL PR_UglyValueString (pubprogfuncs_t *progfuncs, etype_t type, eval_t *val);
pbool PDECL ED_ParseEval (pubprogfuncs_t *progfuncs, eval_t *eval, int type, const char *s); pbool PDECL ED_ParseEval (pubprogfuncs_t *progfuncs, eval_t *eval, int type, const char *s);
//cpu clock stuff (glorified rdtsc), for profile timing only
#if !defined(Sys_GetClock) && defined(_WIN32)
//windows has some specific functions for this (traditionally wrapping rdtsc)
//note: on some systems, you may need to force cpu affinity to a single core via task manager
static unsigned long long Sys_GetClock(void)
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return li.QuadPart;
}
static unsigned long long Sys_GetClockRate(void)
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
return li.QuadPart;
}
#endif
#if !defined(Sys_GetClock) && defined(__unix__)
//linux/unix has some annoying abstraction and shows time in nanoseconds rather than cycles. lets hope we don't waste too much time reading it.
#include <unistd.h>
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS >= 0
static unsigned long long Sys_GetClock(void)
{
struct timespec c;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &c);
return (c.tv_sec*1000000000ull) + tc.tv_nsec;
}
static unsigned long long Sys_GetClockRate(void)
{
return 1000000000ull;
}
#endif
#endif
#ifndef Sys_GetClock
//other systems have no choice but to omit this feature in some way. this is just for profiling, so we can get away with stubs.
#define Sys_GetClock() 0
#define Sys_GetClockRate() 1
#endif
#endif #endif
@ -477,7 +521,7 @@ ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, pr
fdef_t *ED_FindField (progfuncs_t *progfuncs, const char *name); fdef_t *ED_FindField (progfuncs_t *progfuncs, const char *name);
fdef_t *ED_ClassFieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs, const char *classname); fdef_t *ED_ClassFieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs, const char *classname);
fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *pnum, progsnum_t fromprogs); mfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *pnum, progsnum_t fromprogs);
func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, const char *funcname, progsnum_t pnum); func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, const char *funcname, progsnum_t pnum);
//void PDECL PR_Configure (pubprogfuncs_t *progfncs, size_t addressable_size, int max_progs); //void PDECL PR_Configure (pubprogfuncs_t *progfncs, size_t addressable_size, int max_progs);
int PDECL PR_InitEnts(pubprogfuncs_t *progfncs, int maxents); int PDECL PR_InitEnts(pubprogfuncs_t *progfncs, int maxents);

View file

@ -3209,12 +3209,13 @@ QCC_def_t *QCC_PR_ParseImmediate (void)
if (pr_immediate_type == type_string) if (pr_immediate_type == type_string)
{ {
char tmp[8192]; char tmp[8192];
strcpy(tmp, pr_immediate_string); strncpy(tmp, pr_immediate_string, sizeof(tmp)-1);
tmp[sizeof(tmp)-1] = 0;
for(;;) for(;;)
{ {
QCC_PR_Lex (); QCC_PR_Lex ();
if (pr_token_type == tt_immediate && pr_token_type == tt_immediate) if (pr_token_type == tt_immediate && pr_immediate_type == type_string)
strcat(tmp, pr_immediate_string); strcat(tmp, pr_immediate_string);
else else
break; break;

View file

@ -2913,6 +2913,7 @@ int QCC_PR_CheckCompConst(void)
strftime( retbuf, sizeof(retbuf), strftime( retbuf, sizeof(retbuf),
"\"%H:%M\"", localtime( &long_time )); "\"%H:%M\"", localtime( &long_time ));
pr_file_p += 8;
QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL); QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL);
return true; return true;
} }
@ -2930,15 +2931,17 @@ int QCC_PR_CheckCompConst(void)
return true; return true;
} }
if (!strncmp(pr_file_p, "__QCCVER__", 8)) if (!strncmp(pr_file_p, "__RAND__", 8))
{ {
char retbuf[128]; char retbuf[128];
QC_snprintfz(retbuf, sizeof(retbuf), "%i", rand());
time_t long_time; pr_file_p += 8;
time( &long_time ); QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL);
strftime( retbuf, sizeof(retbuf), return true;
"\"%a %d %b %Y\"", localtime( &long_time )); }
if (!strncmp(pr_file_p, "__QCCVER__", 8))
{
pr_file_p += 10; pr_file_p += 10;
QCC_PR_IncludeChunkEx("FTEQCC "__DATE__","__TIME__"", true, NULL, NULL); QCC_PR_IncludeChunkEx("FTEQCC "__DATE__","__TIME__"", true, NULL, NULL);
@ -2947,7 +2950,7 @@ int QCC_PR_CheckCompConst(void)
if (!strncmp(pr_file_p, "__FILE__", 8)) if (!strncmp(pr_file_p, "__FILE__", 8))
{ {
char retbuf[256]; char retbuf[256];
sprintf(retbuf, "\"%s\"", strings + s_file); QC_snprintfz(retbuf, sizeof(retbuf), "\"%s\"", strings + s_file);
pr_file_p += 8; pr_file_p += 8;
QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL); QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL);
@ -2956,7 +2959,7 @@ int QCC_PR_CheckCompConst(void)
if (!strncmp(pr_file_p, "__LINE__", 8)) if (!strncmp(pr_file_p, "__LINE__", 8))
{ {
char retbuf[256]; char retbuf[256];
sprintf(retbuf, "\"%i\"", pr_source_line); QC_snprintfz(retbuf, sizeof(retbuf), "\"%i\"", pr_source_line);
pr_file_p += 8; pr_file_p += 8;
QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL); QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL);
return true; return true;
@ -2964,7 +2967,7 @@ int QCC_PR_CheckCompConst(void)
if (!strncmp(pr_file_p, "__FUNC__", 8)) if (!strncmp(pr_file_p, "__FUNC__", 8))
{ {
char retbuf[256]; char retbuf[256];
sprintf(retbuf, "\"%s\"",pr_scope?pr_scope->name:"<NO FUNCTION>"); QC_snprintfz(retbuf, sizeof(retbuf), "\"%s\"",pr_scope?pr_scope->name:"<NO FUNCTION>");
pr_file_p += 8; pr_file_p += 8;
QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL); QCC_PR_IncludeChunkEx(retbuf, true, NULL, NULL);
return true; return true;

View file

@ -92,7 +92,7 @@ int logprintf(const char *format, ...)
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
int sucess; pbool sucess;
progexterns_t ext; progexterns_t ext;
progfuncs_t funcs; progfuncs_t funcs;
progfuncs = &funcs; progfuncs = &funcs;
@ -113,5 +113,5 @@ int main (int argc, char **argv)
#ifdef _WIN32 #ifdef _WIN32
// fgetc(stdin); //wait for keypress // fgetc(stdin); //wait for keypress
#endif #endif
return !sucess; return sucess?EXIT_SUCCESS:EXIT_FAILURE;
} }

View file

@ -10611,10 +10611,17 @@ void PR_DumpPlatform_f(void)
{"VF_SCREENPSIZE", "const float", CS|MENU, "Provides a reliable way to retrieve the current physical screen size (cvars need vid_restart for them to take effect).", VF_SCREENPSIZE}, {"VF_SCREENPSIZE", "const float", CS|MENU, "Provides a reliable way to retrieve the current physical screen size (cvars need vid_restart for them to take effect).", VF_SCREENPSIZE},
{"VF_VIEWENTITY", "const float", CS, "Changes the RF_EXTERNALMODEL flag on entities to match the new selection, and removes entities flaged with RF_VIEWENTITY. Requires cunning use of .entnum and typically requires calling addentities(MASK_VIEWMODEL) too.", VF_VIEWENTITY}, {"VF_VIEWENTITY", "const float", CS, "Changes the RF_EXTERNALMODEL flag on entities to match the new selection, and removes entities flaged with RF_VIEWENTITY. Requires cunning use of .entnum and typically requires calling addentities(MASK_VIEWMODEL) too.", VF_VIEWENTITY},
{"VF_RT_DESTCOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to write colour info into. 1-based. Additional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy. Written to by both 3d and 2d rendering. Note that any rendertargets may be destroyed on video mode changes or so.", VF_RT_DESTCOLOUR}, {"VF_RT_DESTCOLOUR", "const float", CS|MENU, "The texture name to write colour info into, this includes both 3d and 2d drawing.\nAdditional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy.\nWritten to by both 3d and 2d rendering.\nNote that any rendertarget textures may be destroyed on video mode changes or so. Shaders can name render targets by prefixing texture names with '$rt:', or $sourcecolour.", VF_RT_DESTCOLOUR0},
{"VF_RT_SOURCECOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to use with shaders that specify a $sourcecolour map.", VF_RT_SOURCECOLOUR}, // {"VF_RT_DESTCOLOUR1", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR1},
{"VF_RT_DEPTH", "const float", CS|MENU, "The FrameBuffer texture index to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16bit=4,24bit=5,32bit=6), sizexy.", VF_RT_DEPTH}, // {"VF_RT_DESTCOLOUR2", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR2},
{"VF_RT_RIPPLE", "const float", CS|MENU, "The FrameBuffer texture index to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy.", VF_RT_RIPPLE}, // {"VF_RT_DESTCOLOUR3", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR3},
// {"VF_RT_DESTCOLOUR4", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR4},
// {"VF_RT_DESTCOLOUR5", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR5},
// {"VF_RT_DESTCOLOUR6", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR6},
// {"VF_RT_DESTCOLOUR7", "const float", CS|MENU, "Like VF_RT_DESTCOLOUR, for multiple render targets.", VF_RT_DESTCOLOUR7},
{"VF_RT_SOURCECOLOUR", "const float", CS|MENU, "The texture name to use with shaders that specify a $sourcecolour map.", VF_RT_SOURCECOLOUR},
{"VF_RT_DEPTH", "const float", CS|MENU, "The texture name to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16bit=4,24bit=5,32bit=6), sizexy.", VF_RT_DEPTH},
{"VF_RT_RIPPLE", "const float", CS|MENU, "The texture name to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy.", VF_RT_RIPPLE},
{"RF_VIEWMODEL", "const float", CS, "Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob.", CSQCRF_VIEWMODEL}, {"RF_VIEWMODEL", "const float", CS, "Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob.", CSQCRF_VIEWMODEL},
{"RF_EXTERNALMODEL", "const float", CS, "Specifies that this entity should be displayed in mirrors (and may still cast shadows), but will not otherwise be visible.", CSQCRF_EXTERNALMODEL}, {"RF_EXTERNALMODEL", "const float", CS, "Specifies that this entity should be displayed in mirrors (and may still cast shadows), but will not otherwise be visible.", CSQCRF_EXTERNALMODEL},

View file

@ -762,6 +762,28 @@ void SV_KickSlot_f (void)
Con_Printf("Client %i is not active\n", clnum); Con_Printf("Client %i is not active\n", clnum);
} }
//ipv4ify if its an ipv6 ipv4-mapped address.
netadr_t *NET_IPV4ify(netadr_t *a, netadr_t *tmp)
{
if (a->type == NA_IPV6 &&
!*(int*)&a->address.ip6[0] &&
!*(int*)&a->address.ip6[4] &&
!*(short*)&a->address.ip6[8] &&
*(short*)&a->address.ip6[10]==(short)0xffff)
{
tmp->type = NA_IP;
tmp->connum = a->connum;
tmp->scopeid = a->scopeid;
tmp->port = a->port;
tmp->address.ip[0] = a->address.ip6[12];
tmp->address.ip[1] = a->address.ip6[13];
tmp->address.ip[2] = a->address.ip6[14];
tmp->address.ip[3] = a->address.ip6[15];
a = tmp;
}
return a;
}
//will kick clients if they got banned (without being safe) //will kick clients if they got banned (without being safe)
void SV_EvaluatePenalties(client_t *cl) void SV_EvaluatePenalties(client_t *cl)
{ {
@ -774,12 +796,14 @@ void SV_EvaluatePenalties(client_t *cl)
int numpenalties = 0; int numpenalties = 0;
int numreasons = 0; int numreasons = 0;
int i; int i;
netadr_t tmp, *a;
if (cl->realip.type != NA_INVALID) if (cl->realip.type != NA_INVALID)
{ {
a = NET_IPV4ify(&cl->realip, &tmp);
for (banip = svs.bannedips; banip; banip=banip->next) for (banip = svs.bannedips; banip; banip=banip->next)
{ {
if (NET_CompareAdrMasked(&cl->realip, &banip->adr, &banip->adrmask)) if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask))
{ {
for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++) for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++)
{ {
@ -794,9 +818,10 @@ void SV_EvaluatePenalties(client_t *cl)
} }
} }
} }
a = NET_IPV4ify(&cl->netchan.remote_address, &tmp);
for (banip = svs.bannedips; banip; banip=banip->next) for (banip = svs.bannedips; banip; banip=banip->next)
{ {
if (NET_CompareAdrMasked(&cl->netchan.remote_address, &banip->adr, &banip->adrmask)) if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask))
{ {
for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++) for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++)
{ {
@ -1037,10 +1062,13 @@ char *SV_BannedReason (netadr_t *a)
{ {
char *reason = filterban.value?NULL:""; //"" = banned with no explicit reason char *reason = filterban.value?NULL:""; //"" = banned with no explicit reason
bannedips_t *banip; bannedips_t *banip;
netadr_t tmp;
if (NET_IsLoopBackAddress(a)) if (NET_IsLoopBackAddress(a))
return NULL; // never filter loopback return NULL; // never filter loopback
a = NET_IPV4ify(a, &tmp);
for (banip = svs.bannedips; banip; banip=banip->next) for (banip = svs.bannedips; banip; banip=banip->next)
{ {
if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask)) if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask))
@ -1788,7 +1816,7 @@ static void SV_Status_f (void)
, cl->netchan.qport); , cl->netchan.qport);
if (cl->download) if (cl->download)
{ {
Con_Printf (" %3i %4i", (cl->downloadcount*100)/cl->downloadsize, cl->downloadsize/1024); Con_Printf (" %3g %4u", (cl->downloadcount*100.0)/cl->downloadsize, (unsigned int)(cl->downloadsize/1024));
} }
if (cl->spectator) if (cl->spectator)
Con_Printf(" (s)\n"); Con_Printf(" (s)\n");
@ -2169,7 +2197,7 @@ void SV_User_f (void)
if (*cl->guid) if (*cl->guid)
Con_Printf("guid: %s\n", cl->guid); Con_Printf("guid: %s\n", cl->guid);
if (cl->download) if (cl->download)
Con_Printf ("download: \"%s\" %ik/%ik (%i%%)", cl->downloadfn, cl->downloadcount/1024, cl->downloadsize/1024, (cl->downloadcount*100)/cl->downloadsize); Con_Printf ("download: \"%s\" %uk/%uk (%g%%)", cl->downloadfn, (unsigned int)(cl->downloadcount/1024), (unsigned int)(cl->downloadsize/1024), (cl->downloadcount*100.0)/cl->downloadsize);
if (cl->penalties & BAN_CRIPPLED) if (cl->penalties & BAN_CRIPPLED)
Con_Printf("crippled\n"); Con_Printf("crippled\n");

View file

@ -143,6 +143,7 @@ cvar_t sv_minping = CVARF("sv_minping", "", CVAR_SERVERINFO);
cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "", CVAR_SERVERINFO, "Uses floats for coordinates instead of 16bit values. Affects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999)."); cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "", CVAR_SERVERINFO, "Uses floats for coordinates instead of 16bit values. Affects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999).");
cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1."); cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1.");
cvar_t sv_showconnectionlessmessages = CVARD("sv_showconnectionlessmessages", "0", "Display a line describing each connectionless message that arrives on the server. Primarily a debugging feature, but also potentially useful to admins.");
cvar_t sv_cullplayers_trace = CVARFD("sv_cullplayers_trace", "", CVAR_SERVERINFO, "Attempt to cull player entities using tracelines as an anti-wallhack."); cvar_t sv_cullplayers_trace = CVARFD("sv_cullplayers_trace", "", CVAR_SERVERINFO, "Attempt to cull player entities using tracelines as an anti-wallhack.");
cvar_t sv_cullentities_trace = CVARFD("sv_cullentities_trace", "", CVAR_SERVERINFO, "Attempt to cull non-player entities using tracelines as an extreeme anti-wallhack."); cvar_t sv_cullentities_trace = CVARFD("sv_cullentities_trace", "", CVAR_SERVERINFO, "Attempt to cull non-player entities using tracelines as an extreeme anti-wallhack.");
cvar_t sv_phs = CVARD("sv_phs", "1", "If 1, do not use the phs. It is generally better to use sv_calcphs instead, and leave this as 1."); cvar_t sv_phs = CVARD("sv_phs", "1", "If 1, do not use the phs. It is generally better to use sv_calcphs instead, and leave this as 1.");
@ -3954,6 +3955,9 @@ qboolean SV_ConnectionlessPacket (void)
c = Cmd_Argv(0); c = Cmd_Argv(0);
if (sv_showconnectionlessmessages.ival)
Con_Printf("%s: %s\n", NET_AdrToString (adr, sizeof(adr), &net_from), s);
if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) ) if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
SVC_Ping (); SVC_Ping ();
else if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') ) else if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
@ -4645,8 +4649,8 @@ dominping:
continue; continue;
// packet is not from a known client // packet is not from a known client
// Con_Printf ("%s:sequenced packet without connection\n" if (sv_showconnectionlessmessages.ival)
// ,NET_AdrToString(net_from)); Con_Printf ("%s:sequenced packet without connection\n", NET_AdrToString (com_token, sizeof(com_token), &net_from)); //hack: com_token cos we need some random temp buffer.
} }
return received; return received;
@ -5289,7 +5293,8 @@ void SV_InitLocal (void)
#endif #endif
Cvar_Set(&sv_public, "1"); Cvar_Set(&sv_public, "1");
Cvar_Register (&sv_banproxies, "Server Permissions"); Cvar_Register (&sv_showconnectionlessmessages, cvargroup_servercontrol);
Cvar_Register (&sv_banproxies, cvargroup_serverpermissions);
Cvar_Register (&sv_master, cvargroup_servercontrol); Cvar_Register (&sv_master, cvargroup_servercontrol);
Cvar_Register (&sv_masterport, cvargroup_servercontrol); Cvar_Register (&sv_masterport, cvargroup_servercontrol);

View file

@ -1671,7 +1671,7 @@ void SV_ClearQCStats(void)
} }
extern cvar_t dpcompat_stats; extern cvar_t dpcompat_stats;
void SV_UpdateQCStats(edict_t *ent, int *statsi, const char **statss, float *statsf) void SV_UpdateQCStats(edict_t *ent, int *statsi, char const** statss, float *statsf)
{ {
const char *s; const char *s;
int i; int i;
@ -1722,13 +1722,13 @@ void SV_UpdateQCStats(edict_t *ent, int *statsi, const char **statss, float *sta
} }
/*this function calculates the current stat values for the given client*/ /*this function calculates the current stat values for the given client*/
void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf[MAX_CL_STATS], char *statss[MAX_CL_STATS]) void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf[MAX_CL_STATS], char const **statss)
{ {
edict_t *ent; edict_t *ent;
ent = client->edict; ent = client->edict;
memset (statsi, 0, sizeof(int)*MAX_CL_STATS); memset (statsi, 0, sizeof(int)*MAX_CL_STATS);
memset (statsf, 0, sizeof(float)*MAX_CL_STATS); memset (statsf, 0, sizeof(float)*MAX_CL_STATS);
memset (statss, 0, sizeof(char*)*MAX_CL_STATS); memset ((void*)statss, 0, sizeof(char const*)*MAX_CL_STATS); //cast needed to get msvc to behave.
// if we are a spectator and we are tracking a player, we get his stats // if we are a spectator and we are tracking a player, we get his stats
// so our status bar reflects his // so our status bar reflects his

View file

@ -3070,7 +3070,8 @@ void SV_BeginDownload_f(void)
if (ISNQCLIENT(host_client)) if (ISNQCLIENT(host_client))
{ {
char *s = va("\ncl_downloadbegin %i %s\n", host_client->downloadsize, host_client->downloadfn); //FIXME support 64bit files
char *s = va("\ncl_downloadbegin %u %s\n", (unsigned int)host_client->downloadsize, host_client->downloadfn);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s)); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s));
ClientReliableWrite_String (host_client, s); ClientReliableWrite_String (host_client, s);
host_client->send_message = true; host_client->send_message = true;
@ -5621,7 +5622,7 @@ void AddLinksToPmove_Force ( edict_t *player, areanode_t *node )
link_t *l, *next; link_t *l, *next;
edict_t *check; edict_t *check;
int pl; int pl;
int i; // int i;
int solid; int solid;
pl = EDICT_TO_PROG(svprogfuncs, player); pl = EDICT_TO_PROG(svprogfuncs, player);

View file

@ -2883,20 +2883,53 @@ void JCL_ParseMessage(jclient_t *jcl, xmltree_t *tree)
if (!strcmp(type, "error")) if (!strcmp(type, "error"))
{ {
char *reason = NULL;
ot = XML_ChildOfTree(tree, "error", 0);
if (ot->child)
reason = ot->child->name;
if (XML_ChildOfTree(ot, "remote-server-not-found", 0)) reason = "Remote Server Not Found";
if (XML_ChildOfTree(ot, "bad-request", 0)) reason = "Bad Request";
if (XML_ChildOfTree(ot, "conflict", 0)) reason = "Conflict Error";
if (XML_ChildOfTree(ot, "feature-not-implemented", 0)) reason = "feature-not-implemented";
if (XML_ChildOfTree(ot, "forbidden", 0)) reason = "forbidden";
if (XML_ChildOfTree(ot, "gone", 0)) reason = "'gone' Error";
if (XML_ChildOfTree(ot, "internal-server-error", 0)) reason = "internal-server-error";
if (XML_ChildOfTree(ot, "item-not-found", 0)) reason = "item-not-found";
if (XML_ChildOfTree(ot, "jid-malformed", 0)) reason = "jid-malformed";
if (XML_ChildOfTree(ot, "not-acceptable", 0)) reason = "not-acceptable";
if (XML_ChildOfTree(ot, "not-allowed", 0)) reason = "not-allowed";
if (XML_ChildOfTree(ot, "not-authorized", 0)) reason = "not-authorized";
if (XML_ChildOfTree(ot, "policy-violation", 0)) reason = "policy-violation";
if (XML_ChildOfTree(ot, "recipient-unavailable", 0)) reason = "recipient-unavailable";
if (XML_ChildOfTree(ot, "redirect", 0)) reason = "'redirect' Error";
if (XML_ChildOfTree(ot, "registration-required", 0)) reason = "registration-required";
if (XML_ChildOfTree(ot, "remote-server-not-found", 0)) reason = "remote-server-not-found";
if (XML_ChildOfTree(ot, "remote-server-timeout", 0)) reason = "remote-server-timeout";
if (XML_ChildOfTree(ot, "resource-constraint", 0)) reason = "resource-constraint";
if (XML_ChildOfTree(ot, "service-unavailable", 0)) reason = "service-unavailable";
if (XML_ChildOfTree(ot, "subscription-required", 0)) reason = "subscription-required";
if (XML_ChildOfTree(ot, "undefined-condition", 0)) reason = "undefined-condition";
if (XML_ChildOfTree(ot, "unexpected-request", 0)) reason = "unexpected-request";
ot = XML_ChildOfTree(tree, "body", 0); ot = XML_ChildOfTree(tree, "body", 0);
if (ot) if (ot)
{ {
unparsable = false; unparsable = false;
if (reason)
Con_SubPrintf(ctx, "^1Error: %s (%s): ", reason, f);
else
Con_SubPrintf(ctx, "^1error sending message to %s: ", f);
if (f) if (f)
{ {
if (!strncmp(ot->body, "/me ", 4)) if (!strncmp(ot->body, "/me ", 4))
Con_SubPrintf(ctx, "* ^2%s^7%s\n", f, ot->body+3); Con_SubPrintf(ctx, "* ^2%s^7%s\n", ((!strcmp(jcl->localalias, ">>"))?"me":jcl->localalias), ot->body+3);
else else
Con_SubPrintf(ctx, "^2%s^7: %s\n", f, ot->body); Con_SubPrintf(ctx, "%s\n", ot->body);
} }
} }
else else
Con_SubPrintf(ctx, "error sending message: %s\r", f); Con_SubPrintf(ctx, "error sending message to %s\r", f);
return;
} }
if (f) if (f)
@ -4665,16 +4698,20 @@ void JCL_Command(int accid, char *console)
else if (!strcmp(arg[0]+1, "friend")) else if (!strcmp(arg[0]+1, "friend"))
{ {
//FIXME: validate the name. deal with xml markup. //FIXME: validate the name. deal with xml markup.
//try and make sense of the name given
JCL_ToJID(jcl, arg[1], arg[3], sizeof(arg[3]), false);
if (!strchr(arg[3], '@'))
Con_SubPrintf(console, "Missing @ character. Trying anyway, but this will be assumed to be a server rather than a user.\n", arg[0]);
//can also rename. We should probably read back the groups for the update. //can also rename. We should probably read back the groups for the update.
JCL_SendIQf(jcl, NULL, "set", NULL, "<query xmlns='jabber:iq:roster'><item jid='%s' name='%s'></item></query>", arg[1], arg[2]); JCL_SendIQf(jcl, NULL, "set", NULL, "<query xmlns='jabber:iq:roster'><item jid='%s' name='%s'></item></query>", arg[3], arg[2]);
//start looking for em //start looking for em
JCL_AddClientMessagef(jcl, "<presence to='%s' type='subscribe'/>", arg[1]); JCL_AddClientMessagef(jcl, "<presence to='%s' type='subscribe'/>", arg[13]);
//let em see us //let em see us
if (jcl->preapproval) if (jcl->preapproval)
JCL_AddClientMessagef(jcl, "<presence to='%s' type='subscribed'/>", arg[1]); JCL_AddClientMessagef(jcl, "<presence to='%s' type='subscribed'/>", arg[3]);
} }
else if (!strcmp(arg[0]+1, "unfriend")) else if (!strcmp(arg[0]+1, "unfriend"))
{ {