Rewrote infostrings. Now using infobuffers, which allows for the use of arbitrary blobs, except not using the protocol extension yet in case it needs to be fixed.
Fix sound source issues in Q3. Fix q2 air acceleration/prediction omission. Don't change console completion while typing (while that option is still possible). Shift+tab now cycles completion backwards (now ctrl+shift for cycle subconsoles). Allow a few things to ignore sv_pure - including csprogs files (which is useful for all the mods that come with the csprogs.dat distributed separately). clamp pitch values to the range documented by openal, to hopefully avoid error spam. add some colour coding to the text editor when shader files are being edited/viewed. Changed how overbrights are clamped on q3bsp. Added portalfboscale for explicit texture scales on portal/refract/reflect fbos. qc decompiler can now at least attempt to decompile qtest's qc. fteqccgui can now be pointed at a .pak file, and decompile the progs.dat inside. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5269 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
34029c2434
commit
d1d0d86fea
97 changed files with 4624 additions and 4539 deletions
|
@ -100,6 +100,9 @@ ifneq (,$(findstring -Os,$(FTE_CONFIG_EXTRA)))
|
||||||
CPUOPTIMIZATIONS+=-Os
|
CPUOPTIMIZATIONS+=-Os
|
||||||
BRANDFLAGS:=$(filter-out -O%,$(BRANDFLAGS))
|
BRANDFLAGS:=$(filter-out -O%,$(BRANDFLAGS))
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(findstring DLINK_INTERNAL_BULLET,$(FTE_CONFIG_EXTRA)))
|
||||||
|
INTERNAL_BULLET=1 #bullet plugin will be built into the exe itself
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(BITS),64)
|
ifeq ($(BITS),64)
|
||||||
CC:=$(CC) -m64
|
CC:=$(CC) -m64
|
||||||
|
@ -845,6 +848,9 @@ ifeq (1,$(USE_FREETYPE))
|
||||||
LIBFREETYPE_STATIC=-DFREETYPE_STATIC
|
LIBFREETYPE_STATIC=-DFREETYPE_STATIC
|
||||||
LIBFREETYPE_LDFLAGS=-lfreetype
|
LIBFREETYPE_LDFLAGS=-lfreetype
|
||||||
endif
|
endif
|
||||||
|
ifeq (1,$(strip $(INTERNAL_BULLET)))
|
||||||
|
COMMON_OBJS+=com_phys_bullet.o
|
||||||
|
endif
|
||||||
|
|
||||||
COMMONLIBFLAGS=
|
COMMONLIBFLAGS=
|
||||||
CLIENTLIBFLAGS=$(COMMONLIBFLAGS) $(LIBOPUS_STATIC) $(LIBSPEEX_STATIC) $(OGGVORBISFILE_STATIC) $(LIBFREETYPE_STATIC)
|
CLIENTLIBFLAGS=$(COMMONLIBFLAGS) $(LIBOPUS_STATIC) $(LIBSPEEX_STATIC) $(OGGVORBISFILE_STATIC) $(LIBFREETYPE_STATIC)
|
||||||
|
@ -2171,3 +2177,4 @@ install: sv-rel gl-rel mingl-rel qcc-rel
|
||||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/$(EXE_NAME)-mingl $(DESTDIR)$(bindir)/$(EXE_NAME)-mingl
|
$(INSTALL_PROGRAM) $(RELEASE_DIR)/$(EXE_NAME)-mingl $(DESTDIR)$(bindir)/$(EXE_NAME)-mingl
|
||||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/$(EXE_NAME)-sv $(DESTDIR)$(bindir)/$(EXE_NAME)-sv
|
$(INSTALL_PROGRAM) $(RELEASE_DIR)/$(EXE_NAME)-sv $(DESTDIR)$(bindir)/$(EXE_NAME)-sv
|
||||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqcc $(DESTDIR)$(bindir)/fteqcc
|
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqcc $(DESTDIR)$(bindir)/fteqcc
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ typedef struct {
|
||||||
const char *engine_version;
|
const char *engine_version;
|
||||||
|
|
||||||
int (*checkextension) (const char *ext);
|
int (*checkextension) (const char *ext);
|
||||||
void (*error) (const char *err);
|
void (QDECL *error) (const char *err, ...);
|
||||||
void (*printf) (const char *text, ...);
|
void (*printf) (const char *text, ...);
|
||||||
void (*dprintf) (const char *text, ...);
|
void (*dprintf) (const char *text, ...);
|
||||||
void (*localcmd) (const char *cmd);
|
void (*localcmd) (const char *cmd);
|
||||||
|
@ -129,7 +129,7 @@ typedef struct {
|
||||||
void (*localsound) (const char *sample, int channel, float volume);
|
void (*localsound) (const char *sample, int channel, float volume);
|
||||||
|
|
||||||
// file input / search crap
|
// file input / search crap
|
||||||
struct vfsfile_s *(*fopen) (const char *filename, char *modestring, enum fs_relative fsroot); //modestring should be one of rb,r+b,wb,w+b,ab,wbp. Mostly use a root of FS_GAMEONLY for writes, otherwise FS_GAME for reads.
|
struct vfsfile_s *(*fopen) (const char *filename, const char *modestring, enum fs_relative fsroot); //modestring should be one of rb,r+b,wb,w+b,ab,wbp. Mostly use a root of FS_GAMEONLY for writes, otherwise FS_GAME for reads.
|
||||||
void (*fclose) (struct vfsfile_s *fhandle);
|
void (*fclose) (struct vfsfile_s *fhandle);
|
||||||
char *(*fgets) (struct vfsfile_s *fhandle, char *out, size_t outsize); //returns output buffer, or NULL
|
char *(*fgets) (struct vfsfile_s *fhandle, char *out, size_t outsize); //returns output buffer, or NULL
|
||||||
void (*fprintf) (struct vfsfile_s *fhandle, const char *s, ...);
|
void (*fprintf) (struct vfsfile_s *fhandle, const char *s, ...);
|
||||||
|
@ -142,14 +142,14 @@ typedef struct {
|
||||||
qboolean (*drawgetimagesize)(struct shader_s *pic, int *x, int *y);
|
qboolean (*drawgetimagesize)(struct shader_s *pic, int *x, int *y);
|
||||||
void (*drawquad) (const vec2_t position[4], const vec2_t texcoords[4], struct shader_s *pic, const vec4_t rgba, unsigned int be_flags);
|
void (*drawquad) (const vec2_t position[4], const vec2_t texcoords[4], struct shader_s *pic, const vec4_t rgba, unsigned int be_flags);
|
||||||
|
|
||||||
float (*drawstring) (vec2_t position, const char *text, struct font_s *font, float height, const vec4_t rgba, unsigned int be_flags);
|
float (*drawstring) (const vec2_t position, const char *text, struct font_s *font, float height, const vec4_t rgba, unsigned int be_flags);
|
||||||
float (*stringwidth) (const char *text, struct font_s *font, float height);
|
float (*stringwidth) (const char *text, struct font_s *font, float height);
|
||||||
struct font_s *(*loadfont) (const char *facename, float intendedheight); //with ttf fonts, you'll probably want one for each size.
|
struct font_s *(*loadfont) (const char *facename, float intendedheight); //with ttf fonts, you'll probably want one for each size.
|
||||||
void (*destroyfont) (struct font_s *font);
|
void (*destroyfont) (struct font_s *font);
|
||||||
|
|
||||||
// 3D scene stuff
|
// 3D scene stuff
|
||||||
struct model_s *(*cachemodel)(const char *name);
|
struct model_s *(*cachemodel)(const char *name);
|
||||||
void (*getmodelsize) (struct model_s *model, vec3_t out_mins, vec3_t out_maxs);
|
qboolean (*getmodelsize) (struct model_s *model, vec3_t out_mins, vec3_t out_maxs);
|
||||||
void (*renderscene) (menuscene_t *scene);
|
void (*renderscene) (menuscene_t *scene);
|
||||||
|
|
||||||
// Menu specific stuff
|
// Menu specific stuff
|
||||||
|
|
|
@ -956,7 +956,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
|
||||||
int inwater = VM_LONG(arg[3]);
|
int inwater = VM_LONG(arg[3]);
|
||||||
|
|
||||||
cl.playerview[0].audio.defaulted = false;
|
cl.playerview[0].audio.defaulted = false;
|
||||||
cl.playerview[0].audio.entnum = VM_LONG(arg[0]);
|
cl.playerview[0].audio.entnum = VM_LONG(arg[0])+1;
|
||||||
VectorCopy(org, cl.playerview[0].audio.origin);
|
VectorCopy(org, cl.playerview[0].audio.origin);
|
||||||
VectorCopy(axis[0], cl.playerview[0].audio.forward);
|
VectorCopy(axis[0], cl.playerview[0].audio.forward);
|
||||||
VectorCopy(axis[1], cl.playerview[0].audio.right);
|
VectorCopy(axis[1], cl.playerview[0].audio.right);
|
||||||
|
|
|
@ -1187,10 +1187,12 @@ void CL_RecordMap_f (void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//qw-specific serverdata
|
//qw-specific serverdata
|
||||||
static void CLQW_RecordServerData(sizebuf_t *buf)
|
static void CLQW_RecordServerData(sizebuf_t *buf, int *seq)
|
||||||
{
|
{
|
||||||
extern char gamedirfile[];
|
extern char gamedirfile[];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
infosync_t sync;
|
||||||
|
char serverinfostring[1024];
|
||||||
|
|
||||||
// send the serverdata
|
// send the serverdata
|
||||||
MSG_WriteByte (buf, svc_serverdata);
|
MSG_WriteByte (buf, svc_serverdata);
|
||||||
|
@ -1246,31 +1248,79 @@ static void CLQW_RecordServerData(sizebuf_t *buf)
|
||||||
MSG_WriteFloat(buf, movevars.entgravity);
|
MSG_WriteFloat(buf, movevars.entgravity);
|
||||||
|
|
||||||
// send server info string
|
// send server info string
|
||||||
|
memset(&sync, 0, sizeof(sync));
|
||||||
|
InfoBuf_ToString(&cl.serverinfo, serverinfostring, sizeof(serverinfostring), NULL, NULL, NULL, &sync, NULL);
|
||||||
MSG_WriteByte (buf, svc_stufftext);
|
MSG_WriteByte (buf, svc_stufftext);
|
||||||
MSG_WriteString (buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
|
MSG_WriteString (buf, va("fullserverinfo \"%s\"\n", serverinfostring));
|
||||||
|
while(sync.numkeys)
|
||||||
|
{
|
||||||
|
char *keyname = sync.keys[0].name;
|
||||||
|
char enckey[2048], encdata[2048];
|
||||||
|
if (InfoBuf_EncodeString(keyname,strlen(keyname), enckey, sizeof(enckey)))
|
||||||
|
{
|
||||||
|
size_t k;
|
||||||
|
if (InfoBuf_FindKey(&cl.serverinfo, keyname, &k))
|
||||||
|
{
|
||||||
|
size_t offset, chunk;
|
||||||
|
qboolean final;
|
||||||
|
for (offset = 0 ; offset < cl.serverinfo.keys[k].size; offset += chunk)
|
||||||
|
{
|
||||||
|
chunk = cl.serverinfo.keys[k].size - offset;
|
||||||
|
if (chunk > 1024)
|
||||||
|
chunk = 1024;
|
||||||
|
|
||||||
|
if (!InfoBuf_EncodeString(cl.serverinfo.keys[k].value, chunk, encdata, sizeof(encdata)))
|
||||||
|
break; //shouldn't happen.
|
||||||
|
|
||||||
|
if (buf->cursize > 512)
|
||||||
|
CL_WriteRecordDemoMessage (buf, (*seq)++);
|
||||||
|
|
||||||
|
final = (offset+chunk == cl.serverinfo.keys[k].size) && !cl.serverinfo.keys[k].partial;
|
||||||
|
if (!offset && final)
|
||||||
|
{ //vanilla compat. we must just have a lot of data.
|
||||||
|
MSG_WriteByte(buf, svc_serverinfo);
|
||||||
|
MSG_WriteString(buf, enckey);
|
||||||
|
MSG_WriteString(buf, encdata);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //awkward stuff.
|
||||||
|
MSG_WriteByte(buf, svc_setinfo);
|
||||||
|
MSG_WriteByte(buf, 255); //special meaning to say that this is a partial update
|
||||||
|
MSG_WriteByte(buf, 255); //the serverinfo
|
||||||
|
MSG_WriteLong(buf, (final?0x80000000:0)|offset);
|
||||||
|
MSG_WriteString(buf, enckey);
|
||||||
|
MSG_WriteString(buf, encdata);
|
||||||
|
}
|
||||||
|
offset += chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InfoSync_Remove(&sync, 0);
|
||||||
|
}
|
||||||
|
InfoSync_Clear(&sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
void CLNQ_WriteServerData(sizebuf_t *buf)
|
void CLNQ_WriteServerData(sizebuf_t *buf) //for demo recording
|
||||||
{
|
{
|
||||||
unsigned int protmain;
|
unsigned int protmain;
|
||||||
unsigned int protfl = 0;
|
unsigned int protfl = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const char *val;
|
const char *val;
|
||||||
|
|
||||||
val = Info_ValueForKey(cl.serverinfo, "*csprogs");
|
val = InfoBuf_ValueForKey(&cl.serverinfo, "*csprogs");
|
||||||
if (*val)
|
if (*val)
|
||||||
{
|
{
|
||||||
MSG_WriteByte(buf, svc_stufftext);
|
MSG_WriteByte(buf, svc_stufftext);
|
||||||
MSG_WriteString(buf, va("csqc_progcrc \"%s\"\n", val));
|
MSG_WriteString(buf, va("csqc_progcrc \"%s\"\n", val));
|
||||||
}
|
}
|
||||||
val = Info_ValueForKey(cl.serverinfo, "*csprogssize");
|
val = InfoBuf_ValueForKey(&cl.serverinfo, "*csprogssize");
|
||||||
if (*val)
|
if (*val)
|
||||||
{
|
{
|
||||||
MSG_WriteByte(buf, svc_stufftext);
|
MSG_WriteByte(buf, svc_stufftext);
|
||||||
MSG_WriteString(buf, va("csqc_progsize \"%s\"\n", val));
|
MSG_WriteString(buf, va("csqc_progsize \"%s\"\n", val));
|
||||||
}
|
}
|
||||||
val = Info_ValueForKey(cl.serverinfo, "*csprogsname");
|
val = InfoBuf_ValueForKey(&cl.serverinfo, "*csprogsname");
|
||||||
if (*val)
|
if (*val)
|
||||||
{
|
{
|
||||||
MSG_WriteByte(buf, svc_stufftext);
|
MSG_WriteByte(buf, svc_stufftext);
|
||||||
|
@ -1724,7 +1774,7 @@ void CL_Record_f (void)
|
||||||
|
|
||||||
cls.demorecording = DPB_QUAKEWORLD;
|
cls.demorecording = DPB_QUAKEWORLD;
|
||||||
|
|
||||||
CLQW_RecordServerData(&buf);
|
CLQW_RecordServerData(&buf, &seq);
|
||||||
|
|
||||||
// send music
|
// send music
|
||||||
Media_WriteCurrentTrack(&buf);
|
Media_WriteCurrentTrack(&buf);
|
||||||
|
@ -1881,19 +1931,21 @@ void CL_Record_f (void)
|
||||||
MSG_WriteByte (&buf, player->pl);
|
MSG_WriteByte (&buf, player->pl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*player->userinfo)
|
if (player->userinfo.numkeys)
|
||||||
{
|
{
|
||||||
MSG_WriteByte (&buf, svc_updateentertime);
|
MSG_WriteByte (&buf, svc_updateentertime);
|
||||||
MSG_WriteByte (&buf, i);
|
MSG_WriteByte (&buf, i);
|
||||||
MSG_WriteFloat (&buf, realtime - player->realentertime); //seconds since
|
MSG_WriteFloat (&buf, realtime - player->realentertime); //seconds since
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*player->userinfo)
|
if (player->userinfo.numkeys)
|
||||||
{
|
{
|
||||||
|
char info[MAX_LOCALINFO_STRING];
|
||||||
|
InfoBuf_ToString(&player->userinfo, info, sizeof(info), basicuserinfos, NULL, NULL, NULL, NULL);
|
||||||
MSG_WriteByte (&buf, svc_updateuserinfo);
|
MSG_WriteByte (&buf, svc_updateuserinfo);
|
||||||
MSG_WriteByte (&buf, i);
|
MSG_WriteByte (&buf, i);
|
||||||
MSG_WriteLong (&buf, player->userid);
|
MSG_WriteLong (&buf, player->userid);
|
||||||
MSG_WriteString (&buf, player->userinfo);
|
MSG_WriteString (&buf, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.cursize > buf.maxsize/2)
|
if (buf.cursize > buf.maxsize/2)
|
||||||
|
@ -2954,7 +3006,11 @@ void CL_QTVPlay_f (void)
|
||||||
{
|
{
|
||||||
Q_snprintfz(msg+msglen, sizeof(msg)-msglen,
|
Q_snprintfz(msg+msglen, sizeof(msg)-msglen,
|
||||||
"QTV_EZQUAKE_EXT: 3\n"
|
"QTV_EZQUAKE_EXT: 3\n"
|
||||||
"USERINFO: %s\n", cls.userinfo[0]);
|
"USERINFO: ");
|
||||||
|
msglen += strlen(msg+msglen);
|
||||||
|
InfoBuf_ToString(&cls.userinfo[0], msg+msglen, sizeof(msg)-msglen-1, basicuserinfos, NULL, NULL, NULL, NULL);
|
||||||
|
msglen += strlen(msg+msglen);
|
||||||
|
Q_strncatz(msg+msglen, "\n", sizeof(msg)-msglen);
|
||||||
msglen += strlen(msg+msglen);
|
msglen += strlen(msg+msglen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1416,23 +1416,23 @@ void CL_UpdateSeats(void)
|
||||||
{
|
{
|
||||||
char *ver;
|
char *ver;
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
char newinfo[2048];
|
char infostr[2048];
|
||||||
Q_strncpyz(newinfo, cls.userinfo[cl.splitclients], sizeof(newinfo));
|
infobuf_t *info = &cls.userinfo[cl.splitclients];
|
||||||
|
|
||||||
//some userinfos should always have a value
|
//some userinfos should always have a value
|
||||||
if (!*Info_ValueForKey(newinfo, "name")) //$name-2
|
if (!*InfoBuf_ValueForKey(info, "name")) //$name-2
|
||||||
Info_SetValueForKey(newinfo, "name", va("%s-%i\n", Info_ValueForKey(cls.userinfo[0], "name"), cl.splitclients+1), sizeof(newinfo));
|
InfoBuf_SetKey(info, "name", va("%s-%i\n", InfoBuf_ValueForKey(&cls.userinfo[0], "name"), cl.splitclients+1));
|
||||||
if (cls.protocol != CP_QUAKE2)
|
if (cls.protocol != CP_QUAKE2)
|
||||||
{
|
{
|
||||||
if (!*Info_ValueForKey(newinfo, "team")) //put players on the same team by default. this avoids team damage in coop, and if you're playing on the same computer then you probably want to be on the same team anyway.
|
if (!*InfoBuf_ValueForKey(info, "team")) //put players on the same team by default. this avoids team damage in coop, and if you're playing on the same computer then you probably want to be on the same team anyway.
|
||||||
Info_SetValueForKey(newinfo, "team", Info_ValueForKey(cls.userinfo[0], "team"), sizeof(newinfo));
|
InfoBuf_SetKey(info, "team", InfoBuf_ValueForKey(&cls.userinfo[0], "team"));
|
||||||
if (!*Info_ValueForKey(newinfo, "bottomcolor")) //bottom colour implies team in nq
|
if (!*InfoBuf_ValueForKey(info, "bottomcolor")) //bottom colour implies team in nq
|
||||||
Info_SetValueForKey(newinfo, "bottomcolor", Info_ValueForKey(cls.userinfo[0], "bottomcolor"), sizeof(newinfo));
|
InfoBuf_SetKey(info, "bottomcolor", InfoBuf_ValueForKey(&cls.userinfo[0], "bottomcolor"));
|
||||||
if (!*Info_ValueForKey(newinfo, "topcolor")) //should probably pick a random top colour or something
|
if (!*InfoBuf_ValueForKey(info, "topcolor")) //should probably pick a random top colour or something
|
||||||
Info_SetValueForKey(newinfo, "topcolor", Info_ValueForKey(cls.userinfo[0], "topcolor"), sizeof(newinfo));
|
InfoBuf_SetKey(info, "topcolor", InfoBuf_ValueForKey(&cls.userinfo[0], "topcolor"));
|
||||||
}
|
}
|
||||||
if (!*Info_ValueForKey(newinfo, "skin")) //give players the same skin by default, because we can. q2 cares for teams. qw might as well (its not like anyone actually uses them thanks to enemy-skin forcing).
|
if (!*InfoBuf_ValueForKey(info, "skin")) //give players the same skin by default, because we can. q2 cares for teams. qw might as well (its not like anyone actually uses them thanks to enemy-skin forcing).
|
||||||
Info_SetValueForKey(newinfo, "skin", Info_ValueForKey(cls.userinfo[0], "skin"), sizeof(newinfo));
|
InfoBuf_SetKey(info, "skin", InfoBuf_ValueForKey(&cls.userinfo[0], "skin"));
|
||||||
|
|
||||||
#ifdef SVNREVISION
|
#ifdef SVNREVISION
|
||||||
if (strcmp(STRINGIFY(SVNREVISION), "-"))
|
if (strcmp(STRINGIFY(SVNREVISION), "-"))
|
||||||
|
@ -1440,11 +1440,12 @@ void CL_UpdateSeats(void)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
|
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
|
||||||
Info_SetValueForStarKey(newinfo, "*ver", ver, sizeof(newinfo));
|
InfoBuf_SetStarKey(info, "*ver", ver);
|
||||||
|
InfoBuf_ToString(info, infostr, sizeof(infostr), NULL, NULL, NULL, &cls.userinfosync, info);
|
||||||
|
|
||||||
CL_SendClientCommand(true, "addseat %i %s", cl.splitclients, COM_QuotedString(newinfo, buffer, sizeof(buffer), false));
|
CL_SendClientCommand(true, "addseat %i %s", cl.splitclients, COM_QuotedString(infostr, buffer, sizeof(buffer), false));
|
||||||
}
|
}
|
||||||
else if (cl.splitclients > targ)
|
else if (cl.splitclients > targ && targ >= 1)
|
||||||
CL_SendClientCommand(true, "addseat %i", targ);
|
CL_SendClientCommand(true, "addseat %i", targ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1510,13 +1511,6 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
|
||||||
if (cmd->msec > 100)
|
if (cmd->msec > 100)
|
||||||
cmd->msec = 100;
|
cmd->msec = 100;
|
||||||
|
|
||||||
if (cls.resendinfo)
|
|
||||||
{
|
|
||||||
MSG_WriteByte (&cls.netchan.message, clcq2_userinfo);
|
|
||||||
MSG_WriteString (&cls.netchan.message, cls.userinfo[seat]);
|
|
||||||
cls.resendinfo = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MSG_WriteByte (buf, clcq2_move);
|
MSG_WriteByte (buf, clcq2_move);
|
||||||
|
|
||||||
if (seat)
|
if (seat)
|
||||||
|
@ -1703,6 +1697,96 @@ qboolean CLQW_SendCmd (sizebuf_t *buf, qboolean actuallysend)
|
||||||
return dontdrop;
|
return dontdrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CL_SendUserinfoUpdate(void)
|
||||||
|
{
|
||||||
|
const char *key = cls.userinfosync.keys[0].name;
|
||||||
|
infobuf_t *info = cls.userinfosync.keys[0].context;
|
||||||
|
size_t bloboffset = cls.userinfosync.keys[0].syncpos;
|
||||||
|
unsigned int seat = info - cls.userinfo;
|
||||||
|
size_t blobsize;
|
||||||
|
const char *blobdata = InfoBuf_BlobForKey(info, key, &blobsize);
|
||||||
|
size_t sendsize = blobsize - bloboffset;
|
||||||
|
|
||||||
|
const char *s;
|
||||||
|
qboolean final = true;
|
||||||
|
char enckey[2048];
|
||||||
|
char encval[2048];
|
||||||
|
//handle splitscreen
|
||||||
|
char pl[64];
|
||||||
|
|
||||||
|
if (seat)
|
||||||
|
Q_snprintfz(pl, sizeof(pl), "%i ", seat);
|
||||||
|
else
|
||||||
|
*pl = 0;
|
||||||
|
|
||||||
|
#ifdef Q3CLIENT
|
||||||
|
if (cls.protocol == CP_QUAKE3)
|
||||||
|
{ //q3 sends it all in one go
|
||||||
|
char userinfo[2048];
|
||||||
|
InfoBuf_ToString(info, userinfo, sizeof(userinfo), NULL, NULL, NULL, NULL, NULL);
|
||||||
|
CLQ3_SendClientCommand("userinfo \"%s\"", userinfo);
|
||||||
|
InfoSync_Strip(&cls.userinfosync, info); //can't track this stuff. all or nothing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef Q2CLIENT
|
||||||
|
if (cls.protocol == CP_QUAKE2 && !cls.fteprotocolextensions)
|
||||||
|
{
|
||||||
|
char userinfo[2048];
|
||||||
|
InfoSync_Strip(&cls.userinfosync, info); //can't track this stuff. all or nothing.
|
||||||
|
InfoBuf_ToString(info, userinfo, sizeof(userinfo), NULL, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
MSG_WriteByte (&cls.netchan.message, clcq2_userinfo);
|
||||||
|
SZ_Write(&cls.netchan.message, pl, strlen(pl));
|
||||||
|
MSG_WriteString (&cls.netchan.message, userinfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (seat < max(1,cl.splitclients))
|
||||||
|
{
|
||||||
|
if (sendsize > 1023)
|
||||||
|
{
|
||||||
|
final = false;
|
||||||
|
sendsize = 1023; //should be a multiple of 3
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InfoBuf_EncodeString(key, strlen(key), enckey, sizeof(enckey)) ||
|
||||||
|
!InfoBuf_EncodeString(blobdata+bloboffset, sendsize, encval, sizeof(encval)))
|
||||||
|
{ //some buffer wasn't big enough... shouldn't happen.
|
||||||
|
InfoSync_Remove(&cls.userinfosync, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final && !bloboffset && *encval != '\xff' && *encval != '\xff')
|
||||||
|
{ //vanilla-compatible info.
|
||||||
|
s = va("%ssetinfo \"%s\" \"%s\"", pl, enckey, encval);
|
||||||
|
}
|
||||||
|
else if (cls.fteprotocolextensions2 & PEXT2_INFOBLOBS)
|
||||||
|
{ //only flood servers that actually support it.
|
||||||
|
if (final)
|
||||||
|
s = va("%ssetinfo \"%s\" \"%s\" %u", pl, enckey, encval, bloboffset);
|
||||||
|
else
|
||||||
|
s = va("%ssetinfo \"%s\" \"%s\" %u+", pl, enckey, encval, bloboffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //server doesn't support it, just ignore the key
|
||||||
|
InfoSync_Remove(&cls.userinfosync, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cls.protocol == CP_QUAKE2)
|
||||||
|
MSG_WriteByte (&cls.netchan.message, clcq2_stringcmd);
|
||||||
|
else
|
||||||
|
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||||
|
MSG_WriteString (&cls.netchan.message, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bloboffset+sendsize == blobsize)
|
||||||
|
InfoSync_Remove(&cls.userinfosync, 0);
|
||||||
|
else
|
||||||
|
cls.userinfosync.keys[0].syncpos += sendsize;
|
||||||
|
}
|
||||||
|
|
||||||
void CL_SendCmd (double frametime, qboolean mainloop)
|
void CL_SendCmd (double frametime, qboolean mainloop)
|
||||||
{
|
{
|
||||||
sizebuf_t buf;
|
sizebuf_t buf;
|
||||||
|
@ -2001,6 +2085,10 @@ void CL_SendCmd (double frametime, qboolean mainloop)
|
||||||
Z_Free(clientcmdlist);
|
Z_Free(clientcmdlist);
|
||||||
clientcmdlist = next;
|
clientcmdlist = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//only start spamming userinfo blobs once we receive the initial serverinfo.
|
||||||
|
while (cls.userinfosync.numkeys && cls.netchan.message.cursize < 512 && (cl.haveserverinfo || cls.protocol == CP_QUAKE2 || cls.protocol == CP_QUAKE3))
|
||||||
|
CL_SendUserinfoUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're not doing clc_moves and etc, don't continue unless we wrote something previous
|
// if we're not doing clc_moves and etc, don't continue unless we wrote something previous
|
||||||
|
|
|
@ -432,8 +432,6 @@ void CL_ConnectToDarkPlaces(char *challenge, netadr_t *adr)
|
||||||
cls.fteprotocolextensions2 = 0;
|
cls.fteprotocolextensions2 = 0;
|
||||||
cls.ezprotocolextensions1 = 0;
|
cls.ezprotocolextensions1 = 0;
|
||||||
|
|
||||||
cls.resendinfo = false;
|
|
||||||
|
|
||||||
connectinfo.time = realtime; // for retransmit requests
|
connectinfo.time = realtime; // for retransmit requests
|
||||||
|
|
||||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect\\protocol\\darkplaces 3\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\%s\\name\\%s", 255, 255, 255, 255, challenge, name.string);
|
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect\\protocol\\darkplaces 3\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\%s\\name\\%s", 255, 255, 255, 255, challenge, name.string);
|
||||||
|
@ -619,8 +617,6 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
|
||||||
|
|
||||||
t2 = Sys_DoubleTime ();
|
t2 = Sys_DoubleTime ();
|
||||||
|
|
||||||
cls.resendinfo = false;
|
|
||||||
|
|
||||||
connectinfo.time = realtime+t2-t1; // for retransmit requests
|
connectinfo.time = realtime+t2-t1; // for retransmit requests
|
||||||
|
|
||||||
//fixme: we shouldn't cycle these so much
|
//fixme: we shouldn't cycle these so much
|
||||||
|
@ -652,7 +648,10 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
|
||||||
*a = '@';
|
*a = '@';
|
||||||
}
|
}
|
||||||
//the info itself
|
//the info itself
|
||||||
Q_strncatz(data, cls.userinfo[0], sizeof(data));
|
{
|
||||||
|
static const char *prioritykeys[] = {"name", "password", "spectator", "lang", "rate", "team", "topcolor", "bottomcolor", "skin", "_", "*", NULL};
|
||||||
|
InfoBuf_ToString(&cls.userinfo[0], data+strlen(data), sizeof(data)-strlen(data), prioritykeys, NULL, NULL, &cls.userinfosync, &cls.userinfo[0]);
|
||||||
|
}
|
||||||
if (connectinfo.protocol == CP_QUAKEWORLD) //zquake extension info.
|
if (connectinfo.protocol == CP_QUAKEWORLD) //zquake extension info.
|
||||||
Q_strncatz(data, va("\\*z_ext\\%i", SUPPORTED_Z_EXTENSIONS), sizeof(data));
|
Q_strncatz(data, va("\\*z_ext\\%i", SUPPORTED_Z_EXTENSIONS), sizeof(data));
|
||||||
|
|
||||||
|
@ -1633,6 +1632,8 @@ void CL_ClearState (void)
|
||||||
|
|
||||||
Z_Free(cl.windowtitle);
|
Z_Free(cl.windowtitle);
|
||||||
|
|
||||||
|
InfoBuf_Clear(&cl.serverinfo, true);
|
||||||
|
|
||||||
// wipe the entire cl structure
|
// wipe the entire cl structure
|
||||||
memset (&cl, 0, sizeof(cl));
|
memset (&cl, 0, sizeof(cl));
|
||||||
|
|
||||||
|
@ -1647,7 +1648,7 @@ void CL_ClearState (void)
|
||||||
cl.allocated_client_slots = sv.allocated_client_slots;
|
cl.allocated_client_slots = sv.allocated_client_slots;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SZ_Clear (&cls.netchan.message);
|
// SZ_Clear (&cls.netchan.message);
|
||||||
|
|
||||||
r_worldentity.model = NULL;
|
r_worldentity.model = NULL;
|
||||||
|
|
||||||
|
@ -1666,7 +1667,7 @@ void CL_ClearState (void)
|
||||||
cl.playerview[i].maxspeed = 320;
|
cl.playerview[i].maxspeed = 320;
|
||||||
cl.playerview[i].entgravity = 1;
|
cl.playerview[i].entgravity = 1;
|
||||||
|
|
||||||
cl.playerview[i].chatstate = atoi(Info_ValueForKey(cls.userinfo[i], "chat"));
|
cl.playerview[i].chatstate = atoi(InfoBuf_ValueForKey(&cls.userinfo[i], "chat"));
|
||||||
}
|
}
|
||||||
#ifdef QUAKESTATS
|
#ifdef QUAKESTATS
|
||||||
for (i = 0; i < MAX_CLIENTS; i++) //in case some server doesn't support it
|
for (i = 0; i < MAX_CLIENTS; i++) //in case some server doesn't support it
|
||||||
|
@ -1889,7 +1890,7 @@ void CL_User_f (void)
|
||||||
if (!cl.players[i].userinfovalid)
|
if (!cl.players[i].userinfovalid)
|
||||||
Con_Printf("name: %s\ncolour %i %i\nping: %i\n", cl.players[i].name, cl.players[i].rbottomcolor, cl.players[i].rtopcolor, cl.players[i].ping);
|
Con_Printf("name: %s\ncolour %i %i\nping: %i\n", cl.players[i].name, cl.players[i].rbottomcolor, cl.players[i].rtopcolor, cl.players[i].ping);
|
||||||
else
|
else
|
||||||
Info_Print (cl.players[i].userinfo, "");
|
InfoBuf_Print (&cl.players[i].userinfo, "");
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1953,8 +1954,8 @@ void CL_Color_f (void)
|
||||||
|
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
char *t = Info_ValueForKey (cls.userinfo[pnum], "topcolor");
|
char *t = InfoBuf_ValueForKey(&cls.userinfo[pnum], "topcolor");
|
||||||
char *b = Info_ValueForKey (cls.userinfo[pnum], "bottomcolor");
|
char *b = InfoBuf_ValueForKey(&cls.userinfo[pnum], "bottomcolor");
|
||||||
if (!*t)
|
if (!*t)
|
||||||
t = "0";
|
t = "0";
|
||||||
if (!*b)
|
if (!*b)
|
||||||
|
@ -1973,10 +1974,10 @@ void CL_Color_f (void)
|
||||||
t = Cmd_Argv(1);
|
t = Cmd_Argv(1);
|
||||||
b = (Cmd_Argc()==2)?t:Cmd_Argv(2);
|
b = (Cmd_Argc()==2)?t:Cmd_Argv(2);
|
||||||
if (!strcmp(t, "-1"))
|
if (!strcmp(t, "-1"))
|
||||||
t = Info_ValueForKey (cls.userinfo[pnum], "topcolor");
|
t = InfoBuf_ValueForKey(&cls.userinfo[pnum], "topcolor");
|
||||||
top = CL_ParseColour(t);
|
top = CL_ParseColour(t);
|
||||||
if (!strcmp(b, "-1"))
|
if (!strcmp(b, "-1"))
|
||||||
b = Info_ValueForKey (cls.userinfo[pnum], "bottomcolor");
|
b = InfoBuf_ValueForKey(&cls.userinfo[pnum], "bottomcolor");
|
||||||
bottom = CL_ParseColour(b);
|
bottom = CL_ParseColour(b);
|
||||||
|
|
||||||
Q_snprintfz (num, sizeof(num), (top&0xff000000)?"0x%06x":"%i", top & 0xffffff);
|
Q_snprintfz (num, sizeof(num), (top&0xff000000)?"0x%06x":"%i", top & 0xffffff);
|
||||||
|
@ -2049,7 +2050,7 @@ void CL_PakDownloads(int mode)
|
||||||
void CL_CheckServerPacks(void)
|
void CL_CheckServerPacks(void)
|
||||||
{
|
{
|
||||||
static int oldpure;
|
static int oldpure;
|
||||||
int pure = atof(Info_ValueForKey(cl.serverinfo, "sv_pure"));
|
int pure = atof(InfoBuf_ValueForKey(&cl.serverinfo, "sv_pure"));
|
||||||
if (pure < cl_pure.ival)
|
if (pure < cl_pure.ival)
|
||||||
pure = cl_pure.ival;
|
pure = cl_pure.ival;
|
||||||
pure = bound(0, pure, 2);
|
pure = bound(0, pure, 2);
|
||||||
|
@ -2094,8 +2095,8 @@ void CL_CheckServerInfo(void)
|
||||||
spectating = false;
|
spectating = false;
|
||||||
|
|
||||||
oldteamplay = cl.teamplay;
|
oldteamplay = cl.teamplay;
|
||||||
cl.teamplay = atoi(Info_ValueForKey(cl.serverinfo, "teamplay"));
|
cl.teamplay = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "teamplay"));
|
||||||
cls.deathmatch = cl.deathmatch = atoi(Info_ValueForKey(cl.serverinfo, "deathmatch"));
|
cls.deathmatch = cl.deathmatch = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "deathmatch"));
|
||||||
|
|
||||||
cls.allow_cheats = false;
|
cls.allow_cheats = false;
|
||||||
cls.allow_semicheats=true;
|
cls.allow_semicheats=true;
|
||||||
|
@ -2106,16 +2107,16 @@ void CL_CheckServerInfo(void)
|
||||||
// cls.allow_overbrightlight;
|
// cls.allow_overbrightlight;
|
||||||
|
|
||||||
|
|
||||||
cls.allow_csqc = atoi(Info_ValueForKey(cl.serverinfo, "anycsqc")) || *Info_ValueForKey(cl.serverinfo, "*csprogs");
|
cls.allow_csqc = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "anycsqc")) || *InfoBuf_ValueForKey(&cl.serverinfo, "*csprogs");
|
||||||
cl.csqcdebug = atoi(Info_ValueForKey(cl.serverinfo, "*csqcdebug"));
|
cl.csqcdebug = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "*csqcdebug"));
|
||||||
|
|
||||||
if (spectating || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "watervis")))
|
if (spectating || cls.demoplayback || atoi(InfoBuf_ValueForKey(&cl.serverinfo, "watervis")))
|
||||||
cls.allow_watervis=true;
|
cls.allow_watervis=true;
|
||||||
|
|
||||||
if (spectating || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "allow_skybox")) || atoi(Info_ValueForKey(cl.serverinfo, "allow_skyboxes")))
|
if (spectating || cls.demoplayback || atoi(InfoBuf_ValueForKey(&cl.serverinfo, "allow_skybox")) || atoi(InfoBuf_ValueForKey(&cl.serverinfo, "allow_skyboxes")))
|
||||||
cls.allow_skyboxes=true; //mostly obsolete.
|
cls.allow_skyboxes=true; //mostly obsolete.
|
||||||
|
|
||||||
s = Info_ValueForKey(cl.serverinfo, "fbskins");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "fbskins");
|
||||||
if (*s)
|
if (*s)
|
||||||
cls.allow_fbskins = atof(s);
|
cls.allow_fbskins = atof(s);
|
||||||
else if (cl.teamfortress)
|
else if (cl.teamfortress)
|
||||||
|
@ -2123,7 +2124,7 @@ void CL_CheckServerInfo(void)
|
||||||
else
|
else
|
||||||
cls.allow_fbskins = 1;
|
cls.allow_fbskins = 1;
|
||||||
|
|
||||||
s = Info_ValueForKey(cl.serverinfo, "*cheats");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "*cheats");
|
||||||
if (spectating || cls.demoplayback || !stricmp(s, "on"))
|
if (spectating || cls.demoplayback || !stricmp(s, "on"))
|
||||||
cls.allow_cheats = true;
|
cls.allow_cheats = true;
|
||||||
|
|
||||||
|
@ -2134,14 +2135,14 @@ void CL_CheckServerInfo(void)
|
||||||
cls.allow_cheats = true;
|
cls.allow_cheats = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s = Info_ValueForKey(cl.serverinfo, "strict");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "strict");
|
||||||
if ((!spectating && !cls.demoplayback && *s && strcmp(s, "0")) || !ruleset_allow_semicheats.ival)
|
if ((!spectating && !cls.demoplayback && *s && strcmp(s, "0")) || !ruleset_allow_semicheats.ival)
|
||||||
{
|
{
|
||||||
cls.allow_semicheats = false;
|
cls.allow_semicheats = false;
|
||||||
cls.allow_cheats = false;
|
cls.allow_cheats = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.z_ext = atoi(Info_ValueForKey(cl.serverinfo, "*z_ext"));
|
cls.z_ext = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "*z_ext"));
|
||||||
|
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
||||||
|
@ -2151,22 +2152,22 @@ void CL_CheckServerInfo(void)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
cls.maxfps = atof(Info_ValueForKey(cl.serverinfo, "maxfps"));
|
cls.maxfps = atof(InfoBuf_ValueForKey(&cl.serverinfo, "maxfps"));
|
||||||
if (cls.maxfps < 20)
|
if (cls.maxfps < 20)
|
||||||
cls.maxfps = 72;
|
cls.maxfps = 72;
|
||||||
|
|
||||||
// movement vars for prediction
|
// movement vars for prediction
|
||||||
cl.bunnyspeedcap = Q_atof(Info_ValueForKey(cl.serverinfo, "pm_bunnyspeedcap"));
|
cl.bunnyspeedcap = Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_bunnyspeedcap"));
|
||||||
movevars.slidefix = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_slidefix")) != 0);
|
movevars.slidefix = (Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_slidefix")) != 0);
|
||||||
movevars.airstep = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_airstep")) != 0);
|
movevars.airstep = (Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_airstep")) != 0);
|
||||||
movevars.stepdown = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_stepdown")) != 0);
|
movevars.stepdown = (Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_stepdown")) != 0);
|
||||||
movevars.walljump = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_walljump")));
|
movevars.walljump = (Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_walljump")));
|
||||||
movevars.ktjump = Q_atof(Info_ValueForKey(cl.serverinfo, "pm_ktjump"));
|
movevars.ktjump = Q_atof(InfoBuf_ValueForKey(&cl.serverinfo, "pm_ktjump"));
|
||||||
s = Info_ValueForKey(cl.serverinfo, "pm_stepheight");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "pm_stepheight");
|
||||||
movevars.stepheight = *s?Q_atof(s):PM_DEFAULTSTEPHEIGHT;
|
movevars.stepheight = *s?Q_atof(s):PM_DEFAULTSTEPHEIGHT;
|
||||||
s = Info_ValueForKey(cl.serverinfo, "pm_watersinkspeed");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "pm_watersinkspeed");
|
||||||
movevars.watersinkspeed = *s?Q_atof(s):60;
|
movevars.watersinkspeed = *s?Q_atof(s):60;
|
||||||
s = Info_ValueForKey(cl.serverinfo, "pm_flyfriction");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "pm_flyfriction");
|
||||||
movevars.flyfriction = *s?Q_atof(s):4;
|
movevars.flyfriction = *s?Q_atof(s):4;
|
||||||
}
|
}
|
||||||
movevars.coordsize = cls.netchan.netprim.coordsize;
|
movevars.coordsize = cls.netchan.netprim.coordsize;
|
||||||
|
@ -2174,9 +2175,9 @@ void CL_CheckServerInfo(void)
|
||||||
// Initialize cl.maxpitch & cl.minpitch
|
// Initialize cl.maxpitch & cl.minpitch
|
||||||
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)
|
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)
|
||||||
{
|
{
|
||||||
s = Info_ValueForKey (cl.serverinfo, "maxpitch");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "maxpitch");
|
||||||
cl.maxpitch = *s ? Q_atof(s) : ((cl_fullpitch_nq.ival && !cl.haveserverinfo)?90.0f:80.0f);
|
cl.maxpitch = *s ? Q_atof(s) : ((cl_fullpitch_nq.ival && !cl.haveserverinfo)?90.0f:80.0f);
|
||||||
s = Info_ValueForKey (cl.serverinfo, "minpitch");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "minpitch");
|
||||||
cl.minpitch = *s ? Q_atof(s) : ((cl_fullpitch_nq.ival && !cl.haveserverinfo)?-90.0f:-70.0f);
|
cl.minpitch = *s ? Q_atof(s) : ((cl_fullpitch_nq.ival && !cl.haveserverinfo)?-90.0f:-70.0f);
|
||||||
|
|
||||||
if (cls.protocol == CP_NETQUAKE)
|
if (cls.protocol == CP_NETQUAKE)
|
||||||
|
@ -2195,9 +2196,9 @@ void CL_CheckServerInfo(void)
|
||||||
cl.maxpitch = bound(-89.9, cl.maxpitch, 89.9);
|
cl.maxpitch = bound(-89.9, cl.maxpitch, 89.9);
|
||||||
cl.minpitch = bound(-89.9, cl.minpitch, 89.9);
|
cl.minpitch = bound(-89.9, cl.minpitch, 89.9);
|
||||||
|
|
||||||
cl.hexen2pickups = atoi(Info_ValueForKey(cl.serverinfo, "sv_pupglow"));
|
cl.hexen2pickups = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "sv_pupglow"));
|
||||||
|
|
||||||
allowed = atoi(Info_ValueForKey(cl.serverinfo, "allow"));
|
allowed = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "allow"));
|
||||||
if (allowed & 1)
|
if (allowed & 1)
|
||||||
cls.allow_watervis = true;
|
cls.allow_watervis = true;
|
||||||
// if (allowed & 2)
|
// if (allowed & 2)
|
||||||
|
@ -2224,14 +2225,14 @@ void CL_CheckServerInfo(void)
|
||||||
if (spectating || cls.demoplayback)
|
if (spectating || cls.demoplayback)
|
||||||
cl.fpd = 0;
|
cl.fpd = 0;
|
||||||
else
|
else
|
||||||
cl.fpd = atoi(Info_ValueForKey(cl.serverinfo, "fpd"));
|
cl.fpd = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "fpd"));
|
||||||
|
|
||||||
cl.gamespeed = atof(Info_ValueForKey(cl.serverinfo, "*gamespeed"))/100.f;
|
cl.gamespeed = atof(InfoBuf_ValueForKey(&cl.serverinfo, "*gamespeed"))/100.f;
|
||||||
if (cl.gamespeed < 0.1)
|
if (cl.gamespeed < 0.1)
|
||||||
cl.gamespeed = 1;
|
cl.gamespeed = 1;
|
||||||
|
|
||||||
#ifdef QUAKESTATS
|
#ifdef QUAKESTATS
|
||||||
s = Info_ValueForKey(cl.serverinfo, "status");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "status");
|
||||||
oldstate = cl.matchstate;
|
oldstate = cl.matchstate;
|
||||||
if (!stricmp(s, "standby"))
|
if (!stricmp(s, "standby"))
|
||||||
cl.matchstate = MATCH_STANDBY;
|
cl.matchstate = MATCH_STANDBY;
|
||||||
|
@ -2253,7 +2254,7 @@ void CL_CheckServerInfo(void)
|
||||||
{
|
{
|
||||||
//always update it. this is to try to cope with overtime.
|
//always update it. this is to try to cope with overtime.
|
||||||
oldstate = cl.matchstate = MATCH_INPROGRESS;
|
oldstate = cl.matchstate = MATCH_INPROGRESS;
|
||||||
cl.matchgametimestart = cl.gametime + time - 60*atof(Info_ValueForKey(cl.serverinfo, "timelimit"));
|
cl.matchgametimestart = cl.gametime + time - 60*atof(InfoBuf_ValueForKey(&cl.serverinfo, "timelimit"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2335,11 +2336,11 @@ void CL_FullInfo_f (void)
|
||||||
if (!stricmp(key, pmodel_name) || !stricmp(key, emodel_name))
|
if (!stricmp(key, pmodel_name) || !stricmp(key, emodel_name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Info_SetValueForKey (cls.userinfo[pnum], key, value, sizeof(cls.userinfo[pnum]));
|
InfoBuf_SetKey (&cls.userinfo[pnum], key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CL_SetInfo (int pnum, char *key, char *value)
|
void CL_SetInfoBlob (int pnum, const char *key, const char *value, size_t valuesize)
|
||||||
{
|
{
|
||||||
cvar_t *var;
|
cvar_t *var;
|
||||||
if (!pnum)
|
if (!pnum)
|
||||||
|
@ -2352,25 +2353,11 @@ void CL_SetInfo (int pnum, char *key, char *value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Info_SetValueForStarKey (cls.userinfo[pnum], key, value, sizeof(cls.userinfo[pnum]));
|
InfoBuf_SetStarBlobKey(&cls.userinfo[pnum], key, value, valuesize);
|
||||||
if (cls.state >= ca_connected && !cls.demoplayback)
|
}
|
||||||
{
|
void CL_SetInfo (int pnum, const char *key, const char *value)
|
||||||
if (pnum >= cl.splitclients)
|
{
|
||||||
return;
|
CL_SetInfoBlob(pnum, key, value, strlen(value));
|
||||||
|
|
||||||
#ifdef Q2CLIENT
|
|
||||||
if ((cls.protocol == CP_QUAKE2 || cls.protocol == CP_QUAKE3) && !cls.fteprotocolextensions)
|
|
||||||
cls.resendinfo = true;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (cls.protocol != CP_NETQUAKE || (cls.fteprotocolextensions & PEXT_BIGUSERINFOS))
|
|
||||||
{
|
|
||||||
if (pnum)
|
|
||||||
CL_SendClientCommand(true, "%i setinfo %s \"%s\"", pnum+1, key, value);
|
|
||||||
else
|
|
||||||
CL_SendClientCommand(true, "setinfo %s \"%s\"", key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
|
@ -2385,7 +2372,8 @@ void CL_SetInfo_f (void)
|
||||||
int pnum = CL_TargettedSplit(true);
|
int pnum = CL_TargettedSplit(true);
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
Info_Print (cls.userinfo[pnum], "");
|
InfoBuf_Print (&cls.userinfo[pnum], "");
|
||||||
|
Con_Printf("[%u]", (unsigned int)cls.userinfo[pnum].totalsize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Cmd_Argc() != 3)
|
if (Cmd_Argc() != 3)
|
||||||
|
@ -2402,18 +2390,18 @@ void CL_SetInfo_f (void)
|
||||||
if (!strcmp(Cmd_Argv(1), "*"))
|
if (!strcmp(Cmd_Argv(1), "*"))
|
||||||
if (!strcmp(Cmd_Argv(2), ""))
|
if (!strcmp(Cmd_Argv(2), ""))
|
||||||
{ //clear it out
|
{ //clear it out
|
||||||
char *k;
|
const char *k;
|
||||||
for(i=0;;)
|
for(i=0;;)
|
||||||
{
|
{
|
||||||
k = Info_KeyForNumber(cls.userinfo[pnum], i);
|
k = InfoBuf_KeyForNumber(&cls.userinfo[pnum], i);
|
||||||
if (!*k)
|
if (!k)
|
||||||
break; //no more.
|
break; //no more.
|
||||||
else if (*k == '*')
|
else if (*k == '*')
|
||||||
i++; //can't remove * keys
|
i++; //can't remove * keys
|
||||||
else if ((var = Cvar_FindVar(k)) && var->flags&CVAR_USERINFO)
|
else if ((var = Cvar_FindVar(k)) && (var->flags&CVAR_USERINFO))
|
||||||
i++; //this one is a cvar.
|
i++; //this one is a cvar.
|
||||||
else
|
else
|
||||||
Info_RemoveKey(cls.userinfo[pnum], k); //we can remove this one though, so yay.
|
InfoBuf_RemoveKey(&cls.userinfo[pnum], k); //we can remove this one though, so yay.
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -2422,10 +2410,49 @@ void CL_SetInfo_f (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CL_SetInfo(pnum, Cmd_Argv(1), Cmd_Argv(2));
|
CL_SetInfo(pnum, Cmd_Argv(1), Cmd_Argv(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
void CL_SetInfoBlob_f (void)
|
||||||
|
{
|
||||||
|
qofs_t fsize;
|
||||||
|
void *data;
|
||||||
|
int pnum = CL_TargettedSplit(true);
|
||||||
|
if (Cmd_Argc() == 1)
|
||||||
|
{
|
||||||
|
InfoBuf_Print (&cls.userinfo[pnum], "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Cmd_Argc() != 3)
|
||||||
|
{
|
||||||
|
Con_TPrintf ("usage: setinfo [ <key> <filename> ]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//user isn't allowed to set pmodel, emodel, *foo as these could break stuff.
|
||||||
|
if (!stricmp(Cmd_Argv(1), pmodel_name) || !strcmp(Cmd_Argv(1), emodel_name))
|
||||||
|
return;
|
||||||
|
if (Cmd_Argv(1)[0] == '*')
|
||||||
|
{
|
||||||
|
Con_Printf ("Can't set * keys\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = FS_MallocFile(Cmd_Argv(2), FS_GAME, &fsize);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
Con_Printf ("Unable to read %s\n", Cmd_Argv(2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fsize > 64*1024*1024)
|
||||||
|
Con_Printf ("File is over 64mb\n");
|
||||||
|
else
|
||||||
|
CL_SetInfoBlob(pnum, Cmd_Argv(1), data, fsize);
|
||||||
|
FS_FreeFile(data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void CL_SaveInfo(vfsfile_t *f)
|
void CL_SaveInfo(vfsfile_t *f)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2435,12 +2462,12 @@ void CL_SaveInfo(vfsfile_t *f)
|
||||||
if (i)
|
if (i)
|
||||||
{
|
{
|
||||||
VFS_WRITE(f, va("p%i setinfo * \"\"\n", i+1), 16);
|
VFS_WRITE(f, va("p%i setinfo * \"\"\n", i+1), 16);
|
||||||
Info_WriteToFile(f, cls.userinfo[i], va("p%i setinfo", i+1), 0);
|
InfoBuf_WriteToFile(f, &cls.userinfo[i], va("p%i setinfo", i+1), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VFS_WRITE(f, "setinfo * \"\"\n", 13);
|
VFS_WRITE(f, "setinfo * \"\"\n", 13);
|
||||||
Info_WriteToFile(f, cls.userinfo[i], "setinfo", CVAR_USERINFO);
|
InfoBuf_WriteToFile(f, &cls.userinfo[i], "setinfo", CVAR_USERINFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3921,10 +3948,8 @@ void CL_ServerInfo_f(void)
|
||||||
{
|
{
|
||||||
if (!sv.state && cls.state && Cmd_Argc() < 2)
|
if (!sv.state && cls.state && Cmd_Argc() < 2)
|
||||||
{
|
{
|
||||||
if (cls.demoplayback || cls.protocol != CP_QUAKEWORLD)
|
if (cl.haveserverinfo)
|
||||||
{
|
InfoBuf_Print (&cl.serverinfo, "");
|
||||||
Info_Print (cl.serverinfo, "");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Cmd_ForwardToServer ();
|
Cmd_ForwardToServer ();
|
||||||
}
|
}
|
||||||
|
@ -4117,6 +4142,12 @@ void CL_Demo_SetSpeed_f(void)
|
||||||
Con_Printf("demo playback speed %g%%\n", cl_demospeed.value * 100);
|
Con_Printf("demo playback speed %g%%\n", cl_demospeed.value * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CL_UserinfoChanged(void *ctx, const char *keyname)
|
||||||
|
{
|
||||||
|
InfoSync_Add(&cls.userinfosync, ctx, keyname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CL_Skygroup_f(void);
|
void CL_Skygroup_f(void);
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
|
@ -4133,6 +4164,7 @@ void CL_Init (void)
|
||||||
extern cvar_t noskins;
|
extern cvar_t noskins;
|
||||||
#endif
|
#endif
|
||||||
char *ver;
|
char *ver;
|
||||||
|
size_t seat;
|
||||||
|
|
||||||
cls.state = ca_disconnected;
|
cls.state = ca_disconnected;
|
||||||
|
|
||||||
|
@ -4143,7 +4175,12 @@ void CL_Init (void)
|
||||||
#endif
|
#endif
|
||||||
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
|
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
|
||||||
|
|
||||||
Info_SetValueForStarKey (cls.userinfo[0], "*ver", ver, sizeof(cls.userinfo[0]));
|
for (seat = 0; seat < MAX_SPLITS; seat++)
|
||||||
|
{
|
||||||
|
cls.userinfo[seat].ChangeCTX = &cls.userinfo[seat];
|
||||||
|
cls.userinfo[seat].ChangeCB = CL_UserinfoChanged;
|
||||||
|
InfoBuf_SetStarKey (&cls.userinfo[seat], "*ver", ver);
|
||||||
|
}
|
||||||
|
|
||||||
InitValidation();
|
InitValidation();
|
||||||
|
|
||||||
|
@ -4412,6 +4449,9 @@ void CL_Init (void)
|
||||||
Cmd_AddCommand ("user", CL_User_f);
|
Cmd_AddCommand ("user", CL_User_f);
|
||||||
Cmd_AddCommand ("users", CL_Users_f);
|
Cmd_AddCommand ("users", CL_Users_f);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
Cmd_AddCommand ("setinfoblob", CL_SetInfoBlob_f);
|
||||||
|
#endif
|
||||||
Cmd_AddCommand ("setinfo", CL_SetInfo_f);
|
Cmd_AddCommand ("setinfo", CL_SetInfo_f);
|
||||||
Cmd_AddCommand ("fullinfo", CL_FullInfo_f);
|
Cmd_AddCommand ("fullinfo", CL_FullInfo_f);
|
||||||
|
|
||||||
|
@ -5756,7 +5796,7 @@ void CL_ReadCDKey(void)
|
||||||
{ //q3 cdkey
|
{ //q3 cdkey
|
||||||
//you don't need one, just use a server without sv_strictauth set to 0.
|
//you don't need one, just use a server without sv_strictauth set to 0.
|
||||||
char *buffer;
|
char *buffer;
|
||||||
buffer = COM_LoadTempFile("q3key", NULL);
|
buffer = COM_LoadTempFile("q3key", FSLF_IGNOREPURE, NULL);
|
||||||
if (buffer) //a cdkey is meant to be 16 chars
|
if (buffer) //a cdkey is meant to be 16 chars
|
||||||
{
|
{
|
||||||
char *chr;
|
char *chr;
|
||||||
|
@ -6221,6 +6261,7 @@ to run quit through here before the final handoff to the sys code.
|
||||||
*/
|
*/
|
||||||
void Host_Shutdown(void)
|
void Host_Shutdown(void)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
if (!host_initialized)
|
if (!host_initialized)
|
||||||
return;
|
return;
|
||||||
host_initialized = false;
|
host_initialized = false;
|
||||||
|
@ -6290,6 +6331,10 @@ void Host_Shutdown(void)
|
||||||
Plug_Shutdown(true);
|
Plug_Shutdown(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_SPLITS; i++)
|
||||||
|
InfoBuf_Clear(&cls.userinfo[i], true);
|
||||||
|
InfoSync_Clear(&cls.userinfosync);
|
||||||
|
|
||||||
Con_Shutdown();
|
Con_Shutdown();
|
||||||
COM_BiDi_Shutdown();
|
COM_BiDi_Shutdown();
|
||||||
Memory_DeInit();
|
Memory_DeInit();
|
||||||
|
|
|
@ -1235,10 +1235,10 @@ static int CL_LoadModels(int stage, qboolean dontactuallyload)
|
||||||
qboolean anycsqc;
|
qboolean anycsqc;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
unsigned int chksum;
|
unsigned int chksum;
|
||||||
anycsqc = atoi(Info_ValueForKey(cl.serverinfo, "anycsqc"));
|
anycsqc = atoi(InfoBuf_ValueForKey(&cl.serverinfo, "anycsqc"));
|
||||||
if (cls.demoplayback)
|
if (cls.demoplayback)
|
||||||
anycsqc = true;
|
anycsqc = true;
|
||||||
s = Info_ValueForKey(cl.serverinfo, "*csprogs");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "*csprogs");
|
||||||
chksum = strtoul(s, &endptr, 0);
|
chksum = strtoul(s, &endptr, 0);
|
||||||
if (*endptr)
|
if (*endptr)
|
||||||
{
|
{
|
||||||
|
@ -1515,7 +1515,7 @@ static void Sound_CheckDownloads (void)
|
||||||
// if (cls.fteprotocolextensions & PEXT_CSQC)
|
// if (cls.fteprotocolextensions & PEXT_CSQC)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
s = Info_ValueForKey(cl.serverinfo, "*csprogs");
|
s = InfoBuf_ValueForKey(&cl.serverinfo, "*csprogs");
|
||||||
if (*s) //only allow csqc if the server says so, and the 'checksum' matches.
|
if (*s) //only allow csqc if the server says so, and the 'checksum' matches.
|
||||||
{
|
{
|
||||||
extern cvar_t cl_download_csprogs, cl_nocsqc;
|
extern cvar_t cl_download_csprogs, cl_nocsqc;
|
||||||
|
@ -1640,6 +1640,8 @@ void CL_RequestNextDownload (void)
|
||||||
current_loading_size = cl.contentstage;
|
current_loading_size = cl.contentstage;
|
||||||
if (stage < 0)
|
if (stage < 0)
|
||||||
return;
|
return;
|
||||||
|
//if (cls.userinfosync.numkeys)
|
||||||
|
// return; //don't prespawn until we've actually sent all our initial userinfo.
|
||||||
if (requiredownloads.ival && COM_HasWork())
|
if (requiredownloads.ival && COM_HasWork())
|
||||||
{
|
{
|
||||||
SCR_SetLoadingFile("loading content");
|
SCR_SetLoadingFile("loading content");
|
||||||
|
@ -2457,7 +2459,7 @@ void DL_Abort(qdownload_t *dl, enum qdlabort aborttype)
|
||||||
case DL_DARKPLACES:
|
case DL_DARKPLACES:
|
||||||
case DL_QWCHUNKS:
|
case DL_QWCHUNKS:
|
||||||
{
|
{
|
||||||
char *serverversion = Info_ValueForKey(cl.serverinfo, "*version");
|
char *serverversion = InfoBuf_ValueForKey(&cl.serverinfo, "*version");
|
||||||
if (strncmp(serverversion , "MVDSV ", 6)) //don't tell mvdsv to stop, because it has retarded annoying clientprints that are spammy as fuck, and we don't want that.
|
if (strncmp(serverversion , "MVDSV ", 6)) //don't tell mvdsv to stop, because it has retarded annoying clientprints that are spammy as fuck, and we don't want that.
|
||||||
CL_SendClientCommand(true, "stopdownload");
|
CL_SendClientCommand(true, "stopdownload");
|
||||||
}
|
}
|
||||||
|
@ -3116,7 +3118,7 @@ static void CLQW_ParseServerData (void)
|
||||||
COM_FlushTempoaryPacks();
|
COM_FlushTempoaryPacks();
|
||||||
COM_Gamedir(str, NULL);
|
COM_Gamedir(str, NULL);
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
Info_SetValueForStarKey (svs.info, "*gamedir", str, MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey (&svs.info, "*gamedir", str);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3676,7 +3678,7 @@ static void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caut
|
||||||
COM_FlushTempoaryPacks();
|
COM_FlushTempoaryPacks();
|
||||||
COM_Gamedir(str, NULL);
|
COM_Gamedir(str, NULL);
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
Info_SetValueForStarKey (svs.info, "*gamedir", str, MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey (&svs.info, "*gamedir", str);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3752,29 +3754,29 @@ static void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caut
|
||||||
//fill in the csqc stuff
|
//fill in the csqc stuff
|
||||||
if (!cl_dp_csqc_progscrc)
|
if (!cl_dp_csqc_progscrc)
|
||||||
{
|
{
|
||||||
Info_RemoveKey(cl.serverinfo, "*csprogs");
|
InfoBuf_RemoveKey(&cl.serverinfo, "*csprogs");
|
||||||
Info_RemoveKey(cl.serverinfo, "*csprogssize");
|
InfoBuf_RemoveKey(&cl.serverinfo, "*csprogssize");
|
||||||
Info_RemoveKey(cl.serverinfo, "*csprogsname");
|
InfoBuf_RemoveKey(&cl.serverinfo, "*csprogsname");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc), sizeof(cl.serverinfo));
|
InfoBuf_SetStarKey(&cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc));
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "*csprogssize", va("%i", cl_dp_csqc_progssize), sizeof(cl.serverinfo));
|
InfoBuf_SetStarKey(&cl.serverinfo, "*csprogssize", va("%i", cl_dp_csqc_progssize));
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "*csprogsname", va("%s", cl_dp_csqc_progsname), sizeof(cl.serverinfo));
|
InfoBuf_SetStarKey(&cl.serverinfo, "*csprogsname", va("%s", cl_dp_csqc_progsname));
|
||||||
}
|
}
|
||||||
|
|
||||||
//update gamemode
|
//update gamemode
|
||||||
if (gametype != GAME_COOP)
|
if (gametype != GAME_COOP)
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "deathmatch", "1", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "deathmatch", "1");
|
||||||
else
|
else
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "deathmatch", "0", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "deathmatch", "0");
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "teamplay", "0", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "teamplay", "0");
|
||||||
|
|
||||||
//allow some things by default that quakeworld bans by default
|
//allow some things by default that quakeworld bans by default
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "watervis", "1", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "watervis", "1");
|
||||||
|
|
||||||
//prohibit some things that QW/FTE has enabled by default, which would be frowned upon in NQ
|
//prohibit some things that QW/FTE has enabled by default, which would be frowned upon in NQ
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "fbskins", "0", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "fbskins", "0");
|
||||||
|
|
||||||
//pretend it came from the server, and update cheat/permissions/etc
|
//pretend it came from the server, and update cheat/permissions/etc
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
|
@ -3822,7 +3824,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
|
||||||
CL_SendClientCommand(true, "name \"%s\"\n", name.string);
|
CL_SendClientCommand(true, "name \"%s\"\n", name.string);
|
||||||
CL_SendClientCommand(true, "color %i %i\n", topcolor.ival, bottomcolor.ival);
|
CL_SendClientCommand(true, "color %i %i\n", topcolor.ival, bottomcolor.ival);
|
||||||
if (cl.haveserverinfo)
|
if (cl.haveserverinfo)
|
||||||
Info_Enumerate(cls.userinfo[0], NULL, CLNQ_SendInitialUserInfo);
|
InfoBuf_Enumerate(&cls.userinfo[0], NULL, CLNQ_SendInitialUserInfo);
|
||||||
else if (CPNQ_IS_DP)
|
else if (CPNQ_IS_DP)
|
||||||
{ //dp needs a couple of extras to work properly in certain cases. don't send them on other servers because that generally results in error messages.
|
{ //dp needs a couple of extras to work properly in certain cases. don't send them on other servers because that generally results in error messages.
|
||||||
CL_SendClientCommand(true, "rate %s", rate.string);
|
CL_SendClientCommand(true, "rate %s", rate.string);
|
||||||
|
@ -4168,7 +4170,7 @@ static void CLQ2_ParseClientinfo(int i, char *s)
|
||||||
|
|
||||||
player = &cl.players[i];
|
player = &cl.players[i];
|
||||||
|
|
||||||
*player->userinfo = '\0';
|
InfoBuf_Clear(&player->userinfo, true);
|
||||||
cl.players[i].userinfovalid = true;
|
cl.players[i].userinfovalid = true;
|
||||||
|
|
||||||
model = strchr(s, '\\');
|
model = strchr(s, '\\');
|
||||||
|
@ -4192,12 +4194,12 @@ static void CLQ2_ParseClientinfo(int i, char *s)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
skin = "";
|
skin = "";
|
||||||
Info_SetValueForKey(player->userinfo, "model", model, MAX_INFO_STRING);
|
InfoBuf_SetValueForKey(&player->userinfo, "model", model);
|
||||||
Info_SetValueForKey(player->userinfo, "skin", skin, MAX_INFO_STRING);
|
InfoBuf_SetValueForKey(&player->userinfo, "skin", skin);
|
||||||
#else
|
#else
|
||||||
Info_SetValueForKey(player->userinfo, "skin", model, sizeof(player->userinfo));
|
InfoBuf_SetValueForKey(&player->userinfo, "skin", model);
|
||||||
#endif
|
#endif
|
||||||
Info_SetValueForKey(player->userinfo, "name", name, sizeof(player->userinfo));
|
InfoBuf_SetValueForKey(&player->userinfo, "name", name);
|
||||||
|
|
||||||
cl.players[i].userid = i;
|
cl.players[i].userid = i;
|
||||||
cl.players[i].rbottomcolor = 1;
|
cl.players[i].rbottomcolor = 1;
|
||||||
|
@ -4288,6 +4290,8 @@ static void CLQ2_ParseConfigString (void)
|
||||||
{
|
{
|
||||||
Media_NamedTrack (s, NULL);
|
Media_NamedTrack (s, NULL);
|
||||||
}
|
}
|
||||||
|
else if (i == Q2CS_AIRACCEL)
|
||||||
|
Q_strncpyz(cl.q2airaccel, s, sizeof(cl.q2airaccel));
|
||||||
else if (i >= Q2CS_MODELS && i < Q2CS_MODELS+Q2MAX_MODELS)
|
else if (i >= Q2CS_MODELS && i < Q2CS_MODELS+Q2MAX_MODELS)
|
||||||
{
|
{
|
||||||
if (*s == '/')
|
if (*s == '/')
|
||||||
|
@ -4756,7 +4760,7 @@ static void CLQ2_ParseStartSoundPacket(void)
|
||||||
{ //a 'sexed' sound
|
{ //a 'sexed' sound
|
||||||
if (ent > 0 && ent <= MAX_CLIENTS)
|
if (ent > 0 && ent <= MAX_CLIENTS)
|
||||||
{
|
{
|
||||||
char *model = Info_ValueForKey(cl.players[ent-1].userinfo, "skin");
|
char *model = InfoBuf_ValueForKey(&cl.players[ent-1].userinfo, "skin");
|
||||||
char *skin;
|
char *skin;
|
||||||
skin = strchr(model, '/');
|
skin = strchr(model, '/');
|
||||||
if (skin)
|
if (skin)
|
||||||
|
@ -4975,7 +4979,7 @@ void CL_NewTranslation (int slot)
|
||||||
player->ttopcolor = TOP_DEFAULT;
|
player->ttopcolor = TOP_DEFAULT;
|
||||||
player->tbottomcolor = BOTTOM_DEFAULT;
|
player->tbottomcolor = BOTTOM_DEFAULT;
|
||||||
|
|
||||||
mod = Info_ValueForKey(player->userinfo, "skin");
|
mod = InfoBuf_ValueForKey(&player->userinfo, "skin");
|
||||||
skin = strchr(mod, '/');
|
skin = strchr(mod, '/');
|
||||||
if (skin)
|
if (skin)
|
||||||
*skin++ = 0;
|
*skin++ = 0;
|
||||||
|
@ -5077,22 +5081,22 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
|
||||||
int i;
|
int i;
|
||||||
char *col;
|
char *col;
|
||||||
int ospec = player->spectator;
|
int ospec = player->spectator;
|
||||||
Q_strncpyz (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name));
|
Q_strncpyz (player->name, InfoBuf_ValueForKey (&player->userinfo, "name"), sizeof(player->name));
|
||||||
Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team));
|
Q_strncpyz (player->team, InfoBuf_ValueForKey (&player->userinfo, "team"), sizeof(player->team));
|
||||||
|
|
||||||
col = Info_ValueForKey (player->userinfo, "topcolor");
|
col = InfoBuf_ValueForKey (&player->userinfo, "topcolor");
|
||||||
if (!strncmp(col, "0x", 2))
|
if (!strncmp(col, "0x", 2))
|
||||||
player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16);
|
player->rtopcolor = 0xff000000|strtoul(col+2, NULL, 16);
|
||||||
else
|
else
|
||||||
player->rtopcolor = atoi(col);
|
player->rtopcolor = atoi(col);
|
||||||
|
|
||||||
col = Info_ValueForKey (player->userinfo, "bottomcolor");
|
col = InfoBuf_ValueForKey (&player->userinfo, "bottomcolor");
|
||||||
if (!strncmp(col, "0x", 2))
|
if (!strncmp(col, "0x", 2))
|
||||||
player->rbottomcolor = 0xff000000|strtoul(col+2, NULL, 16);
|
player->rbottomcolor = 0xff000000|strtoul(col+2, NULL, 16);
|
||||||
else
|
else
|
||||||
player->rbottomcolor = atoi(col);
|
player->rbottomcolor = atoi(col);
|
||||||
|
|
||||||
i = atoi(Info_ValueForKey (player->userinfo, "*spectator"));
|
i = atoi(InfoBuf_ValueForKey (&player->userinfo, "*spectator"));
|
||||||
if (i == 2)
|
if (i == 2)
|
||||||
player->spectator = 2;
|
player->spectator = 2;
|
||||||
else if (i)
|
else if (i)
|
||||||
|
@ -5108,7 +5112,7 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
|
||||||
|
|
||||||
#ifdef HEXEN2
|
#ifdef HEXEN2
|
||||||
/*if we're running hexen2, they have to be some class...*/
|
/*if we're running hexen2, they have to be some class...*/
|
||||||
player->h2playerclass = atoi(Info_ValueForKey (player->userinfo, "cl_playerclass"));
|
player->h2playerclass = atoi(InfoBuf_ValueForKey (&player->userinfo, "cl_playerclass"));
|
||||||
if (player->h2playerclass > 5)
|
if (player->h2playerclass > 5)
|
||||||
player->h2playerclass = 5;
|
player->h2playerclass = 5;
|
||||||
if (player->h2playerclass < 1)
|
if (player->h2playerclass < 1)
|
||||||
|
@ -5168,7 +5172,7 @@ static void CL_UpdateUserinfo (void)
|
||||||
|
|
||||||
player = &cl.players[slot];
|
player = &cl.players[slot];
|
||||||
player->userid = MSG_ReadLong ();
|
player->userid = MSG_ReadLong ();
|
||||||
Q_strncpyz (player->userinfo, MSG_ReadString(), sizeof(player->userinfo));
|
InfoBuf_FromString(&player->userinfo, MSG_ReadString(), false);
|
||||||
player->userinfovalid = true;
|
player->userinfovalid = true;
|
||||||
|
|
||||||
CL_ProcessUserInfo (slot, player);
|
CL_ProcessUserInfo (slot, player);
|
||||||
|
@ -5178,7 +5182,7 @@ static void CL_UpdateUserinfo (void)
|
||||||
if (slot == cl.playerview[0].playernum && player->name[0])
|
if (slot == cl.playerview[0].playernum && player->name[0])
|
||||||
{
|
{
|
||||||
char *qz;
|
char *qz;
|
||||||
qz = Info_ValueForKey(player->userinfo, "Qizmo");
|
qz = InfoBuf_ValueForKey(&player->userinfo, "Qizmo");
|
||||||
if (*qz)
|
if (*qz)
|
||||||
TP_ExecTrigger("f_qizmoconnect", false);
|
TP_ExecTrigger("f_qizmoconnect", false);
|
||||||
}
|
}
|
||||||
|
@ -5193,27 +5197,55 @@ static void CL_ParseSetInfo (void)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
player_info_t *player;
|
player_info_t *player;
|
||||||
char key[MAX_QWMSGLEN];
|
char *temp;
|
||||||
char value[MAX_QWMSGLEN];
|
char *key;
|
||||||
|
char *val;
|
||||||
|
unsigned int offset;
|
||||||
|
qboolean final;
|
||||||
|
size_t keysize;
|
||||||
|
size_t valsize;
|
||||||
|
|
||||||
slot = MSG_ReadByte ();
|
slot = MSG_ReadByte ();
|
||||||
|
|
||||||
Q_strncpyz (key, MSG_ReadString(), sizeof(key));
|
if (slot == 255)
|
||||||
Q_strncpyz (value, MSG_ReadString(), sizeof(value));
|
{
|
||||||
|
slot = MSG_ReadByte();
|
||||||
|
offset = MSG_ReadLong();
|
||||||
|
final = !!(offset & 0x80000000);
|
||||||
|
offset &= ~0x80000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final = true;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (slot >= MAX_CLIENTS)
|
temp = MSG_ReadString();
|
||||||
Con_Printf("INVALID SETINFO %i: %s=%s\n", slot, key, value);
|
key = InfoBuf_DecodeString(temp, temp+strlen(temp), &keysize);
|
||||||
|
|
||||||
|
temp = MSG_ReadString();
|
||||||
|
val = InfoBuf_DecodeString(temp, temp+strlen(temp), &valsize);
|
||||||
|
|
||||||
|
if (slot == 255)
|
||||||
|
InfoBuf_SyncReceive(&cl.serverinfo, key, keysize, val, valsize, offset, final);
|
||||||
|
else if (slot >= MAX_CLIENTS)
|
||||||
|
Con_Printf("INVALID SETINFO %i: %s=%s\n", slot, key, val);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player = &cl.players[slot];
|
player = &cl.players[slot];
|
||||||
|
|
||||||
Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
|
if (offset)
|
||||||
|
Con_DPrintf("SETINFO %s: %s+=%s\n", player->name, key, val);
|
||||||
|
else
|
||||||
|
Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, val);
|
||||||
|
|
||||||
Info_SetValueForStarKey (player->userinfo, key, value, sizeof(player->userinfo));
|
InfoBuf_SyncReceive(&player->userinfo, key, keysize, val, valsize, offset, final);
|
||||||
player->userinfovalid = true;
|
player->userinfovalid = true;
|
||||||
|
|
||||||
CL_ProcessUserInfo (slot, player);
|
CL_ProcessUserInfo (slot, player);
|
||||||
}
|
}
|
||||||
|
Z_Free(key);
|
||||||
|
Z_Free(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5233,7 +5265,7 @@ static void CL_ServerInfo (void)
|
||||||
|
|
||||||
Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
|
Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
|
||||||
|
|
||||||
Info_SetValueForStarKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&cl.serverinfo, key, value);
|
||||||
|
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
}
|
}
|
||||||
|
@ -5286,11 +5318,11 @@ static void CL_SetStatMovevar(int pnum, int stat, int ivalue, float value)
|
||||||
{
|
{
|
||||||
case STAT_FRAGLIMIT:
|
case STAT_FRAGLIMIT:
|
||||||
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
||||||
Info_SetValueForKey(cl.serverinfo, "fraglimit", va("%g", value), sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "fraglimit", va("%g", value));
|
||||||
break;
|
break;
|
||||||
case STAT_TIMELIMIT:
|
case STAT_TIMELIMIT:
|
||||||
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP)
|
||||||
Info_SetValueForKey(cl.serverinfo, "timelimit", va("%g", value), sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "timelimit", va("%g", value));
|
||||||
break;
|
break;
|
||||||
case STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR: //0
|
case STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR: //0
|
||||||
case STAT_MOVEVARS_AIRCONTROL_PENALTY: //0
|
case STAT_MOVEVARS_AIRCONTROL_PENALTY: //0
|
||||||
|
@ -5714,7 +5746,7 @@ static int CL_PlayerColor(player_info_t *plr, qboolean *name_coloured)
|
||||||
// 0-6 is standard colors (red to white)
|
// 0-6 is standard colors (red to white)
|
||||||
// 7-13 is using secondard charactermask
|
// 7-13 is using secondard charactermask
|
||||||
// 14 and afterwards repeats
|
// 14 and afterwards repeats
|
||||||
t = Info_ValueForKey(plr->userinfo, "tc");
|
t = InfoBuf_ValueForKey(&plr->userinfo, "tc");
|
||||||
if (*t)
|
if (*t)
|
||||||
c = atoi(t);
|
c = atoi(t);
|
||||||
else
|
else
|
||||||
|
@ -6194,20 +6226,20 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds
|
||||||
if (Cmd_Argc() == 2)
|
if (Cmd_Argc() == 2)
|
||||||
{
|
{
|
||||||
cl.haveserverinfo = true;
|
cl.haveserverinfo = true;
|
||||||
Q_strncpyz (cl.serverinfo, Cmd_Argv(1), sizeof(cl.serverinfo));
|
InfoBuf_FromString(&cl.serverinfo, Cmd_Argv(1), false);
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _MSC_VER > 1200
|
#if _MSC_VER > 1200
|
||||||
if (cls.netchan.remote_address.type != NA_LOOPBACK)
|
if (cls.netchan.remote_address.type != NA_LOOPBACK)
|
||||||
Sys_RecentServer("+connect", cls.servername, va("%s (%s)", Info_ValueForKey(cl.serverinfo, "hostname"), cls.servername), "Join QW Server");
|
Sys_RecentServer("+connect", cls.servername, va("%s (%s)", InfoBuf_ValueForKey(&cl.serverinfo, "hostname"), cls.servername), "Join QW Server");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(stufftext, "//svi ", 6)) //for serverinfo over NQ protocols
|
else if (!strncmp(stufftext, "//svi ", 6)) //for serverinfo over NQ protocols
|
||||||
{
|
{
|
||||||
Cmd_TokenizeString(stufftext+2, false, false);
|
Cmd_TokenizeString(stufftext+2, false, false);
|
||||||
Con_DPrintf("SERVERINFO: %s=%s\n", Cmd_Argv(1), Cmd_Argv(2));
|
Con_DPrintf("SERVERINFO: %s=%s\n", Cmd_Argv(1), Cmd_Argv(2));
|
||||||
Info_SetValueForStarKey (cl.serverinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&cl.serverinfo, Cmd_Argv(1), Cmd_Argv(2));
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6241,8 +6273,8 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds
|
||||||
{
|
{
|
||||||
if (!cl.haveserverinfo)
|
if (!cl.haveserverinfo)
|
||||||
{
|
{
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "maxpitch", (atoi(stufftext+13))? "90":"", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "maxpitch", (atoi(stufftext+13))? "90":"");
|
||||||
Info_SetValueForStarKey(cl.serverinfo, "minpitch", (atoi(stufftext+13))?"-90":"", sizeof(cl.serverinfo));
|
InfoBuf_SetKey(&cl.serverinfo, "minpitch", (atoi(stufftext+13))?"-90":"");
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6363,12 +6395,12 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds
|
||||||
{
|
{
|
||||||
player_info_t *player = &cl.players[slot];
|
player_info_t *player = &cl.players[slot];
|
||||||
Con_DPrintf("SETINFO %s: %s\n", player->name, value);
|
Con_DPrintf("SETINFO %s: %s\n", player->name, value);
|
||||||
Q_strncpyz(player->userinfo, value, sizeof(player->userinfo));
|
InfoBuf_FromString(&player->userinfo, value, false);
|
||||||
player->userinfovalid = true;
|
player->userinfovalid = true;
|
||||||
CL_ProcessUserInfo (slot, player);
|
CL_ProcessUserInfo (slot, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp(stufftext, "//ui ", 5)) //ui <slot> <key> <value>. Full user info updates.
|
else if (!strncmp(stufftext, "//ui ", 5)) //ui <slot> <key> <value>. Partial user info updates.
|
||||||
{
|
{
|
||||||
unsigned int slot;
|
unsigned int slot;
|
||||||
const char *key, *value;
|
const char *key, *value;
|
||||||
|
@ -6380,7 +6412,7 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds
|
||||||
{
|
{
|
||||||
player_info_t *player = &cl.players[slot];
|
player_info_t *player = &cl.players[slot];
|
||||||
Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
|
Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value);
|
||||||
Info_SetValueForStarKey (player->userinfo, key, value, sizeof(player->userinfo));
|
InfoBuf_SetValueForStarKey (&player->userinfo, key, value);
|
||||||
CL_ProcessUserInfo (slot, player);
|
CL_ProcessUserInfo (slot, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7871,7 +7903,7 @@ void CLNQ_ParseServerMessage (void)
|
||||||
strcpy(cl.players[i].name, MSG_ReadString());
|
strcpy(cl.players[i].name, MSG_ReadString());
|
||||||
if (*cl.players[i].name)
|
if (*cl.players[i].name)
|
||||||
cl.players[i].userid = i+1;
|
cl.players[i].userid = i+1;
|
||||||
Info_SetValueForKey(cl.players[i].userinfo, "name", cl.players[i].name, sizeof(cl.players[i].userinfo));
|
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "name", cl.players[i].name);
|
||||||
if (!cl.nqplayernamechanged)
|
if (!cl.nqplayernamechanged)
|
||||||
cl.nqplayernamechanged = realtime+2;
|
cl.nqplayernamechanged = realtime+2;
|
||||||
|
|
||||||
|
@ -7901,9 +7933,9 @@ void CLNQ_ParseServerMessage (void)
|
||||||
// cl.players[i].rbottomcolor = (a&0xf0)>>4;
|
// cl.players[i].rbottomcolor = (a&0xf0)>>4;
|
||||||
// sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor);
|
// sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor);
|
||||||
|
|
||||||
Info_SetValueForKey(cl.players[i].userinfo, "topcolor", va("%i", a&0x0f), sizeof(cl.players[i].userinfo));
|
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "topcolor", va("%i", a&0x0f));
|
||||||
Info_SetValueForKey(cl.players[i].userinfo, "bottomcolor", va("%i", (a&0xf0)>>4), sizeof(cl.players[i].userinfo));
|
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "bottomcolor", va("%i", (a&0xf0)>>4));
|
||||||
Info_SetValueForKey(cl.players[i].userinfo, "team", va("%i", (a&0xf0)>>4), sizeof(cl.players[i].userinfo));
|
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "team", va("%i", (a&0xf0)>>4));
|
||||||
CL_ProcessUserInfo (i, &cl.players[i]);
|
CL_ProcessUserInfo (i, &cl.players[i]);
|
||||||
|
|
||||||
// CLNQ_CheckPlayerIsSpectator(i);
|
// CLNQ_CheckPlayerIsSpectator(i);
|
||||||
|
|
|
@ -544,7 +544,7 @@ static qintptr_t VARGS Plug_GetPlayerInfo(void *offset, quintptr_t mask, const q
|
||||||
out->activetime = realtime - cl.players[i].realentertime;
|
out->activetime = realtime - cl.players[i].realentertime;
|
||||||
out->userid = cl.players[i].userid;
|
out->userid = cl.players[i].userid;
|
||||||
out->spectator = cl.players[i].spectator;
|
out->spectator = cl.players[i].spectator;
|
||||||
Q_strncpyz(out->userinfo, cl.players[i].userinfo, sizeof(out->userinfo));
|
InfoBuf_ToString(&cl.players[i].userinfo, out->userinfo, sizeof(out->userinfo), basicuserinfos, NULL, NULL, NULL, NULL);
|
||||||
Q_strncpyz(out->team, cl.players[i].team, sizeof(out->team));
|
Q_strncpyz(out->team, cl.players[i].team, sizeof(out->team));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +589,7 @@ static qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const q
|
||||||
if (VM_OOB(arg[0], outlen))
|
if (VM_OOB(arg[0], outlen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Q_strncpyz(outptr, cl.serverinfo, outlen);
|
InfoBuf_ToString(&cl.serverinfo, outptr, outlen, NULL, NULL, NULL, NULL, NULL);
|
||||||
Q_strncatz(outptr, va("\\intermission\\%i", cl.intermissionmode), outlen);
|
Q_strncatz(outptr, va("\\intermission\\%i", cl.intermissionmode), outlen);
|
||||||
switch(cls.demoplayback)
|
switch(cls.demoplayback)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1769,7 +1769,7 @@ void SCR_DrawGameClock(void)
|
||||||
|
|
||||||
flags = (show_gameclock.value-1);
|
flags = (show_gameclock.value-1);
|
||||||
if (flags & 1)
|
if (flags & 1)
|
||||||
timelimit = 60 * atof(Info_ValueForKey(cl.serverinfo, "timelimit"));
|
timelimit = 60 * atof(InfoBuf_ValueForKey(&cl.serverinfo, "timelimit"));
|
||||||
else
|
else
|
||||||
timelimit = 0;
|
timelimit = 0;
|
||||||
|
|
||||||
|
|
|
@ -664,7 +664,7 @@ void UI_RegisterFont(char *fontName, int pointSize, fontInfo_t *font)
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
|
snprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
|
||||||
|
|
||||||
in.c = COM_LoadTempFile(name, &sz);
|
in.c = COM_LoadTempFile(name, 0, &sz);
|
||||||
if (sz == sizeof(fontInfo_t))
|
if (sz == sizeof(fontInfo_t))
|
||||||
{
|
{
|
||||||
for(i=0; i<GLYPHS_PER_FONT; i++)
|
for(i=0; i<GLYPHS_PER_FONT; i++)
|
||||||
|
|
|
@ -114,7 +114,7 @@ typedef struct
|
||||||
short gravity;
|
short gravity;
|
||||||
short delta_angles[3]; // add to command angles to get view direction
|
short delta_angles[3]; // add to command angles to get view direction
|
||||||
// changed by spawns, rotating objects, and teleporters
|
// changed by spawns, rotating objects, and teleporters
|
||||||
short pad;
|
// short pad;
|
||||||
} q2pmove_state_t;
|
} q2pmove_state_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -156,11 +156,11 @@ typedef struct colourised_s {
|
||||||
#define MAX_DISPLAYEDNAME 16
|
#define MAX_DISPLAYEDNAME 16
|
||||||
typedef struct player_info_s
|
typedef struct player_info_s
|
||||||
{
|
{
|
||||||
int userid;
|
int userid;
|
||||||
char userinfo[EXTENDED_INFO_STRING];
|
infobuf_t userinfo;
|
||||||
qboolean userinfovalid; //set if we actually know the userinfo (ie: false on vanilla nq servers)
|
qboolean userinfovalid; //set if we actually know the userinfo (ie: false on vanilla nq servers)
|
||||||
char teamstatus[128];
|
char teamstatus[128];
|
||||||
float teamstatustime;
|
float teamstatustime;
|
||||||
|
|
||||||
// scoreboard information
|
// scoreboard information
|
||||||
int spectator;
|
int spectator;
|
||||||
|
@ -474,8 +474,6 @@ typedef struct
|
||||||
|
|
||||||
int protocol_q2;
|
int protocol_q2;
|
||||||
|
|
||||||
|
|
||||||
qboolean resendinfo;
|
|
||||||
qboolean findtrack;
|
qboolean findtrack;
|
||||||
|
|
||||||
int framecount;
|
int framecount;
|
||||||
|
@ -487,8 +485,8 @@ typedef struct
|
||||||
netchan_t netchan;
|
netchan_t netchan;
|
||||||
float lastarbiatarypackettime; //used to mark when packets were sent to prevent mvdsv servers from causing us to disconnect.
|
float lastarbiatarypackettime; //used to mark when packets were sent to prevent mvdsv servers from causing us to disconnect.
|
||||||
|
|
||||||
// private userinfo for sending to masterless servers
|
infobuf_t userinfo[MAX_SPLITS];
|
||||||
char userinfo[MAX_SPLITS][EXTENDED_INFO_STRING];
|
infosync_t userinfosync;
|
||||||
|
|
||||||
char servername[MAX_OSPATH]; // name of server from original connect
|
char servername[MAX_OSPATH]; // name of server from original connect
|
||||||
|
|
||||||
|
@ -757,7 +755,7 @@ typedef struct
|
||||||
qboolean stillloading; // set when doing something slow, and the game is still loading.
|
qboolean stillloading; // set when doing something slow, and the game is still loading.
|
||||||
|
|
||||||
qboolean haveserverinfo; //nq servers will usually be false. don't override stuff if we already know better.
|
qboolean haveserverinfo; //nq servers will usually be false. don't override stuff if we already know better.
|
||||||
char serverinfo[MAX_SERVERINFO_STRING];
|
infobuf_t serverinfo;
|
||||||
char serverpaknames[1024];
|
char serverpaknames[1024];
|
||||||
char serverpakcrcs[1024];
|
char serverpakcrcs[1024];
|
||||||
qboolean serverpakschanged;
|
qboolean serverpakschanged;
|
||||||
|
@ -899,6 +897,7 @@ typedef struct
|
||||||
qboolean gamedirchanged;
|
qboolean gamedirchanged;
|
||||||
|
|
||||||
#ifdef Q2CLIENT
|
#ifdef Q2CLIENT
|
||||||
|
char q2airaccel[16];
|
||||||
char q2statusbar[1024];
|
char q2statusbar[1024];
|
||||||
char q2layout[MAX_SPLITS][1024];
|
char q2layout[MAX_SPLITS][1024];
|
||||||
int parse_entities;
|
int parse_entities;
|
||||||
|
@ -1089,7 +1088,7 @@ void CL_Reconnect_f (void);
|
||||||
void CL_ConnectionlessPacket (void);
|
void CL_ConnectionlessPacket (void);
|
||||||
qboolean CL_DemoBehind(void);
|
qboolean CL_DemoBehind(void);
|
||||||
void CL_SaveInfo(vfsfile_t *f);
|
void CL_SaveInfo(vfsfile_t *f);
|
||||||
void CL_SetInfo (int pnum, char *key, char *value);
|
void CL_SetInfo (int pnum, const char *key, const char *value);
|
||||||
|
|
||||||
void CL_BeginServerConnect(const char *host, int port, qboolean noproxy);
|
void CL_BeginServerConnect(const char *host, int port, qboolean noproxy);
|
||||||
char *CL_TryingToConnect(void);
|
char *CL_TryingToConnect(void);
|
||||||
|
@ -1197,7 +1196,7 @@ void CL_BaseMove (usercmd_t *cmd, int pnum, float priortime, float extratime);
|
||||||
int Master_FindBestRoute(char *server, char *out, size_t outsize, int *directcost, int *chainedcost);
|
int Master_FindBestRoute(char *server, char *out, size_t outsize, int *directcost, int *chainedcost);
|
||||||
|
|
||||||
float CL_KeyState (kbutton_t *key, int pnum, qboolean noslowstart);
|
float CL_KeyState (kbutton_t *key, int pnum, qboolean noslowstart);
|
||||||
char *Key_KeynumToString (int keynum, int modifier);
|
const char *Key_KeynumToString (int keynum, int modifier);
|
||||||
int Key_StringToKeynum (const char *str, int *modifier);
|
int Key_StringToKeynum (const char *str, int *modifier);
|
||||||
char *Key_GetBinding(int keynum, int bindmap, int modifier);
|
char *Key_GetBinding(int keynum, int bindmap, int modifier);
|
||||||
void Key_GetBindMap(int *bindmaps);
|
void Key_GetBindMap(int *bindmaps);
|
||||||
|
@ -1688,7 +1687,7 @@ void Stats_NewMap(void);
|
||||||
void Stats_Clear(void);
|
void Stats_Clear(void);
|
||||||
void Stats_Init(void);
|
void Stats_Init(void);
|
||||||
|
|
||||||
enum uploadfmt;
|
//enum uploadfmt;
|
||||||
/*struct mediacallbacks_s
|
/*struct mediacallbacks_s
|
||||||
{ //functions provided by the engine/renderer, for faster/off-thread updates
|
{ //functions provided by the engine/renderer, for faster/off-thread updates
|
||||||
qboolean pbocanoffthread;
|
qboolean pbocanoffthread;
|
||||||
|
|
|
@ -107,7 +107,7 @@ sfx_t *S_PrecacheSexedSound(int entnum, const char *soundname)
|
||||||
{ //a 'sexed' sound
|
{ //a 'sexed' sound
|
||||||
if (entnum > 0 && entnum <= MAX_CLIENTS)
|
if (entnum > 0 && entnum <= MAX_CLIENTS)
|
||||||
{
|
{
|
||||||
char *model = Info_ValueForKey(cl.players[entnum-1].userinfo, "skin");
|
char *model = InfoBuf_ValueForKey(&cl.players[entnum-1].userinfo, "skin");
|
||||||
char *skin;
|
char *skin;
|
||||||
skin = strchr(model, '/');
|
skin = strchr(model, '/');
|
||||||
if (skin)
|
if (skin)
|
||||||
|
@ -2140,7 +2140,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
|
||||||
ent.model=NULL;
|
ent.model=NULL;
|
||||||
|
|
||||||
player = &cl.players[(s1->skinnum&0xff)%MAX_CLIENTS];
|
player = &cl.players[(s1->skinnum&0xff)%MAX_CLIENTS];
|
||||||
modelname = Info_ValueForKey(player->userinfo, "skin");
|
modelname = InfoBuf_ValueForKey(&player->userinfo, "skin");
|
||||||
if (!modelname[0])
|
if (!modelname[0])
|
||||||
modelname = "male";
|
modelname = "male";
|
||||||
skin = strchr(modelname, '/');
|
skin = strchr(modelname, '/');
|
||||||
|
|
|
@ -513,7 +513,7 @@ qboolean CLQ3_SystemInfoChanged(char *str)
|
||||||
value = "baseq3";
|
value = "baseq3";
|
||||||
COM_Gamedir(value, NULL);
|
COM_Gamedir(value, NULL);
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
Info_SetValueForStarKey (svs.info, "*gamedir", value, MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey (&svs.info, "*gamedir", value);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,12 +899,6 @@ void CLQ3_SendCmd(usercmd_t *cmd)
|
||||||
usercmd_t *to, *from;
|
usercmd_t *to, *from;
|
||||||
extern int keycatcher;
|
extern int keycatcher;
|
||||||
|
|
||||||
if (cls.resendinfo)
|
|
||||||
{
|
|
||||||
cls.resendinfo = false;
|
|
||||||
CLQ3_SendClientCommand("userinfo \"%s\"", cls.userinfo[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//reuse the q1 array
|
//reuse the q1 array
|
||||||
cmd->servertime = cl.servertime*1000;
|
cmd->servertime = cl.servertime*1000;
|
||||||
cmd->weapon = ccs.selected_weapon;
|
cmd->weapon = ccs.selected_weapon;
|
||||||
|
@ -1044,19 +1038,23 @@ void CLQ3_SendAuthPacket(netadr_t *gameserver)
|
||||||
|
|
||||||
void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport)
|
void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport)
|
||||||
{
|
{
|
||||||
|
char infostr[1024];
|
||||||
char data[2048];
|
char data[2048];
|
||||||
char adrbuf[MAX_ADR_SIZE];
|
char adrbuf[MAX_ADR_SIZE];
|
||||||
sizebuf_t msg;
|
sizebuf_t msg;
|
||||||
|
static const char *nonq3[] = {"challenge", "qport", "protocol", "ip", "chat", NULL};
|
||||||
|
|
||||||
memset(&ccs, 0, sizeof(ccs));
|
memset(&ccs, 0, sizeof(ccs));
|
||||||
|
|
||||||
|
InfoBuf_ToString(&cls.userinfo[0], infostr, sizeof(infostr), basicuserinfos, nonq3, NULL, &cls.userinfosync, &cls.userinfo[0]);
|
||||||
|
|
||||||
cl.splitclients = 1;
|
cl.splitclients = 1;
|
||||||
msg.data = data;
|
msg.data = data;
|
||||||
msg.cursize = 0;
|
msg.cursize = 0;
|
||||||
msg.overflowed = msg.allowoverflow = 0;
|
msg.overflowed = msg.allowoverflow = 0;
|
||||||
msg.maxsize = sizeof(data);
|
msg.maxsize = sizeof(data);
|
||||||
MSG_WriteLong(&msg, -1);
|
MSG_WriteLong(&msg, -1);
|
||||||
MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", challenge, qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), &net_local_cl_ipadr), cls.userinfo[0]));
|
MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", challenge, qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), &net_local_cl_ipadr), infostr));
|
||||||
#ifdef HUFFNETWORK
|
#ifdef HUFFNETWORK
|
||||||
Huff_EncryptPacket(&msg, 12);
|
Huff_EncryptPacket(&msg, 12);
|
||||||
if (!Huff_CompressionCRC(HUFFCRC_QUAKE3))
|
if (!Huff_CompressionCRC(HUFFCRC_QUAKE3))
|
||||||
|
|
|
@ -1440,15 +1440,16 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
|
||||||
|
|
||||||
for (i = 0; i < c->num; i++)
|
for (i = 0; i < c->num; i++)
|
||||||
{
|
{
|
||||||
|
int col = (con_commandmatch == i+1)?3:2;
|
||||||
s = (conchar_t*)(con->completionline+1);
|
s = (conchar_t*)(con->completionline+1);
|
||||||
|
|
||||||
//note: if cl_chatmode is 0, then we shouldn't show the leading /, however that is how the console link stuff recognises it as command text, so we always display it.
|
//note: if cl_chatmode is 0, then we shouldn't show the leading /, however that is how the console link stuff recognises it as command text, so we always display it.
|
||||||
cmd = c->completions[i].text;
|
cmd = c->completions[i].text;
|
||||||
// desc = c->completions[i].desc;
|
// desc = c->completions[i].desc;
|
||||||
// if (desc)
|
// if (desc)
|
||||||
// end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("^[^2/%s\\tip\\%s^]\t", cmd, desc), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);
|
// end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("^[^%i/%s\\tip\\%s^]\t", col, cmd, desc), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);
|
||||||
// else
|
// else
|
||||||
end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("^[^2/%s^]\t", cmd), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);
|
end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("^[^%i/%s^]\t", col, cmd), s+con->completionline->length, (con->completionline->maxlength-con->completionline->length)*sizeof(maskedtext[0]), true);
|
||||||
con->completionline->length = end - s;
|
con->completionline->length = end - s;
|
||||||
}
|
}
|
||||||
if (c->extra)
|
if (c->extra)
|
||||||
|
@ -2645,7 +2646,7 @@ void Con_DrawConsole (int lines, qboolean noback)
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
char *buf;
|
char *buf;
|
||||||
shader->defaulttextures->base = Image_CreateTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA);
|
shader->defaulttextures->base = Image_CreateTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA);
|
||||||
if ((buf = COM_LoadFile (key, 5, &fsize)))
|
if ((buf = FS_LoadMallocFile (key, &fsize)))
|
||||||
Image_LoadTextureFromMemory(shader->defaulttextures->base, shader->defaulttextures->base->flags|IF_NOWORKER, key, key, buf, fsize);
|
Image_LoadTextureFromMemory(shader->defaulttextures->base, shader->defaulttextures->base->flags|IF_NOWORKER, key, key, buf, fsize);
|
||||||
}
|
}
|
||||||
shader->width = shader->defaulttextures->base->width;
|
shader->width = shader->defaulttextures->base->width;
|
||||||
|
|
|
@ -618,7 +618,7 @@ static void Stats_LoadFragFile(char *name)
|
||||||
strcpy(filename, name);
|
strcpy(filename, name);
|
||||||
COM_DefaultExtension(filename, ".dat", sizeof(filename));
|
COM_DefaultExtension(filename, ".dat", sizeof(filename));
|
||||||
|
|
||||||
file = COM_LoadTempFile(filename, NULL);
|
file = COM_LoadTempFile(filename, 0, NULL);
|
||||||
if (!file || !*file)
|
if (!file || !*file)
|
||||||
{
|
{
|
||||||
Con_DPrintf("Couldn't load %s\n", filename);
|
Con_DPrintf("Couldn't load %s\n", filename);
|
||||||
|
|
|
@ -2801,7 +2801,7 @@ void Image_WriteKTXFile(const char *filename, struct pendingtextureinfo *mips)
|
||||||
|
|
||||||
VFS_CLOSE(file);
|
VFS_CLOSE(file);
|
||||||
}
|
}
|
||||||
static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, char *fname, qbyte *filedata, size_t filesize)
|
static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
|
||||||
{
|
{
|
||||||
static const char magic[12] = {0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
|
static const char magic[12] = {0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||||
ktxheader_t *header;
|
ktxheader_t *header;
|
||||||
|
@ -3038,7 +3038,7 @@ static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, char *fn
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMAGEFMT_PKM
|
#ifdef IMAGEFMT_PKM
|
||||||
static struct pendingtextureinfo *Image_ReadPKMFile(unsigned int flags, char *fname, qbyte *filedata, size_t filesize)
|
static struct pendingtextureinfo *Image_ReadPKMFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
|
||||||
{
|
{
|
||||||
struct pendingtextureinfo *mips;
|
struct pendingtextureinfo *mips;
|
||||||
unsigned int encoding, blockbytes;
|
unsigned int encoding, blockbytes;
|
||||||
|
@ -3157,7 +3157,7 @@ typedef struct {
|
||||||
unsigned int miscflags2;
|
unsigned int miscflags2;
|
||||||
} dds10header_t;
|
} dds10header_t;
|
||||||
|
|
||||||
static struct pendingtextureinfo *Image_ReadDDSFile(unsigned int flags, char *fname, qbyte *filedata, size_t filesize)
|
static struct pendingtextureinfo *Image_ReadDDSFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
|
||||||
{
|
{
|
||||||
int nummips;
|
int nummips;
|
||||||
int mipnum;
|
int mipnum;
|
||||||
|
@ -3362,7 +3362,7 @@ static struct pendingtextureinfo *Image_ReadDDSFile(unsigned int flags, char *fn
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMAGEFMT_BLP
|
#ifdef IMAGEFMT_BLP
|
||||||
static struct pendingtextureinfo *Image_ReadBLPFile(unsigned int flags, char *fname, qbyte *filedata, size_t filesize)
|
static struct pendingtextureinfo *Image_ReadBLPFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
|
||||||
{
|
{
|
||||||
//FIXME: cba with endian.
|
//FIXME: cba with endian.
|
||||||
int miplevel;
|
int miplevel;
|
||||||
|
@ -6212,7 +6212,7 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd
|
||||||
#if 1
|
#if 1
|
||||||
//always frees filedata, even on failure.
|
//always frees filedata, even on failure.
|
||||||
//also frees the textures fallback data, but only on success
|
//also frees the textures fallback data, but only on success
|
||||||
static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname, char *fname, qbyte *filedata, int filesize)
|
static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname, const char *fname, qbyte *filedata, int filesize)
|
||||||
{
|
{
|
||||||
qboolean hasalpha;
|
qboolean hasalpha;
|
||||||
qbyte *rgbadata;
|
qbyte *rgbadata;
|
||||||
|
@ -6267,7 +6267,7 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char
|
||||||
COM_FileExtension(fname, ext, sizeof(ext));
|
COM_FileExtension(fname, ext, sizeof(ext));
|
||||||
Q_strncatz(aname, "_alpha.", sizeof(aname));
|
Q_strncatz(aname, "_alpha.", sizeof(aname));
|
||||||
Q_strncatz(aname, ext, sizeof(aname));
|
Q_strncatz(aname, ext, sizeof(aname));
|
||||||
if (!strchr(aname, ':') && (alph = COM_LoadFile (aname, 5, &alphsize)))
|
if (!strchr(aname, ':') && (alph = FS_LoadMallocFile (aname, &alphsize)))
|
||||||
{
|
{
|
||||||
if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname)))
|
if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname)))
|
||||||
{
|
{
|
||||||
|
@ -6324,7 +6324,7 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char
|
||||||
|
|
||||||
//always frees filedata, even on failure.
|
//always frees filedata, even on failure.
|
||||||
//also frees the textures fallback data, but only on success
|
//also frees the textures fallback data, but only on success
|
||||||
qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, char *fname, qbyte *filedata, int filesize)
|
qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, const char *fname, qbyte *filedata, int filesize)
|
||||||
{
|
{
|
||||||
struct pendingtextureinfo *mips = Image_LoadMipsFromMemory(flags, iname, fname, filedata, filesize);
|
struct pendingtextureinfo *mips = Image_LoadMipsFromMemory(flags, iname, fname, filedata, filesize);
|
||||||
if (mips)
|
if (mips)
|
||||||
|
@ -6406,7 +6406,7 @@ qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname,
|
||||||
COM_FileExtension(fname, ext, sizeof(ext));
|
COM_FileExtension(fname, ext, sizeof(ext));
|
||||||
Q_strncatz(aname, "_alpha.", sizeof(aname));
|
Q_strncatz(aname, "_alpha.", sizeof(aname));
|
||||||
Q_strncatz(aname, ext, sizeof(aname));
|
Q_strncatz(aname, ext, sizeof(aname));
|
||||||
if (!strchr(aname, ':') && (alph = COM_LoadFile (aname, 5, &alphsize)))
|
if (!strchr(aname, ':') && (alph = FS_LoadMallocFile (aname, &alphsize)))
|
||||||
{
|
{
|
||||||
if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname)))
|
if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname)))
|
||||||
{
|
{
|
||||||
|
@ -6465,7 +6465,7 @@ qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, char *subpath, unsigned int texflags)
|
static struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, char *subpath, unsigned int texflags)
|
||||||
{
|
{
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
|
@ -6529,12 +6529,12 @@ struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, ch
|
||||||
for (j = 0; j < countof(cmscheme); j++)
|
for (j = 0; j < countof(cmscheme); j++)
|
||||||
{
|
{
|
||||||
Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s_%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name);
|
Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s_%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name);
|
||||||
buf = COM_LoadFile(fname, 5, &filesize);
|
buf = FS_LoadMallocFile(fname, &filesize);
|
||||||
if (buf)
|
if (buf)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name);
|
Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name);
|
||||||
buf = COM_LoadFile(fname, 5, &filesize);
|
buf = FS_LoadMallocFile(fname, &filesize);
|
||||||
if (buf)
|
if (buf)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6592,7 +6592,7 @@ nextface:;
|
||||||
return mips;
|
return mips;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *bestname, size_t bestnamesize, unsigned int *bestflags)
|
qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *bestname, size_t bestnamesize, unsigned int *bestflags)
|
||||||
{
|
{
|
||||||
char fname[MAX_QPATH], nicename[MAX_QPATH];
|
char fname[MAX_QPATH], nicename[MAX_QPATH];
|
||||||
int i, e;
|
int i, e;
|
||||||
|
@ -6827,8 +6827,6 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
|
||||||
int imgheight;
|
int imgheight;
|
||||||
qboolean alphaed;
|
qboolean alphaed;
|
||||||
|
|
||||||
// Sys_Sleep(0.3);
|
|
||||||
|
|
||||||
if ((tex->flags & IF_TEXTYPE) == IF_CUBEMAP)
|
if ((tex->flags & IF_TEXTYPE) == IF_CUBEMAP)
|
||||||
{ //cubemaps require special handling because they are (normally) 6 files instead of 1.
|
{ //cubemaps require special handling because they are (normally) 6 files instead of 1.
|
||||||
//the exception is single-file dds cubemaps, but we don't support those.
|
//the exception is single-file dds cubemaps, but we don't support those.
|
||||||
|
@ -6963,7 +6961,7 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
|
||||||
if (Image_LoadTextureFromMemory(tex, tex->flags, tex->ident, fname, buf, fsize))
|
if (Image_LoadTextureFromMemory(tex, tex->flags, tex->ident, fname, buf, fsize))
|
||||||
{
|
{
|
||||||
BZ_Free(tex->fallbackdata);
|
BZ_Free(tex->fallbackdata);
|
||||||
tex->fallbackdata = NULL;
|
tex->fallbackdata = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7057,7 +7055,10 @@ static image_t *Image_CreateTexture_Internal (const char *identifier, const char
|
||||||
tex->next = imagelist;
|
tex->next = imagelist;
|
||||||
imagelist = tex;
|
imagelist = tex;
|
||||||
|
|
||||||
tex->flags = flags;
|
if ((vid.flags & VID_SRGBAWARE) && !(flags & IF_NOSRGB))
|
||||||
|
tex->flags = flags | IF_SRGB; //guess...
|
||||||
|
else
|
||||||
|
tex->flags = flags;
|
||||||
tex->width = 0;
|
tex->width = 0;
|
||||||
tex->height = 0;
|
tex->height = 0;
|
||||||
tex->regsequence = r_regsequence;
|
tex->regsequence = r_regsequence;
|
||||||
|
@ -7597,7 +7598,7 @@ texid_t R_LoadBumpmapTexture(const char *name, const char *subpath)
|
||||||
|
|
||||||
TRACE(("dbg: Mod_LoadBumpmapTexture: opening %s\n", fname));
|
TRACE(("dbg: Mod_LoadBumpmapTexture: opening %s\n", fname));
|
||||||
|
|
||||||
if ((buf = COM_LoadFile (fname, 5, &fsize)))
|
if ((buf = FS_LoadMallocFile (fname, &fsize)))
|
||||||
{
|
{
|
||||||
if ((data = ReadTargaFile(buf, fsize, &image_width, &image_height, &hasalpha, 2))) //Only load a greyscale image.
|
if ((data = ReadTargaFile(buf, fsize, &image_width, &image_height, &hasalpha, 2))) //Only load a greyscale image.
|
||||||
{
|
{
|
||||||
|
|
|
@ -455,7 +455,7 @@ void Key_UpdateCompletionDesc(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompleteCommand (qboolean force)
|
void CompleteCommand (qboolean force, int direction)
|
||||||
{
|
{
|
||||||
const char *cmd, *s;
|
const char *cmd, *s;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
|
@ -535,7 +535,9 @@ void CompleteCommand (qboolean force)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con_commandmatch++;
|
con_commandmatch += direction;
|
||||||
|
if (con_commandmatch <= 0)
|
||||||
|
con_commandmatch += c->num;
|
||||||
Key_UpdateCompletionDesc();
|
Key_UpdateCompletionDesc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,14 +1697,15 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
||||||
Cbuf_AddText("\nvid_toggle\n", RESTRICT_LOCAL);
|
Cbuf_AddText("\nvid_toggle\n", RESTRICT_LOCAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (con_commandmatch)
|
if ((con_commandmatch && !strchr(key_lines[edit_line], ' ')) || shift)
|
||||||
{ //if that isn't actually a command, and we can actually complete it to something, then lets try to complete it.
|
{ //if that isn't actually a command, and we can actually complete it to something, then lets try to complete it.
|
||||||
char *txt = key_lines[edit_line];
|
char *txt = key_lines[edit_line];
|
||||||
if (*txt == '/')
|
if (*txt == '/')
|
||||||
txt++;
|
txt++;
|
||||||
if (!Cmd_IsCommand(txt) && Cmd_CompleteCommand(txt, true, true, con_commandmatch, NULL))
|
|
||||||
|
if ((shift||!Cmd_IsCommand(txt)) && Cmd_CompleteCommand(txt, true, true, con_commandmatch, NULL))
|
||||||
{
|
{
|
||||||
CompleteCommand (true);
|
CompleteCommand (true, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Con_Footerf(con, false, "");
|
Con_Footerf(con, false, "");
|
||||||
|
@ -1723,6 +1726,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
||||||
key_lines[edit_line] = BZ_Malloc(1);
|
key_lines[edit_line] = BZ_Malloc(1);
|
||||||
key_lines[edit_line][0] = '\0';
|
key_lines[edit_line][0] = '\0';
|
||||||
key_linepos = 0;
|
key_linepos = 0;
|
||||||
|
con_commandmatch = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1733,21 +1737,21 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
||||||
txt++;
|
txt++;
|
||||||
if (Cmd_CompleteCommand(txt, true, true, con->commandcompletion, NULL))
|
if (Cmd_CompleteCommand(txt, true, true, con->commandcompletion, NULL))
|
||||||
{
|
{
|
||||||
CompleteCommand (true);
|
CompleteCommand (true, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == K_TAB)
|
if (key == K_TAB)
|
||||||
{ // command completion
|
{ // command completion
|
||||||
if (shift)
|
if (ctrl&&shift)
|
||||||
{
|
{
|
||||||
Con_CycleConsole();
|
Con_CycleConsole();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con->commandcompletion)
|
if (con->commandcompletion)
|
||||||
CompleteCommand (ctrl);
|
CompleteCommand (ctrl, shift?-1:1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1802,9 +1806,29 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
||||||
if (rkey != '`' || key_linepos==0)
|
if (rkey != '`' || key_linepos==0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con_commandmatch)
|
if (con_commandmatch)
|
||||||
con_commandmatch = 1;
|
{ //if they're typing, try to retain the current completion guess.
|
||||||
Key_EntryLine(&key_lines[edit_line], 0, &key_linepos, key, unicode);
|
cmd_completion_t *c;
|
||||||
|
char *txt = key_lines[edit_line];
|
||||||
|
char *guess = Cmd_CompleteCommand(*txt=='/'?txt+1:txt, true, true, con_commandmatch, NULL);
|
||||||
|
Key_EntryLine(&key_lines[edit_line], 0, &key_linepos, key, unicode);
|
||||||
|
if (guess)
|
||||||
|
{
|
||||||
|
guess = Z_StrDup(guess);
|
||||||
|
txt = key_lines[edit_line];
|
||||||
|
c = Cmd_Complete(*txt=='/'?txt+1:txt, true);
|
||||||
|
for (con_commandmatch = c->num; con_commandmatch > 1; con_commandmatch--)
|
||||||
|
{
|
||||||
|
if (!strcmp(guess, c->completions[con_commandmatch-1].text))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Z_Free(guess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Key_EntryLine(&key_lines[edit_line], 0, &key_linepos, key, unicode);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1999,9 +2023,9 @@ static char *Key_KeynumToStringRaw (int keynum)
|
||||||
return "<UNKNOWN KEYNUM>";
|
return "<UNKNOWN KEYNUM>";
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Key_KeynumToString (int keynum, int modifier)
|
const char *Key_KeynumToString (int keynum, int modifier)
|
||||||
{
|
{
|
||||||
char *r = Key_KeynumToStringRaw(keynum);
|
const char *r = Key_KeynumToStringRaw(keynum);
|
||||||
if (r[0] == '<' && r[1])
|
if (r[0] == '<' && r[1])
|
||||||
modifier = 0; //would be too weird.
|
modifier = 0; //would be too weird.
|
||||||
switch(modifier)
|
switch(modifier)
|
||||||
|
|
|
@ -567,7 +567,7 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
||||||
int y = ypos+option->common.posy;
|
int y = ypos+option->common.posy;
|
||||||
int keys[8], keymods[countof(keys)];
|
int keys[8], keymods[countof(keys)];
|
||||||
int keycount;
|
int keycount;
|
||||||
char *keyname;
|
const char *keyname;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
Draw_FunStringWidth(x, y, option->bind.caption, option->bind.captionwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
Draw_FunStringWidth(x, y, option->bind.caption, option->bind.captionwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||||
|
|
|
@ -1390,7 +1390,7 @@ void Media_LoadTrackNames (char *listname)
|
||||||
char *trackname;
|
char *trackname;
|
||||||
mediatrack_t *newtrack;
|
mediatrack_t *newtrack;
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
char *data = COM_LoadTempFile(listname, &fsize);
|
char *data = COM_LoadTempFile(listname, FSLF_IGNOREPURE, &fsize);
|
||||||
|
|
||||||
loadedtracknames=true;
|
loadedtracknames=true;
|
||||||
|
|
||||||
|
@ -3210,13 +3210,16 @@ static void QDECL capture_avi_video(void *vctx, int frame, void *vdata, int stri
|
||||||
qbyte *data, *in, *out;
|
qbyte *data, *in, *out;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
if (stride < 0) //if stride is negative, then its bottom-up, but the data pointer is at the start of the buffer (rather than 'first row')
|
||||||
|
vdata = (char*)vdata - stride*(height-1);
|
||||||
|
|
||||||
//we need to output a packed bottom-up bgr image.
|
//we need to output a packed bottom-up bgr image.
|
||||||
|
|
||||||
//switch the input from logically top-down to bottom-up (regardless of the physical ordering of its rows)
|
//switch the input from logical-top-down to bottom-up (regardless of the physical ordering of its rows)
|
||||||
in = (qbyte*)vdata + stride*(height-1);
|
in = (qbyte*)vdata + stride*(height-1);
|
||||||
stride = -stride;
|
stride = -stride;
|
||||||
|
|
||||||
if (fmt == TF_BGR24 && stride == width*3)
|
if (fmt == TF_BGR24 && stride == width*-3)
|
||||||
{ //no work needed!
|
{ //no work needed!
|
||||||
data = in;
|
data = in;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ static shader_t *MN_CachePic(const char *picname)
|
||||||
{
|
{
|
||||||
return R2D_SafeCachePic(picname);
|
return R2D_SafeCachePic(picname);
|
||||||
}
|
}
|
||||||
static qboolean MN_DrawGetImageSize(void *pic, int *w, int *h)
|
static qboolean MN_DrawGetImageSize(struct shader_s *pic, int *w, int *h)
|
||||||
{
|
{
|
||||||
return R_GetShaderSizes(pic, w, h, true)>0;
|
return R_GetShaderSizes(pic, w, h, true)>0;
|
||||||
}
|
}
|
||||||
|
@ -234,8 +234,8 @@ static void MN_RenderScene(menuscene_t *scene)
|
||||||
ent.keynum = i;
|
ent.keynum = i;
|
||||||
ent.model = scene->entlist[i].model;
|
ent.model = scene->entlist[i].model;
|
||||||
VectorCopy(e->matrix[0], ent.axis[0]); ent.origin[0] = e->matrix[0][3];
|
VectorCopy(e->matrix[0], ent.axis[0]); ent.origin[0] = e->matrix[0][3];
|
||||||
VectorCopy(e->matrix[1], ent.axis[1]); ent.origin[1] = e->matrix[0][7];
|
VectorCopy(e->matrix[1], ent.axis[1]); ent.origin[1] = e->matrix[1][3];
|
||||||
VectorCopy(e->matrix[2], ent.axis[2]); ent.origin[2] = e->matrix[0][11];
|
VectorCopy(e->matrix[2], ent.axis[2]); ent.origin[2] = e->matrix[2][3];
|
||||||
|
|
||||||
ent.scale = 1;
|
ent.scale = 1;
|
||||||
ent.framestate.g[FS_REG].frame[0] = e->frame[0];
|
ent.framestate.g[FS_REG].frame[0] = e->frame[0];
|
||||||
|
@ -263,8 +263,8 @@ static void MN_RenderScene(menuscene_t *scene)
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorCopy(scene->viewmatrix[0], r_refdef.viewaxis[0]); r_refdef.vieworg[0] = scene->viewmatrix[0][3];
|
VectorCopy(scene->viewmatrix[0], r_refdef.viewaxis[0]); r_refdef.vieworg[0] = scene->viewmatrix[0][3];
|
||||||
VectorCopy(scene->viewmatrix[1], r_refdef.viewaxis[1]); r_refdef.vieworg[1] = scene->viewmatrix[0][7];
|
VectorCopy(scene->viewmatrix[1], r_refdef.viewaxis[1]); r_refdef.vieworg[1] = scene->viewmatrix[1][3];
|
||||||
VectorCopy(scene->viewmatrix[2], r_refdef.viewaxis[2]); r_refdef.vieworg[2] = scene->viewmatrix[0][11];
|
VectorCopy(scene->viewmatrix[2], r_refdef.viewaxis[2]); r_refdef.vieworg[2] = scene->viewmatrix[2][3];
|
||||||
|
|
||||||
r_refdef.viewangles[0] = -(atan2(r_refdef.viewaxis[0][2], sqrt(r_refdef.viewaxis[0][1]*r_refdef.viewaxis[0][1]+r_refdef.viewaxis[0][0]*r_refdef.viewaxis[0][0])) * 180 / M_PI);
|
r_refdef.viewangles[0] = -(atan2(r_refdef.viewaxis[0][2], sqrt(r_refdef.viewaxis[0][1]*r_refdef.viewaxis[0][1]+r_refdef.viewaxis[0][0]*r_refdef.viewaxis[0][0])) * 180 / M_PI);
|
||||||
r_refdef.viewangles[1] = (atan2(r_refdef.viewaxis[0][1], r_refdef.viewaxis[0][0]) * 180 / M_PI);
|
r_refdef.viewangles[1] = (atan2(r_refdef.viewaxis[0][1], r_refdef.viewaxis[0][0]) * 180 / M_PI);
|
||||||
|
|
|
@ -763,7 +763,7 @@ const char *presetexec[] =
|
||||||
"seta gl_polyblend 0;"
|
"seta gl_polyblend 0;"
|
||||||
"seta gl_flashblend 0;"
|
"seta gl_flashblend 0;"
|
||||||
"seta gl_specular 0;"
|
"seta gl_specular 0;"
|
||||||
"seta r_deluxmapping 0;"
|
"seta r_deluxemapping 0;"
|
||||||
"seta r_loadlit 0;"
|
"seta r_loadlit 0;"
|
||||||
"seta r_fastsky 1;"
|
"seta r_fastsky 1;"
|
||||||
"seta r_drawflame 0;"
|
"seta r_drawflame 0;"
|
||||||
|
@ -893,12 +893,12 @@ const char *presetexec[] =
|
||||||
"r_shadow_realtime_dlight 1;"
|
"r_shadow_realtime_dlight 1;"
|
||||||
// "gl_detail 1;"
|
// "gl_detail 1;"
|
||||||
"r_lightstylesmooth 1;"
|
"r_lightstylesmooth 1;"
|
||||||
"r_deluxmapping 2;"
|
"r_deluxemapping 2;"
|
||||||
"gl_texture_anisotropic_filtering 4;"
|
"gl_texture_anisotropic_filtering 4;"
|
||||||
|
|
||||||
, // realtime options
|
, // realtime options
|
||||||
"r_bloom 1;"
|
"r_bloom 1;"
|
||||||
"r_deluxmapping 0;" //won't be seen anyway
|
"r_deluxemapping 0;" //won't be seen anyway
|
||||||
"r_particledesc \"high tsshaft\";"
|
"r_particledesc \"high tsshaft\";"
|
||||||
"r_waterstyle 3;"
|
"r_waterstyle 3;"
|
||||||
"r_glsl_offsetmapping 1;"
|
"r_glsl_offsetmapping 1;"
|
||||||
|
@ -959,7 +959,7 @@ void M_Menu_Preset_f (void)
|
||||||
#else
|
#else
|
||||||
bias = 1;
|
bias = 1;
|
||||||
#endif
|
#endif
|
||||||
if (r_deluxmapping_cvar.ival)
|
if (r_deluxemapping_cvar.ival)
|
||||||
item = 2; //nice
|
item = 2; //nice
|
||||||
else if (gl_load24bit.ival)
|
else if (gl_load24bit.ival)
|
||||||
item = 3; //normal
|
item = 3; //normal
|
||||||
|
@ -1571,7 +1571,7 @@ void M_Menu_Lighting_f (void)
|
||||||
#endif
|
#endif
|
||||||
MB_COMBOCVAR("Lightmap Format", r_lightmap_format, lightmapformatopts, lightmapformatvalues, "Selects which format to use for lightmaps."),
|
MB_COMBOCVAR("Lightmap Format", r_lightmap_format, lightmapformatopts, lightmapformatvalues, "Selects which format to use for lightmaps."),
|
||||||
MB_COMBOCVAR("LIT Loading", r_loadlits, loadlitopts, loadlitvalues, "Determines if the engine should use external colored lighting for maps. The generated setting will cause the engine to generate colored lighting for maps that don't have the associated data."),
|
MB_COMBOCVAR("LIT Loading", r_loadlits, loadlitopts, loadlitvalues, "Determines if the engine should use external colored lighting for maps. The generated setting will cause the engine to generate colored lighting for maps that don't have the associated data."),
|
||||||
MB_COMBOCVAR("Deluxmapping", r_deluxmapping_cvar, loadlitopts, loadlitvalues, "Controls whether static lighting should respond to lighting directions."),
|
MB_COMBOCVAR("Deluxemapping", r_deluxemapping_cvar, loadlitopts, loadlitvalues, "Controls whether static lighting should respond to lighting directions."),
|
||||||
MB_CHECKBOXCVAR("Lightstyle Lerp", r_lightstylesmooth, 0),
|
MB_CHECKBOXCVAR("Lightstyle Lerp", r_lightstylesmooth, 0),
|
||||||
MB_SPACING(4),
|
MB_SPACING(4),
|
||||||
MB_COMBOCVAR("Flash Blend", r_flashblend, fbopts, fbvalues, "Disables or enables the spherical light effect for dynamic lights. Traced means the sphere effect will be line of sight checked before displaying the effect."),
|
MB_COMBOCVAR("Flash Blend", r_flashblend, fbopts, fbvalues, "Disables or enables the spherical light effect for dynamic lights. Traced means the sphere effect will be line of sight checked before displaying the effect."),
|
||||||
|
|
|
@ -385,7 +385,7 @@ typedef enum backendmode_e
|
||||||
|
|
||||||
typedef struct rendererinfo_s {
|
typedef struct rendererinfo_s {
|
||||||
char *description;
|
char *description;
|
||||||
char *name[4];
|
char *name[5];
|
||||||
r_qrenderer_t rtype;
|
r_qrenderer_t rtype;
|
||||||
//FIXME: all but the vid stuff really should be filled in by the video code, simplifying system-specific stuff.
|
//FIXME: all but the vid stuff really should be filled in by the video code, simplifying system-specific stuff.
|
||||||
|
|
||||||
|
|
|
@ -1531,7 +1531,7 @@ void QCBUILTIN PF_R_PolygonBegin(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
twod = qcflags & DRAWFLAG_2D;
|
twod = qcflags & DRAWFLAG_2D;
|
||||||
|
|
||||||
if ((qcflags & 3) == DRAWFLAG_ADD)
|
if ((qcflags & 3) == DRAWFLAG_ADD)
|
||||||
beflags = BEF_NOSHADOWS|BEF_FORCEADDITIVE;
|
beflags = BEF_NOSHADOWS|BEF_FORCEADDITIVE;
|
||||||
else
|
else
|
||||||
|
@ -2053,7 +2053,7 @@ nogameaccess:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static uploadfmt_t PR_TranslateTextureFormat(int qcformat)
|
uploadfmt_t PR_TranslateTextureFormat(int qcformat)
|
||||||
{
|
{
|
||||||
switch(qcformat)
|
switch(qcformat)
|
||||||
{
|
{
|
||||||
|
@ -2291,7 +2291,7 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VF_ENVMAP:
|
case VF_ENVMAP:
|
||||||
Q_strncpyz(r_refdef.nearenvmap.texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.rt_sourcecolour));
|
Q_strncpyz(r_refdef.nearenvmap.texname, PR_GetStringOfs(prinst, OFS_PARM1), sizeof(r_refdef.nearenvmap.texname));
|
||||||
BE_RenderToTextureUpdate2d(false);
|
BE_RenderToTextureUpdate2d(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3694,13 +3694,13 @@ static const char *PF_cs_serverkey_internal(const char *keyname)
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
if (sv.state >= ss_loading)
|
if (sv.state >= ss_loading)
|
||||||
{
|
{
|
||||||
ret = Info_ValueForKey(svs.info, keyname);
|
ret = InfoBuf_ValueForKey(&svs.info, keyname);
|
||||||
if (!*ret)
|
if (!*ret)
|
||||||
ret = Info_ValueForKey(localinfo, keyname);
|
ret = InfoBuf_ValueForKey(&svs.localinfo, keyname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ret = Info_ValueForKey(cl.serverinfo, keyname);
|
ret = InfoBuf_ValueForKey(&cl.serverinfo, keyname);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3810,7 +3810,7 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = Info_ValueForKey(cl.players[pnum].userinfo, keyname);
|
ret = InfoBuf_ValueForKey(&cl.players[pnum].userinfo, keyname);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3834,6 +3834,34 @@ static void QCBUILTIN PF_cs_serverkeyfloat (pubprogfuncs_t *prinst, struct globa
|
||||||
else
|
else
|
||||||
G_FLOAT(OFS_RETURN) = (prinst->callargc >= 2)?G_FLOAT(OFS_PARM1):0;
|
G_FLOAT(OFS_RETURN) = (prinst->callargc >= 2)?G_FLOAT(OFS_PARM1):0;
|
||||||
}
|
}
|
||||||
|
static void QCBUILTIN PF_cs_serverkeyblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
const char *keyname = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
int qcptr = G_INT(OFS_PARM1);
|
||||||
|
int qcsize = G_INT(OFS_PARM2);
|
||||||
|
void *ptr;
|
||||||
|
size_t blobsize = 0;
|
||||||
|
const char *blob;
|
||||||
|
|
||||||
|
if (qcptr < 0 || qcptr+qcsize >= prinst->stringtablesize)
|
||||||
|
{
|
||||||
|
PR_BIError(prinst, "PF_cs_serverkeyblob: invalid pointer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = (struct reverbproperties_s*)(prinst->stringtable + qcptr);
|
||||||
|
|
||||||
|
blob = InfoBuf_BlobForKey(&cl.serverinfo, keyname, &blobsize);
|
||||||
|
|
||||||
|
if (qcptr)
|
||||||
|
{
|
||||||
|
blobsize = min(blobsize, qcsize);
|
||||||
|
memcpy(ptr, blob, blobsize);
|
||||||
|
G_INT(OFS_RETURN) = blobsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
G_INT(OFS_RETURN) = blobsize;
|
||||||
|
}
|
||||||
|
|
||||||
//string(float pnum, string keyname)
|
//string(float pnum, string keyname)
|
||||||
static void QCBUILTIN PF_cs_getplayerkeystring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_cs_getplayerkeystring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
|
@ -3883,6 +3911,50 @@ static void QCBUILTIN PF_cs_getplayerkeyfloat (pubprogfuncs_t *prinst, struct gl
|
||||||
else
|
else
|
||||||
G_FLOAT(OFS_RETURN) = (prinst->callargc >= 3)?G_FLOAT(OFS_PARM2):0;
|
G_FLOAT(OFS_RETURN) = (prinst->callargc >= 3)?G_FLOAT(OFS_PARM2):0;
|
||||||
}
|
}
|
||||||
|
static void QCBUILTIN PF_cs_getplayerkeyblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
int pnum = G_FLOAT(OFS_PARM0);
|
||||||
|
const char *keyname = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
|
int qcptr = G_INT(OFS_PARM2);
|
||||||
|
int qcsize = G_INT(OFS_PARM3);
|
||||||
|
void *ptr;
|
||||||
|
if (pnum < 0)
|
||||||
|
{
|
||||||
|
if (csqc_resortfrags)
|
||||||
|
{
|
||||||
|
Sbar_SortFrags(true, false);
|
||||||
|
csqc_resortfrags = false;
|
||||||
|
}
|
||||||
|
if (pnum >= -scoreboardlines)
|
||||||
|
{//sort by
|
||||||
|
pnum = fragsort[-(pnum+1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qcptr < 0 || qcptr+qcsize >= prinst->stringtablesize)
|
||||||
|
{
|
||||||
|
PR_BIError(prinst, "PF_cs_getplayerkeyblob: invalid pointer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = (struct reverbproperties_s*)(prinst->stringtable + qcptr);
|
||||||
|
|
||||||
|
if ((unsigned int)pnum >= (unsigned int)cl.allocated_client_slots)
|
||||||
|
G_INT(OFS_RETURN) = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t blobsize = 0;
|
||||||
|
const char *blob = InfoBuf_BlobForKey(&cl.players[pnum].userinfo, keyname, &blobsize);
|
||||||
|
|
||||||
|
if (qcptr)
|
||||||
|
{
|
||||||
|
blobsize = min(blobsize, qcsize);
|
||||||
|
memcpy(ptr, blob, blobsize);
|
||||||
|
G_INT(OFS_RETURN) = blobsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
G_INT(OFS_RETURN) = blobsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void QCBUILTIN PF_cs_infokey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_cs_infokey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
|
@ -6092,6 +6164,7 @@ static struct {
|
||||||
{"abort", PF_Abort, 211}, //#211 void() abort (FTE_MULTITHREADED)
|
{"abort", PF_Abort, 211}, //#211 void() abort (FTE_MULTITHREADED)
|
||||||
// {"sleep", PF_Fixme, 212},//{"sleep", PF_Sleep, 0, 0, 0, 212},
|
// {"sleep", PF_Fixme, 212},//{"sleep", PF_Sleep, 0, 0, 0, 212},
|
||||||
{"forceinfokey", PF_NoCSQC, 213},//{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213},
|
{"forceinfokey", PF_NoCSQC, 213},//{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213},
|
||||||
|
{"forceinfokeyblob", PF_NoCSQC, 0},//{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213},
|
||||||
{"chat", PF_NoCSQC, 214},//{"chat", PF_chat, 0, 0, 0, 214},// #214 void(string filename, float starttag, entity edict) SV_Chat (FTE_NPCCHAT)
|
{"chat", PF_NoCSQC, 214},//{"chat", PF_chat, 0, 0, 0, 214},// #214 void(string filename, float starttag, entity edict) SV_Chat (FTE_NPCCHAT)
|
||||||
|
|
||||||
{"particle2", PF_cs_particle2, 215}, //215 (FTE_PEXT_HEXEN2)
|
{"particle2", PF_cs_particle2, 215}, //215 (FTE_PEXT_HEXEN2)
|
||||||
|
@ -6296,7 +6369,8 @@ static struct {
|
||||||
{"runstandardplayerphysics",PF_cs_runplayerphysics, 347}, // #347 void() runstandardplayerphysics (EXT_CSQC)
|
{"runstandardplayerphysics",PF_cs_runplayerphysics, 347}, // #347 void() runstandardplayerphysics (EXT_CSQC)
|
||||||
|
|
||||||
{"getplayerkeyvalue", PF_cs_getplayerkeystring, 348}, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
|
{"getplayerkeyvalue", PF_cs_getplayerkeystring, 348}, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
|
||||||
{"getplayerkeyfloat", PF_cs_getplayerkeyfloat, 0}, // #348 string(float playernum, string keyname) getplayerkeyvalue
|
{"getplayerkeyfloat", PF_cs_getplayerkeyfloat, 0}, // #348 string(float playernum, string keyname) getplayerkeyvalue
|
||||||
|
{"getplayerkeyblob", PF_cs_getplayerkeyblob, 0}, // #0 int(float playernum, string keyname, optional void *outptr, int size) getplayerkeyblob
|
||||||
|
|
||||||
{"isdemo", PF_cl_playingdemo, 349}, // #349 float() isdemo (EXT_CSQC)
|
{"isdemo", PF_cl_playingdemo, 349}, // #349 float() isdemo (EXT_CSQC)
|
||||||
//350
|
//350
|
||||||
|
@ -6309,6 +6383,7 @@ static struct {
|
||||||
|
|
||||||
{"serverkey", PF_cs_serverkey, 354}, // #354 string(string key) serverkey;
|
{"serverkey", PF_cs_serverkey, 354}, // #354 string(string key) serverkey;
|
||||||
{"serverkeyfloat", PF_cs_serverkeyfloat, 0}, // #0 float(string key) serverkeyfloat;
|
{"serverkeyfloat", PF_cs_serverkeyfloat, 0}, // #0 float(string key) serverkeyfloat;
|
||||||
|
{"serverkeyblob", PF_cs_serverkeyblob, 0},
|
||||||
{"getentitytoken", PF_cs_getentitytoken, 355}, // #355 string() getentitytoken;
|
{"getentitytoken", PF_cs_getentitytoken, 355}, // #355 string() getentitytoken;
|
||||||
{"findfont", PF_CL_findfont, 356},
|
{"findfont", PF_CL_findfont, 356},
|
||||||
{"loadfont", PF_CL_loadfont, 357},
|
{"loadfont", PF_CL_loadfont, 357},
|
||||||
|
@ -6618,6 +6693,7 @@ static struct {
|
||||||
{"setbindmaps", PF_cl_SetBindMap, 632},
|
{"setbindmaps", PF_cl_SetBindMap, 632},
|
||||||
|
|
||||||
{"digest_hex", PF_digest_hex, 639},
|
{"digest_hex", PF_digest_hex, 639},
|
||||||
|
{"digest_ptr", PF_digest_ptr, 0},
|
||||||
{"V_CalcRefdef", PF_V_CalcRefdef, 640},
|
{"V_CalcRefdef", PF_V_CalcRefdef, 640},
|
||||||
|
|
||||||
{NULL}
|
{NULL}
|
||||||
|
@ -6901,9 +6977,11 @@ void *PDECL CSQC_PRLoadFile (const char *path, unsigned char *(PDECL *buf_get)(v
|
||||||
char newname[MAX_QPATH];
|
char newname[MAX_QPATH];
|
||||||
snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csprogs_checksum);
|
snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csprogs_checksum);
|
||||||
|
|
||||||
|
//we can use FSLF_IGNOREPURE because we have our own hashes/size checks instead.
|
||||||
|
//this should make it slightly easier for server admins
|
||||||
if (csprogs_checksum)
|
if (csprogs_checksum)
|
||||||
{
|
{
|
||||||
file = COM_LoadTempFile (newname, sz);
|
file = COM_LoadTempFile (newname, FSLF_IGNOREPURE, sz);
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
|
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
|
||||||
|
@ -6921,7 +6999,7 @@ void *PDECL CSQC_PRLoadFile (const char *path, unsigned char *(PDECL *buf_get)(v
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
file = COM_LoadTempFile (path, sz);
|
file = COM_LoadTempFile (path, FSLF_IGNOREPURE, sz);
|
||||||
|
|
||||||
if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum
|
if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum
|
||||||
{
|
{
|
||||||
|
@ -6956,7 +7034,7 @@ void *PDECL CSQC_PRLoadFile (const char *path, unsigned char *(PDECL *buf_get)(v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
file = COM_LoadTempFile (path, sz);
|
file = COM_LoadTempFile (path, 0, sz);
|
||||||
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
|
@ -7137,7 +7215,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
|
||||||
csqc_mayread = false;
|
csqc_mayread = false;
|
||||||
|
|
||||||
csqc_singlecheats = cls.demoplayback;
|
csqc_singlecheats = cls.demoplayback;
|
||||||
cheats = Info_ValueForKey(cl.serverinfo, "*cheats");
|
cheats = InfoBuf_ValueForKey(&cl.serverinfo, "*cheats");
|
||||||
if (!Q_strcasecmp(cheats, "ON") || atoi(cheats))
|
if (!Q_strcasecmp(cheats, "ON") || atoi(cheats))
|
||||||
csqc_singlecheats = true;
|
csqc_singlecheats = true;
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
|
@ -7353,7 +7431,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
|
||||||
str = (string_t*)PR_FindGlobal(csqcprogs, "mapname", 0, NULL);
|
str = (string_t*)PR_FindGlobal(csqcprogs, "mapname", 0, NULL);
|
||||||
if (str)
|
if (str)
|
||||||
{
|
{
|
||||||
char *s = Info_ValueForKey(cl.serverinfo, "map");
|
char *s = InfoBuf_ValueForKey(&cl.serverinfo, "map");
|
||||||
if (!*s)
|
if (!*s)
|
||||||
s = cl.model_name[1];
|
s = cl.model_name[1];
|
||||||
if (!*s)
|
if (!*s)
|
||||||
|
|
|
@ -711,7 +711,8 @@ void QCBUILTIN PF_CL_uploadimage (pubprogfuncs_t *prinst, struct globalvars_s *p
|
||||||
int width = G_INT(OFS_PARM1);
|
int width = G_INT(OFS_PARM1);
|
||||||
int height = G_INT(OFS_PARM2);
|
int height = G_INT(OFS_PARM2);
|
||||||
int src = G_INT(OFS_PARM3); //ptr
|
int src = G_INT(OFS_PARM3); //ptr
|
||||||
int size = width * height * 4;
|
int size = (prinst->callargc > 4)?G_INT(OFS_PARM4):(width * height * 4);
|
||||||
|
uploadfmt_t format = (prinst->callargc > 5)?PR_TranslateTextureFormat(G_INT(OFS_PARM5)):TF_RGBA32;
|
||||||
void *imgptr;
|
void *imgptr;
|
||||||
texid_t tid;
|
texid_t tid;
|
||||||
|
|
||||||
|
@ -735,11 +736,30 @@ void QCBUILTIN PF_CL_uploadimage (pubprogfuncs_t *prinst, struct globalvars_s *p
|
||||||
if (!TEXVALID(tid))
|
if (!TEXVALID(tid))
|
||||||
tid = Image_CreateTexture(imagename, NULL, RT_IMAGEFLAGS);
|
tid = Image_CreateTexture(imagename, NULL, RT_IMAGEFLAGS);
|
||||||
|
|
||||||
Image_Upload(tid, TF_RGBA32, imgptr, NULL, width, height, RT_IMAGEFLAGS);
|
if (!format)
|
||||||
tid->width = width;
|
{
|
||||||
tid->height = height;
|
void *data = BZ_Malloc(size);
|
||||||
|
memcpy(data, imgptr, size);
|
||||||
G_INT(OFS_RETURN) = 1;
|
G_INT(OFS_RETURN) = Image_LoadTextureFromMemory(tid, tid->flags, tid->ident, imagename, data, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int blockbytes, blockwidth, blockheight;
|
||||||
|
//get format info
|
||||||
|
Image_BlockSizeForEncoding(format, &blockbytes, &blockwidth, &blockheight);
|
||||||
|
//round up as appropriate
|
||||||
|
blockwidth = ((width+blockwidth-1)/blockwidth)*blockwidth;
|
||||||
|
blockheight = ((height+blockheight-1)/blockheight)*blockheight;
|
||||||
|
if (size != blockwidth*blockheight*blockbytes)
|
||||||
|
G_INT(OFS_RETURN) = 0; //size isn't right. which means the pointer might be invalid too.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Image_Upload(tid, format, imgptr, NULL, width, height, RT_IMAGEFLAGS);
|
||||||
|
tid->width = width;
|
||||||
|
tid->height = height;
|
||||||
|
G_INT(OFS_RETURN) = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//warning: not threadable. hopefully noone abuses it.
|
//warning: not threadable. hopefully noone abuses it.
|
||||||
|
@ -2152,6 +2172,9 @@ static struct {
|
||||||
//unproject 310
|
//unproject 310
|
||||||
//project 311
|
//project 311
|
||||||
|
|
||||||
|
{"r_uploadimage", PF_CL_uploadimage, 0},
|
||||||
|
{"r_readimage", PF_CL_readimage, 0},
|
||||||
|
|
||||||
|
|
||||||
{"print_csqc", PF_print, 339},
|
{"print_csqc", PF_print, 339},
|
||||||
{"keynumtostring_csqc", PF_cl_keynumtostring, 340},
|
{"keynumtostring_csqc", PF_cl_keynumtostring, 340},
|
||||||
|
@ -2317,6 +2340,7 @@ static struct {
|
||||||
{"crypto_getmykeyfp", PF_crypto_getmykeyfp, 636},
|
{"crypto_getmykeyfp", PF_crypto_getmykeyfp, 636},
|
||||||
{"crypto_getmyidfp", PF_crypto_getmyidfp, 637},
|
{"crypto_getmyidfp", PF_crypto_getmyidfp, 637},
|
||||||
{"digest_hex", PF_digest_hex, 639},
|
{"digest_hex", PF_digest_hex, 639},
|
||||||
|
{"digest_ptr", PF_digest_ptr, 0},
|
||||||
{"crypto_getmyidstatus", PF_crypto_getmyidfp, 641},
|
{"crypto_getmyidstatus", PF_crypto_getmyidfp, 641},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4293,7 +4293,7 @@ TRACE(("dbg: Surf_NewMap: tp\n"));
|
||||||
|
|
||||||
void Surf_PreNewMap(void)
|
void Surf_PreNewMap(void)
|
||||||
{
|
{
|
||||||
r_loadbumpmapping = r_deluxmapping || r_glsl_offsetmapping.ival;
|
r_loadbumpmapping = r_deluxemapping || r_glsl_offsetmapping.ival;
|
||||||
#ifdef RTLIGHTS
|
#ifdef RTLIGHTS
|
||||||
r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival;
|
r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -447,7 +447,8 @@ image_t *Image_CreateTexture(const char *identifier, const char *subpath, unsign
|
||||||
image_t *QDECL Image_GetTexture (const char *identifier, const char *subpath, unsigned int flags, void *fallbackdata, void *fallbackpalette, int fallbackwidth, int fallbackheight, uploadfmt_t fallbackfmt);
|
image_t *QDECL Image_GetTexture (const char *identifier, const char *subpath, unsigned int flags, void *fallbackdata, void *fallbackpalette, int fallbackwidth, int fallbackheight, uploadfmt_t fallbackfmt);
|
||||||
qboolean Image_UnloadTexture(image_t *tex); //true if it did something.
|
qboolean Image_UnloadTexture(image_t *tex); //true if it did something.
|
||||||
void Image_DestroyTexture (image_t *tex);
|
void Image_DestroyTexture (image_t *tex);
|
||||||
qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, char *fname, qbyte *filedata, int filesize); //intended really for worker threads, but should be fine from the main thread too
|
qboolean Image_LoadTextureFromMemory(texid_t tex, int flags, const char *iname, const char *fname, qbyte *filedata, int filesize); //intended really for worker threads, but should be fine from the main thread too
|
||||||
|
qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *bestname, size_t bestnamesize, unsigned int *bestflags);
|
||||||
void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags);
|
void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags);
|
||||||
void Image_Purge(void); //purge any textures which are not needed any more (releases memory, but doesn't give null pointers).
|
void Image_Purge(void); //purge any textures which are not needed any more (releases memory, but doesn't give null pointers).
|
||||||
void Image_Init(void);
|
void Image_Init(void);
|
||||||
|
@ -626,8 +627,8 @@ extern cvar_t r_telestyle;
|
||||||
extern cvar_t r_dynamic;
|
extern cvar_t r_dynamic;
|
||||||
extern cvar_t r_novis;
|
extern cvar_t r_novis;
|
||||||
extern cvar_t r_netgraph;
|
extern cvar_t r_netgraph;
|
||||||
extern cvar_t r_deluxmapping_cvar;
|
extern cvar_t r_deluxemapping_cvar;
|
||||||
extern qboolean r_deluxmapping;
|
extern qboolean r_deluxemapping;
|
||||||
extern cvar_t r_softwarebanding_cvar;
|
extern cvar_t r_softwarebanding_cvar;
|
||||||
extern qboolean r_softwarebanding;
|
extern qboolean r_softwarebanding;
|
||||||
extern cvar_t r_lightprepass_cvar;
|
extern cvar_t r_lightprepass_cvar;
|
||||||
|
|
|
@ -120,7 +120,7 @@ cvar_t r_wireframe = CVARFD ("r_wireframe", "0",
|
||||||
CVAR_CHEAT, "Developer feature where everything is drawn with wireframe over the top. Only active where cheats are permitted.");
|
CVAR_CHEAT, "Developer feature where everything is drawn with wireframe over the top. Only active where cheats are permitted.");
|
||||||
cvar_t r_wireframe_smooth = CVAR ("r_wireframe_smooth", "0");
|
cvar_t r_wireframe_smooth = CVAR ("r_wireframe_smooth", "0");
|
||||||
cvar_t r_refract_fbo = CVARD ("r_refract_fbo", "1", "Use an fbo for refraction. If 0, just renders as a portal and uses a copy of the current framebuffer.");
|
cvar_t r_refract_fbo = CVARD ("r_refract_fbo", "1", "Use an fbo for refraction. If 0, just renders as a portal and uses a copy of the current framebuffer.");
|
||||||
cvar_t r_refractreflect_scale = CVARD ("r_refractreflect_scale", "0.5", "Use a different scale for refraction and reflection. Because $reasons.");
|
cvar_t r_refractreflect_scale = CVARD ("r_refractreflect_scale", "0.5", "Use a different scale for refraction and reflection texturemaps. Because $reasons.");
|
||||||
cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0");
|
cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0");
|
||||||
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
|
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
|
||||||
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
|
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
|
||||||
|
@ -344,9 +344,9 @@ cvar_t gl_ati_truform_type = CVAR ("gl_ati_truform_type", "1");
|
||||||
cvar_t r_tessellation_level = CVAR ("r_tessellation_level", "5");
|
cvar_t r_tessellation_level = CVAR ("r_tessellation_level", "5");
|
||||||
cvar_t gl_blend2d = CVAR ("gl_blend2d", "1");
|
cvar_t gl_blend2d = CVAR ("gl_blend2d", "1");
|
||||||
cvar_t gl_blendsprites = CVARD ("gl_blendsprites", "0", "Blend sprites instead of alpha testing them");
|
cvar_t gl_blendsprites = CVARD ("gl_blendsprites", "0", "Blend sprites instead of alpha testing them");
|
||||||
cvar_t r_deluxmapping_cvar = CVARAFD ("r_deluxemapping", "0", "r_glsl_deluxemapping",
|
cvar_t r_deluxemapping_cvar = CVARAFD ("r_deluxemapping", "1", "r_glsl_deluxemapping",
|
||||||
CVAR_ARCHIVE|CVAR_RENDERERLATCH, "Enables bumpmapping based upon precomputed light directions.\n0=off\n1=use if available\n2=auto-generate (if possible)");
|
CVAR_ARCHIVE|CVAR_RENDERERLATCH, "Enables bumpmapping based upon precomputed light directions.\n0=off\n1=use if available\n2=auto-generate (if possible)");
|
||||||
qboolean r_deluxmapping;
|
qboolean r_deluxemapping;
|
||||||
cvar_t r_shaderblobs = CVARD ("r_shaderblobs", "0", "If enabled, can massively accelerate vid restarts / loading (especially with the d3d renderer). Can cause issues when upgrading engine versions, so this is disabled by default.");
|
cvar_t r_shaderblobs = CVARD ("r_shaderblobs", "0", "If enabled, can massively accelerate vid restarts / loading (especially with the d3d renderer). Can cause issues when upgrading engine versions, so this is disabled by default.");
|
||||||
cvar_t gl_compress = CVARFD ("gl_compress", "0", CVAR_ARCHIVE, "Enable automatic texture compression even for textures which are not pre-compressed.");
|
cvar_t gl_compress = CVARFD ("gl_compress", "0", CVAR_ARCHIVE, "Enable automatic texture compression even for textures which are not pre-compressed.");
|
||||||
cvar_t gl_conback = CVARFCD ("gl_conback", "",
|
cvar_t gl_conback = CVARFCD ("gl_conback", "",
|
||||||
|
@ -529,7 +529,7 @@ void GLRenderer_Init(void)
|
||||||
|
|
||||||
Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES);
|
Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES);
|
||||||
|
|
||||||
Cvar_Register (&r_deluxmapping_cvar, GRAPHICALNICETIES);
|
Cvar_Register (&r_deluxemapping_cvar, GRAPHICALNICETIES);
|
||||||
|
|
||||||
#ifdef R_XFLIP
|
#ifdef R_XFLIP
|
||||||
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
|
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
|
||||||
|
@ -1464,7 +1464,7 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
|
||||||
if (host_basepal)
|
if (host_basepal)
|
||||||
Z_Free(host_basepal);
|
Z_Free(host_basepal);
|
||||||
host_basepal = BZ_Malloc(768);
|
host_basepal = BZ_Malloc(768);
|
||||||
pcx = COM_LoadTempFile("pics/colormap.pcx", &sz);
|
pcx = COM_LoadTempFile("pics/colormap.pcx", 0, &sz);
|
||||||
if (!pcx || !ReadPCXPalette(pcx, sz, host_basepal))
|
if (!pcx || !ReadPCXPalette(pcx, sz, host_basepal))
|
||||||
{
|
{
|
||||||
memcpy(host_basepal, default_quakepal, 768);
|
memcpy(host_basepal, default_quakepal, 768);
|
||||||
|
@ -1522,7 +1522,7 @@ TRACE(("dbg: R_ApplyRenderer: vid applied\n"));
|
||||||
R_GenPaletteLookup();
|
R_GenPaletteLookup();
|
||||||
|
|
||||||
r_softwarebanding = false;
|
r_softwarebanding = false;
|
||||||
r_deluxmapping = false;
|
r_deluxemapping = false;
|
||||||
r_lightprepass = false;
|
r_lightprepass = false;
|
||||||
|
|
||||||
W_LoadWadFile("gfx.wad");
|
W_LoadWadFile("gfx.wad");
|
||||||
|
|
|
@ -346,7 +346,7 @@ char *Get_Q2ConfigString(int i)
|
||||||
if (i >= Q2CS_SOUNDS && i < Q2CS_SOUNDS + Q2MAX_SOUNDS)
|
if (i >= Q2CS_SOUNDS && i < Q2CS_SOUNDS + Q2MAX_SOUNDS)
|
||||||
return cl.sound_name [i-Q2CS_SOUNDS];
|
return cl.sound_name [i-Q2CS_SOUNDS];
|
||||||
if (i == Q2CS_AIRACCEL)
|
if (i == Q2CS_AIRACCEL)
|
||||||
return "4";
|
return cl.q2airaccel;
|
||||||
if (i >= Q2CS_PLAYERSKINS && i < Q2CS_GENERAL+Q2MAX_GENERAL)
|
if (i >= Q2CS_PLAYERSKINS && i < Q2CS_GENERAL+Q2MAX_GENERAL)
|
||||||
return cl.configstring_general[i-Q2CS_PLAYERSKINS]?cl.configstring_general[i-Q2CS_PLAYERSKINS]:"";
|
return cl.configstring_general[i-Q2CS_PLAYERSKINS]?cl.configstring_general[i-Q2CS_PLAYERSKINS]:"";
|
||||||
//#define Q2CS_LIGHTS (Q2CS_IMAGES +Q2MAX_IMAGES)
|
//#define Q2CS_LIGHTS (Q2CS_IMAGES +Q2MAX_IMAGES)
|
||||||
|
@ -465,7 +465,7 @@ void Sbar_ExecuteLayoutString (char *s, int seat)
|
||||||
Draw_FunString (x+32, y+16, va("Ping: %i", ping));
|
Draw_FunString (x+32, y+16, va("Ping: %i", ping));
|
||||||
Draw_FunString (x+32, y+24, va("Time: %i", time));
|
Draw_FunString (x+32, y+24, va("Time: %i", time));
|
||||||
|
|
||||||
p = R2D_SafeCachePic(va("players/%s_i.pcx", Info_ValueForKey(cl.players[value].userinfo, "skin")));
|
p = R2D_SafeCachePic(va("players/%s_i.pcx", InfoBuf_ValueForKey(&cl.players[value].userinfo, "skin")));
|
||||||
if (!p || !R_GetShaderSizes(p, NULL, NULL, false)) //display a default if the icon couldn't be found.
|
if (!p || !R_GetShaderSizes(p, NULL, NULL, false)) //display a default if the icon couldn't be found.
|
||||||
p = R2D_SafeCachePic("players/male/grunt_i.pcx");
|
p = R2D_SafeCachePic("players/male/grunt_i.pcx");
|
||||||
R2D_ScalePic (x, y, 32, 32, p);
|
R2D_ScalePic (x, y, 32, 32, p);
|
||||||
|
@ -3289,7 +3289,7 @@ ping time frags name
|
||||||
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8, false, false);},NOFILL)
|
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8, false, false);},NOFILL)
|
||||||
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8, false, false);},NOFILL)
|
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8, false, false);},NOFILL)
|
||||||
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8, false, false);},NOFILL)
|
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8, false, false);},NOFILL)
|
||||||
#define COLUMN_AFK COLUMN(afk, 0, {int cs = atoi(Info_ValueForKey(s->userinfo, "chat")); if (cs)Draw_FunStringWidth(x+4, y, (cs&2)?"afk":"msg", 4*8, false, false);},NOFILL)
|
#define COLUMN_AFK COLUMN(afk, 0, {int cs = atoi(InfoBuf_ValueForKey(&s->userinfo, "chat")); if (cs)Draw_FunStringWidth(x+4, y, (cs&2)?"afk":"msg", 4*8, false, false);},NOFILL)
|
||||||
|
|
||||||
|
|
||||||
//columns are listed here in display order
|
//columns are listed here in display order
|
||||||
|
@ -3519,7 +3519,7 @@ if (showcolumns & (1<<COLUMN##title)) \
|
||||||
{
|
{
|
||||||
int background_color;
|
int background_color;
|
||||||
// Electro's scoreboard eyecandy: red vs blue are common teams, force the colours
|
// Electro's scoreboard eyecandy: red vs blue are common teams, force the colours
|
||||||
Q_strncpyz (team, Info_ValueForKey(s->userinfo, "team"), sizeof(team));
|
Q_strncpyz (team, InfoBuf_ValueForKey(&s->userinfo, "team"), sizeof(team));
|
||||||
|
|
||||||
if (S_Voip_Speaking(k))
|
if (S_Voip_Speaking(k))
|
||||||
background_color = 0x00ff00;
|
background_color = 0x00ff00;
|
||||||
|
|
|
@ -181,6 +181,7 @@ typedef enum uploadfmt
|
||||||
PTI_DEPTH32,
|
PTI_DEPTH32,
|
||||||
PTI_DEPTH24_8,
|
PTI_DEPTH24_8,
|
||||||
|
|
||||||
|
//non-native formats (generally requiring weird palettes that are not supported by hardware)
|
||||||
TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/
|
TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/
|
||||||
TF_MIP4_R8, /*8bit 4-mip greyscale image*/
|
TF_MIP4_R8, /*8bit 4-mip greyscale image*/
|
||||||
TF_MIP4_SOLID8, /*8bit 4-mip image in default palette*/
|
TF_MIP4_SOLID8, /*8bit 4-mip image in default palette*/
|
||||||
|
|
|
@ -49,7 +49,7 @@ char *Skin_FindName (player_info_t *sc)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s = Info_ValueForKey(sc->userinfo, "skin");
|
s = InfoBuf_ValueForKey(&sc->userinfo, "skin");
|
||||||
if (s && s[0])
|
if (s && s[0])
|
||||||
Q_strncpyz(name, s, sizeof(name));
|
Q_strncpyz(name, s, sizeof(name));
|
||||||
else
|
else
|
||||||
|
@ -212,7 +212,7 @@ void Skin_WorkerLoad(void *skinptr, void *data, size_t a, size_t b)
|
||||||
size_t pcxsize;
|
size_t pcxsize;
|
||||||
|
|
||||||
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", skin->name);
|
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", skin->name);
|
||||||
raw = COM_LoadTempFile (name, &pcxsize);
|
raw = COM_LoadTempFile (name, FSLF_IGNOREPURE, &pcxsize);
|
||||||
if (!raw)
|
if (!raw)
|
||||||
{
|
{
|
||||||
//use 24bit skins even if gl_load24bit is failed
|
//use 24bit skins even if gl_load24bit is failed
|
||||||
|
@ -223,7 +223,7 @@ void Skin_WorkerLoad(void *skinptr, void *data, size_t a, size_t b)
|
||||||
if (*baseskin.string)
|
if (*baseskin.string)
|
||||||
{
|
{
|
||||||
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", baseskin.string);
|
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", baseskin.string);
|
||||||
raw = COM_LoadTempFile (name, &pcxsize);
|
raw = COM_LoadTempFile (name, FSLF_IGNOREPURE, &pcxsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!raw)
|
if (!raw)
|
||||||
|
@ -463,7 +463,7 @@ void Skin_NextDownload (void)
|
||||||
sc = &cl.players[i];
|
sc = &cl.players[i];
|
||||||
if (!sc->name[0])
|
if (!sc->name[0])
|
||||||
continue;
|
continue;
|
||||||
skinname = Info_ValueForKey(sc->userinfo, "skin");
|
skinname = InfoBuf_ValueForKey(&sc->userinfo, "skin");
|
||||||
slash = strchr(skinname, '/');
|
slash = strchr(skinname, '/');
|
||||||
if (slash)
|
if (slash)
|
||||||
{
|
{
|
||||||
|
|
|
@ -842,6 +842,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
pitch = (float)chan->rate/(1<<PITCHSHIFT);
|
pitch = (float)chan->rate/(1<<PITCHSHIFT);
|
||||||
|
pitch = bound(0.5, pitch, 2.0); //openal documents a limit on the allowed range of pitches. clamp to avoid error spam. openal-soft doesn't enforce anything other than it >=0
|
||||||
palSourcef(src, AL_PITCH, pitch);
|
palSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
#ifdef USEEFX
|
#ifdef USEEFX
|
||||||
|
|
|
@ -907,7 +907,7 @@ static void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
|
||||||
else
|
else
|
||||||
Q_snprintfz(namebuffer, sizeof(namebuffer), "%s%s", prefixes[pre], name);
|
Q_snprintfz(namebuffer, sizeof(namebuffer), "%s%s", prefixes[pre], name);
|
||||||
|
|
||||||
data = COM_LoadFile(namebuffer, 5, &filesize);
|
data = FS_LoadMallocFile(namebuffer, &filesize);
|
||||||
if (data)
|
if (data)
|
||||||
break;
|
break;
|
||||||
COM_FileExtension(namebuffer, orig, sizeof(orig));
|
COM_FileExtension(namebuffer, orig, sizeof(orig));
|
||||||
|
@ -917,7 +917,7 @@ static void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
|
||||||
if (!strcmp(orig, extensions[ex]+1))
|
if (!strcmp(orig, extensions[ex]+1))
|
||||||
continue;
|
continue;
|
||||||
Q_snprintfz(namebuffer, sizeof(namebuffer), "%s%s", altname, extensions[ex]);
|
Q_snprintfz(namebuffer, sizeof(namebuffer), "%s%s", altname, extensions[ex]);
|
||||||
data = COM_LoadFile(namebuffer, 5, &filesize);
|
data = FS_LoadMallocFile(namebuffer, &filesize);
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
Con_DPrintf("found a mangled name: %s\n", namebuffer);
|
Con_DPrintf("found a mangled name: %s\n", namebuffer);
|
||||||
|
|
|
@ -2396,7 +2396,6 @@ int global_nCmdShow;
|
||||||
HWND hwnd_dialog;
|
HWND hwnd_dialog;
|
||||||
|
|
||||||
static const IID qIID_IShellLinkW = {0x000214F9L, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
|
static const IID qIID_IShellLinkW = {0x000214F9L, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
|
||||||
static const IID qIID_IPersistFile = {0x0000010BL, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
|
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
||||||
|
@ -2764,11 +2763,11 @@ void Win7_TaskListInit(void)
|
||||||
#define UPD_BUILDTYPE "test"
|
#define UPD_BUILDTYPE "test"
|
||||||
//WARNING: Security comes from the fact that the triptohell.info certificate is hardcoded in the tls code.
|
//WARNING: Security comes from the fact that the triptohell.info certificate is hardcoded in the tls code.
|
||||||
//this will correctly detect insecure tls proxies also.
|
//this will correctly detect insecure tls proxies also.
|
||||||
#define UPDATE_URL_ROOT "https://triptohell.info/moodles/"
|
// #define UPDATE_URL_ROOT "https://triptohell.info/moodles/"
|
||||||
#define UPDATE_URL_TESTED UPDATE_URL_ROOT "autoup/"
|
// #define UPDATE_URL_TESTED UPDATE_URL_ROOT "autoup/"
|
||||||
#define UPDATE_URL_NIGHTLY UPDATE_URL_ROOT
|
// #define UPDATE_URL_NIGHTLY UPDATE_URL_ROOT
|
||||||
#define UPDATE_URL_VERSION "%sversion.txt"
|
// #define UPDATE_URL_VERSION "%sversion.txt"
|
||||||
#ifdef NOLEGACY
|
/* #ifdef NOLEGACY
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#define UPDATE_URL_BUILD "%snocompat64/fte" EXETYPE "64.exe"
|
#define UPDATE_URL_BUILD "%snocompat64/fte" EXETYPE "64.exe"
|
||||||
#else
|
#else
|
||||||
|
@ -2780,7 +2779,7 @@ void Win7_TaskListInit(void)
|
||||||
#else
|
#else
|
||||||
#define UPDATE_URL_BUILD "%swin32/fte" EXETYPE ".exe"
|
#define UPDATE_URL_BUILD "%swin32/fte" EXETYPE ".exe"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SERVERONLY)
|
#if defined(SERVERONLY)
|
||||||
|
@ -3150,6 +3149,7 @@ static BOOL microsoft_accessU(LPCSTR pszFolder, DWORD dwAccessDesired)
|
||||||
#define BFFM_SETOKTEXT (WM_USER + 105) //v6
|
#define BFFM_SETOKTEXT (WM_USER + 105) //v6
|
||||||
#define BFFM_SETEXPANDED (WM_USER + 106) //v6
|
#define BFFM_SETEXPANDED (WM_USER + 106) //v6
|
||||||
#endif
|
#endif
|
||||||
|
static const IID qIID_IPersistFile = {0x0000010BL, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
|
||||||
|
|
||||||
static WNDPROC omgwtfwhyohwhy;
|
static WNDPROC omgwtfwhyohwhy;
|
||||||
static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM lp)
|
static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM lp)
|
||||||
|
@ -4297,6 +4297,8 @@ void *WIN_CreateCursor(const char *filename, float hotx, float hoty, float scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: CreateIconIndirect does NOT understand DPI scaling, and will show a tiny cursor in such cases.
|
||||||
|
// we should rescale scale by vid_conautoscale etc.
|
||||||
if (scale != 1)
|
if (scale != 1)
|
||||||
{
|
{
|
||||||
int nw,nh;
|
int nw,nh;
|
||||||
|
@ -4363,8 +4365,8 @@ void *WIN_CreateCursor(const char *filename, float hotx, float hoty, float scale
|
||||||
// Create the alpha cursor with the alpha DIB section.
|
// Create the alpha cursor with the alpha DIB section.
|
||||||
hAlphaCursor = CreateIconIndirect(&ii);
|
hAlphaCursor = CreateIconIndirect(&ii);
|
||||||
|
|
||||||
DeleteObject(ii.hbmColor);
|
DeleteObject(ii.hbmColor);
|
||||||
DeleteObject(ii.hbmMask);
|
DeleteObject(ii.hbmMask);
|
||||||
|
|
||||||
return hAlphaCursor;
|
return hAlphaCursor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,6 +393,86 @@ void Con_EditorMoveCursor(console_t *con, conline_t *newline, int newoffset, qbo
|
||||||
con->userline = newline;
|
con->userline = newline;
|
||||||
con->useroffset = newoffset;
|
con->useroffset = newoffset;
|
||||||
}
|
}
|
||||||
|
static conchar_t *Con_Editor_Equals(conchar_t *start, conchar_t *end, const char *match)
|
||||||
|
{
|
||||||
|
conchar_t *n;
|
||||||
|
unsigned int ccode, flags;
|
||||||
|
|
||||||
|
for (; start < end; start = n)
|
||||||
|
{
|
||||||
|
n = Font_Decode(start, &flags, &ccode);
|
||||||
|
if (*match)
|
||||||
|
{
|
||||||
|
if (ccode != *(unsigned char*)match++)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (ccode == ' ' || ccode == '\t')
|
||||||
|
break; //found whitespace after the token, its complete.
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (*match)
|
||||||
|
return NULL; //truncated
|
||||||
|
|
||||||
|
//and skip any trailing whitespace, because we can.
|
||||||
|
for (; start < end; start = n)
|
||||||
|
{
|
||||||
|
n = Font_Decode(start, &flags, &ccode);
|
||||||
|
if (ccode == ' ' || ccode == '\t')
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
static conchar_t *Con_Editor_SkipWhite(conchar_t *start, conchar_t *end)
|
||||||
|
{
|
||||||
|
conchar_t *n;
|
||||||
|
unsigned int ccode, flags;
|
||||||
|
for (; start < end; start = n)
|
||||||
|
{
|
||||||
|
n = Font_Decode(start, &flags, &ccode);
|
||||||
|
if (ccode == ' ' || ccode == '\t')
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
static void Con_Editor_LineChanged_Shader(conline_t *line)
|
||||||
|
{
|
||||||
|
static const char *maplines[] = {"map", "clampmap"};
|
||||||
|
size_t i;
|
||||||
|
conchar_t *start = (conchar_t*)(line+1), *end = start + line->length, *n;
|
||||||
|
|
||||||
|
start = Con_Editor_SkipWhite(start, end);
|
||||||
|
|
||||||
|
line->flags &= ~(CONL_BREAKPOINT|CONL_EXECUTION);
|
||||||
|
|
||||||
|
for (i = 0; i < countof(maplines); i++)
|
||||||
|
{
|
||||||
|
n = Con_Editor_Equals(start, end, maplines[i]);
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
char mapname[8192];
|
||||||
|
char fname[MAX_QPATH];
|
||||||
|
flocation_t loc;
|
||||||
|
unsigned int flags;
|
||||||
|
image_t img;
|
||||||
|
memset(&img, 0, sizeof(img));
|
||||||
|
img.ident = mapname;
|
||||||
|
COM_DeFunString(n, end, mapname, sizeof(mapname), true, true);
|
||||||
|
if (!Image_LocateHighResTexture(&img, &loc, fname, sizeof(fname), &flags))
|
||||||
|
line->flags |= CONL_BREAKPOINT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void Con_Editor_LineChanged(console_t *con, conline_t *line)
|
||||||
|
{
|
||||||
|
if (!Q_strncasecmp(con->name, "scripts/", 8))
|
||||||
|
Con_Editor_LineChanged_Shader(line);
|
||||||
|
}
|
||||||
qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
||||||
{
|
{
|
||||||
extern qboolean keydown[K_MAX];
|
extern qboolean keydown[K_MAX];
|
||||||
|
@ -430,6 +510,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
||||||
con->useroffset--;
|
con->useroffset--;
|
||||||
memmove((conchar_t*)(con->userline+1)+con->useroffset, (conchar_t*)(con->userline+1)+con->useroffset+1, (con->userline->length - con->useroffset)*sizeof(conchar_t));
|
memmove((conchar_t*)(con->userline+1)+con->useroffset, (conchar_t*)(con->userline+1)+con->useroffset+1, (con->userline->length - con->useroffset)*sizeof(conchar_t));
|
||||||
con->userline->length -= 1;
|
con->userline->length -= 1;
|
||||||
|
Con_Editor_LineChanged(con, con->userline);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case K_DEL:
|
case K_DEL:
|
||||||
|
@ -444,6 +525,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
||||||
{
|
{
|
||||||
memmove((conchar_t*)(con->userline+1)+con->useroffset, (conchar_t*)(con->userline+1)+con->useroffset+1, (con->userline->length - con->useroffset)*sizeof(conchar_t));
|
memmove((conchar_t*)(con->userline+1)+con->useroffset, (conchar_t*)(con->userline+1)+con->useroffset+1, (con->userline->length - con->useroffset)*sizeof(conchar_t));
|
||||||
con->userline->length -= 1;
|
con->userline->length -= 1;
|
||||||
|
Con_Editor_LineChanged(con, con->userline);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case K_ENTER: /*split the line into two, selecting the new line*/
|
case K_ENTER: /*split the line into two, selecting the new line*/
|
||||||
|
@ -553,7 +635,7 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
||||||
// "F12: Go to definition\n"
|
// "F12: Go to definition\n"
|
||||||
);
|
);
|
||||||
Cbuf_AddText("toggleconsole\n", RESTRICT_LOCAL);
|
Cbuf_AddText("toggleconsole\n", RESTRICT_LOCAL);
|
||||||
break;
|
return true;
|
||||||
case K_F2:
|
case K_F2:
|
||||||
/*{
|
/*{
|
||||||
char file[1024];
|
char file[1024];
|
||||||
|
@ -721,7 +803,10 @@ qboolean Con_Editor_Key(console_t *con, unsigned int unicode, int key)
|
||||||
if (con->flags & CONF_KEEPSELECTION)
|
if (con->flags & CONF_KEEPSELECTION)
|
||||||
Con_Editor_DeleteSelection(con);
|
Con_Editor_DeleteSelection(con);
|
||||||
if (Con_InsertConChars(con, con->userline, con->useroffset, c, l))
|
if (Con_InsertConChars(con, con->userline, con->useroffset, c, l))
|
||||||
|
{
|
||||||
con->useroffset += l;
|
con->useroffset += l;
|
||||||
|
Con_Editor_LineChanged(con, con->userline);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -782,6 +867,7 @@ console_t *Con_TextEditor(const char *fname, const char *line, qboolean newfile)
|
||||||
{
|
{
|
||||||
static int editorcascade;
|
static int editorcascade;
|
||||||
console_t *con;
|
console_t *con;
|
||||||
|
conline_t *l;
|
||||||
con = Con_FindConsole(fname);
|
con = Con_FindConsole(fname);
|
||||||
if (con)
|
if (con)
|
||||||
{
|
{
|
||||||
|
@ -820,7 +906,7 @@ console_t *Con_TextEditor(const char *fname, const char *line, qboolean newfile)
|
||||||
con->redirect = Con_Editor_Key;
|
con->redirect = Con_Editor_Key;
|
||||||
con->mouseover = Con_Editor_MouseOver;
|
con->mouseover = Con_Editor_MouseOver;
|
||||||
con->close = Con_Editor_Close;
|
con->close = Con_Editor_Close;
|
||||||
con->maxlines = 0x7fffffff; //line limit is effectively unbounded.
|
con->maxlines = 0x7fffffff; //line limit is effectively unbounded, for a 31-bit process.
|
||||||
|
|
||||||
if (!newfile)
|
if (!newfile)
|
||||||
{
|
{
|
||||||
|
@ -835,6 +921,9 @@ console_t *Con_TextEditor(const char *fname, const char *line, qboolean newfile)
|
||||||
}
|
}
|
||||||
VFS_CLOSE(file);
|
VFS_CLOSE(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (l = con->oldest; l; l = l->newer)
|
||||||
|
Con_Editor_LineChanged(con, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
con->display = con->oldest;
|
con->display = con->oldest;
|
||||||
|
|
|
@ -96,7 +96,7 @@ static void Validation_Version(void)
|
||||||
{
|
{
|
||||||
signed_buffer_t *resp;
|
signed_buffer_t *resp;
|
||||||
|
|
||||||
resp = Security_Generate_Crc(cl.playerview[0].playernum, cl.players[cl.playerview[0].playernum].userinfo, cl.serverinfo);
|
resp = NULL;//Security_Generate_Crc(cl.playerview[0].playernum, cl.players[cl.playerview[0].playernum].userinfo, cl.serverinfo);
|
||||||
if (!resp || !resp->buf)
|
if (!resp || !resp->buf)
|
||||||
auth = "";
|
auth = "";
|
||||||
else
|
else
|
||||||
|
@ -186,7 +186,7 @@ void Validation_CheckIfResponse(char *text)
|
||||||
{
|
{
|
||||||
signed_buffer_t *resp;
|
signed_buffer_t *resp;
|
||||||
|
|
||||||
resp = Security_Verify_Response(f_query_client, crc, cl.players[f_query_client].userinfo, cl.serverinfo);
|
resp = NULL;//Security_Verify_Response(f_query_client, crc, cl.players[f_query_client].userinfo, cl.serverinfo);
|
||||||
|
|
||||||
if (resp && resp->size && *resp->buf)
|
if (resp && resp->size && *resp->buf)
|
||||||
Con_Printf(CON_NOTICE "Authentication Successful.\n");
|
Con_Printf(CON_NOTICE "Authentication Successful.\n");
|
||||||
|
|
|
@ -115,23 +115,3 @@ extern unsigned int d_8to24rgbtable[256];
|
||||||
extern unsigned int d_8to24srgbtable[256];
|
extern unsigned int d_8to24srgbtable[256];
|
||||||
extern unsigned int d_8to24bgrtable[256];
|
extern unsigned int d_8to24bgrtable[256];
|
||||||
extern unsigned int d_quaketo24srgbtable[256];
|
extern unsigned int d_quaketo24srgbtable[256];
|
||||||
|
|
||||||
#ifdef GLQUAKE
|
|
||||||
//called when gamma ramps need to be reapplied
|
|
||||||
qboolean GLVID_ApplyGammaRamps (unsigned int size, unsigned short *ramps);
|
|
||||||
|
|
||||||
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette);
|
|
||||||
// Called at startup to set up translation tables, takes 256 8 bit RGB values
|
|
||||||
// the palette data will go away after the call, so it must be copied off if
|
|
||||||
// the video driver will need it again
|
|
||||||
|
|
||||||
void GLVID_Crashed(void);
|
|
||||||
|
|
||||||
void GLVID_Update (vrect_t *rects);
|
|
||||||
// flushes the given rectangles from the view buffer to the screen
|
|
||||||
|
|
||||||
void GLVID_SwapBuffers(void);
|
|
||||||
enum uploadfmt;
|
|
||||||
char *GLVID_GetRGBInfo(int *bytestride, int *truewidth, int *trueheight, enum uploadfmt *fmt);
|
|
||||||
void GLVID_SetCaption(const char *caption);
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ void W_LoadWadFile (char *filename)
|
||||||
if (wad_base)
|
if (wad_base)
|
||||||
Z_Free(wad_base);
|
Z_Free(wad_base);
|
||||||
|
|
||||||
wad_base = COM_LoadFile (filename, 0, NULL);
|
wad_base = COM_LoadFile (filename, 0, 0, NULL);
|
||||||
if (!wad_base)
|
if (!wad_base)
|
||||||
{
|
{
|
||||||
wad_numlumps = 0;
|
wad_numlumps = 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define WINQUAKE_H
|
#define WINQUAKE_H
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
void GLVID_Crashed(void);
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(WIN32)
|
#if defined(_WIN32) && !defined(WIN32)
|
||||||
#define WIN32 _WIN32
|
#define WIN32 _WIN32
|
||||||
|
|
|
@ -727,7 +727,7 @@ static char *Skin_To_TFSkin (char *myskin)
|
||||||
|
|
||||||
static char *Macro_TF_Skin (void)
|
static char *Macro_TF_Skin (void)
|
||||||
{
|
{
|
||||||
return Skin_To_TFSkin(Info_ValueForKey(cl.players[cl.playerview[SP].playernum].userinfo, "skin"));
|
return Skin_To_TFSkin(InfoBuf_ValueForKey(&cl.players[cl.playerview[SP].playernum].userinfo, "skin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Spike: added these:
|
//Spike: added these:
|
||||||
|
@ -1485,7 +1485,7 @@ static void TP_LoadLocFile (char *filename, qbool quiet)
|
||||||
Q_snprintfz (fullpath, sizeof(fullpath) - 4, "locs/%s", filename);
|
Q_snprintfz (fullpath, sizeof(fullpath) - 4, "locs/%s", filename);
|
||||||
COM_DefaultExtension (fullpath, ".loc", sizeof(fullpath));
|
COM_DefaultExtension (fullpath, ".loc", sizeof(fullpath));
|
||||||
|
|
||||||
buf = (char *) COM_LoadTempFile (fullpath, NULL);
|
buf = (char *) COM_LoadTempFile (fullpath, 0, NULL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
|
@ -3189,19 +3189,19 @@ char *Utils_TF_ColorToTeam(int color)
|
||||||
switch (color)
|
switch (color)
|
||||||
{
|
{
|
||||||
case 13:
|
case 13:
|
||||||
if (*(s = Info_ValueForKey(cl.serverinfo, "team1")) || *(s = Info_ValueForKey(cl.serverinfo, "t1")))
|
if (*(s = InfoBuf_ValueForKey(&cl.serverinfo, "team1")) || *(s = InfoBuf_ValueForKey(&cl.serverinfo, "t1")))
|
||||||
return s;
|
return s;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (*(s = Info_ValueForKey(cl.serverinfo, "team2")) || *(s = Info_ValueForKey(cl.serverinfo, "t2")))
|
if (*(s = InfoBuf_ValueForKey(&cl.serverinfo, "team2")) || *(s = InfoBuf_ValueForKey(&cl.serverinfo, "t2")))
|
||||||
return s;
|
return s;
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
if (*(s = Info_ValueForKey(cl.serverinfo, "team3")) || *(s = Info_ValueForKey(cl.serverinfo, "t3")))
|
if (*(s = InfoBuf_ValueForKey(&cl.serverinfo, "team3")) || *(s = InfoBuf_ValueForKey(&cl.serverinfo, "t3")))
|
||||||
return s;
|
return s;
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
if (*(s = Info_ValueForKey(cl.serverinfo, "team4")) || *(s = Info_ValueForKey(cl.serverinfo, "t4")))
|
if (*(s = InfoBuf_ValueForKey(&cl.serverinfo, "team4")) || *(s = InfoBuf_ValueForKey(&cl.serverinfo, "t4")))
|
||||||
return s;
|
return s;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -3343,7 +3343,7 @@ static void TP_FindPoint (void)
|
||||||
name = tp_name_enemy.string;
|
name = tp_name_enemy.string;
|
||||||
|
|
||||||
if (!eyes)
|
if (!eyes)
|
||||||
name = va("%s%s%s", name, name[0] ? " " : "", Skin_To_TFSkin(Info_ValueForKey(bestinfo->userinfo, "skin")));
|
name = va("%s%s%s", name, name[0] ? " " : "", Skin_To_TFSkin(InfoBuf_ValueForKey(&bestinfo->userinfo, "skin")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -725,7 +725,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if (defined(CSQC_DAT) || !defined(CLIENTONLY)) && defined(PLUGINS) //use ode only if we have a constant world state, and the library is enbled in some form.
|
#if (defined(CSQC_DAT) || !defined(CLIENTONLY)) && (defined(PLUGINS)||defined(USE_INTERNAL_BULLET)||defined(USE_INTERNAL_ODE)) //use ode only if we have a constant world state, and the library is enbled in some form.
|
||||||
#define USERBE
|
#define USERBE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -2336,7 +2336,7 @@ void Cmd_Complete_End(cmd_completion_t *c)
|
||||||
int QDECL Cmd_Complete_Sort(const void *a, const void *b)
|
int QDECL Cmd_Complete_Sort(const void *a, const void *b)
|
||||||
{ //FIXME: its possible that they're equal (eg: filesystem searches). we should strip one in that case, but gah.
|
{ //FIXME: its possible that they're equal (eg: filesystem searches). we should strip one in that case, but gah.
|
||||||
const struct cmd_completion_opt_s *c1 = a, *c2 = b;
|
const struct cmd_completion_opt_s *c1 = a, *c2 = b;
|
||||||
return strcmp(c1->text, c2->text);
|
return Q_strcasecmp(c1->text, c2->text);
|
||||||
}
|
}
|
||||||
cmd_completion_t *Cmd_Complete(const char *partial, qboolean caseinsens)
|
cmd_completion_t *Cmd_Complete(const char *partial, qboolean caseinsens)
|
||||||
{
|
{
|
||||||
|
@ -2351,7 +2351,7 @@ cmd_completion_t *Cmd_Complete(const char *partial, qboolean caseinsens)
|
||||||
qboolean quoted = false;
|
qboolean quoted = false;
|
||||||
|
|
||||||
static cmd_completion_t c;
|
static cmd_completion_t c;
|
||||||
|
|
||||||
if (!partial)
|
if (!partial)
|
||||||
{
|
{
|
||||||
Cmd_Complete_End(&c);
|
Cmd_Complete_End(&c);
|
||||||
|
@ -2725,7 +2725,7 @@ void Cmd_ExecuteString (const char *text, int level)
|
||||||
return; //let the csqc handle it if it wants.
|
return; //let the csqc handle it if it wants.
|
||||||
#endif
|
#endif
|
||||||
#if defined(MENU_NATIVECODE)
|
#if defined(MENU_NATIVECODE)
|
||||||
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, cmd_argv))
|
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, (char const*const*)cmd_argv))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
Cmd_ForwardToServer ();
|
Cmd_ForwardToServer ();
|
||||||
|
@ -2890,7 +2890,7 @@ void Cmd_ExecuteString (const char *text, int level)
|
||||||
return; //let the csqc handle it if it wants.
|
return; //let the csqc handle it if it wants.
|
||||||
#endif
|
#endif
|
||||||
#if defined(MENU_NATIVECODE)
|
#if defined(MENU_NATIVECODE)
|
||||||
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, cmd_argv))
|
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, (char const*const*)cmd_argv))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b)
|
||||||
{
|
{
|
||||||
char st[40];
|
char st[40];
|
||||||
Q_snprintfz(st, sizeof(st), "%d", (int) a);
|
Q_snprintfz(st, sizeof(st), "%d", (int) a);
|
||||||
if (strcmp(st, Info_ValueForKey(cls.userinfo[0], ctx)))
|
if (strcmp(st, InfoBuf_ValueForKey(&cls.userinfo[0], ctx)))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey (cls.userinfo[0], ctx, st, sizeof(cls.userinfo[0]));
|
InfoBuf_SetKey(&cls.userinfo[0], ctx, st);
|
||||||
if (cls.state >= ca_connected && (cls.protocol == CP_QUAKEWORLD || (cls.fteprotocolextensions2 & PEXT2_PREDINFO)))
|
if (cls.state >= ca_connected && (cls.protocol == CP_QUAKEWORLD || (cls.fteprotocolextensions2 & PEXT2_PREDINFO)))
|
||||||
CL_SendClientCommand(true, "setinfo %s %s", (char*)ctx, st);
|
CL_SendClientCommand(true, "setinfo %s %s", (char*)ctx, st);
|
||||||
}
|
}
|
||||||
|
@ -2571,7 +2571,7 @@ static frameinfo_t *ParseFrameInfo(char *modelname, int *numgroups)
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
com_tokentype_t ttype;
|
com_tokentype_t ttype;
|
||||||
Q_snprintfz(fname, sizeof(fname), "%s.framegroups", modelname);
|
Q_snprintfz(fname, sizeof(fname), "%s.framegroups", modelname);
|
||||||
line = file = COM_LoadFile(fname, 5, &fsize);
|
line = file = FS_LoadMallocFile(fname, &fsize);
|
||||||
if (!file)
|
if (!file)
|
||||||
return NULL;
|
return NULL;
|
||||||
while(line && *line)
|
while(line && *line)
|
||||||
|
@ -2650,7 +2650,7 @@ static qboolean Mod_ParseModelEvents(model_t *mod, galiasanimation_t *anims, uns
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
char *line, *file, *eol;
|
char *line, *file, *eol;
|
||||||
Q_snprintfz(fname, sizeof(fname), "%s.events", modelname);
|
Q_snprintfz(fname, sizeof(fname), "%s.events", modelname);
|
||||||
line = file = COM_LoadFile(fname, 5, &fsize);
|
line = file = FS_LoadMallocFile(fname, &fsize);
|
||||||
if (!file)
|
if (!file)
|
||||||
return false;
|
return false;
|
||||||
while(line && *line)
|
while(line && *line)
|
||||||
|
@ -3914,7 +3914,7 @@ int Mod_ReadFlagsFromMD1(char *name, int md3version)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinmodel = (dmdl_t *)COM_LoadFile(fname, 5, &fsize);
|
pinmodel = (dmdl_t *)FS_LoadMallocFile(fname, &fsize);
|
||||||
if (pinmodel)
|
if (pinmodel)
|
||||||
{
|
{
|
||||||
if (fsize >= sizeof(dmdl_t) && LittleLong(pinmodel->ident) == IDPOLYHEADER)
|
if (fsize >= sizeof(dmdl_t) && LittleLong(pinmodel->ident) == IDPOLYHEADER)
|
||||||
|
@ -5812,7 +5812,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
|
||||||
COM_StripExtension(mod->name, psaname, sizeof(psaname));
|
COM_StripExtension(mod->name, psaname, sizeof(psaname));
|
||||||
Q_strncatz(psaname, ".psa", sizeof(psaname));
|
Q_strncatz(psaname, ".psa", sizeof(psaname));
|
||||||
buffer = NULL;//test
|
buffer = NULL;//test
|
||||||
psabuffer = COM_LoadFile(psaname, 5, &psasize);
|
psabuffer = FS_LoadMallocFile(psaname, &psasize);
|
||||||
if (psabuffer)
|
if (psabuffer)
|
||||||
{
|
{
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -362,7 +362,7 @@ void deleetstring(char *result, const char *leet);
|
||||||
|
|
||||||
extern char com_token[65536];
|
extern char com_token[65536];
|
||||||
|
|
||||||
typedef enum {TTP_UNKNOWN, TTP_STRING, TTP_LINEENDING, TTP_RAWTOKEN, TTP_EOF, TTP_PUNCTUATION} com_tokentype_t;
|
typedef enum com_tokentype_e {TTP_UNKNOWN, TTP_STRING, TTP_LINEENDING, TTP_RAWTOKEN, TTP_EOF, TTP_PUNCTUATION} com_tokentype_t;
|
||||||
extern com_tokentype_t com_tokentype;
|
extern com_tokentype_t com_tokentype;
|
||||||
|
|
||||||
//these cast away the const for the return value.
|
//these cast away the const for the return value.
|
||||||
|
@ -616,7 +616,7 @@ vfsfile_t *CL_OpenFileInPackage(searchpathfuncs_t *search, char *name);
|
||||||
qboolean CL_ListFilesInPackage(searchpathfuncs_t *search, char *name, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm, void *recursioninfo);
|
qboolean CL_ListFilesInPackage(searchpathfuncs_t *search, char *name, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm, void *recursioninfo);
|
||||||
|
|
||||||
qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, size_t *fsize);
|
qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, size_t *fsize);
|
||||||
qbyte *COM_LoadTempFile (const char *path, size_t *fsize);
|
qbyte *COM_LoadTempFile (const char *path, unsigned int locateflags, size_t *fsize);
|
||||||
qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize); //allocates a little bit more without freeing old temp
|
qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize); //allocates a little bit more without freeing old temp
|
||||||
//qbyte *COM_LoadHunkFile (const char *path);
|
//qbyte *COM_LoadHunkFile (const char *path);
|
||||||
|
|
||||||
|
@ -704,7 +704,7 @@ qbyte *FS_LoadMallocFile (const char *path, size_t *fsize);
|
||||||
qofs_t FS_LoadFile(const char *name, void **file);
|
qofs_t FS_LoadFile(const char *name, void **file);
|
||||||
void FS_FreeFile(void *file);
|
void FS_FreeFile(void *file);
|
||||||
|
|
||||||
qbyte *COM_LoadFile (const char *path, int usehunk, size_t *filesize);
|
qbyte *COM_LoadFile (const char *path, unsigned int locateflags, int usehunk, size_t *filesize);
|
||||||
|
|
||||||
qboolean COM_LoadMapPackFile(const char *name, qofs_t offset);
|
qboolean COM_LoadMapPackFile(const char *name, qofs_t offset);
|
||||||
void COM_FlushTempoaryPacks(void);
|
void COM_FlushTempoaryPacks(void);
|
||||||
|
@ -724,15 +724,79 @@ unsigned int COM_RemapMapChecksum(struct model_s *model, unsigned int checksum);
|
||||||
|
|
||||||
#define MAX_INFO_KEY 256
|
#define MAX_INFO_KEY 256
|
||||||
char *Info_ValueForKey (const char *s, const char *key);
|
char *Info_ValueForKey (const char *s, const char *key);
|
||||||
void Info_RemoveKey (char *s, const char *key);
|
|
||||||
char *Info_KeyForNumber (const char *s, int num);
|
|
||||||
void Info_RemovePrefixedKeys (char *start, char prefix);
|
|
||||||
void Info_RemoveNonStarKeys (char *start);
|
|
||||||
void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize);
|
void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize);
|
||||||
void Info_SetValueForStarKey (char *s, const char *key, const char *value, int maxsize);
|
void Info_SetValueForStarKey (char *s, const char *key, const char *value, int maxsize);
|
||||||
|
void Info_RemovePrefixedKeys (char *start, char prefix);
|
||||||
|
void Info_RemoveKey (char *s, const char *key);
|
||||||
|
char *Info_KeyForNumber (const char *s, int num);
|
||||||
void Info_Print (const char *s, const char *lineprefix);
|
void Info_Print (const char *s, const char *lineprefix);
|
||||||
|
/*
|
||||||
|
void Info_RemoveNonStarKeys (char *start);
|
||||||
void Info_Enumerate (const char *s, void *ctx, void(*cb)(void *ctx, const char *key, const char *value));
|
void Info_Enumerate (const char *s, void *ctx, void(*cb)(void *ctx, const char *key, const char *value));
|
||||||
void Info_WriteToFile(vfsfile_t *f, char *info, char *commandname, int cvarflags);
|
void Info_WriteToFile(vfsfile_t *f, char *info, char *commandname, int cvarflags);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Info Buffers
|
||||||
|
Keynames are still length limited, and may not contain nulls, but neither restriction applies to values.
|
||||||
|
Using base64 encoding, we're able to encode problematic chars like quotes and newlines (and nulls).
|
||||||
|
This allows mods to store image files inside userinfo.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct infokey_s
|
||||||
|
{
|
||||||
|
qbyte partial:1; //partial values read as "".
|
||||||
|
qbyte large:1; //requires partial/encoded transmission
|
||||||
|
char *name;
|
||||||
|
size_t size;
|
||||||
|
size_t buffersize; //to avoid excessive reallocs
|
||||||
|
char *value;
|
||||||
|
} *keys;
|
||||||
|
size_t numkeys;
|
||||||
|
size_t totalsize; //so we can limit userinfo abuse.
|
||||||
|
|
||||||
|
void (*ChangeCB)(void *context, const char *key); //usually calls InfoSync_Add on all the interested parties.
|
||||||
|
void *ChangeCTX;
|
||||||
|
} infobuf_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
void *context;
|
||||||
|
char *name;
|
||||||
|
size_t syncpos; //reset to 0 when dirty.
|
||||||
|
} *keys;
|
||||||
|
size_t numkeys;
|
||||||
|
} infosync_t;
|
||||||
|
void InfoSync_Remove(infosync_t *sync, size_t k);
|
||||||
|
void InfoSync_Add(infosync_t *sync, void *context, const char *name);
|
||||||
|
void InfoSync_Clear(infosync_t *sync); //wipes all memory etc.
|
||||||
|
void InfoSync_Strip(infosync_t *sync, void *context); //Clears away all infos from that context.
|
||||||
|
extern const char *basicuserinfos[]; //note: has a leading *
|
||||||
|
extern const char *privateuserinfos[]; //key names that are not broadcast from the server
|
||||||
|
qboolean InfoBuf_FindKey (infobuf_t *info, const char *key, size_t *idx);
|
||||||
|
const char *InfoBuf_KeyForNumber (infobuf_t *info, int num);
|
||||||
|
const char *InfoBuf_BlobForKey (infobuf_t *info, const char *key, size_t *blobsize);
|
||||||
|
char *InfoBuf_ReadKey (infobuf_t *info, const char *key, char *outbuf, size_t outsize);
|
||||||
|
char *InfoBuf_ValueForKey (infobuf_t *info, const char *key);
|
||||||
|
qboolean InfoBuf_RemoveKey (infobuf_t *info, const char *key);
|
||||||
|
qboolean InfoBuf_SetKey (infobuf_t *info, const char *key, const char *val); //refuses to set *keys.
|
||||||
|
qboolean InfoBuf_SetStarKey (infobuf_t *info, const char *key, const char *val);
|
||||||
|
qboolean InfoBuf_SetStarBlobKey (infobuf_t *info, const char *key, const char *val, size_t valsize);
|
||||||
|
#define InfoBuf_SetValueForKey InfoBuf_SetKey
|
||||||
|
#define InfoBuf_SetValueForStarKey InfoBuf_SetStarKey
|
||||||
|
void InfoBuf_Clear(infobuf_t *info, qboolean all);
|
||||||
|
void InfoBuf_Clone(infobuf_t *dest, infobuf_t *src);
|
||||||
|
void InfoBuf_FromString(infobuf_t *info, const char *infostring, qboolean append);
|
||||||
|
char *InfoBuf_DecodeString(const char *instart, const char *inend, size_t *sz);
|
||||||
|
qboolean InfoBuf_EncodeString(const char *n, size_t s, char *out, size_t outsize);
|
||||||
|
size_t InfoBuf_ToString(infobuf_t *info, char *infostring, size_t maxsize, const char **priority, const char **ignore, const char **exclusive, infosync_t *sync, void *synccontext); //_ and * can be used to indicate ALL such keys.
|
||||||
|
qboolean InfoBuf_SyncReceive (infobuf_t *info, const char *key, size_t keysize, const char *val, size_t valsize, size_t offset, qboolean final);
|
||||||
|
void InfoBuf_Print(infobuf_t *info, const char *prefix);
|
||||||
|
void InfoBuf_WriteToFile(vfsfile_t *f, infobuf_t *info, const char *commandname, int cvarflags);
|
||||||
|
void InfoBuf_Enumerate (infobuf_t *info, void *ctx, void(*cb)(void *ctx, const char *key, const char *value));
|
||||||
|
|
||||||
|
|
||||||
void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf);
|
void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf);
|
||||||
unsigned int Com_BlockChecksum (const void *buffer, int length);
|
unsigned int Com_BlockChecksum (const void *buffer, int length);
|
||||||
|
|
|
@ -156,7 +156,7 @@
|
||||||
// Outdated stuff
|
// Outdated stuff
|
||||||
#define SVRANKING //legacy server-side ranking system.
|
#define SVRANKING //legacy server-side ranking system.
|
||||||
////#define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm.
|
////#define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm.
|
||||||
#define SVCHAT //ancient lame builtin to support NPC-style chat...
|
//#define SVCHAT //ancient lame builtin to support NPC-style chat...
|
||||||
////#define SV_MASTER //Support running the server as a master server. Should probably not be used.
|
////#define SV_MASTER //Support running the server as a master server. Should probably not be used.
|
||||||
////#define WEBSERVER //outdated sv_http cvar. new stuff acts via sv_port_tcp instead (which also gives https).
|
////#define WEBSERVER //outdated sv_http cvar. new stuff acts via sv_port_tcp instead (which also gives https).
|
||||||
////#define QUAKESPYAPI //define this if you want the engine to be usable via gamespy/quakespy, which has been dead for a long time now. forces the client to use a single port for all outgoing connections, which hurts reconnects.
|
////#define QUAKESPYAPI //define this if you want the engine to be usable via gamespy/quakespy, which has been dead for a long time now. forces the client to use a single port for all outgoing connections, which hurts reconnects.
|
||||||
|
|
|
@ -154,6 +154,8 @@
|
||||||
#undef HAVE_MEDIA_ENCODER //capture/capturedemo work.
|
#undef HAVE_MEDIA_ENCODER //capture/capturedemo work.
|
||||||
#undef HAVE_SPEECHTOTEXT //windows speech-to-text thing
|
#undef HAVE_SPEECHTOTEXT //windows speech-to-text thing
|
||||||
|
|
||||||
|
//#define USE_INTERNAL_BULLET
|
||||||
|
|
||||||
#ifdef COMPILE_OPTS
|
#ifdef COMPILE_OPTS
|
||||||
//things to configure qclib, which annoyingly doesn't include this file itself
|
//things to configure qclib, which annoyingly doesn't include this file itself
|
||||||
-DOMIT_QCC //disable the built-in qcc
|
-DOMIT_QCC //disable the built-in qcc
|
||||||
|
@ -162,6 +164,10 @@
|
||||||
-DNO_ZLIB //disable zlib
|
-DNO_ZLIB //disable zlib
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_INTERNAL_BULLET //makefile will respond to this by trying to link bullet into the engine itself, instead of as a plugin.
|
||||||
|
-DLINK_INTERNAL_BULLET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
-DNO_SPEEX //disable static speex
|
-DNO_SPEEX //disable static speex
|
||||||
#ifndef BOTLIB_STATIC
|
#ifndef BOTLIB_STATIC
|
||||||
|
|
|
@ -784,13 +784,7 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
if (var->flags & CVAR_SERVERINFO)
|
if (var->flags & CVAR_SERVERINFO)
|
||||||
{
|
{
|
||||||
// char *old = Info_ValueForKey(svs.info, var->name);
|
InfoBuf_SetKey (&svs.info, var->name, value);
|
||||||
// if (strcmp(old, value)) //only spam the server if it actually changed
|
|
||||||
{
|
|
||||||
Info_SetValueForKey (svs.info, var->name, value, MAX_SERVERINFO_STRING);
|
|
||||||
SV_SendServerInfoChange(var->name, value);
|
|
||||||
// SV_BroadcastCommand ("fullserverinfo \"%s\"\n", svs.info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
|
@ -802,23 +796,10 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
||||||
}
|
}
|
||||||
if (var->flags & CVAR_USERINFO)
|
if (var->flags & CVAR_USERINFO)
|
||||||
{
|
{
|
||||||
char *old = Info_ValueForKey(cls.userinfo[0], var->name);
|
char *old = InfoBuf_ValueForKey(&cls.userinfo[0], var->name);
|
||||||
if (strcmp(old, value)) //only spam the server if it actually changed
|
if (strcmp(old, value)) //only spam the server if it actually changed
|
||||||
{ //this helps with config execs
|
{ //this helps with config execs
|
||||||
Info_SetValueForKey (cls.userinfo[0], var->name, value, sizeof(cls.userinfo[0]));
|
InfoBuf_SetKey (&cls.userinfo[0], var->name, value);
|
||||||
if (cls.state >= ca_connected)
|
|
||||||
{
|
|
||||||
#if defined(Q2CLIENT) || defined(Q3CLIENT)
|
|
||||||
if (cls.protocol == CP_QUAKE2 || cls.protocol == CP_QUAKE3) //q2 just resends the lot. Kinda bad...
|
|
||||||
{
|
|
||||||
cls.resendinfo = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
CL_SendClientCommand(true, "setinfo \"%s\" \"%s\"\n", var->name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2138,14 +2138,16 @@ Filename are reletive to the quake directory.
|
||||||
Always appends a 0 qbyte to the loaded data.
|
Always appends a 0 qbyte to the loaded data.
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
qbyte *COM_LoadFile (const char *path, int usehunk, size_t *filesize)
|
qbyte *COM_LoadFile (const char *path, unsigned int locateflags, int usehunk, size_t *filesize)
|
||||||
{
|
{
|
||||||
vfsfile_t *f;
|
vfsfile_t *f;
|
||||||
qbyte *buf;
|
qbyte *buf;
|
||||||
qofs_t len;
|
qofs_t len;
|
||||||
flocation_t loc;
|
flocation_t loc;
|
||||||
|
|
||||||
if (!FS_FLocateFile(path, FSLF_IFFOUND, &loc) || !loc.search)
|
locateflags &= ~FSLF_DEEPONFAILURE; //disable any flags that can't be supported here
|
||||||
|
|
||||||
|
if (!FS_FLocateFile(path, locateflags, &loc) || !loc.search)
|
||||||
return NULL; //wasn't found
|
return NULL; //wasn't found
|
||||||
|
|
||||||
if (loc.len > 0x7fffffff) //don't malloc 5000gb sparse files or anything crazy on a 32bit system...
|
if (loc.len > 0x7fffffff) //don't malloc 5000gb sparse files or anything crazy on a 32bit system...
|
||||||
|
@ -2198,7 +2200,7 @@ qbyte *COM_LoadFile (const char *path, int usehunk, size_t *filesize)
|
||||||
|
|
||||||
qbyte *FS_LoadMallocFile (const char *path, size_t *fsize)
|
qbyte *FS_LoadMallocFile (const char *path, size_t *fsize)
|
||||||
{
|
{
|
||||||
return COM_LoadFile (path, 5, fsize);
|
return COM_LoadFile (path, 0, 5, fsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize)
|
void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize)
|
||||||
|
@ -2223,13 +2225,13 @@ void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize)
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
qbyte *COM_LoadTempFile (const char *path, size_t *fsize)
|
qbyte *COM_LoadTempFile (const char *path, unsigned int locateflags, size_t *fsize)
|
||||||
{
|
{
|
||||||
return COM_LoadFile (path, 2, fsize);
|
return COM_LoadFile (path, locateflags, 2, fsize);
|
||||||
}
|
}
|
||||||
qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize)
|
qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize)
|
||||||
{
|
{
|
||||||
return COM_LoadFile (path, 6, fsize);
|
return COM_LoadFile (path, 0, 6, fsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// uses temp hunk if larger than bufsize
|
// uses temp hunk if larger than bufsize
|
||||||
|
@ -2241,7 +2243,7 @@ qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, siz
|
||||||
|
|
||||||
loadbuf = (qbyte *)buffer;
|
loadbuf = (qbyte *)buffer;
|
||||||
loadsize = bufsize;
|
loadsize = bufsize;
|
||||||
buf = COM_LoadFile (path, 4, fsize);
|
buf = COM_LoadFile (path, 0, 4, fsize);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -2251,7 +2253,7 @@ qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, siz
|
||||||
qofs_t FS_LoadFile(const char *name, void **file)
|
qofs_t FS_LoadFile(const char *name, void **file)
|
||||||
{
|
{
|
||||||
size_t fsz;
|
size_t fsz;
|
||||||
*file = COM_LoadFile (name, 5, &fsz);
|
*file = FS_LoadMallocFile (name, &fsz);
|
||||||
if (!*file)
|
if (!*file)
|
||||||
return (qofs_t)-1;
|
return (qofs_t)-1;
|
||||||
return fsz;
|
return fsz;
|
||||||
|
@ -3119,8 +3121,8 @@ const gamemode_info_t gamemode_info[] = {
|
||||||
#ifndef NOLEGACY
|
#ifndef NOLEGACY
|
||||||
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
|
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
|
||||||
//two quakes - one without extra game dirs which should avoid fuckups from nquake's configs (which screw over cvars that every nq progs.dat depends upon but which the ezquake id1-only less-compatible gamecode ignores).
|
//two quakes - one without extra game dirs which should avoid fuckups from nquake's configs (which screw over cvars that every nq progs.dat depends upon but which the ezquake id1-only less-compatible gamecode ignores).
|
||||||
{"-quake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
{"-quake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||||
{"-netquake", "nq", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
{"-netquake", "nq", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1"}, "Quake", "https://triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||||
//quake's mission packs should not be favoured over the base game nor autodetected
|
//quake's mission packs should not be favoured over the base game nor autodetected
|
||||||
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.
|
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.
|
||||||
//and q2 also has a rogue/pak0.pak file that we don't want to find and cause quake2 to look like dissolution of eternity
|
//and q2 also has a rogue/pak0.pak file that we don't want to find and cause quake2 to look like dissolution of eternity
|
||||||
|
|
|
@ -1,6 +1,44 @@
|
||||||
#include "quakedef.h"
|
#include "quakedef.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
|
//#define AVAIL_BZLIB
|
||||||
|
//#define DYNAMIC_BZLIB
|
||||||
|
|
||||||
|
#ifdef AVAIL_BZLIB
|
||||||
|
# include <bzlib.h>
|
||||||
|
# ifdef DYNAMIC_BZLIB
|
||||||
|
# ifndef WINAPI
|
||||||
|
# define WINAPI
|
||||||
|
# endif
|
||||||
|
# define BZ2_bzDecompressInit pBZ2_bzDecompressInit
|
||||||
|
# define BZ2_bzDecompress pBZ2_bzDecompress
|
||||||
|
# define BZ2_bzDecompressEnd pBZ2_bzDecompressEnd
|
||||||
|
static int (WINAPI *BZ2_bzDecompressInit)(bz_stream *strm, int verbosity, int small);
|
||||||
|
static int (WINAPI *BZ2_bzDecompress)(bz_stream* strm);
|
||||||
|
static int (WINAPI *BZ2_bzDecompressEnd)(bz_stream *strm);
|
||||||
|
static qboolean BZLIB_LOADED(void)
|
||||||
|
{
|
||||||
|
static qboolean tried;
|
||||||
|
static void *handle;
|
||||||
|
if (!tried)
|
||||||
|
{
|
||||||
|
static dllfunction_t funcs[] =
|
||||||
|
{
|
||||||
|
{(void*)&BZ2_bzDecompressInit, "BZ2_bzDecompressInit"},
|
||||||
|
{(void*)&BZ2_bzDecompress, "BZ2_bzDecompress"},
|
||||||
|
{(void*)&BZ2_bzDecompressEnd, "BZ2_bzDecompressEnd"},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
tried = true;
|
||||||
|
handle = Sys_LoadLibrary("libbz2", funcs);
|
||||||
|
}
|
||||||
|
return handle != NULL;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# define BZLIB_LOADED() 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef AVAIL_ZLIB
|
#ifdef AVAIL_ZLIB
|
||||||
# define ZIPCRYPT
|
# define ZIPCRYPT
|
||||||
|
|
||||||
|
@ -504,9 +542,6 @@ vfsfile_t *FS_GZ_WriteFilter(vfsfile_t *outfile, qboolean autoclosefile, qboolea
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PACKAGE_PK3
|
#ifdef PACKAGE_PK3
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -520,11 +555,12 @@ typedef struct
|
||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
} zpackfile_t;
|
} zpackfile_t;
|
||||||
#define ZFL_DEFLATED 1 //need to use zlib
|
#define ZFL_DEFLATED (1u<<0) //need to use zlib
|
||||||
#define ZFL_STORED 2 //direct access is okay
|
#define ZFL_BZIP2 (1u<<1) //bzip2 compression
|
||||||
#define ZFL_SYMLINK 4 //file is a symlink
|
#define ZFL_STORED (1u<<2) //direct access is okay
|
||||||
#define ZFL_CORRUPT 8 //file is corrupt or otherwise unreadable (usually just means we don't support reading it rather than actually corrupt, but hey).
|
#define ZFL_SYMLINK (1u<<3) //file is a symlink
|
||||||
#define ZFL_WEAKENCRYPT 16 //traditional zip encryption
|
#define ZFL_CORRUPT (1u<<4) //file is corrupt or otherwise unreadable (usually just means we don't support reading it rather than actually corrupt, but hey).
|
||||||
|
#define ZFL_WEAKENCRYPT (1u<<5) //traditional zip encryption
|
||||||
|
|
||||||
|
|
||||||
typedef struct zipfile_s
|
typedef struct zipfile_s
|
||||||
|
@ -712,9 +748,12 @@ static int QDECL FSZIP_GeneratePureCRC(searchpathfuncs_t *handle, int seed, int
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AVAIL_ZLIB
|
|
||||||
struct decompressstate
|
struct decompressstate
|
||||||
{
|
{
|
||||||
|
struct decompressstate *(*Reinit)(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc);
|
||||||
|
qofs_t (*Read)(struct decompressstate *st, qbyte *buffer, qofs_t bytes);
|
||||||
|
void (*Destroy)(struct decompressstate *st);
|
||||||
|
|
||||||
zipfile_t *source;
|
zipfile_t *source;
|
||||||
qofs_t cstart; //position of start of data
|
qofs_t cstart; //position of start of data
|
||||||
qofs_t cofs; //current read offset
|
qofs_t cofs; //current read offset
|
||||||
|
@ -731,9 +770,16 @@ struct decompressstate
|
||||||
const z_crc_t * crctable;
|
const z_crc_t * crctable;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef AVAIL_ZLIB
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
|
#endif
|
||||||
|
#ifdef AVAIL_BZLIB
|
||||||
|
bz_stream bstrm;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(AVAIL_ZLIB) || defined(AVAIL_BZLIB)
|
||||||
|
|
||||||
#ifdef ZIPCRYPT
|
#ifdef ZIPCRYPT
|
||||||
#define CRC32(c, b) ((*(st->crctable+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
|
#define CRC32(c, b) ((*(st->crctable+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
|
||||||
|
|
||||||
|
@ -791,47 +837,8 @@ static void FSZIP_DecryptBlock(struct decompressstate *st, char *block, size_t b
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct decompressstate *FSZIP_Decompress_Init(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc)
|
#ifdef AVAIL_ZLIB
|
||||||
{
|
static qofs_t FSZIP_Deflate_Read(struct decompressstate *st, qbyte *buffer, qofs_t bytes)
|
||||||
struct decompressstate *st;
|
|
||||||
if (!ZLIB_LOADED())
|
|
||||||
{
|
|
||||||
Con_Printf("zlib not available\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
st = Z_Malloc(sizeof(*st));
|
|
||||||
st->source = source;
|
|
||||||
|
|
||||||
#ifdef ZIPCRYPT
|
|
||||||
if (password && csize >= 12)
|
|
||||||
{
|
|
||||||
char entropy[12];
|
|
||||||
if (Sys_LockMutex(source->mutex))
|
|
||||||
{
|
|
||||||
VFS_SEEK(source->raw, start);
|
|
||||||
VFS_READ(source->raw, entropy, sizeof(entropy));
|
|
||||||
Sys_UnlockMutex(source->mutex);
|
|
||||||
}
|
|
||||||
if (!FSZIP_SetupCrytoKeys(st, password, entropy, crc))
|
|
||||||
{
|
|
||||||
Con_Printf("Invalid password, cannot decrypt %s\n", filename);
|
|
||||||
Z_Free(st);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
start += sizeof(entropy);
|
|
||||||
csize -= sizeof(entropy);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
st->cstart = st->cofs = start;
|
|
||||||
st->cend = start + csize;
|
|
||||||
st->usize = usize;
|
|
||||||
st->strm.data_type = Z_UNKNOWN;
|
|
||||||
qinflateInit2(&st->strm, -MAX_WBITS);
|
|
||||||
return st;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qofs_t FSZIP_Decompress_Read(struct decompressstate *st, qbyte *buffer, qofs_t bytes)
|
|
||||||
{
|
{
|
||||||
qboolean eof = false;
|
qboolean eof = false;
|
||||||
int err;
|
int err;
|
||||||
|
@ -893,11 +900,171 @@ static qofs_t FSZIP_Decompress_Read(struct decompressstate *st, qbyte *buffer, q
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FSZIP_Decompress_Destroy(struct decompressstate *st)
|
static void FSZIP_Deflate_Destroy(struct decompressstate *st)
|
||||||
{
|
{
|
||||||
qinflateEnd(&st->strm);
|
qinflateEnd(&st->strm);
|
||||||
Z_Free(st);
|
Z_Free(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct decompressstate *FSZIP_Deflate_Init(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc)
|
||||||
|
{
|
||||||
|
struct decompressstate *st;
|
||||||
|
if (!ZLIB_LOADED())
|
||||||
|
{
|
||||||
|
Con_Printf("zlib not available\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
st = Z_Malloc(sizeof(*st));
|
||||||
|
st->Reinit = FSZIP_Deflate_Init;
|
||||||
|
st->Read = FSZIP_Deflate_Read;
|
||||||
|
st->Destroy = FSZIP_Deflate_Destroy;
|
||||||
|
st->source = source;
|
||||||
|
|
||||||
|
#ifdef ZIPCRYPT
|
||||||
|
if (password && csize >= 12)
|
||||||
|
{
|
||||||
|
char entropy[12];
|
||||||
|
if (Sys_LockMutex(source->mutex))
|
||||||
|
{
|
||||||
|
VFS_SEEK(source->raw, start);
|
||||||
|
VFS_READ(source->raw, entropy, sizeof(entropy));
|
||||||
|
Sys_UnlockMutex(source->mutex);
|
||||||
|
}
|
||||||
|
if (!FSZIP_SetupCrytoKeys(st, password, entropy, crc))
|
||||||
|
{
|
||||||
|
Con_Printf("Invalid password, cannot decrypt %s\n", filename);
|
||||||
|
Z_Free(st);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
start += sizeof(entropy);
|
||||||
|
csize -= sizeof(entropy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
st->cstart = st->cofs = start;
|
||||||
|
st->cend = start + csize;
|
||||||
|
st->usize = usize;
|
||||||
|
|
||||||
|
st->strm.data_type = Z_UNKNOWN;
|
||||||
|
qinflateInit2(&st->strm, -MAX_WBITS);
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AVAIL_BZLIB
|
||||||
|
static qofs_t FSZIP_BZip2_Read(struct decompressstate *st, qbyte *buffer, qofs_t bytes)
|
||||||
|
{
|
||||||
|
qboolean eof = false;
|
||||||
|
int err;
|
||||||
|
qofs_t read = 0;
|
||||||
|
while(bytes)
|
||||||
|
{
|
||||||
|
if (st->readoffset < st->bstrm.total_out_lo32)
|
||||||
|
{
|
||||||
|
unsigned int consume = st->bstrm.total_out_lo32-st->readoffset;
|
||||||
|
if (consume > bytes)
|
||||||
|
consume = bytes;
|
||||||
|
memcpy(buffer, st->outbuffer+st->readoffset, consume);
|
||||||
|
buffer += consume;
|
||||||
|
bytes -= consume;
|
||||||
|
read += consume;
|
||||||
|
st->readoffset += consume;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (eof)
|
||||||
|
break; //no input available, and nothing in the buffers.
|
||||||
|
|
||||||
|
st->bstrm.total_out_lo32 = 0;
|
||||||
|
st->bstrm.total_out_hi32 = 0;
|
||||||
|
st->bstrm.avail_out = sizeof(st->outbuffer);
|
||||||
|
st->bstrm.next_out = st->outbuffer;
|
||||||
|
st->readoffset = 0;
|
||||||
|
if (!st->bstrm.avail_in)
|
||||||
|
{
|
||||||
|
qofs_t sz;
|
||||||
|
sz = st->cend - st->cofs;
|
||||||
|
if (sz > sizeof(st->inbuffer))
|
||||||
|
sz = sizeof(st->inbuffer);
|
||||||
|
if (sz)
|
||||||
|
{
|
||||||
|
//feed it.
|
||||||
|
if (Sys_LockMutex(st->source->mutex))
|
||||||
|
{
|
||||||
|
VFS_SEEK(st->source->raw, st->cofs);
|
||||||
|
st->bstrm.avail_in = VFS_READ(st->source->raw, st->inbuffer, sz);
|
||||||
|
Sys_UnlockMutex(st->source->mutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
st->bstrm.avail_in = 0;
|
||||||
|
st->bstrm.next_in = st->inbuffer;
|
||||||
|
st->cofs += st->bstrm.avail_in;
|
||||||
|
#ifdef ZIPCRYPT
|
||||||
|
if (st->encrypted)
|
||||||
|
FSZIP_DecryptBlock(st, st->inbuffer, st->bstrm.avail_in);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (!st->bstrm.avail_in)
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
err = BZ2_bzDecompress(&st->bstrm);
|
||||||
|
if (err == BZ_FINISH_OK)
|
||||||
|
eof = true;
|
||||||
|
else if (err < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FSZIP_BZip2_Destroy(struct decompressstate *st)
|
||||||
|
{
|
||||||
|
BZ2_bzDecompressEnd(&st->bstrm);
|
||||||
|
Z_Free(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct decompressstate *FSZIP_BZip2_Init(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc)
|
||||||
|
{
|
||||||
|
struct decompressstate *st;
|
||||||
|
if (!BZLIB_LOADED())
|
||||||
|
{
|
||||||
|
Con_Printf("bzlib not available\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
st = Z_Malloc(sizeof(*st));
|
||||||
|
st->Reinit = FSZIP_BZip2_Init;
|
||||||
|
st->Read = FSZIP_BZip2_Read;
|
||||||
|
st->Destroy = FSZIP_BZip2_Destroy;
|
||||||
|
st->source = source;
|
||||||
|
|
||||||
|
#ifdef ZIPCRYPT
|
||||||
|
if (password && csize >= 12)
|
||||||
|
{
|
||||||
|
char entropy[12];
|
||||||
|
if (Sys_LockMutex(source->mutex))
|
||||||
|
{
|
||||||
|
VFS_SEEK(source->raw, start);
|
||||||
|
VFS_READ(source->raw, entropy, sizeof(entropy));
|
||||||
|
Sys_UnlockMutex(source->mutex);
|
||||||
|
}
|
||||||
|
if (!FSZIP_SetupCrytoKeys(st, password, entropy, crc))
|
||||||
|
{
|
||||||
|
Con_Printf("Invalid password, cannot decrypt %s\n", filename);
|
||||||
|
Z_Free(st);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
start += sizeof(entropy);
|
||||||
|
csize -= sizeof(entropy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
st->cstart = st->cofs = start;
|
||||||
|
st->cend = start + csize;
|
||||||
|
st->usize = usize;
|
||||||
|
|
||||||
|
BZ2_bzDecompressInit(&st->bstrm, 0, false);
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static vfsfile_t *FSZIP_Decompress_ToTempFile(struct decompressstate *decompress)
|
static vfsfile_t *FSZIP_Decompress_ToTempFile(struct decompressstate *decompress)
|
||||||
{ //if they're going to seek on a file in a zip, let's just copy it out
|
{ //if they're going to seek on a file in a zip, let's just copy it out
|
||||||
qofs_t cstart = decompress->cstart, csize = decompress->cend - cstart;
|
qofs_t cstart = decompress->cstart, csize = decompress->cend - cstart;
|
||||||
|
@ -906,61 +1073,48 @@ static vfsfile_t *FSZIP_Decompress_ToTempFile(struct decompressstate *decompress
|
||||||
struct decompressstate *nc;
|
struct decompressstate *nc;
|
||||||
qbyte buffer[16384];
|
qbyte buffer[16384];
|
||||||
vfsfile_t *defer;
|
vfsfile_t *defer;
|
||||||
|
struct decompressstate *(*Reinit)(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc) = decompress->Reinit;
|
||||||
zipfile_t *source = decompress->source;
|
zipfile_t *source = decompress->source;
|
||||||
|
#ifdef ZIPCRYPT //we need to preserve any crypto stuff if we're restarting the stream
|
||||||
qboolean encrypted = decompress->encrypted;
|
qboolean encrypted = decompress->encrypted;
|
||||||
unsigned int cryptkeys[3];
|
unsigned int cryptkeys[3];
|
||||||
const z_crc_t *crctab = decompress->crctable;
|
const z_crc_t *crctab = decompress->crctable;
|
||||||
|
|
||||||
memcpy(cryptkeys, decompress->initialkey, sizeof(cryptkeys));
|
memcpy(cryptkeys, decompress->initialkey, sizeof(cryptkeys));
|
||||||
|
#endif
|
||||||
|
|
||||||
defer = FS_OpenTemp();
|
defer = FS_OpenTemp();
|
||||||
if (defer)
|
if (defer)
|
||||||
{
|
{
|
||||||
FSZIP_Decompress_Destroy(decompress);
|
decompress->Destroy(decompress);
|
||||||
decompress = NULL;
|
decompress = NULL;
|
||||||
|
|
||||||
nc = FSZIP_Decompress_Init(source, cstart, csize, usize, NULL, NULL, 0);
|
nc = Reinit(source, cstart, csize, usize, NULL, NULL, 0);
|
||||||
|
#ifdef ZIPCRYPT
|
||||||
nc->encrypted = encrypted;
|
nc->encrypted = encrypted;
|
||||||
nc->crctable = crctab;
|
nc->crctable = crctab;
|
||||||
memcpy(nc->initialkey, cryptkeys, sizeof(nc->initialkey));
|
memcpy(nc->initialkey, cryptkeys, sizeof(nc->initialkey));
|
||||||
memcpy(nc->cryptkey, cryptkeys, sizeof(nc->cryptkey));
|
memcpy(nc->cryptkey, cryptkeys, sizeof(nc->cryptkey));
|
||||||
|
#endif
|
||||||
|
|
||||||
while (upos < usize)
|
while (upos < usize)
|
||||||
{
|
{
|
||||||
chunk = usize - upos;
|
chunk = usize - upos;
|
||||||
if (chunk > sizeof(buffer))
|
if (chunk > sizeof(buffer))
|
||||||
chunk = sizeof(buffer);
|
chunk = sizeof(buffer);
|
||||||
if (!FSZIP_Decompress_Read(nc, buffer, chunk))
|
if (!nc->Read(nc, buffer, chunk))
|
||||||
break;
|
break;
|
||||||
if (VFS_WRITE(defer, buffer, chunk) != chunk)
|
if (VFS_WRITE(defer, buffer, chunk) != chunk)
|
||||||
break;
|
break;
|
||||||
upos += chunk;
|
upos += chunk;
|
||||||
}
|
}
|
||||||
FSZIP_Decompress_Destroy(nc);
|
nc->Destroy(nc);
|
||||||
|
|
||||||
return defer;
|
return defer;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct decompressstate
|
|
||||||
{
|
|
||||||
int nothing;
|
|
||||||
};
|
|
||||||
struct decompressstate *FSZIP_Decompress_Init(zipfile_t *source, qofs_t start, qofs_t csize, qofs_t usize, char *filename, char *password, unsigned int crc)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
qofs_t FSZIP_Decompress_Read(struct decompressstate *st, qbyte *buffer, qofs_t bytes)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FSZIP_Decompress_Destroy(struct decompressstate *st)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
vfsfile_t *FSZIP_Decompress_ToTempFile(struct decompressstate *decompress)
|
vfsfile_t *FSZIP_Decompress_ToTempFile(struct decompressstate *decompress)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -992,7 +1146,7 @@ static int QDECL VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int byt
|
||||||
|
|
||||||
if (vfsz->decompress)
|
if (vfsz->decompress)
|
||||||
{
|
{
|
||||||
read = FSZIP_Decompress_Read(vfsz->decompress, buffer, bytestoread);
|
read = vfsz->decompress->Read(vfsz->decompress, buffer, bytestoread);
|
||||||
}
|
}
|
||||||
else if (Sys_LockMutex(vfsz->parent->mutex))
|
else if (Sys_LockMutex(vfsz->parent->mutex))
|
||||||
{
|
{
|
||||||
|
@ -1056,7 +1210,7 @@ static qboolean QDECL VFSZIP_Close (struct vfsfile_s *file)
|
||||||
VFS_CLOSE(vfsz->defer);
|
VFS_CLOSE(vfsz->defer);
|
||||||
|
|
||||||
if (vfsz->decompress)
|
if (vfsz->decompress)
|
||||||
FSZIP_Decompress_Destroy(vfsz->decompress);
|
vfsz->decompress->Destroy(vfsz->decompress);
|
||||||
|
|
||||||
FSZIP_ClosePath(&vfsz->parent->pub);
|
FSZIP_ClosePath(&vfsz->parent->pub);
|
||||||
Z_Free(vfsz);
|
Z_Free(vfsz);
|
||||||
|
@ -1131,6 +1285,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef AVAIL_ZLIB
|
||||||
if (flags & ZFL_DEFLATED)
|
if (flags & ZFL_DEFLATED)
|
||||||
{
|
{
|
||||||
#ifdef ZIPCRYPT
|
#ifdef ZIPCRYPT
|
||||||
|
@ -1139,7 +1294,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
|
||||||
#else
|
#else
|
||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
#endif
|
#endif
|
||||||
vfsz->decompress = FSZIP_Decompress_Init(zip, vfsz->startpos, datasize, vfsz->length, pf->name, password, pf->crc);
|
vfsz->decompress = FSZIP_Deflate_Init(zip, vfsz->startpos, datasize, vfsz->length, pf->name, password, pf->crc);
|
||||||
if (!vfsz->decompress)
|
if (!vfsz->decompress)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1150,6 +1305,28 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef AVAIL_BZLIB
|
||||||
|
if (flags & ZFL_BZIP2)
|
||||||
|
{
|
||||||
|
#ifdef ZIPCRYPT
|
||||||
|
//FIXME: Cvar_Get is not threadsafe, and nor is accessing the cvar...
|
||||||
|
char *password = (flags & ZFL_WEAKENCRYPT)?Cvar_Get("fs_zip_password", "thisispublic", 0, "Filesystem")->string:NULL;
|
||||||
|
#else
|
||||||
|
char *password = NULL;
|
||||||
|
#endif
|
||||||
|
vfsz->decompress = FSZIP_BZip2_Init(zip, vfsz->startpos, datasize, vfsz->length, pf->name, password, pf->crc);
|
||||||
|
if (!vfsz->decompress)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
windows explorer tends to use deflate64 on large files, which zlib and thus we, do not support, thus this is a 'common' failure path
|
||||||
|
this might also trigger from other errors, of course.
|
||||||
|
*/
|
||||||
|
Z_Free(vfsz);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Sys_LockMutex(zip->mutex))
|
if (Sys_LockMutex(zip->mutex))
|
||||||
{
|
{
|
||||||
|
@ -1159,7 +1336,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (vfsz->decompress)
|
if (vfsz->decompress)
|
||||||
FSZIP_Decompress_Destroy(vfsz->decompress);
|
vfsz->decompress->Destroy(vfsz->decompress);
|
||||||
Z_Free(vfsz);
|
Z_Free(vfsz);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1376,9 +1553,15 @@ static qboolean FSZIP_ValidateLocalHeader(zipfile_t *zip, zpackfile_t *zfile, qo
|
||||||
return false; //FIXME: proper spanned zips fragment compressed data over multiple spans, but we don't support that
|
return false; //FIXME: proper spanned zips fragment compressed data over multiple spans, but we don't support that
|
||||||
|
|
||||||
if (local.cmethod == 0)
|
if (local.cmethod == 0)
|
||||||
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED)) == ZFL_STORED;
|
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED|ZFL_BZIP2)) == ZFL_STORED;
|
||||||
|
#ifdef AVAIL_ZLIB
|
||||||
if (local.cmethod == 8)
|
if (local.cmethod == 8)
|
||||||
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED)) == ZFL_DEFLATED;
|
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED|ZFL_BZIP2)) == ZFL_DEFLATED;
|
||||||
|
#endif
|
||||||
|
#ifdef AVAIL_BZLIB
|
||||||
|
if (local.cmethod == 12)
|
||||||
|
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED|ZFL_BZIP2)) == ZFL_BZIP2;
|
||||||
|
#endif
|
||||||
return false; //some other method that we don't know.
|
return false; //some other method that we don't know.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,13 +1722,12 @@ static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipce
|
||||||
//2-5: reduce
|
//2-5: reduce
|
||||||
//6: implode
|
//6: implode
|
||||||
//7: tokenize
|
//7: tokenize
|
||||||
else if (entry->cmethod == 8)
|
else if (entry->cmethod == 8) //8: deflate
|
||||||
entry->flags |= ZFL_DEFLATED;
|
entry->flags |= ZFL_DEFLATED;
|
||||||
//8: deflate64 - patented. sometimes written by microsoft's crap, so this might be problematic. only minor improvements.
|
//9: deflate64 - patented. sometimes written by microsoft's crap, so this might be problematic. only minor improvements.
|
||||||
//10: implode
|
//10: implode
|
||||||
//12: bzip2
|
else if (entry->cmethod == 12) //12: bzip2
|
||||||
// else if (entry->cmethod == 12)
|
entry->flags |= ZFL_BZIP2;
|
||||||
// entry->flags |= ZFL_BZIP2;
|
|
||||||
// else if (entry->cmethod == 14)
|
// else if (entry->cmethod == 14)
|
||||||
// entry->flags |= ZFL_LZMA;
|
// entry->flags |= ZFL_LZMA;
|
||||||
//19: lz77
|
//19: lz77
|
||||||
|
|
|
@ -3558,18 +3558,20 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||||
out += (m%loadmodel->lightmaps.merge)*mapsize;
|
out += (m%loadmodel->lightmaps.merge)*mapsize;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
//q3bsp has 4-fold overbrights, so if we're not using overbrights then we basically need to scale the values up by 4
|
||||||
|
//this will require clamping, which can result in oversaturation of channels, meaning discolouration
|
||||||
for(s = 0; s < mapsize; )
|
for(s = 0; s < mapsize; )
|
||||||
{
|
{
|
||||||
|
float scale = (1<<(2-gl_overbright.ival));
|
||||||
float i;
|
float i;
|
||||||
vec3_t l;
|
vec3_t l;
|
||||||
l[0] = *in++;
|
l[0] = *in++;
|
||||||
l[1] = *in++;
|
l[1] = *in++;
|
||||||
l[2] = *in++;
|
l[2] = *in++;
|
||||||
i = VectorNormalize(l);
|
VectorScale(l, scale, l); //it should be noted that this maths is wrong if you're trying to use srgb lightmaps.
|
||||||
i *= (1<<(2-gl_overbright.ival));
|
i = max(l[0], max(l[1], l[2]));
|
||||||
if (i > 255)
|
if (i > 255)
|
||||||
i = 255; //don't oversaturate (clamping results in discolouration, which looks weird)
|
VectorScale(l, 255/i, l); //clamp the brightest channel, scaling the others down to retain chromiance.
|
||||||
VectorScale(l, i, l);
|
|
||||||
out[s++] = l[0];
|
out[s++] = l[0];
|
||||||
out[s++] = l[1];
|
out[s++] = l[1];
|
||||||
out[s++] = l[2];
|
out[s++] = l[2];
|
||||||
|
|
|
@ -251,11 +251,13 @@ void SV_LogPlayer(client_t *cl, char *msg)
|
||||||
if (cl->protocol == SCP_BAD)
|
if (cl->protocol == SCP_BAD)
|
||||||
return; //don't log botclients
|
return; //don't log botclients
|
||||||
|
|
||||||
snprintf(line, sizeof(line),
|
Q_snprintfz(line, sizeof(line)-1,
|
||||||
"%s\\%s\\%i\\%s\\%s\\%i\\guid\\%s%s\n",
|
"%s\\%s\\%i\\%s\\%s\\%i\\guid\\%s",
|
||||||
msg, cl->name, cl->userid,
|
msg, cl->name, cl->userid,
|
||||||
NET_BaseAdrToString(remote_adr, sizeof(remote_adr), &cl->netchan.remote_address), (cl->realip_status > 0 ? NET_BaseAdrToString(realip_adr, sizeof(realip_adr), &cl->realip) : "??"),
|
NET_BaseAdrToString(remote_adr, sizeof(remote_adr), &cl->netchan.remote_address), (cl->realip_status > 0 ? NET_BaseAdrToString(realip_adr, sizeof(realip_adr), &cl->realip) : "??"),
|
||||||
cl->netchan.remote_address.port, cl->guid, cl->userinfo);
|
cl->netchan.remote_address.port, cl->guid);
|
||||||
|
InfoBuf_ToString(&cl->userinfo, line+strlen(line), sizeof(line)-1-strlen(line), NULL, NULL, NULL, NULL, NULL);
|
||||||
|
Q_strncatz(line, "\n", sizeof(line));
|
||||||
|
|
||||||
Log_String(LOG_PLAYER, line);
|
Log_String(LOG_PLAYER, line);
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,7 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
|
||||||
mask |= PEXT2_VOICECHAT;
|
mask |= PEXT2_VOICECHAT;
|
||||||
#endif
|
#endif
|
||||||
mask |= PEXT2_SETANGLEDELTA;
|
mask |= PEXT2_SETANGLEDELTA;
|
||||||
|
// mask |= PEXT2_INFOBLOBS;
|
||||||
|
|
||||||
if (pext_replacementdeltas.ival)
|
if (pext_replacementdeltas.ival)
|
||||||
mask |= PEXT2_REPLACEMENTDELTAS;
|
mask |= PEXT2_REPLACEMENTDELTAS;
|
||||||
|
|
|
@ -23,14 +23,15 @@ struct
|
||||||
qintptr_t (*initfunction)(qintptr_t *args);
|
qintptr_t (*initfunction)(qintptr_t *args);
|
||||||
} staticplugins[] =
|
} staticplugins[] =
|
||||||
{
|
{
|
||||||
#if defined(USERBE) && !defined(QUAKETC)
|
#if defined(USE_INTERNAL_BULLET)
|
||||||
// {"Bullet_internal", Plug_Bullet_Init},
|
{"Bullet_internal", Plug_Bullet_Init},
|
||||||
// {"ODE_internal", Plug_ODE_Init},
|
#endif
|
||||||
|
#if defined(USE_INTERNAL_ODE)
|
||||||
|
{"ODE_internal", Plug_ODE_Init},
|
||||||
#endif
|
#endif
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef GLQUAKE
|
#ifdef GLQUAKE
|
||||||
#include "glquake.h"
|
#include "glquake.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2780,7 +2780,7 @@ void QCBUILTIN PF_callfunction (pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
||||||
void QCBUILTIN PF_loadfromfile (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
void QCBUILTIN PF_loadfromfile (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
const char *filename = PR_GetStringOfs(prinst, OFS_PARM0);
|
const char *filename = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
const char *file = COM_LoadTempFile(filename, NULL);
|
const char *file = COM_LoadTempFile(filename, 0, NULL);
|
||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
@ -4439,14 +4439,11 @@ void QCBUILTIN PF_crc16 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
|
||||||
G_FLOAT(OFS_RETURN) = QCRC_Block(str, len);
|
G_FLOAT(OFS_RETURN) = QCRC_Block(str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals, const char *hashtype, const void *str, size_t len)
|
||||||
{
|
{
|
||||||
const char *hashtype = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
||||||
const char *str = PF_VarString(prinst, 1, pr_globals);
|
|
||||||
int digestsize, i;
|
int digestsize, i;
|
||||||
unsigned char digest[64];
|
unsigned char digest[64];
|
||||||
unsigned char hexdig[sizeof(digest)*2+1];
|
unsigned char hexdig[sizeof(digest)*2+1];
|
||||||
size_t len = strlen(str);
|
|
||||||
|
|
||||||
if (!strcmp(hashtype, "MD4"))
|
if (!strcmp(hashtype, "MD4"))
|
||||||
{
|
{
|
||||||
|
@ -4487,6 +4484,27 @@ void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
|
||||||
G_INT(OFS_RETURN) = 0;
|
G_INT(OFS_RETURN) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
const char *hashtype = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
const char *str = PF_VarString(prinst, 1, pr_globals);
|
||||||
|
PF_digest_internal(prinst, pr_globals, hashtype, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QCBUILTIN PF_digest_ptr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
const char *hashtype = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
int qcptr = G_INT(OFS_PARM1);
|
||||||
|
int size = G_INT(OFS_PARM2);
|
||||||
|
if (qcptr < 0 || qcptr+size >= prinst->stringtablesize)
|
||||||
|
{
|
||||||
|
PR_BIError(prinst, "PF_digest_ptr: invalid dest\n");
|
||||||
|
G_INT(OFS_RETURN) = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PF_digest_internal(prinst, pr_globals, hashtype, prinst->stringtable + qcptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
// #510 string(string in) uri_escape = #510;
|
// #510 string(string in) uri_escape = #510;
|
||||||
void QCBUILTIN PF_uri_escape (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
void QCBUILTIN PF_uri_escape (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
|
|
|
@ -356,6 +356,7 @@ void QCBUILTIN PF_strpad (pubprogfuncs_t *prinst, struct globalvars_s *pr_global
|
||||||
void QCBUILTIN PF_strtrim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
void QCBUILTIN PF_strtrim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||||
|
|
||||||
void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||||
|
void QCBUILTIN PF_digest_ptr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||||
|
|
||||||
void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||||
void QCBUILTIN PF_edict_for_num (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
void QCBUILTIN PF_edict_for_num (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||||
|
@ -501,12 +502,14 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, const char *filename, int *line, int
|
||||||
void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored);
|
void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored);
|
||||||
void PR_Common_SaveGame(vfsfile_t *f, pubprogfuncs_t *prinst, qboolean binary);
|
void PR_Common_SaveGame(vfsfile_t *f, pubprogfuncs_t *prinst, qboolean binary);
|
||||||
|
|
||||||
|
uploadfmt_t PR_TranslateTextureFormat(int qcformat);
|
||||||
|
|
||||||
//FIXME
|
//FIXME
|
||||||
pbool PR_RunWarning (pubprogfuncs_t *ppf, char *error, ...);
|
pbool PR_RunWarning (pubprogfuncs_t *ppf, char *error, ...);
|
||||||
|
|
||||||
|
|
||||||
/*these are server ones, provided by pr_cmds.c, as required by pr_q1qvm.c*/
|
/*these are server ones, provided by pr_cmds.c, as required by pr_q1qvm.c*/
|
||||||
int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *value);
|
int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *value, size_t valsize);
|
||||||
#ifdef VM_Q1
|
#ifdef VM_Q1
|
||||||
void PR_SV_FillWorldGlobals(world_t *w);
|
void PR_SV_FillWorldGlobals(world_t *w);
|
||||||
model_t *QDECL SVPR_GetCModel(world_t *w, int modelindex);
|
model_t *QDECL SVPR_GetCModel(world_t *w, int modelindex);
|
||||||
|
|
|
@ -73,6 +73,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues.
|
#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues.
|
||||||
#define PEXT2_PREDINFO 0x00000020 //movevar stats, NQ input sequences+acks.
|
#define PEXT2_PREDINFO 0x00000020 //movevar stats, NQ input sequences+acks.
|
||||||
#define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding.
|
#define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding.
|
||||||
|
#define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc.
|
||||||
|
|
||||||
//EzQuake/Mvdsv extensions
|
//EzQuake/Mvdsv extensions
|
||||||
#define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding...
|
#define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding...
|
||||||
|
|
|
@ -8,10 +8,7 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char name[256];
|
char name[256];
|
||||||
char *data;
|
vfsfile_t *file;
|
||||||
int bufferlen;
|
|
||||||
qofs_t len;
|
|
||||||
qofs_t ofs;
|
|
||||||
int accessmode;
|
int accessmode;
|
||||||
int owner;
|
int owner;
|
||||||
} vm_fopen_files_t;
|
} vm_fopen_files_t;
|
||||||
|
@ -20,7 +17,6 @@ vm_fopen_files_t vm_fopen_files[MAX_VM_FILES];
|
||||||
qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner)
|
qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
size_t insize;
|
|
||||||
|
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return !!FS_FLocateFile(name, FSLF_IFFOUND, NULL);
|
return !!FS_FLocateFile(name, FSLF_IFFOUND, NULL);
|
||||||
|
@ -28,7 +24,7 @@ qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner)
|
||||||
*handle = 0;
|
*handle = 0;
|
||||||
|
|
||||||
for (i = 0; i < MAX_VM_FILES; i++)
|
for (i = 0; i < MAX_VM_FILES; i++)
|
||||||
if (!vm_fopen_files[i].data)
|
if (!vm_fopen_files[i].file)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == MAX_VM_FILES) //too many already open
|
if (i == MAX_VM_FILES) //too many already open
|
||||||
|
@ -46,39 +42,27 @@ qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner)
|
||||||
switch (fmode)
|
switch (fmode)
|
||||||
{
|
{
|
||||||
case VM_FS_READ:
|
case VM_FS_READ:
|
||||||
vm_fopen_files[i].data = FS_LoadMallocFile(name, &insize);
|
vm_fopen_files[i].file = FS_OpenVFS(name, "rb", FS_GAME);
|
||||||
vm_fopen_files[i].bufferlen = vm_fopen_files[i].len = insize;
|
|
||||||
vm_fopen_files[i].ofs = 0;
|
|
||||||
if (vm_fopen_files[i].data)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
break;
|
break;
|
||||||
/*
|
|
||||||
case VM_FS_APPEND:
|
case VM_FS_APPEND:
|
||||||
case VM_FS_APPEND2:
|
case VM_FS_APPEND_SYNC:
|
||||||
vm_fopen_files[i].data = FS_LoadMallocFile(name);
|
vm_fopen_files[i].file = FS_OpenVFS(name, "ab", FS_GAMEONLY);
|
||||||
vm_fopen_files[i].ofs = vm_fopen_files[i].bufferlen = vm_fopen_files[i].len = com_filesize;
|
break;
|
||||||
if (vm_fopen_files[i].data)
|
case VM_FS_WRITE:
|
||||||
break;
|
vm_fopen_files[i].file = FS_OpenVFS(name, "wb", FS_GAMEONLY);
|
||||||
//fall through
|
|
||||||
case VM_FS_WRITE:
|
|
||||||
vm_fopen_files[i].bufferlen = 8192;
|
|
||||||
vm_fopen_files[i].data = BZ_Malloc(vm_fopen_files[i].bufferlen);
|
|
||||||
vm_fopen_files[i].len = 0;
|
|
||||||
vm_fopen_files[i].ofs = 0;
|
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
default: //bad
|
default: //bad
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!vm_fopen_files[i].file)
|
||||||
|
return -1;
|
||||||
|
|
||||||
Q_strncpyz(vm_fopen_files[i].name, name, sizeof(vm_fopen_files[i].name));
|
Q_strncpyz(vm_fopen_files[i].name, name, sizeof(vm_fopen_files[i].name));
|
||||||
vm_fopen_files[i].accessmode = fmode;
|
vm_fopen_files[i].accessmode = fmode;
|
||||||
vm_fopen_files[i].owner = owner;
|
vm_fopen_files[i].owner = owner;
|
||||||
|
|
||||||
*handle = i+1;
|
*handle = i+1;
|
||||||
return vm_fopen_files[i].len;
|
return VFS_GETLEN(vm_fopen_files[i].file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_fclose (int fnum, int owner)
|
void VM_fclose (int fnum, int owner)
|
||||||
|
@ -91,22 +75,10 @@ void VM_fclose (int fnum, int owner)
|
||||||
if (vm_fopen_files[fnum].owner != owner)
|
if (vm_fopen_files[fnum].owner != owner)
|
||||||
return; //cgs?
|
return; //cgs?
|
||||||
|
|
||||||
if (!vm_fopen_files[fnum].data)
|
if (!vm_fopen_files[fnum].file)
|
||||||
return; //not open
|
return; //not open
|
||||||
|
VFS_CLOSE(vm_fopen_files[fnum].file);
|
||||||
switch(vm_fopen_files[fnum].accessmode)
|
vm_fopen_files[fnum].file = NULL;
|
||||||
{
|
|
||||||
case VM_FS_READ:
|
|
||||||
BZ_Free(vm_fopen_files[fnum].data);
|
|
||||||
break;
|
|
||||||
case VM_FS_WRITE:
|
|
||||||
case VM_FS_APPEND:
|
|
||||||
case VM_FS_APPEND2:
|
|
||||||
COM_WriteFile(vm_fopen_files[fnum].name, FS_GAMEONLY, vm_fopen_files[fnum].data, vm_fopen_files[fnum].len);
|
|
||||||
BZ_Free(vm_fopen_files[fnum].data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
vm_fopen_files[fnum].data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int VM_FRead (char *dest, int quantity, int fnum, int owner)
|
int VM_FRead (char *dest, int quantity, int fnum, int owner)
|
||||||
|
@ -118,76 +90,68 @@ int VM_FRead (char *dest, int quantity, int fnum, int owner)
|
||||||
if (vm_fopen_files[fnum].owner != owner)
|
if (vm_fopen_files[fnum].owner != owner)
|
||||||
return 0; //cgs?
|
return 0; //cgs?
|
||||||
|
|
||||||
if (!vm_fopen_files[fnum].data)
|
if (!vm_fopen_files[fnum].file)
|
||||||
return 0; //not open
|
return 0; //not open
|
||||||
|
if (!vm_fopen_files[fnum].file->ReadBytes)
|
||||||
if (quantity > vm_fopen_files[fnum].len - vm_fopen_files[fnum].ofs)
|
return 0;
|
||||||
quantity = vm_fopen_files[fnum].len - vm_fopen_files[fnum].ofs;
|
return VFS_READ(vm_fopen_files[fnum].file, dest, quantity);
|
||||||
memcpy(dest, vm_fopen_files[fnum].data + vm_fopen_files[fnum].ofs, quantity);
|
|
||||||
vm_fopen_files[fnum].ofs += quantity;
|
|
||||||
|
|
||||||
return quantity;
|
|
||||||
}
|
}
|
||||||
int VM_FWrite (const char *dest, int quantity, int fnum, int owner)
|
int VM_FWrite (const char *dest, int quantity, int fnum, int owner)
|
||||||
{
|
{
|
||||||
/*
|
fnum--;
|
||||||
int fnum = G_FLOAT(OFS_PARM0);
|
if (fnum < 0 || fnum >= MAX_VM_FILES)
|
||||||
char *msg = PF_VarString(prinst, 1, pr_globals);
|
return 0; //out of range
|
||||||
int len = strlen(msg);
|
|
||||||
if (fnum < 0 || fnum >= MAX_QC_FILES)
|
|
||||||
return; //out of range
|
|
||||||
|
|
||||||
if (!pf_fopen_files[fnum].data)
|
if (vm_fopen_files[fnum].owner != owner)
|
||||||
return; //not open
|
return 0; //cgs?
|
||||||
|
|
||||||
if (pf_fopen_files[fnum].prinst != prinst)
|
if (!vm_fopen_files[fnum].file)
|
||||||
return; //this just isn't ours.
|
return 0; //not open
|
||||||
|
if (!vm_fopen_files[fnum].file->WriteBytes)
|
||||||
|
return 0;
|
||||||
|
quantity = VFS_WRITE(vm_fopen_files[fnum].file, dest, quantity);
|
||||||
|
|
||||||
if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len)
|
if (vm_fopen_files[fnum].accessmode == VM_FS_APPEND_SYNC)
|
||||||
{
|
VFS_FLUSH(vm_fopen_files[fnum].file);
|
||||||
char *newbuf;
|
return quantity;
|
||||||
pf_fopen_files[fnum].bufferlen = pf_fopen_files[fnum].bufferlen*2 + len;
|
|
||||||
newbuf = BZF_Malloc(pf_fopen_files[fnum].bufferlen);
|
|
||||||
memcpy(newbuf, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
|
|
||||||
BZ_Free(pf_fopen_files[fnum].data);
|
|
||||||
pf_fopen_files[fnum].data = newbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, msg, len);
|
|
||||||
if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len)
|
|
||||||
pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len;
|
|
||||||
pf_fopen_files[fnum].ofs+=len;
|
|
||||||
*/
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
qboolean VM_FSeek (int fnum, qofs_t offset, int seektype, int owner)
|
qboolean VM_FSeek (int fnum, qofs_t offset, int seektype, int owner)
|
||||||
{
|
{
|
||||||
|
qofs_t fsize;
|
||||||
fnum--;
|
fnum--;
|
||||||
if (fnum < 0 || fnum >= MAX_VM_FILES)
|
if (fnum < 0 || fnum >= MAX_VM_FILES)
|
||||||
return false; //out of range
|
return false; //out of range
|
||||||
if (vm_fopen_files[fnum].owner != owner)
|
if (vm_fopen_files[fnum].owner != owner)
|
||||||
return false; //cgs?
|
return false; //cgs?
|
||||||
if (!vm_fopen_files[fnum].data)
|
if (!vm_fopen_files[fnum].file)
|
||||||
return false; //not open
|
return false; //not open
|
||||||
|
switch(vm_fopen_files[fnum].file->seekstyle)
|
||||||
switch(seektype)
|
|
||||||
{
|
{
|
||||||
case 0:
|
case SS_SEEKABLE:
|
||||||
offset = vm_fopen_files[fnum].ofs + offset;
|
case SS_SLOW:
|
||||||
case 1:
|
fsize = VFS_GETLEN(vm_fopen_files[fnum].file); //can't cache it if we're writing
|
||||||
offset = vm_fopen_files[fnum].len + offset;
|
switch(seektype)
|
||||||
break;
|
{
|
||||||
default:
|
case 0:
|
||||||
case 2:
|
offset += VFS_TELL(vm_fopen_files[fnum].file);
|
||||||
//offset = 0 + offset;
|
return 0;
|
||||||
break;
|
case 1:
|
||||||
|
offset += fsize;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 2:
|
||||||
|
offset += 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (offset > fsize)
|
||||||
|
return false;
|
||||||
|
VFS_SEEK(vm_fopen_files[fnum].file, offset);
|
||||||
|
return true;
|
||||||
|
case SS_PIPE:
|
||||||
|
case SS_UNSEEKABLE:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// if (offset < 0)
|
return false; //should be unreachable.
|
||||||
// offset = 0;
|
|
||||||
if (offset > vm_fopen_files[fnum].len)
|
|
||||||
offset = vm_fopen_files[fnum].len;
|
|
||||||
vm_fopen_files[fnum].ofs = offset;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
qofs_t VM_FTell (int fnum, int owner)
|
qofs_t VM_FTell (int fnum, int owner)
|
||||||
{
|
{
|
||||||
|
@ -196,10 +160,10 @@ qofs_t VM_FTell (int fnum, int owner)
|
||||||
return 0; //out of range
|
return 0; //out of range
|
||||||
if (vm_fopen_files[fnum].owner != owner)
|
if (vm_fopen_files[fnum].owner != owner)
|
||||||
return 0; //cgs?
|
return 0; //cgs?
|
||||||
if (!vm_fopen_files[fnum].data)
|
if (!vm_fopen_files[fnum].file)
|
||||||
return 0; //not open
|
return 0; //not open
|
||||||
|
|
||||||
return vm_fopen_files[fnum].ofs;
|
return VFS_TELL(vm_fopen_files[fnum].file);
|
||||||
}
|
}
|
||||||
void VM_fcloseall (int owner)
|
void VM_fcloseall (int owner)
|
||||||
{
|
{
|
||||||
|
@ -370,16 +334,14 @@ int VMQ3_Cvar_Register(q3vmcvar_t *v, char *name, char *defval, int flags)
|
||||||
if ((flags & CVAR_USERINFO) && !(c->flags & CVAR_USERINFO))
|
if ((flags & CVAR_USERINFO) && !(c->flags & CVAR_USERINFO))
|
||||||
{
|
{
|
||||||
c->flags |= CVAR_USERINFO;
|
c->flags |= CVAR_USERINFO;
|
||||||
Info_SetValueForKey(cls.userinfo[0], c->name, c->string, sizeof(cls.userinfo[0]));
|
InfoBuf_SetKey(&cls.userinfo[0], c->name, c->string);
|
||||||
cls.resendinfo = true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef CLIENTONLY
|
#ifndef CLIENTONLY
|
||||||
if ((flags & CVAR_SERVERINFO) && !(c->flags & CVAR_SERVERINFO))
|
if ((flags & CVAR_SERVERINFO) && !(c->flags & CVAR_SERVERINFO))
|
||||||
{
|
{
|
||||||
c->flags |= CVAR_SERVERINFO;
|
c->flags |= CVAR_SERVERINFO;
|
||||||
Info_SetValueForKey (svs.info, c->name, c->string, MAX_SERVERINFO_STRING);
|
InfoBuf_SetKey (&svs.info, c->name, c->string);
|
||||||
SV_SendServerInfoChange(c->name, c->string);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < MAX_VMQ3_CVARS; i++)
|
for (i = 0; i < MAX_VMQ3_CVARS; i++)
|
||||||
|
|
|
@ -87,7 +87,7 @@ void Script_Get_File_And_Line(int handle, char *filename, int *line);
|
||||||
#define VM_FS_READ 0
|
#define VM_FS_READ 0
|
||||||
#define VM_FS_WRITE 1
|
#define VM_FS_WRITE 1
|
||||||
#define VM_FS_APPEND 2
|
#define VM_FS_APPEND 2
|
||||||
#define VM_FS_APPEND2 3 //I don't know, don't ask me. look at q3 source
|
#define VM_FS_APPEND_SYNC 3 //I don't know, don't ask me. look at q3 source
|
||||||
qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner);
|
qofs_t VM_fopen (const char *name, int *handle, int fmode, int owner);
|
||||||
int VM_FRead (char *dest, int quantity, int fnum, int owner);
|
int VM_FRead (char *dest, int quantity, int fnum, int owner);
|
||||||
int VM_FWrite (const char *dest, int quantity, int fnum, int owner);
|
int VM_FWrite (const char *dest, int quantity, int fnum, int owner);
|
||||||
|
|
|
@ -1524,7 +1524,7 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Vector4Set(map->colorsb, 255, 255, 255, 255);
|
Vector4Set(map->colorsb, 255, 255, 255, 255);
|
||||||
VectorCopy(mesh->st_array[i], map->tc[0]);
|
Vector2Copy(mesh->st_array[i], map->tc[0]);
|
||||||
if (mesh->lmst_array[0])
|
if (mesh->lmst_array[0])
|
||||||
Vector2Copy(mesh->lmst_array[0][i], map->tc[1]);
|
Vector2Copy(mesh->lmst_array[0][i], map->tc[1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,7 @@ typedef struct
|
||||||
float m_model[16];
|
float m_model[16];
|
||||||
unsigned int lastpasscount;
|
unsigned int lastpasscount;
|
||||||
vbo_t *batchvbo;
|
vbo_t *batchvbo;
|
||||||
|
program_t *curprog;
|
||||||
|
|
||||||
shader_t *shader_rtlight;
|
shader_t *shader_rtlight;
|
||||||
IDirect3DTexture9 *curtex[MAX_TMUS];
|
IDirect3DTexture9 *curtex[MAX_TMUS];
|
||||||
|
@ -1070,6 +1071,8 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
identity:
|
identity:
|
||||||
|
case RGB_GEN_UNKNOWN:
|
||||||
|
case RGB_GEN_IDENTITY_OVERBRIGHT:
|
||||||
case RGB_GEN_IDENTITY:
|
case RGB_GEN_IDENTITY:
|
||||||
block = D3DCOLOR_RGBA(255, 255, 255, 255);
|
block = D3DCOLOR_RGBA(255, 255, 255, 255);
|
||||||
while((cnt)--)
|
while((cnt)--)
|
||||||
|
@ -1459,6 +1462,11 @@ static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, c
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
for (j = 0; j < cnt; j++, dst+=2,src+=2)
|
||||||
|
{
|
||||||
|
dst[0] = src[0];
|
||||||
|
dst[1] = src[1];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1862,109 +1870,6 @@ static void deformgen(const deformv_t *deformv, int cnt, vecV_t *src, vecV_t *ds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*does not do the draw call, does not consider indicies (except for billboard generation) */
|
|
||||||
static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vertcount)
|
|
||||||
{
|
|
||||||
int vdec;
|
|
||||||
void *map;
|
|
||||||
int i;
|
|
||||||
unsigned int passno = 0, tmu;
|
|
||||||
|
|
||||||
int lastpass = pass->numMergedPasses;
|
|
||||||
|
|
||||||
for (i = 0; i < lastpass; i++)
|
|
||||||
{
|
|
||||||
if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay))
|
|
||||||
continue;
|
|
||||||
if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay))
|
|
||||||
continue;
|
|
||||||
if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright))
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == lastpass)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*all meshes in a chain must have the same features*/
|
|
||||||
vdec = 0;
|
|
||||||
|
|
||||||
/*we only use one colour, generated from the first pass*/
|
|
||||||
vdec |= BE_GenerateColourMods(vertcount, pass);
|
|
||||||
|
|
||||||
tmu = 0;
|
|
||||||
/*activate tmus*/
|
|
||||||
for (passno = 0; passno < lastpass; passno++)
|
|
||||||
{
|
|
||||||
if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay))
|
|
||||||
continue;
|
|
||||||
if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay))
|
|
||||||
continue;
|
|
||||||
if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SelectPassTexture(tmu, pass+passno);
|
|
||||||
|
|
||||||
vdec |= D3D_VDEC_ST0<<tmu;
|
|
||||||
if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_BASE && !pass[passno].numtcmods)
|
|
||||||
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t)));
|
|
||||||
else if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_LIGHTMAP && !pass[passno].numtcmods)
|
|
||||||
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vbovdata_t)));
|
|
||||||
else if (pass[passno].tcgen == TC_GEN_SKYBOX)
|
|
||||||
{
|
|
||||||
vdec |= D3D_VDEC_CM;
|
|
||||||
allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec3_t));
|
|
||||||
GenerateTCMods3(pass+passno, map);
|
|
||||||
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu]));
|
|
||||||
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec3_t), sizeof(vec3_t)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec2_t));
|
|
||||||
GenerateTCMods(pass+passno, map);
|
|
||||||
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu]));
|
|
||||||
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec2_t), sizeof(vec2_t)));
|
|
||||||
}
|
|
||||||
tmu++;
|
|
||||||
}
|
|
||||||
/*deactivate any extras*/
|
|
||||||
for (; tmu < shaderstate.lastpasscount; )
|
|
||||||
{
|
|
||||||
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, NULL, 0, 0));
|
|
||||||
BindTexture(tmu, NULL);
|
|
||||||
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_COLOROP, D3DTOP_DISABLE));
|
|
||||||
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
|
|
||||||
tmu++;
|
|
||||||
}
|
|
||||||
shaderstate.lastpasscount = tmu;
|
|
||||||
|
|
||||||
// if (meshchain->normals_array &&
|
|
||||||
// meshchain->2 &&
|
|
||||||
// meshchain->tnormals_array)
|
|
||||||
// vdec |= D3D_VDEC_NORMS;
|
|
||||||
|
|
||||||
if (vdec != shaderstate.curvertdecl)
|
|
||||||
{
|
|
||||||
shaderstate.curvertdecl = vdec;
|
|
||||||
d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl]));
|
|
||||||
}
|
|
||||||
|
|
||||||
BE_ApplyShaderBits(pass->shaderbits);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BE_SubmitMeshChain(unsigned int vertbase, unsigned int firstvert, unsigned int vertcount, unsigned int idxfirst, int unsigned idxcount)
|
|
||||||
{
|
|
||||||
if (shaderstate.flags & BEF_LINES)
|
|
||||||
IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_LINELIST, vertbase, firstvert, vertcount, idxfirst, idxcount/2);
|
|
||||||
else
|
|
||||||
IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, vertbase, firstvert, vertcount, idxfirst, idxcount/3);
|
|
||||||
RQuantAdd(RQUANT_DRAWS, 1);
|
|
||||||
|
|
||||||
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb)
|
static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1997,7 +1902,6 @@ static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb)
|
||||||
*retblue = gammatable[*retblue];
|
*retblue = gammatable[*retblue];
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BE_ApplyUniforms(program_t *prog, int permu)
|
static void BE_ApplyUniforms(program_t *prog, int permu)
|
||||||
{
|
{
|
||||||
struct programpermu_s *perm = &prog->permu[permu];
|
struct programpermu_s *perm = &prog->permu[permu];
|
||||||
|
@ -2005,8 +1909,12 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
|
||||||
vec4_t param4;
|
vec4_t param4;
|
||||||
int h;
|
int h;
|
||||||
int i;
|
int i;
|
||||||
IDirect3DDevice9_SetVertexShader(pD3DDev9, perm->h.hlsl.vert);
|
if (shaderstate.curprog != prog)
|
||||||
IDirect3DDevice9_SetPixelShader(pD3DDev9, perm->h.hlsl.frag);
|
{
|
||||||
|
shaderstate.curprog = prog;
|
||||||
|
IDirect3DDevice9_SetVertexShader(pD3DDev9, perm->h.hlsl.vert);
|
||||||
|
IDirect3DDevice9_SetPixelShader(pD3DDev9, perm->h.hlsl.frag);
|
||||||
|
}
|
||||||
for (i = 0, pp = perm->parm; i < perm->numparms; i++, pp++)
|
for (i = 0, pp = perm->parm; i < perm->numparms; i++, pp++)
|
||||||
{
|
{
|
||||||
h = pp->handle;
|
h = pp->handle;
|
||||||
|
@ -2169,6 +2077,208 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int BE_DrawMeshChain_SetupProgram(program_t *p)
|
||||||
|
{
|
||||||
|
unsigned int vdec = 0;
|
||||||
|
unsigned int perm = 0;
|
||||||
|
#ifdef SKELETALMODELS
|
||||||
|
if (shaderstate.batchvbo && shaderstate.batchvbo->numbones)
|
||||||
|
{
|
||||||
|
if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded)
|
||||||
|
perm |= PERMUTATION_SKELETAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded)
|
||||||
|
perm |= PERMUTATION_BUMPMAP;
|
||||||
|
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded)
|
||||||
|
perm |= PERMUTATION_FULLBRIGHT;
|
||||||
|
if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay)))
|
||||||
|
perm |= PERMUTATION_UPPERLOWER;
|
||||||
|
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded)
|
||||||
|
perm |= PERMUTATION_FOG;
|
||||||
|
#ifdef NONSKELETALMODELS
|
||||||
|
if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff)
|
||||||
|
{
|
||||||
|
perm |= PERMUTATION_FRAMEBLEND;
|
||||||
|
vdec |= D3D_VDEC_POS2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// if (p->permu[perm|PERMUTATION_DELUXE].h.loaded && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
|
||||||
|
// perm |= PERMUTATION_DELUXE;
|
||||||
|
#if MAXRLIGHTMAPS > 1
|
||||||
|
if (shaderstate.curbatch && shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded)
|
||||||
|
perm |= PERMUTATION_LIGHTSTYLES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vdec |= D3D_VDEC_COL4B;//BE_GenerateColourMods(vertcount, s->passes);
|
||||||
|
|
||||||
|
BE_ApplyUniforms(p, perm);
|
||||||
|
|
||||||
|
return vdec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*does not do the draw call, does not consider indicies (except for billboard generation) */
|
||||||
|
static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vertcount)
|
||||||
|
{
|
||||||
|
int vdec;
|
||||||
|
void *map;
|
||||||
|
int i;
|
||||||
|
unsigned int passno = 0, tmu;
|
||||||
|
|
||||||
|
int lastpass = pass->numMergedPasses;
|
||||||
|
|
||||||
|
for (i = 0; i < lastpass; i++)
|
||||||
|
{
|
||||||
|
if (pass[i].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay))
|
||||||
|
continue;
|
||||||
|
if (pass[i].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay))
|
||||||
|
continue;
|
||||||
|
if (pass[i].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == lastpass)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*all meshes in a chain must have the same features*/
|
||||||
|
vdec = 0;
|
||||||
|
|
||||||
|
/*we only use one colour, generated from the first pass*/
|
||||||
|
vdec |= BE_GenerateColourMods(vertcount, pass);
|
||||||
|
|
||||||
|
if (pass->prog)
|
||||||
|
{
|
||||||
|
vdec |= BE_DrawMeshChain_SetupProgram(pass->prog);
|
||||||
|
|
||||||
|
tmu = 0;
|
||||||
|
/*activate tmus*/
|
||||||
|
for (passno = 0; passno < lastpass; passno++)
|
||||||
|
{
|
||||||
|
SelectPassTexture(tmu, pass+passno);
|
||||||
|
tmu++;
|
||||||
|
}
|
||||||
|
/*deactivate any extras*/
|
||||||
|
for (; tmu < shaderstate.lastpasscount; )
|
||||||
|
{
|
||||||
|
BindTexture(tmu, NULL);
|
||||||
|
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_COLOROP, D3DTOP_DISABLE));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
|
||||||
|
tmu++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
vdec |= D3D_VDEC_ST0|D3D_VDEC_ST1;
|
||||||
|
if (shaderstate.batchvbo)
|
||||||
|
{
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t)));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vbovdata_t)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mesh_t *mesh;
|
||||||
|
unsigned int mno;
|
||||||
|
float *outtc, *outlm;
|
||||||
|
|
||||||
|
allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(vec4_t));
|
||||||
|
outtc = map;
|
||||||
|
outlm = outtc + vertcount*2;
|
||||||
|
for (mno = 0; mno < shaderstate.nummeshes; mno++)
|
||||||
|
{
|
||||||
|
mesh = shaderstate.meshlist[mno];
|
||||||
|
|
||||||
|
memcpy(outtc, mesh->st_array, sizeof(vec2_t)*mesh->numvertexes);
|
||||||
|
memcpy(outlm, mesh->lmst_array[0], sizeof(vec2_t)*mesh->numvertexes);
|
||||||
|
}
|
||||||
|
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0]));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(vec4_t), sizeof(vec2_t)));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(vec2_t), sizeof(vec2_t)));
|
||||||
|
}
|
||||||
|
shaderstate.lastpasscount = max(2, tmu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (shaderstate.curprog)
|
||||||
|
{
|
||||||
|
shaderstate.curprog = NULL;
|
||||||
|
IDirect3DDevice9_SetVertexShader(pD3DDev9, NULL);
|
||||||
|
IDirect3DDevice9_SetPixelShader(pD3DDev9, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmu = 0;
|
||||||
|
/*activate tmus*/
|
||||||
|
for (passno = 0; passno < lastpass; passno++)
|
||||||
|
{
|
||||||
|
if (pass[passno].texgen == T_GEN_UPPEROVERLAY && !TEXLOADED(shaderstate.curtexnums->upperoverlay))
|
||||||
|
continue;
|
||||||
|
if (pass[passno].texgen == T_GEN_LOWEROVERLAY && !TEXLOADED(shaderstate.curtexnums->loweroverlay))
|
||||||
|
continue;
|
||||||
|
if (pass[passno].texgen == T_GEN_FULLBRIGHT && !TEXLOADED(shaderstate.curtexnums->fullbright))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SelectPassTexture(tmu, pass+passno);
|
||||||
|
|
||||||
|
vdec |= D3D_VDEC_ST0<<tmu;
|
||||||
|
if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_BASE/* && !pass[passno].numtcmods*/)
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t)));
|
||||||
|
else if (shaderstate.batchvbo)// && pass[passno].tcgen == TC_GEN_LIGHTMAP/* && !pass[passno].numtcmods*/)
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord[0].d3d.buff, shaderstate.batchvbo->lmcoord[0].d3d.offs, sizeof(vbovdata_t)));
|
||||||
|
else if (pass[passno].tcgen == TC_GEN_SKYBOX)
|
||||||
|
{
|
||||||
|
vdec |= D3D_VDEC_CM;
|
||||||
|
allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec3_t));
|
||||||
|
GenerateTCMods3(pass+passno, map);
|
||||||
|
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu]));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec3_t), sizeof(vec3_t)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec2_t));
|
||||||
|
GenerateTCMods(pass+passno, map);
|
||||||
|
d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu]));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec2_t), sizeof(vec2_t)));
|
||||||
|
}
|
||||||
|
tmu++;
|
||||||
|
}
|
||||||
|
/*deactivate any extras*/
|
||||||
|
for (; tmu < shaderstate.lastpasscount; )
|
||||||
|
{
|
||||||
|
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, NULL, 0, 0));
|
||||||
|
BindTexture(tmu, NULL);
|
||||||
|
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_COLOROP, D3DTOP_DISABLE));
|
||||||
|
d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, tmu, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
|
||||||
|
tmu++;
|
||||||
|
}
|
||||||
|
shaderstate.lastpasscount = tmu;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (meshchain->normals_array &&
|
||||||
|
// meshchain->2 &&
|
||||||
|
// meshchain->tnormals_array)
|
||||||
|
// vdec |= D3D_VDEC_NORMS;
|
||||||
|
|
||||||
|
if (vdec != shaderstate.curvertdecl)
|
||||||
|
{
|
||||||
|
shaderstate.curvertdecl = vdec;
|
||||||
|
d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl]));
|
||||||
|
}
|
||||||
|
|
||||||
|
BE_ApplyShaderBits(pass->shaderbits);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BE_SubmitMeshChain(unsigned int vertbase, unsigned int firstvert, unsigned int vertcount, unsigned int idxfirst, int unsigned idxcount)
|
||||||
|
{
|
||||||
|
if (shaderstate.flags & BEF_LINES)
|
||||||
|
IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_LINELIST, vertbase, firstvert, vertcount, idxfirst, idxcount/2);
|
||||||
|
else
|
||||||
|
IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, vertbase, firstvert, vertcount, idxfirst, idxcount/3);
|
||||||
|
RQuantAdd(RQUANT_DRAWS, 1);
|
||||||
|
|
||||||
|
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
|
||||||
|
}
|
||||||
|
|
||||||
static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned int vertfirst, unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount)
|
static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned int vertfirst, unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount)
|
||||||
{
|
{
|
||||||
int vdec = D3D_VDEC_ST0|D3D_VDEC_ST1|D3D_VDEC_NORM;
|
int vdec = D3D_VDEC_ST0|D3D_VDEC_ST1|D3D_VDEC_NORM;
|
||||||
|
@ -2208,7 +2318,7 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in
|
||||||
perm |= PERMUTATION_LIGHTSTYLES;
|
perm |= PERMUTATION_LIGHTSTYLES;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vdec |= BE_GenerateColourMods(vertcount, s->passes);
|
vdec |= D3D_VDEC_COL4B;//BE_GenerateColourMods(vertcount, s->passes);
|
||||||
|
|
||||||
BE_ApplyUniforms(p, perm);
|
BE_ApplyUniforms(p, perm);
|
||||||
|
|
||||||
|
|
|
@ -796,8 +796,6 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette)
|
||||||
|
|
||||||
D3D9_Set2D();
|
D3D9_Set2D();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height);
|
// pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height);
|
||||||
vid.pixelwidth = width;
|
vid.pixelwidth = width;
|
||||||
vid.pixelheight = height;
|
vid.pixelheight = height;
|
||||||
|
@ -1006,10 +1004,12 @@ static qboolean (D3D9_SCR_UpdateScreen) (void)
|
||||||
if (vid_srgb.modified)
|
if (vid_srgb.modified)
|
||||||
{
|
{
|
||||||
vid_srgb.modified = false;
|
vid_srgb.modified = false;
|
||||||
vid.flags &= VID_SRGB_FB;
|
//VID_SRGBAWARE defines whether textures are meant to be srgb or not.
|
||||||
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival)
|
//as it requires a vid_reload, we don't mess with it here.
|
||||||
|
//that said, we can still change srgb freely otherwise.
|
||||||
|
vid.flags &= VID_SRGBAWARE;
|
||||||
|
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival<0)
|
||||||
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
|
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
|
||||||
|
|
||||||
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,8 +1182,13 @@ static void (D3D9_Draw_Init) (void)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
vid_srgb.modified = false;
|
vid_srgb.modified = false;
|
||||||
vid.flags &= VID_SRGB_FB;
|
//VID_SRGBAWARE defines whether textures are meant to be srgb or not.
|
||||||
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival)
|
//we're doing a vid_reload here, so we can change it here easily enough
|
||||||
|
if (vid_srgb.ival > 0) //d3d9 does srgb using post-process stuff for us.
|
||||||
|
vid.flags |= VID_SRGBAWARE;
|
||||||
|
else
|
||||||
|
vid.flags = 0;
|
||||||
|
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival<0)
|
||||||
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
|
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
|
||||||
|
|
||||||
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
|
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
|
||||||
|
@ -1351,6 +1356,7 @@ rendererinfo_t d3d9rendererinfo =
|
||||||
"D3D",
|
"D3D",
|
||||||
"Direct3d",
|
"Direct3d",
|
||||||
"DirectX",
|
"DirectX",
|
||||||
|
"2" //this is evil, but worth a laugh.
|
||||||
},
|
},
|
||||||
QR_DIRECT3D9,
|
QR_DIRECT3D9,
|
||||||
|
|
||||||
|
|
|
@ -802,7 +802,7 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
|
||||||
scd.BufferCount = 1+info->triplebuffer; //back buffer count
|
scd.BufferCount = 1+info->triplebuffer; //back buffer count
|
||||||
if (info->srgb)
|
if (info->srgb)
|
||||||
{
|
{
|
||||||
if (info->srgb >= 3) //fixme: detect properly.
|
if (info->srgb >= 2) //fixme: detect properly.
|
||||||
scd.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; //on nvidia, outputs linear rgb to srgb devices, which means info->srgb is effectively set
|
scd.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; //on nvidia, outputs linear rgb to srgb devices, which means info->srgb is effectively set
|
||||||
else
|
else
|
||||||
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
@ -956,7 +956,7 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
|
||||||
//non-linear formats.
|
//non-linear formats.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((vid.flags & VID_SRGB_FB) && info->srgb != 1)
|
if ((vid.flags & VID_SRGB_FB) && info->srgb >= 0)
|
||||||
vid.flags |= VID_SRGBAWARE;
|
vid.flags |= VID_SRGBAWARE;
|
||||||
|
|
||||||
vid.numpages = scd.BufferCount;
|
vid.numpages = scd.BufferCount;
|
||||||
|
|
|
@ -24,7 +24,6 @@ extern cvar_t gl_overbright;
|
||||||
extern cvar_t r_tessellation;
|
extern cvar_t r_tessellation;
|
||||||
extern cvar_t r_wireframe;
|
extern cvar_t r_wireframe;
|
||||||
extern cvar_t r_refract_fbo;
|
extern cvar_t r_refract_fbo;
|
||||||
extern cvar_t r_refractreflect_scale;
|
|
||||||
|
|
||||||
extern texid_t missing_texture;
|
extern texid_t missing_texture;
|
||||||
extern texid_t missing_texture_gloss;
|
extern texid_t missing_texture_gloss;
|
||||||
|
@ -5132,7 +5131,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||||
|
|
||||||
if ((bs->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects)
|
if ((bs->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects)
|
||||||
{
|
{
|
||||||
float renderscale = r_refractreflect_scale.value;
|
float renderscale = bs->portalfboscale;
|
||||||
vrect_t orect = r_refdef.vrect;
|
vrect_t orect = r_refdef.vrect;
|
||||||
pxrect_t oprect = r_refdef.pxrect;
|
pxrect_t oprect = r_refdef.pxrect;
|
||||||
if (!shaderstate.tex_reflection[r_refdef.recurse])
|
if (!shaderstate.tex_reflection[r_refdef.recurse])
|
||||||
|
@ -5155,7 +5154,13 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||||
shaderstate.tex_reflection[r_refdef.recurse]->width = r_refdef.pxrect.width;
|
shaderstate.tex_reflection[r_refdef.recurse]->width = r_refdef.pxrect.width;
|
||||||
shaderstate.tex_reflection[r_refdef.recurse]->height = r_refdef.pxrect.height;
|
shaderstate.tex_reflection[r_refdef.recurse]->height = r_refdef.pxrect.height;
|
||||||
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection[r_refdef.recurse]);
|
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection[r_refdef.recurse]);
|
||||||
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shaderstate.tex_reflection[r_refdef.recurse]->width, shaderstate.tex_reflection[r_refdef.recurse]->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
if ((vid.flags&VID_FP16) && sh_config.texfmt[PTI_RGBA16F])
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, shaderstate.tex_reflection[r_refdef.recurse]->width, shaderstate.tex_reflection[r_refdef.recurse]->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
else if ((vid.flags&(VID_SRGBAWARE|VID_FP16)) && sh_config.texfmt[PTI_RGBA8_SRGB])
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8_EXT, shaderstate.tex_reflection[r_refdef.recurse]->width, shaderstate.tex_reflection[r_refdef.recurse]->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
else
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shaderstate.tex_reflection[r_refdef.recurse]->width, shaderstate.tex_reflection[r_refdef.recurse]->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -5177,7 +5182,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||||
{
|
{
|
||||||
if (r_refract_fboival || (bs->flags&SHADER_HASPORTAL))
|
if (r_refract_fboival || (bs->flags&SHADER_HASPORTAL))
|
||||||
{
|
{
|
||||||
float renderscale = min(1, r_refractreflect_scale.value);
|
float renderscale = min(1, bs->portalfboscale);
|
||||||
vrect_t ovrect = r_refdef.vrect;
|
vrect_t ovrect = r_refdef.vrect;
|
||||||
pxrect_t oprect = r_refdef.pxrect;
|
pxrect_t oprect = r_refdef.pxrect;
|
||||||
r_refdef.vrect.x = 0;
|
r_refdef.vrect.x = 0;
|
||||||
|
@ -5200,7 +5205,12 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||||
shaderstate.tex_refraction[r_refdef.recurse]->width = r_refdef.pxrect.width;
|
shaderstate.tex_refraction[r_refdef.recurse]->width = r_refdef.pxrect.width;
|
||||||
shaderstate.tex_refraction[r_refdef.recurse]->height = r_refdef.pxrect.height;
|
shaderstate.tex_refraction[r_refdef.recurse]->height = r_refdef.pxrect.height;
|
||||||
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction[r_refdef.recurse]);
|
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction[r_refdef.recurse]);
|
||||||
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
if ((vid.flags&VID_FP16) && sh_config.texfmt[PTI_RGBA16F])
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
else if ((vid.flags&(VID_SRGBAWARE|VID_FP16)) && sh_config.texfmt[PTI_RGBA16F])
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8_EXT, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
else
|
||||||
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -5252,7 +5262,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||||
}
|
}
|
||||||
if ((bs->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
|
if ((bs->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
|
||||||
{
|
{
|
||||||
float renderscale = r_refractreflect_scale.value;
|
float renderscale = bs->portalfboscale;
|
||||||
vrect_t orect = r_refdef.vrect;
|
vrect_t orect = r_refdef.vrect;
|
||||||
pxrect_t oprect = r_refdef.pxrect;
|
pxrect_t oprect = r_refdef.pxrect;
|
||||||
r_refdef.vrect.x = 0;
|
r_refdef.vrect.x = 0;
|
||||||
|
|
|
@ -403,7 +403,7 @@ void GLDraw_Init (void)
|
||||||
|
|
||||||
|
|
||||||
//figure out which extra features we can support on these drivers.
|
//figure out which extra features we can support on these drivers.
|
||||||
r_deluxmapping = r_deluxmapping_cvar.ival;
|
r_deluxemapping = r_deluxemapping_cvar.ival;
|
||||||
r_lightprepass = r_lightprepass_cvar.ival && sh_config.progs_supported;
|
r_lightprepass = r_lightprepass_cvar.ival && sh_config.progs_supported;
|
||||||
r_softwarebanding = r_softwarebanding_cvar.ival && sh_config.progs_supported;
|
r_softwarebanding = r_softwarebanding_cvar.ival && sh_config.progs_supported;
|
||||||
if (gl_config.gles && gl_config.glversion < 3.0)
|
if (gl_config.gles && gl_config.glversion < 3.0)
|
||||||
|
|
|
@ -1131,7 +1131,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
|
||||||
char *buf;
|
char *buf;
|
||||||
char dollname[MAX_QPATH];
|
char dollname[MAX_QPATH];
|
||||||
Q_snprintfz(dollname, sizeof(dollname), "%s.doll", mod->name);
|
Q_snprintfz(dollname, sizeof(dollname), "%s.doll", mod->name);
|
||||||
buf = COM_LoadFile(dollname, 5, &filesize);
|
buf = FS_LoadMallocFile(dollname, &filesize);
|
||||||
if (buf)
|
if (buf)
|
||||||
{
|
{
|
||||||
mod->dollinfo = rag_createdollfromstring(mod, dollname, numbones, buf);
|
mod->dollinfo = rag_createdollfromstring(mod, dollname, numbones, buf);
|
||||||
|
@ -1273,7 +1273,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||||
char altname[MAX_QPATH];
|
char altname[MAX_QPATH];
|
||||||
Q_snprintfz(altname, sizeof(altname), "%s.%s", mdlbase, token);
|
Q_snprintfz(altname, sizeof(altname), "%s.%s", mdlbase, token);
|
||||||
TRACE(("Mod_LoadModel: Trying to load (replacement) model \"%s\"\n", altname));
|
TRACE(("Mod_LoadModel: Trying to load (replacement) model \"%s\"\n", altname));
|
||||||
buf = (unsigned *)COM_LoadFile (altname, 5, &filesize);
|
buf = (unsigned *)FS_LoadMallocFile (altname, &filesize);
|
||||||
|
|
||||||
if (buf)
|
if (buf)
|
||||||
Q_strncpyz(mod->name, altname, sizeof(mod->name));
|
Q_strncpyz(mod->name, altname, sizeof(mod->name));
|
||||||
|
@ -1281,7 +1281,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->publicname));
|
TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->publicname));
|
||||||
buf = (unsigned *)COM_LoadFile (mod->publicname, 5, &filesize);
|
buf = (unsigned *)FS_LoadMallocFile (mod->publicname, &filesize);
|
||||||
if (buf)
|
if (buf)
|
||||||
Q_strncpyz(mod->name, mod->publicname, sizeof(mod->name));
|
Q_strncpyz(mod->name, mod->publicname, sizeof(mod->name));
|
||||||
else if (!buf)
|
else if (!buf)
|
||||||
|
@ -1837,7 +1837,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
||||||
samples = ql2->lmsize;
|
samples = ql2->lmsize;
|
||||||
|
|
||||||
litdata = shifts+ql2->numsurfs;
|
litdata = shifts+ql2->numsurfs;
|
||||||
if (r_deluxmapping)
|
if (r_deluxemapping)
|
||||||
luxdata = litdata+samples*3;
|
luxdata = litdata+samples*3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1906,7 +1906,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!luxdata && r_loadlits.ival && r_deluxmapping)
|
if (!luxdata && r_loadlits.ival && r_deluxemapping)
|
||||||
{ //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous.
|
{ //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous.
|
||||||
char luxname[MAX_QPATH];
|
char luxname[MAX_QPATH];
|
||||||
size_t luxsz = 0;
|
size_t luxsz = 0;
|
||||||
|
@ -1971,14 +1971,14 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RUNTIMELIGHTING
|
#ifdef RUNTIMELIGHTING
|
||||||
if (!lightmodel && r_loadlits.value == 2 && (!litdata || (!luxdata && r_deluxmapping)))
|
if (!lightmodel && r_loadlits.value == 2 && (!litdata || (!luxdata && r_deluxemapping)))
|
||||||
{
|
{
|
||||||
writelitfile = !litdata;
|
writelitfile = !litdata;
|
||||||
numlightdata = l->filelen;
|
numlightdata = l->filelen;
|
||||||
lightmodel = loadmodel;
|
lightmodel = loadmodel;
|
||||||
relitsurface = 0;
|
relitsurface = 0;
|
||||||
}
|
}
|
||||||
else if (!lightmodel && r_deluxmapping_cvar.value>1 && r_deluxmapping && !luxdata
|
else if (!lightmodel && r_deluxemapping_cvar.value>1 && r_deluxemapping && !luxdata
|
||||||
#ifdef RTLIGHTS
|
#ifdef RTLIGHTS
|
||||||
&& !(r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value<=0)
|
&& !(r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value<=0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -2008,7 +2008,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*if we're relighting, make sure there's the proper lux data to be updated*/
|
/*if we're relighting, make sure there's the proper lux data to be updated*/
|
||||||
if (lightmodel == loadmodel && r_deluxmapping && !luxdata)
|
if (lightmodel == loadmodel && r_deluxemapping && !luxdata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
luxdata = ZG_Malloc(&loadmodel->memgroup, samples*3);
|
luxdata = ZG_Malloc(&loadmodel->memgroup, samples*3);
|
||||||
|
|
|
@ -1064,7 +1064,7 @@ qboolean R_LoadRTLights(void)
|
||||||
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
|
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
|
||||||
strncat(fname, ".rtlights", MAX_QPATH-1);
|
strncat(fname, ".rtlights", MAX_QPATH-1);
|
||||||
|
|
||||||
file = COM_LoadTempFile(fname, NULL);
|
file = COM_LoadTempFile(fname, 0, NULL);
|
||||||
if (file)
|
if (file)
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1987,7 +1987,7 @@ void GLR_RenderView (void)
|
||||||
}
|
}
|
||||||
else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || forcedfb)
|
else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || forcedfb)
|
||||||
{
|
{
|
||||||
unsigned int rtflags = IF_NOMIPMAP|IF_CLAMP|IF_RENDERTARGET;
|
unsigned int rtflags = IF_NOMIPMAP|IF_CLAMP|IF_RENDERTARGET|IF_NOSRGB;
|
||||||
enum uploadfmt fmt;
|
enum uploadfmt fmt;
|
||||||
|
|
||||||
r_refdef.flags |= RDF_RENDERSCALE;
|
r_refdef.flags |= RDF_RENDERSCALE;
|
||||||
|
|
|
@ -321,7 +321,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr)
|
||||||
else if (!Q_stricmp(token, "lightmap"))
|
else if (!Q_stricmp(token, "lightmap"))
|
||||||
lhs = !r_fullbright.value;
|
lhs = !r_fullbright.value;
|
||||||
else if (!Q_stricmp(token, "deluxmap") || !Q_stricmp(token, "deluxe"))
|
else if (!Q_stricmp(token, "deluxmap") || !Q_stricmp(token, "deluxe"))
|
||||||
lhs = r_deluxmapping;
|
lhs = r_deluxemapping;
|
||||||
else if (!Q_stricmp(token, "softwarebanding"))
|
else if (!Q_stricmp(token, "softwarebanding"))
|
||||||
lhs = r_softwarebanding;
|
lhs = r_softwarebanding;
|
||||||
|
|
||||||
|
@ -374,7 +374,7 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr)
|
||||||
// else if (!Q_stricmp(token, "GLSL"))
|
// else if (!Q_stricmp(token, "GLSL"))
|
||||||
// lhs = 1;
|
// lhs = 1;
|
||||||
else if (!Q_stricmp(token, "deluxeMaps") || !Q_stricmp(token, "deluxe"))
|
else if (!Q_stricmp(token, "deluxeMaps") || !Q_stricmp(token, "deluxe"))
|
||||||
lhs = r_deluxmapping;
|
lhs = r_deluxemapping;
|
||||||
else if (!Q_stricmp(token, "portalMaps"))
|
else if (!Q_stricmp(token, "portalMaps"))
|
||||||
lhs = false;
|
lhs = false;
|
||||||
//end qfusion
|
//end qfusion
|
||||||
|
@ -1149,21 +1149,21 @@ const struct sh_defaultsamplers_s sh_defaultsamplers[] =
|
||||||
{"s_reflectcube", 1u<<9},
|
{"s_reflectcube", 1u<<9},
|
||||||
{"s_reflectmask", 1u<<10},
|
{"s_reflectmask", 1u<<10},
|
||||||
{"s_lightmap", 1u<<11},
|
{"s_lightmap", 1u<<11},
|
||||||
{"s_deluxmap", 1u<<12},
|
{"s_deluxemap", 1u<<12},
|
||||||
#if MAXRLIGHTMAPS > 1
|
#if MAXRLIGHTMAPS > 1
|
||||||
{"s_lightmap1", 1u<<13},
|
{"s_lightmap1", 1u<<13},
|
||||||
{"s_lightmap2", 1u<<14},
|
{"s_lightmap2", 1u<<14},
|
||||||
{"s_lightmap3", 1u<<15},
|
{"s_lightmap3", 1u<<15},
|
||||||
{"s_deluxmap1", 1u<<16},
|
{"s_deluxemap1", 1u<<16},
|
||||||
{"s_deluxmap2", 1u<<17},
|
{"s_deluxemap2", 1u<<17},
|
||||||
{"s_deluxmap3", 1u<<18},
|
{"s_deluxemap3", 1u<<18},
|
||||||
#else
|
#else
|
||||||
{"s_lightmap1", 0},
|
{"s_lightmap1", 0},
|
||||||
{"s_lightmap2", 0},
|
{"s_lightmap2", 0},
|
||||||
{"s_lightmap3", 0},
|
{"s_lightmap3", 0},
|
||||||
{"s_deluxmap1", 0},
|
{"s_deluxemap1", 0},
|
||||||
{"s_deluxmap2", 0},
|
{"s_deluxemap2", 0},
|
||||||
{"s_deluxmap3", 0},
|
{"s_deluxemap3", 0},
|
||||||
#endif
|
#endif
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
@ -1258,6 +1258,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
||||||
script += 7;
|
script += 7;
|
||||||
while (*script != '\n' && *script != '\r')
|
while (*script != '\n' && *script != '\r')
|
||||||
{
|
{
|
||||||
|
size_t len;
|
||||||
int i;
|
int i;
|
||||||
char *start;
|
char *start;
|
||||||
while (*script == ' ' || *script == '\t')
|
while (*script == ' ' || *script == '\t')
|
||||||
|
@ -1266,9 +1267,18 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
||||||
while (*script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
|
while (*script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
|
||||||
script++;
|
script++;
|
||||||
|
|
||||||
|
#ifndef NOLEGACY
|
||||||
|
if (script-start >= 8 && !strncmp(start, "deluxmap", 8))
|
||||||
|
{ //FIXME: remove this some time.
|
||||||
|
start = va("deluxemap%s",start+8);
|
||||||
|
len = strlen(start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
len = script-start;
|
||||||
for (i = 0; sh_defaultsamplers[i].name; i++)
|
for (i = 0; sh_defaultsamplers[i].name; i++)
|
||||||
{
|
{
|
||||||
if (!strncmp(start, sh_defaultsamplers[i].name+2, script-start) && sh_defaultsamplers[i].name[2+script-start] == 0)
|
if (!strncmp(start, sh_defaultsamplers[i].name+2, len) && sh_defaultsamplers[i].name[2+len] == 0)
|
||||||
{
|
{
|
||||||
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
|
prog->defaulttextures |= sh_defaultsamplers[i].defaulttexbits;
|
||||||
break;
|
break;
|
||||||
|
@ -1656,7 +1666,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
||||||
permutationdefines[pn++] = "#define RELIEFMAPPING\n";
|
permutationdefines[pn++] = "#define RELIEFMAPPING\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_deluxmapping) //fixme: should be per-model really
|
if (r_deluxemapping) //fixme: should be per-model really
|
||||||
permutationdefines[pn++] = "#define DELUXE\n";
|
permutationdefines[pn++] = "#define DELUXE\n";
|
||||||
}
|
}
|
||||||
permutationdefines[pn++] = NULL;
|
permutationdefines[pn++] = NULL;
|
||||||
|
@ -1832,7 +1842,7 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
|
||||||
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
Con_DPrintf("Loaded %s from disk\n", sh_config.progpath?va(sh_config.progpath, basicname):basicname);
|
// Con_DPrintf("Loaded %s from disk\n", sh_config.progpath?va(sh_config.progpath, basicname):basicname);
|
||||||
g->failed = !Shader_LoadPermutations(g->name, &g->prog, file, qrtype, 0, blobname);
|
g->failed = !Shader_LoadPermutations(g->name, &g->prog, file, qrtype, 0, blobname);
|
||||||
FS_FreeFile(file);
|
FS_FreeFile(file);
|
||||||
return;
|
return;
|
||||||
|
@ -1860,6 +1870,18 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *Shader_NameForGeneric(program_t *prog)
|
||||||
|
{
|
||||||
|
sgeneric_t *g;
|
||||||
|
for (g = sgenerics; g; g = g->next)
|
||||||
|
{
|
||||||
|
if (prog == &g->prog)
|
||||||
|
return g->name;
|
||||||
|
}
|
||||||
|
return "INLINE";
|
||||||
|
}
|
||||||
|
|
||||||
program_t *Shader_FindGeneric(char *name, int qrtype)
|
program_t *Shader_FindGeneric(char *name, int qrtype)
|
||||||
{
|
{
|
||||||
sgeneric_t *g;
|
sgeneric_t *g;
|
||||||
|
@ -1982,51 +2004,55 @@ struct shader_field_names_s shader_attr_names[] =
|
||||||
|
|
||||||
struct shader_field_names_s shader_unif_names[] =
|
struct shader_field_names_s shader_unif_names[] =
|
||||||
{
|
{
|
||||||
|
/**///tagged names are available to vulkan
|
||||||
|
|
||||||
/*matricies*/
|
/*matricies*/
|
||||||
{"m_model", SP_M_MODEL},
|
/**/{"m_model", SP_M_MODEL}, //the model matrix
|
||||||
{"m_view", SP_M_VIEW},
|
{"m_view", SP_M_VIEW}, //the view matrix
|
||||||
{"m_modelview", SP_M_MODELVIEW},
|
{"m_modelview", SP_M_MODELVIEW},//the combined modelview matrix
|
||||||
{"m_projection", SP_M_PROJECTION},
|
{"m_projection", SP_M_PROJECTION},//projection matrix
|
||||||
{"m_modelviewprojection", SP_M_MODELVIEWPROJECTION},
|
/**/{"m_modelviewprojection", SP_M_MODELVIEWPROJECTION},//fancy mvp matrix. probably has degraded precision.
|
||||||
{"m_bones", SP_M_ENTBONES},
|
{"m_bones", SP_M_ENTBONES}, //bone matrix array. should normally be read via sys/skeletal.h
|
||||||
{"m_invviewprojection", SP_M_INVVIEWPROJECTION},
|
{"m_invviewprojection", SP_M_INVVIEWPROJECTION},//inverted vp matrix
|
||||||
{"m_invmodelviewprojection",SP_M_INVMODELVIEWPROJECTION},
|
{"m_invmodelviewprojection",SP_M_INVMODELVIEWPROJECTION},//inverted mvp matrix.
|
||||||
|
/**///m_modelinv
|
||||||
|
|
||||||
/*viewer properties*/
|
/*viewer properties*/
|
||||||
{"v_eyepos", SP_V_EYEPOS},
|
{"v_eyepos", SP_V_EYEPOS}, //eye pos in worldspace
|
||||||
{"w_fog", SP_W_FOG},
|
/**/{"w_fog", SP_W_FOG}, //read by sys/fog.h
|
||||||
{"w_user", SP_W_USER},
|
{"w_user", SP_W_USER}, //set via VF_USERDATA
|
||||||
|
|
||||||
/*ent properties*/
|
/*ent properties*/
|
||||||
{"e_vblend", SP_E_VBLEND},
|
{"e_vblend", SP_E_VBLEND}, //v_position1+v_position2 scalers
|
||||||
{"e_lmscale", SP_E_LMSCALE}, /*overbright shifting*/
|
/**/{"e_lmscale", SP_E_LMSCALE}, /*overbright shifting*/
|
||||||
{"e_vlscale", SP_E_VLSCALE}, /*no lightmaps, no overbrights*/
|
{"e_vlscale", SP_E_VLSCALE}, /*no lightmaps, no overbrights*/
|
||||||
{"e_origin", SP_E_ORIGIN},
|
{"e_origin", SP_E_ORIGIN}, //the ents origin in worldspace
|
||||||
{"e_time", SP_E_TIME},
|
/**/{"e_time", SP_E_TIME}, //r_refdef.time - entity->time
|
||||||
{"e_eyepos", SP_E_EYEPOS},
|
/**/{"e_eyepos", SP_E_EYEPOS}, //eye pos in modelspace
|
||||||
{"e_colour", SP_E_COLOURS},
|
{"e_colour", SP_E_COLOURS}, //colormod/alpha, even if colormod isn't set
|
||||||
{"e_colourident", SP_E_COLOURSIDENT},
|
/**/{"e_colourident", SP_E_COLOURSIDENT}, //colormod,alpha or 1,1,1,alpha if colormod isn't set
|
||||||
{"e_glowmod", SP_E_GLOWMOD},
|
/**/{"e_glowmod", SP_E_GLOWMOD}, //fullbright scalers (for hdr mostly)
|
||||||
{"e_uppercolour", SP_E_TOPCOLOURS},
|
/**/{"e_uppercolour", SP_E_TOPCOLOURS}, //q1 player colours
|
||||||
{"e_lowercolour", SP_E_BOTTOMCOLOURS},
|
/**/{"e_lowercolour", SP_E_BOTTOMCOLOURS},//q1 player colours
|
||||||
{"e_light_dir", SP_E_L_DIR},
|
/**/{"e_light_dir", SP_E_L_DIR}, //lightgrid light dir. dotproducts should be clamped to 0-1.
|
||||||
{"e_light_mul", SP_E_L_MUL},
|
/**/{"e_light_mul", SP_E_L_MUL}, //lightgrid light scaler.
|
||||||
{"e_light_ambient", SP_E_L_AMBIENT},
|
/**/{"e_light_ambient", SP_E_L_AMBIENT}, //lightgrid light value for the unlit side.
|
||||||
|
|
||||||
{"s_colour", SP_S_COLOUR},
|
{"s_colour", SP_S_COLOUR}, //the rgbgen/alphagen stuff. obviously doesn't work with per-vertex ones.
|
||||||
|
|
||||||
/*rtlight properties, use with caution*/
|
/*rtlight properties, use with caution*/
|
||||||
{"l_lightscreen", SP_LIGHTSCREEN},
|
{"l_lightscreen", SP_LIGHTSCREEN}, //screenspace position of the current rtlight
|
||||||
{"l_lightradius", SP_LIGHTRADIUS},
|
/**/{"l_lightradius", SP_LIGHTRADIUS}, //radius of the current rtlight
|
||||||
{"l_lightcolour", SP_LIGHTCOLOUR},
|
/**/{"l_lightcolour", SP_LIGHTCOLOUR}, //rgb values of the current rtlight
|
||||||
{"l_lightposition", SP_LIGHTPOSITION},
|
/**/{"l_lightposition", SP_LIGHTPOSITION}, //light position in modelspace
|
||||||
{"l_lightcolourscale", SP_LIGHTCOLOURSCALE},
|
/**/{"l_lightcolourscale", SP_LIGHTCOLOURSCALE},//ambient/diffuse/specular scalers
|
||||||
{"l_cubematrix", SP_LIGHTCUBEMATRIX},
|
/**/{"l_cubematrix", SP_LIGHTCUBEMATRIX},//matrix used to control the rtlight's cubemap projection
|
||||||
{"l_shadowmapproj", SP_LIGHTSHADOWMAPPROJ},
|
/**/{"l_shadowmapproj", SP_LIGHTSHADOWMAPPROJ}, //compacted projection matrix for shadowmaps
|
||||||
{"l_shadowmapscale", SP_LIGHTSHADOWMAPSCALE},
|
/**/{"l_shadowmapscale", SP_LIGHTSHADOWMAPSCALE},//should probably use a samplerRect instead...
|
||||||
|
|
||||||
|
{"e_sourcesize", SP_SOURCESIZE}, //size of VF_SOURCECOLOUR image
|
||||||
|
{"e_rendertexturescale", SP_RENDERTEXTURESCALE}, //scaler for $currentrender, when npot isn't supported.
|
||||||
|
|
||||||
{"e_sourcesize", SP_SOURCESIZE},
|
|
||||||
{"e_rendertexturescale", SP_RENDERTEXTURESCALE},
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2434,6 +2460,12 @@ static void Shader_Translucent(shader_t *shader, shaderpass_t *pass, char **ptr)
|
||||||
shader->flags |= SHADER_BLEND;
|
shader->flags |= SHADER_BLEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Shader_PortalFBOScale(shader_t *shader, shaderpass_t *pass, char **ptr)
|
||||||
|
{
|
||||||
|
shader->portalfboscale = Shader_ParseFloat(shader, ptr, 0);
|
||||||
|
shader->portalfboscale = max(shader->portalfboscale, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void Shader_DP_Camera(shader_t *shader, shaderpass_t *pass, char **ptr)
|
static void Shader_DP_Camera(shader_t *shader, shaderpass_t *pass, char **ptr)
|
||||||
{
|
{
|
||||||
shader->sort = SHADER_SORT_PORTAL;
|
shader->sort = SHADER_SORT_PORTAL;
|
||||||
|
@ -2623,6 +2655,7 @@ static shaderkey_t shaderkeys[] =
|
||||||
{"uppermap", Shader_UpperMap, "fte"},
|
{"uppermap", Shader_UpperMap, "fte"},
|
||||||
{"lowermap", Shader_LowerMap, "fte"},
|
{"lowermap", Shader_LowerMap, "fte"},
|
||||||
{"reflectmask", Shader_ReflectMask, "fte"},
|
{"reflectmask", Shader_ReflectMask, "fte"},
|
||||||
|
{"portalfboscale", Shader_PortalFBOScale, "fte"}, //portal/mirror/refraction/reflection FBOs are resized by this scale
|
||||||
|
|
||||||
/*program stuff at the material level is an outdated practise.*/
|
/*program stuff at the material level is an outdated practise.*/
|
||||||
{"program", Shader_ProgramName, "fte"}, //usable with any renderer that has a usable shader language...
|
{"program", Shader_ProgramName, "fte"}, //usable with any renderer that has a usable shader language...
|
||||||
|
@ -4087,6 +4120,7 @@ char *Shader_Skip ( char *ptr )
|
||||||
|
|
||||||
void Shader_Reset(shader_t *s)
|
void Shader_Reset(shader_t *s)
|
||||||
{
|
{
|
||||||
|
extern cvar_t r_refractreflect_scale;
|
||||||
char name[MAX_QPATH];
|
char name[MAX_QPATH];
|
||||||
int id = s->id;
|
int id = s->id;
|
||||||
int uses = s->uses;
|
int uses = s->uses;
|
||||||
|
@ -4103,6 +4137,7 @@ void Shader_Reset(shader_t *s)
|
||||||
s->defaulttextures = NULL;
|
s->defaulttextures = NULL;
|
||||||
Shader_Free(s);
|
Shader_Free(s);
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
|
s->portalfboscale = r_refractreflect_scale.value; //unless otherwise specified, this cvar specifies the value.
|
||||||
|
|
||||||
s->remapto = s;
|
s->remapto = s;
|
||||||
s->id = id;
|
s->id = id;
|
||||||
|
@ -6819,15 +6854,42 @@ static qboolean Shader_ParseShader(char *parsename, shader_t *s)
|
||||||
size_t offset = 0, length;
|
size_t offset = 0, length;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
shadercachefile_t *sourcefile = NULL;
|
shadercachefile_t *sourcefile = NULL;
|
||||||
|
char *file;
|
||||||
|
const char *token;
|
||||||
|
|
||||||
|
//if the named shader is a .shader file then just directly load it.
|
||||||
|
token = COM_GetFileExtension(parsename, NULL);
|
||||||
|
if (!strcmp(token, ".shader") || !*token)
|
||||||
|
{
|
||||||
|
char shaderfile[MAX_QPATH];
|
||||||
|
if (!*token)
|
||||||
|
{
|
||||||
|
Q_snprintfz(shaderfile, sizeof(shaderfile), "%s.shader", parsename);
|
||||||
|
file = COM_LoadTempMoreFile(shaderfile, &length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
file = COM_LoadTempMoreFile(parsename, &length);
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
Shader_Reset(s);
|
||||||
|
token = COM_ParseExt (&file, true, false); //we need to skip over the leading {.
|
||||||
|
if (*token != '{')
|
||||||
|
token = COM_ParseExt (&file, true, false); //try again, in case we found some legacy name.
|
||||||
|
if (*token == '{')
|
||||||
|
{
|
||||||
|
Shader_ReadShader(s, file, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Con_Printf("file %s.shader does not appear to contain a shader\n", shaderfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Shader_LocateSource(parsename, &buf, &length, &offset, &sourcefile))
|
if (Shader_LocateSource(parsename, &buf, &length, &offset, &sourcefile))
|
||||||
{
|
{
|
||||||
// the shader is in the shader scripts
|
// the shader is in the shader scripts
|
||||||
if (buf && offset < length )
|
if (buf && offset < length )
|
||||||
{
|
{
|
||||||
char *file, *token;
|
|
||||||
|
|
||||||
|
|
||||||
file = buf + offset;
|
file = buf + offset;
|
||||||
token = COM_ParseExt (&file, true, true);
|
token = COM_ParseExt (&file, true, true);
|
||||||
if ( !file || token[0] != '{' )
|
if ( !file || token[0] != '{' )
|
||||||
|
@ -6974,8 +7036,9 @@ static shader_t *R_LoadShader (const char *name, unsigned int usageflags, shader
|
||||||
}
|
}
|
||||||
if (Shader_ParseShader(cleanname, s))
|
if (Shader_ParseShader(cleanname, s))
|
||||||
return s;
|
return s;
|
||||||
if (Shader_ParseShader(shortname, s))
|
if (strcmp(cleanname, shortname))
|
||||||
return s;
|
if (Shader_ParseShader(shortname, s))
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a default shader
|
// make a default shader
|
||||||
|
@ -7045,7 +7108,7 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
|
||||||
|
|
||||||
if (p->prog)
|
if (p->prog)
|
||||||
{
|
{
|
||||||
sprintf(o, "program\n");
|
sprintf(o, "program %s\n", Shader_NameForGeneric(p->prog));
|
||||||
o+=strlen(o);
|
o+=strlen(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7277,7 +7340,7 @@ char *Shader_Decompose(shader_t *s)
|
||||||
|
|
||||||
if (s->prog)
|
if (s->prog)
|
||||||
{
|
{
|
||||||
sprintf(o, "program\n");
|
sprintf(o, "program %s\n", Shader_NameForGeneric(s->prog));
|
||||||
o+=strlen(o);
|
o+=strlen(o);
|
||||||
|
|
||||||
p = s->passes;
|
p = s->passes;
|
||||||
|
@ -7396,6 +7459,8 @@ char *Shader_GetShaderBody(shader_t *s, char *fname, size_t fnamesize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
saveshaderbody = NULL;
|
||||||
return adr;
|
return adr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7526,8 +7591,9 @@ void Shader_DoReload(void)
|
||||||
}
|
}
|
||||||
if (Shader_ParseShader(cleanname, s))
|
if (Shader_ParseShader(cleanname, s))
|
||||||
continue;
|
continue;
|
||||||
if (Shader_ParseShader(shortname, s))
|
if (strcmp(cleanname, shortname))
|
||||||
continue;
|
if (Shader_ParseShader(shortname, s))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (s->generator)
|
if (s->generator)
|
||||||
{
|
{
|
||||||
|
@ -7666,7 +7732,7 @@ void Shader_RemapShader_f(void)
|
||||||
char *destname = Cmd_Argv(2);
|
char *destname = Cmd_Argv(2);
|
||||||
float timeoffset = atof(Cmd_Argv(3));
|
float timeoffset = atof(Cmd_Argv(3));
|
||||||
|
|
||||||
if (!Cmd_FromGamecode() && strcmp(Info_ValueForKey(cl.serverinfo, "*cheats"), "ON"))
|
if (!Cmd_FromGamecode() && strcmp(InfoBuf_ValueForKey(&cl.serverinfo, "*cheats"), "ON"))
|
||||||
{
|
{
|
||||||
Con_Printf("%s may only be used from gamecode, or when cheats are enabled\n", Cmd_Argv(0));
|
Con_Printf("%s may only be used from gamecode, or when cheats are enabled\n", Cmd_Argv(0));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1353,16 +1353,23 @@ static const char *glsl_hdrs[] =
|
||||||
"uniform samplerCube s_reflectcube;"
|
"uniform samplerCube s_reflectcube;"
|
||||||
"uniform sampler2D s_reflectmask;"
|
"uniform sampler2D s_reflectmask;"
|
||||||
"uniform sampler2D s_lightmap;"
|
"uniform sampler2D s_lightmap;"
|
||||||
"uniform sampler2D s_deluxmap;"
|
"uniform sampler2D s_deluxemap;"
|
||||||
"\n#define s_lightmap0 s_lightmap\n"
|
"\n#define s_lightmap0 s_lightmap\n"
|
||||||
"#define s_deluxmap0 s_deluxmap\n"
|
"#define s_deluxemap0 s_deluxemap\n"
|
||||||
#if MAXRLIGHTMAPS > 1
|
#if MAXRLIGHTMAPS > 1
|
||||||
"uniform sampler2D s_lightmap1;"
|
"uniform sampler2D s_lightmap1;"
|
||||||
"uniform sampler2D s_lightmap2;"
|
"uniform sampler2D s_lightmap2;"
|
||||||
"uniform sampler2D s_lightmap3;"
|
"uniform sampler2D s_lightmap3;"
|
||||||
"uniform sampler2D s_deluxmap1;"
|
"uniform sampler2D s_deluxemap1;"
|
||||||
"uniform sampler2D s_deluxmap2;"
|
"uniform sampler2D s_deluxemap2;"
|
||||||
"uniform sampler2D s_deluxmap3;\n"
|
"uniform sampler2D s_deluxemap3;\n"
|
||||||
|
|
||||||
|
//FIXME: remove these some time.
|
||||||
|
// "#define s_deluxmap s_deluxemap\n"
|
||||||
|
// "#define s_deluxmap0 s_deluxemap0\n"
|
||||||
|
// "#define s_deluxmap1 s_deluxemap1\n"
|
||||||
|
// "#define s_deluxmap2 s_deluxemap2\n"
|
||||||
|
// "#define s_deluxmap3 s_deluxemap3\n"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
"#ifdef USEUBOS\n"
|
"#ifdef USEUBOS\n"
|
||||||
|
@ -2107,14 +2114,14 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
|
||||||
"uniform samplerCube s_reflectcube;\n",
|
"uniform samplerCube s_reflectcube;\n",
|
||||||
"uniform sampler2D s_reflectmask;\n",
|
"uniform sampler2D s_reflectmask;\n",
|
||||||
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
|
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
|
||||||
"uniform sampler2D s_deluxmap;\n#define s_deluxmap0 s_deluxmap\n",
|
"uniform sampler2D s_deluxemap;\n#define s_deluxemap0 s_deluxemap\n",
|
||||||
|
|
||||||
"uniform sampler2D s_lightmap1;\n",
|
"uniform sampler2D s_lightmap1;\n",
|
||||||
"uniform sampler2D s_lightmap2;\n",
|
"uniform sampler2D s_lightmap2;\n",
|
||||||
"uniform sampler2D s_lightmap3;\n",
|
"uniform sampler2D s_lightmap3;\n",
|
||||||
"uniform sampler2D s_deluxmap1;\n",
|
"uniform sampler2D s_deluxemap1;\n",
|
||||||
"uniform sampler2D s_deluxmap2;\n",
|
"uniform sampler2D s_deluxemap2;\n",
|
||||||
"uniform sampler2D s_deluxmap3;\n",
|
"uniform sampler2D s_deluxemap3;\n",
|
||||||
};
|
};
|
||||||
for (i = 0; i < countof(defaultsamplernames); i++)
|
for (i = 0; i < countof(defaultsamplernames); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1506,6 +1506,19 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
|
||||||
|
|
||||||
if (!GL_Init(info, getglfunc))
|
if (!GL_Init(info, getglfunc))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (qwglGetPixelFormatAttribfvARB) //just for debugging info.
|
||||||
|
{
|
||||||
|
int iAttributeNames[] = {WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB, WGL_ALPHA_BITS_ARB, WGL_PIXEL_TYPE_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB};
|
||||||
|
float fAttributeValues[countof(iAttributeNames)] = {0};
|
||||||
|
if (qwglGetPixelFormatAttribfvARB(maindc, currentpixelformat, 0, countof(iAttributeNames), iAttributeNames, fAttributeValues))
|
||||||
|
{
|
||||||
|
Con_DPrintf("Colour buffer: GL_R%gG%gB%gA%g%s\n", fAttributeValues[0], fAttributeValues[1], fAttributeValues[2], fAttributeValues[3], fAttributeValues[5]==WGL_TYPE_RGBA_FLOAT_ARB?"F":((vid.flags & VID_SRGBAWARE)?"_SRGB":""));
|
||||||
|
Con_DPrintf("Depth buffer: GL_DEPTH%g_STENCIL%g\n", fAttributeValues[5], fAttributeValues[6]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
qSwapBuffers(maindc);
|
qSwapBuffers(maindc);
|
||||||
|
|
||||||
#ifdef VKQUAKE
|
#ifdef VKQUAKE
|
||||||
|
@ -2299,7 +2312,7 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
|
||||||
iAttribute[iAttributes++] = WGL_SUPPORT_OPENGL_ARB; iAttribute[iAttributes++] = GL_TRUE;
|
iAttribute[iAttributes++] = WGL_SUPPORT_OPENGL_ARB; iAttribute[iAttributes++] = GL_TRUE;
|
||||||
iAttribute[iAttributes++] = WGL_ACCELERATION_ARB; iAttribute[iAttributes++] = WGL_FULL_ACCELERATION_ARB;
|
iAttribute[iAttributes++] = WGL_ACCELERATION_ARB; iAttribute[iAttributes++] = WGL_FULL_ACCELERATION_ARB;
|
||||||
|
|
||||||
if (info->srgb>=3 && modestate != MS_WINDOWED)
|
if (info->srgb>=2 && modestate != MS_WINDOWED)
|
||||||
{ //half-float backbuffers!
|
{ //half-float backbuffers!
|
||||||
|
|
||||||
//'as has been the case since Windows Vista, fp16 swap chains are expected to have linear color data'
|
//'as has been the case since Windows Vista, fp16 swap chains are expected to have linear color data'
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -592,6 +592,7 @@ struct shader_s
|
||||||
byte_vec4_t fog_color;
|
byte_vec4_t fog_color;
|
||||||
float fog_dist;
|
float fog_dist;
|
||||||
float portaldist;
|
float portaldist;
|
||||||
|
float portalfboscale; //if we're using texturemaps for portal recursion, this is the scale of the texture relative to the screen.
|
||||||
|
|
||||||
int numdeforms;
|
int numdeforms;
|
||||||
deformv_t deforms[SHADER_DEFORM_MAX];
|
deformv_t deforms[SHADER_DEFORM_MAX];
|
||||||
|
@ -714,6 +715,7 @@ void Shader_RemapShader_f(void);
|
||||||
void Shader_ShowShader_f(void);
|
void Shader_ShowShader_f(void);
|
||||||
|
|
||||||
program_t *Shader_FindGeneric(char *name, int qrtype);
|
program_t *Shader_FindGeneric(char *name, int qrtype);
|
||||||
|
const char *Shader_NameForGeneric(program_t *prog);
|
||||||
void Shader_ReleaseGeneric(program_t *prog);
|
void Shader_ReleaseGeneric(program_t *prog);
|
||||||
|
|
||||||
mfog_t *Mod_FogForOrigin(model_t *wmodel, vec3_t org);
|
mfog_t *Mod_FogForOrigin(model_t *wmodel, vec3_t org);
|
||||||
|
@ -838,7 +840,11 @@ qboolean GLBE_BeginShadowMap(int id, int w, int h, int *restorefbo);
|
||||||
void GLBE_EndShadowMap(int restorefbo);
|
void GLBE_EndShadowMap(int restorefbo);
|
||||||
void GLBE_SetupForShadowMap(dlight_t *dl, int texwidth, int texheight, float shadowscale);
|
void GLBE_SetupForShadowMap(dlight_t *dl, int texwidth, int texheight, float shadowscale);
|
||||||
|
|
||||||
|
qboolean GLVID_ApplyGammaRamps (unsigned int size, unsigned short *ramps); //called when gamma ramps need to be reapplied
|
||||||
|
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette); //the platform-specific function to init gl state
|
||||||
|
void GLVID_SwapBuffers(void);
|
||||||
|
char *GLVID_GetRGBInfo(int *bytestride, int *truewidth, int *trueheight, enum uploadfmt *fmt);
|
||||||
|
void GLVID_SetCaption(const char *caption);
|
||||||
#endif
|
#endif
|
||||||
#ifdef D3D8QUAKE
|
#ifdef D3D8QUAKE
|
||||||
void D3D8BE_Init(void);
|
void D3D8BE_Init(void);
|
||||||
|
|
|
@ -525,7 +525,12 @@ int DecompileReadData(char *srcfilename, char *buf, size_t bufsize)
|
||||||
|
|
||||||
memcpy(&progs, buf, sizeof(progs));
|
memcpy(&progs, buf, sizeof(progs));
|
||||||
|
|
||||||
if (progs.version == PROG_VERSION)
|
if (progs.version == PROG_QTESTVERSION)
|
||||||
|
{
|
||||||
|
defsz = -32; //ddefs_t is 32bit
|
||||||
|
stsz = -16; //statements is mostly 16bit. there's some line numbers in there too.
|
||||||
|
}
|
||||||
|
else if (progs.version == PROG_VERSION)
|
||||||
stsz = defsz = 16;
|
stsz = defsz = 16;
|
||||||
else if (progs.version == 7)
|
else if (progs.version == 7)
|
||||||
{
|
{
|
||||||
|
@ -559,8 +564,10 @@ int DecompileReadData(char *srcfilename, char *buf, size_t bufsize)
|
||||||
|
|
||||||
// if (numstatements > MAX_STATEMENTS)
|
// if (numstatements > MAX_STATEMENTS)
|
||||||
// Sys_Error("Too many statements");
|
// Sys_Error("Too many statements");
|
||||||
if (stsz == 16)
|
if (stsz == 32)
|
||||||
{
|
statements = (dstatement32_t*)(buf+progs.ofs_statements);
|
||||||
|
else if (stsz == 16)
|
||||||
|
{ //need to expand the statements to 32bit.
|
||||||
const dstatement16_t *statements6 = (const dstatement16_t*)(buf+progs.ofs_statements);
|
const dstatement16_t *statements6 = (const dstatement16_t*)(buf+progs.ofs_statements);
|
||||||
statements = malloc(numstatements * sizeof(*statements));
|
statements = malloc(numstatements * sizeof(*statements));
|
||||||
for (i = 0; i < numstatements; i++)
|
for (i = 0; i < numstatements; i++)
|
||||||
|
@ -582,8 +589,29 @@ int DecompileReadData(char *srcfilename, char *buf, size_t bufsize)
|
||||||
statements[i].c = (unsigned short)statements6[i].c;
|
statements[i].c = (unsigned short)statements6[i].c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (stsz == 32)
|
else if (stsz == -16)
|
||||||
statements = (dstatement32_t*)(buf+progs.ofs_statements);
|
{
|
||||||
|
const qtest_statement_t *statements3 = (const qtest_statement_t*)(buf+progs.ofs_statements);
|
||||||
|
statements = malloc(numstatements * sizeof(*statements));
|
||||||
|
for (i = 0; i < numstatements; i++)
|
||||||
|
{
|
||||||
|
statements[i].op = statements3[i].op;
|
||||||
|
|
||||||
|
if (statements[i].op == OP_GOTO)
|
||||||
|
statements[i].a = (signed short)statements3[i].a;
|
||||||
|
else
|
||||||
|
statements[i].a = (unsigned short)statements3[i].a;
|
||||||
|
|
||||||
|
if (statements[i].op == OP_IF_I || statements[i].op == OP_IFNOT_I ||
|
||||||
|
statements[i].op == OP_IF_F || statements[i].op == OP_IFNOT_F ||
|
||||||
|
statements[i].op == OP_IF_S || statements[i].op == OP_IFNOT_S)
|
||||||
|
statements[i].b = (signed short)statements3[i].b;
|
||||||
|
else
|
||||||
|
statements[i].b = (unsigned short)statements3[i].b;
|
||||||
|
|
||||||
|
statements[i].c = (unsigned short)statements3[i].c;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Sys_Error("Unrecognised progs version");
|
Sys_Error("Unrecognised progs version");
|
||||||
|
|
||||||
|
@ -615,6 +643,45 @@ int DecompileReadData(char *srcfilename, char *buf, size_t bufsize)
|
||||||
fields[i].type = gd16[i].type;
|
fields[i].type = gd16[i].type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (defsz == -32)
|
||||||
|
{
|
||||||
|
const qtest_function_t *funcin = (const qtest_function_t*)(buf+progs.ofs_functions);
|
||||||
|
const qtest_def_t *gdqt = (const qtest_def_t*)(buf+progs.ofs_globaldefs);
|
||||||
|
globals = malloc(numglobaldefs * sizeof(*globals));
|
||||||
|
for (i = 0; i < numglobaldefs; i++)
|
||||||
|
{
|
||||||
|
globals[i].ofs = gdqt[i].ofs;
|
||||||
|
globals[i].s_name = gdqt[i].s_name;
|
||||||
|
globals[i].type = gdqt[i].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gdqt = (const qtest_def_t*)(buf+progs.ofs_fielddefs);
|
||||||
|
fields = malloc(numfielddefs * sizeof(*fields));
|
||||||
|
for (i = 0; i < numfielddefs; i++)
|
||||||
|
{
|
||||||
|
fields[i].ofs = gdqt[i].ofs;
|
||||||
|
fields[i].s_name = gdqt[i].s_name;
|
||||||
|
fields[i].type = gdqt[i].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
functions = malloc(numfunctions * sizeof(*functions));
|
||||||
|
for (i = 0; i < numfunctions; i++)
|
||||||
|
{
|
||||||
|
functions[i].first_statement = funcin[i].first_statement; // negative numbers are builtins
|
||||||
|
functions[i].parm_start = funcin[i].parm_start;
|
||||||
|
functions[i].locals = funcin[i].locals; // total ints of parms + locals
|
||||||
|
|
||||||
|
functions[i].profile = funcin[i].profile; // runtime
|
||||||
|
|
||||||
|
functions[i].s_name = funcin[i].s_name;
|
||||||
|
functions[i].s_file = funcin[i].s_file; // source file defined in
|
||||||
|
|
||||||
|
functions[i].numparms = funcin[i].numparms;
|
||||||
|
for (j = 0; j < MAX_PARMS; j++)
|
||||||
|
functions[i].parm_size[j] = funcin[i].parm_size[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
globals = (QCC_ddef32_t*)(buf+progs.ofs_globaldefs);
|
globals = (QCC_ddef32_t*)(buf+progs.ofs_globaldefs);
|
||||||
|
@ -2775,7 +2842,7 @@ void DecompileFunction(const char *name, int *lastglobal)
|
||||||
}
|
}
|
||||||
QCC_CatVFile(Decompileofile, "\n{\n");
|
QCC_CatVFile(Decompileofile, "\n{\n");
|
||||||
|
|
||||||
startpos = Decompileofile->fsize;
|
startpos = Decompileofile->size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fprintf(Decompileprofile, "%s", DecompileProfiles[findex]);
|
fprintf(Decompileprofile, "%s", DecompileProfiles[findex]);
|
||||||
|
@ -3014,7 +3081,7 @@ void DecompileProgsDat(char *name, void *buf, size_t bufsize)
|
||||||
DecompileReadData(name, buf, bufsize);
|
DecompileReadData(name, buf, bufsize);
|
||||||
DecompileDecompileFunctions(c);
|
DecompileDecompileFunctions(c);
|
||||||
|
|
||||||
printf("Done.");
|
printf("Done.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *DecompileGlobalStringNoContents(gofs_t ofs)
|
char *DecompileGlobalStringNoContents(gofs_t ofs)
|
||||||
|
|
|
@ -1100,13 +1100,14 @@ int QCC_CopyStringLength (const char *str, size_t length);
|
||||||
|
|
||||||
|
|
||||||
typedef struct qcc_cachedsourcefile_s {
|
typedef struct qcc_cachedsourcefile_s {
|
||||||
char filename[128];
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
size_t bufsize;
|
||||||
size_t zhdrofs;
|
size_t zhdrofs;
|
||||||
int zcrc;
|
int zcrc;
|
||||||
char *file;
|
char *file;
|
||||||
enum{FT_CODE, FT_DATA} type; //quakec source file or not.
|
enum{FT_CODE, FT_DATA} type; //quakec source file or not.
|
||||||
struct qcc_cachedsourcefile_s *next;
|
struct qcc_cachedsourcefile_s *next;
|
||||||
|
char filename[1];
|
||||||
} qcc_cachedsourcefile_t;
|
} qcc_cachedsourcefile_t;
|
||||||
extern qcc_cachedsourcefile_t *qcc_sourcefile;
|
extern qcc_cachedsourcefile_t *qcc_sourcefile;
|
||||||
int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell, pbool legacyembed);
|
int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell, pbool legacyembed);
|
||||||
|
@ -1164,18 +1165,26 @@ extern void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);
|
||||||
extern void *(*pHash_Add)(hashtable_t *table, const char *name, void *data, bucket_t *);
|
extern void *(*pHash_Add)(hashtable_t *table, const char *name, void *data, bucket_t *);
|
||||||
extern void (*pHash_RemoveData)(hashtable_t *table, const char *name, void *data);
|
extern void (*pHash_RemoveData)(hashtable_t *table, const char *name, void *data);
|
||||||
|
|
||||||
typedef struct vfile_s
|
//when originally running from a .dat, we load up all the functions and work from those rather than actual files.
|
||||||
{ //when originally running from a .dat, we load up all the functions and work from those rather than actual files.
|
//(these get re-written into the resulting .dat)
|
||||||
//(these get re-written into the resulting .dat)
|
typedef struct qcc_cachedsourcefile_s vfile_t;
|
||||||
struct vfile_s *next;
|
|
||||||
void *fdata;
|
|
||||||
size_t fsize;
|
|
||||||
size_t msize;
|
|
||||||
char name[1];
|
|
||||||
} vfile_t;
|
|
||||||
vfile_t *QCC_FindVFile(const char *name);
|
vfile_t *QCC_FindVFile(const char *name);
|
||||||
vfile_t *QCC_AddVFile(const char *name, void *data, size_t size);
|
vfile_t *QCC_AddVFile(const char *name, void *data, size_t size);
|
||||||
void QCC_CatVFile(vfile_t *, const char *fmt, ...);
|
void QCC_CatVFile(vfile_t *, const char *fmt, ...);
|
||||||
void QCC_InsertVFile(vfile_t *, size_t pos, const char *fmt, ...);
|
void QCC_InsertVFile(vfile_t *, size_t pos, const char *fmt, ...);
|
||||||
|
|
||||||
//void *QCC_ReadFile(const char *fname, unsigned char *(*buf_get)(void *ctx, size_t len), void *buf_ctx, size_t *out_size, pbool issourcefile);
|
//void *QCC_ReadFile(const char *fname, unsigned char *(*buf_get)(void *ctx, size_t len), void *buf_ctx, size_t *out_size, pbool issourcefile);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char name[56];
|
||||||
|
int filepos, filelen;
|
||||||
|
} packfile_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char id[4];
|
||||||
|
int dirofs;
|
||||||
|
int dirlen;
|
||||||
|
} packheader_t;
|
||||||
|
|
|
@ -889,10 +889,17 @@ void ResizeBuf(int hand, int newsize)
|
||||||
}
|
}
|
||||||
void SafeWrite(int hand, const void *buf, long count)
|
void SafeWrite(int hand, const void *buf, long count)
|
||||||
{
|
{
|
||||||
if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
|
if (qccfile[hand].stdio)
|
||||||
ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
|
{
|
||||||
|
fwrite(buf, 1, count, qccfile[hand].stdio);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
|
||||||
|
ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
|
||||||
|
|
||||||
memcpy(&qccfile[hand].buff[qccfile[hand].ofs], buf, count);
|
memcpy(&qccfile[hand].buff[qccfile[hand].ofs], buf, count);
|
||||||
|
}
|
||||||
qccfile[hand].ofs+=count;
|
qccfile[hand].ofs+=count;
|
||||||
if (qccfile[hand].ofs > qccfile[hand].maxofs)
|
if (qccfile[hand].ofs > qccfile[hand].maxofs)
|
||||||
qccfile[hand].maxofs = qccfile[hand].ofs;
|
qccfile[hand].maxofs = qccfile[hand].ofs;
|
||||||
|
@ -903,7 +910,10 @@ int SafeSeek(int hand, int ofs, int mode)
|
||||||
return qccfile[hand].ofs;
|
return qccfile[hand].ofs;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ResizeBuf(hand, ofs+1024);
|
if (qccfile[hand].stdio)
|
||||||
|
fseek(qccfile[hand].stdio, ofs, SEEK_SET);
|
||||||
|
else
|
||||||
|
ResizeBuf(hand, ofs+1024);
|
||||||
qccfile[hand].ofs = ofs;
|
qccfile[hand].ofs = ofs;
|
||||||
if (qccfile[hand].ofs > qccfile[hand].maxofs)
|
if (qccfile[hand].ofs > qccfile[hand].maxofs)
|
||||||
qccfile[hand].maxofs = qccfile[hand].ofs;
|
qccfile[hand].maxofs = qccfile[hand].ofs;
|
||||||
|
@ -1220,7 +1230,7 @@ char *QCC_SanitizeCharSet(char *mem, size_t *len, pbool *freeresult, int *origfm
|
||||||
|
|
||||||
static unsigned char *PDECL QCC_LoadFileHunk(void *ctx, size_t size)
|
static unsigned char *PDECL QCC_LoadFileHunk(void *ctx, size_t size)
|
||||||
{ //2 ensures we can always put a \n in there.
|
{ //2 ensures we can always put a \n in there.
|
||||||
return (unsigned char*)qccHunkAlloc(sizeof(qcc_cachedsourcefile_t)+size+2) + sizeof(qcc_cachedsourcefile_t);
|
return (unsigned char*)qccHunkAlloc(sizeof(qcc_cachedsourcefile_t)+strlen(ctx)+size+2) + sizeof(qcc_cachedsourcefile_t) + strlen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
long QCC_LoadFile (char *filename, void **bufferptr)
|
long QCC_LoadFile (char *filename, void **bufferptr)
|
||||||
|
@ -1234,13 +1244,13 @@ long QCC_LoadFile (char *filename, void **bufferptr)
|
||||||
int orig;
|
int orig;
|
||||||
pbool warned = false;
|
pbool warned = false;
|
||||||
|
|
||||||
mem = externs->ReadFile(filename, QCC_LoadFileHunk, NULL, &len, true);
|
mem = externs->ReadFile(filename, QCC_LoadFileHunk, filename, &len, true);
|
||||||
if (!mem)
|
if (!mem)
|
||||||
{
|
{
|
||||||
QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
|
QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sfile = (qcc_cachedsourcefile_t*)(mem-sizeof(qcc_cachedsourcefile_t));
|
sfile = (qcc_cachedsourcefile_t*)(mem-sizeof(qcc_cachedsourcefile_t)-strlen(filename));
|
||||||
mem[len] = 0;
|
mem[len] = 0;
|
||||||
|
|
||||||
mem = QCC_SanitizeCharSet(mem, &len, NULL, &orig);
|
mem = QCC_SanitizeCharSet(mem, &len, NULL, &orig);
|
||||||
|
@ -1284,10 +1294,10 @@ void QCC_AddFile (char *filename)
|
||||||
char *mem;
|
char *mem;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
mem = externs->ReadFile(filename, QCC_LoadFileHunk, NULL, &len, false);
|
mem = externs->ReadFile(filename, QCC_LoadFileHunk, filename, &len, false);
|
||||||
if (!mem)
|
if (!mem)
|
||||||
externs->Abort("failed to find file %s", filename);
|
externs->Abort("failed to find file %s", filename);
|
||||||
sfile = (qcc_cachedsourcefile_t*)(mem-sizeof(qcc_cachedsourcefile_t));
|
sfile = (qcc_cachedsourcefile_t*)(mem-sizeof(qcc_cachedsourcefile_t)-strlen(filename));
|
||||||
mem[len] = '\0';
|
mem[len] = '\0';
|
||||||
|
|
||||||
sfile->size = len;
|
sfile->size = len;
|
||||||
|
|
|
@ -3657,11 +3657,10 @@ void QCC_PR_Lex (void)
|
||||||
|
|
||||||
QCC_PR_LexWhitespace (false);
|
QCC_PR_LexWhitespace (false);
|
||||||
|
|
||||||
if (currentchunk)
|
pr_token_line_last = pr_token_line;
|
||||||
pr_token_line_last = currentchunk->currentlinenumber-1 + pr_token_line;
|
|
||||||
else
|
|
||||||
pr_token_line_last = pr_token_line;
|
|
||||||
pr_token_line = pr_source_line;
|
pr_token_line = pr_source_line;
|
||||||
|
if (currentchunk)
|
||||||
|
pr_token_line += currentchunk->currentlinenumber-1;
|
||||||
|
|
||||||
if (!pr_file_p)
|
if (!pr_file_p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -350,31 +350,132 @@ static pbool QCC_RegSetValue(HKEY base, char *keyname, char *valuename, int type
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#undef printf
|
||||||
|
#undef Sys_Error
|
||||||
|
void Sys_Error(const char *text, ...);
|
||||||
|
|
||||||
|
pbool qcc_vfiles_changed;
|
||||||
static vfile_t *qcc_vfiles;
|
static vfile_t *qcc_vfiles;
|
||||||
|
HWND mainwindow;
|
||||||
|
HINSTANCE ghInstance;
|
||||||
|
static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) ;
|
||||||
|
void QCC_SaveVFiles(void)
|
||||||
|
{
|
||||||
|
vfile_t *f;
|
||||||
|
if (qcc_vfiles_changed)
|
||||||
|
{
|
||||||
|
switch (MessageBox(mainwindow, "Save files as archive?", "FTEQCCGUI", MB_YESNOCANCEL))
|
||||||
|
{
|
||||||
|
case IDYES:
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
char oldpath[MAX_PATH+10];
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hInstance = ghInstance;
|
||||||
|
ofn.lpstrFile = filename;
|
||||||
|
ofn.lpstrTitle = "Output archive";
|
||||||
|
ofn.nMaxFile = sizeof(filename)-1;
|
||||||
|
ofn.lpstrFilter = "QuakeC Projects\0*.zip\0All files\0*.*\0";
|
||||||
|
memset(filename, 0, sizeof(filename));
|
||||||
|
GetCurrentDirectory(sizeof(oldpath)-1, oldpath);
|
||||||
|
ofn.lpstrInitialDir = oldpath;
|
||||||
|
if (GetSaveFileName(&ofn))
|
||||||
|
{
|
||||||
|
int h = SafeOpenWrite(ofn.lpstrFile, -1);
|
||||||
|
|
||||||
|
progfuncs_t funcs;
|
||||||
|
progexterns_t ext;
|
||||||
|
memset(&funcs, 0, sizeof(funcs));
|
||||||
|
funcs.funcs.parms = &ext;
|
||||||
|
memset(&ext, 0, sizeof(ext));
|
||||||
|
ext.ReadFile = GUIReadFile;
|
||||||
|
ext.FileSize = GUIFileSize;
|
||||||
|
ext.WriteFile = QCC_WriteFile;
|
||||||
|
ext.Sys_Error = Sys_Error;
|
||||||
|
ext.Printf = GUIprintf;
|
||||||
|
|
||||||
|
qccprogfuncs = &funcs;
|
||||||
|
WriteSourceFiles(qcc_vfiles, h, true, false);
|
||||||
|
qccprogfuncs = NULL;
|
||||||
|
|
||||||
|
SafeClose(h);
|
||||||
|
|
||||||
|
qcc_vfiles_changed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDNO:
|
||||||
|
{
|
||||||
|
char oldworkingdir[MAX_PATH], newdir[MAX_PATH+10], workingdir[MAX_PATH];
|
||||||
|
BROWSEINFO bi;
|
||||||
|
LPITEMIDLIST il;
|
||||||
|
memset(&bi, 0, sizeof(bi));
|
||||||
|
bi.hwndOwner = mainwindow;
|
||||||
|
bi.pidlRoot = NULL;
|
||||||
|
GetCurrentDirectory(sizeof(oldworkingdir)-1, oldworkingdir);
|
||||||
|
GetCurrentDirectory(sizeof(workingdir)-1, workingdir);
|
||||||
|
bi.pszDisplayName = workingdir;
|
||||||
|
bi.lpszTitle = "Where do you want the source?";
|
||||||
|
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
|
||||||
|
bi.lpfn = StupidBrowseCallbackProc;
|
||||||
|
bi.lParam = 0;
|
||||||
|
bi.iImage = 0;
|
||||||
|
il = SHBrowseForFolder(&bi);
|
||||||
|
if (il)
|
||||||
|
{
|
||||||
|
SHGetPathFromIDList(il, newdir);
|
||||||
|
CoTaskMemFree(il);
|
||||||
|
|
||||||
|
for (f = qcc_vfiles; f; f = f->next)
|
||||||
|
{
|
||||||
|
char nname[MAX_PATH];
|
||||||
|
int h;
|
||||||
|
QC_snprintfz(nname, sizeof(nname), "%s\\%s", newdir, f->filename);
|
||||||
|
h = SafeOpenWrite(f->filename, -1);
|
||||||
|
if (h >= 0)
|
||||||
|
{
|
||||||
|
SafeWrite(h, f->file, f->size);
|
||||||
|
SafeClose(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetCurrentDirectory(oldworkingdir); //revert microsoft stupidity.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void QCC_CloseAllVFiles(void)
|
void QCC_CloseAllVFiles(void)
|
||||||
{
|
{
|
||||||
vfile_t *f;
|
vfile_t *f;
|
||||||
|
|
||||||
while(qcc_vfiles)
|
while(qcc_vfiles)
|
||||||
{
|
{
|
||||||
f = qcc_vfiles;
|
f = qcc_vfiles;
|
||||||
qcc_vfiles = f->next;
|
qcc_vfiles = f->next;
|
||||||
|
|
||||||
free(f->fdata);
|
free(f->file);
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
|
qcc_vfiles_changed = false;
|
||||||
}
|
}
|
||||||
vfile_t *QCC_FindVFile(const char *name)
|
vfile_t *QCC_FindVFile(const char *name)
|
||||||
{
|
{
|
||||||
vfile_t *f;
|
vfile_t *f;
|
||||||
for (f = qcc_vfiles; f; f = f->next)
|
for (f = qcc_vfiles; f; f = f->next)
|
||||||
{
|
{
|
||||||
if (!strcmp(f->name, name))
|
if (!strcmp(f->filename, name))
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
//give it another go, for case
|
//give it another go, for case
|
||||||
for (f = qcc_vfiles; f; f = f->next)
|
for (f = qcc_vfiles; f; f = f->next)
|
||||||
{
|
{
|
||||||
if (!QC_strcasecmp(f->name, name))
|
if (!QC_strcasecmp(f->filename, name))
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -386,14 +487,17 @@ vfile_t *QCC_AddVFile(const char *name, void *data, size_t size)
|
||||||
{
|
{
|
||||||
f = malloc(sizeof(vfile_t) + strlen(name));
|
f = malloc(sizeof(vfile_t) + strlen(name));
|
||||||
f->next = qcc_vfiles;
|
f->next = qcc_vfiles;
|
||||||
strcpy(f->name, name);
|
strcpy(f->filename, name);
|
||||||
qcc_vfiles = f;
|
qcc_vfiles = f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
free(f->fdata);
|
free(f->file);
|
||||||
f->fdata = malloc(size);
|
f->file = malloc(size);
|
||||||
memcpy(f->fdata, data, size);
|
f->type = FT_CODE;
|
||||||
f->fsize = f->msize = size;
|
memcpy(f->file, data, size);
|
||||||
|
f->size = f->bufsize = size;
|
||||||
|
|
||||||
|
qcc_vfiles_changed = true;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
void QCC_CatVFile(vfile_t *f, const char *fmt, ...)
|
void QCC_CatVFile(vfile_t *f, const char *fmt, ...)
|
||||||
|
@ -407,14 +511,14 @@ void QCC_CatVFile(vfile_t *f, const char *fmt, ...)
|
||||||
va_end (argptr);
|
va_end (argptr);
|
||||||
|
|
||||||
n = strlen(msg);
|
n = strlen(msg);
|
||||||
if (f->fsize+n > f->msize)
|
if (f->size+n > f->bufsize)
|
||||||
{
|
{
|
||||||
size_t msize = f->msize + n + 8192;
|
size_t msize = f->bufsize + n + 8192;
|
||||||
f->fdata = realloc(f->fdata, msize);
|
f->file = realloc(f->file, msize);
|
||||||
f->msize = msize;
|
f->bufsize = msize;
|
||||||
}
|
}
|
||||||
memcpy((char*)f->fdata+f->fsize, msg, n);
|
memcpy((char*)f->file+f->size, msg, n);
|
||||||
f->fsize += n;
|
f->size += n;
|
||||||
}
|
}
|
||||||
void QCC_InsertVFile(vfile_t *f, size_t pos, const char *fmt, ...)
|
void QCC_InsertVFile(vfile_t *f, size_t pos, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -426,15 +530,15 @@ void QCC_InsertVFile(vfile_t *f, size_t pos, const char *fmt, ...)
|
||||||
va_end (argptr);
|
va_end (argptr);
|
||||||
|
|
||||||
n = strlen(msg);
|
n = strlen(msg);
|
||||||
if (f->fsize+n > f->msize)
|
if (f->size+n > f->bufsize)
|
||||||
{
|
{
|
||||||
size_t msize = f->msize + n + 8192;
|
size_t msize = f->bufsize + n + 8192;
|
||||||
f->fdata = realloc(f->fdata, msize);
|
f->file = realloc(f->file, msize);
|
||||||
f->msize = msize;
|
f->bufsize = msize;
|
||||||
}
|
}
|
||||||
memmove((char*)f->fdata+pos+n, (char*)f->fdata+pos, f->fsize-pos);
|
memmove((char*)f->file+pos+n, (char*)f->file+pos, f->size-pos);
|
||||||
f->fsize += n;
|
f->size += n;
|
||||||
memcpy((char*)f->fdata+pos, msg, n);
|
memcpy((char*)f->file+pos, msg, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCC_EnumerateFilesResult(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize)
|
void QCC_EnumerateFilesResult(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize)
|
||||||
|
@ -442,6 +546,7 @@ void QCC_EnumerateFilesResult(const char *name, const void *compdata, size_t com
|
||||||
void *buffer = malloc(plainsize);
|
void *buffer = malloc(plainsize);
|
||||||
if (QC_decode(NULL, compsize, plainsize, method, compdata, buffer))
|
if (QC_decode(NULL, compsize, plainsize, method, compdata, buffer))
|
||||||
QCC_AddVFile(name, buffer, plainsize);
|
QCC_AddVFile(name, buffer, plainsize);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +564,7 @@ static void *QCC_ReadFile(const char *fname, unsigned char *(*buf_get)(void *ctx
|
||||||
vfile_t *v = QCC_FindVFile(fname);
|
vfile_t *v = QCC_FindVFile(fname);
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
len = v->fsize;
|
len = v->size;
|
||||||
if (buf_get)
|
if (buf_get)
|
||||||
buffer = buf_get(buf_ctx, len+1);
|
buffer = buf_get(buf_ctx, len+1);
|
||||||
else
|
else
|
||||||
|
@ -467,9 +572,9 @@ static void *QCC_ReadFile(const char *fname, unsigned char *(*buf_get)(void *ctx
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
((char*)buffer)[len] = 0;
|
((char*)buffer)[len] = 0;
|
||||||
if (len > v->fsize)
|
if (len > v->size)
|
||||||
len = v->fsize;
|
len = v->size;
|
||||||
memcpy(buffer, v->fdata, len);
|
memcpy(buffer, v->file, len);
|
||||||
if (out_size)
|
if (out_size)
|
||||||
*out_size = len;
|
*out_size = len;
|
||||||
return buffer;
|
return buffer;
|
||||||
|
@ -510,7 +615,7 @@ int PDECL QCC_RawFileSize (const char *fname)
|
||||||
|
|
||||||
vfile_t *v = QCC_FindVFile(fname);
|
vfile_t *v = QCC_FindVFile(fname);
|
||||||
if (v)
|
if (v)
|
||||||
return v->fsize;
|
return v->size;
|
||||||
|
|
||||||
f = fopen(fname, "rb");
|
f = fopen(fname, "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
|
@ -3029,6 +3134,7 @@ static void EditorReload(editor_t *editor)
|
||||||
//2: draw extra focus to it
|
//2: draw extra focus to it
|
||||||
void EditFile(const char *name, int line, pbool setcontrol)
|
void EditFile(const char *name, int line, pbool setcontrol)
|
||||||
{
|
{
|
||||||
|
const char *ext;
|
||||||
char title[1024];
|
char title[1024];
|
||||||
editor_t *neweditor;
|
editor_t *neweditor;
|
||||||
WNDCLASS wndclass;
|
WNDCLASS wndclass;
|
||||||
|
@ -3081,6 +3187,33 @@ void EditFile(const char *name, int line, pbool setcontrol)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext = strrchr(name, '.');
|
||||||
|
if (ext)
|
||||||
|
{
|
||||||
|
if (!QC_strcasecmp(ext, ".wav"))
|
||||||
|
{
|
||||||
|
size_t flensz;
|
||||||
|
char *rawfile = QCC_ReadFile(name, NULL, NULL, &flensz);
|
||||||
|
//fixme: thread this...
|
||||||
|
BOOL (WINAPI *pPlaySound)(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
|
||||||
|
HMODULE winmm = LoadLibrary("winmm.dll");
|
||||||
|
pPlaySound = (void*)GetProcAddress(winmm, "PlaySoundA");
|
||||||
|
if (pPlaySound)
|
||||||
|
pPlaySound(rawfile, NULL, SND_MEMORY|SND_SYNC|SND_NODEFAULT);
|
||||||
|
free(rawfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!QC_strcasecmp(ext, ".ogg") || !QC_strcasecmp(ext, ".mp3") || !QC_strcasecmp(ext, ".opus") ||
|
||||||
|
!QC_strcasecmp(ext, ".bsp") || !QC_strcasecmp(ext, ".mdl") || !QC_strcasecmp(ext, ".md2") || !QC_strcasecmp(ext, ".md3") || !QC_strcasecmp(ext, ".iqm") ||
|
||||||
|
!QC_strcasecmp(ext, ".wad") || !QC_strcasecmp(ext, ".lmp") || !QC_strcasecmp(ext, ".png") || !QC_strcasecmp(ext, ".tga") || !QC_strcasecmp(ext, ".jpeg") ||
|
||||||
|
!QC_strcasecmp(ext, ".jpg") || !QC_strcasecmp(ext, ".dds") || !QC_strcasecmp(ext, ".ktx") || !QC_strcasecmp(ext, ".bmp") || !QC_strcasecmp(ext, ".pcx") ||
|
||||||
|
!QC_strcasecmp(ext, ".bin") || !QC_strcasecmp(ext, ".dat") || !QC_strcasecmp(ext, ".pak") || !QC_strcasecmp(ext, ".pk3") || !QC_strcasecmp(ext, ".dem") || !QC_strcasecmp(ext, ".spr"))
|
||||||
|
{
|
||||||
|
if (IDOK != MessageBox(NULL, "The file extension implies that it is a binary file. Open as text anyway?", "FTEQCCGUI", MB_OKCANCEL))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
neweditor = malloc(sizeof(editor_t));
|
neweditor = malloc(sizeof(editor_t));
|
||||||
if (!neweditor)
|
if (!neweditor)
|
||||||
{
|
{
|
||||||
|
@ -6985,6 +7118,26 @@ static void Packager_MessageCallback(void *ctx, const char *fmt, ...)
|
||||||
outlen = GUIEmitOutputText(outputbox, outlen, message, strlen(message), RGB(0, 0, 0));
|
outlen = GUIEmitOutputText(outputbox, outlen, message, strlen(message), RGB(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI_DoDecompile(void *buf, size_t size)
|
||||||
|
{
|
||||||
|
char *c = ReadProgsCopyright(buf, size);
|
||||||
|
if (!c || !*c)
|
||||||
|
c = "COPYRIGHT OWNER NOT KNOWN"; //all work is AUTOMATICALLY copyrighted under the terms of the Berne Convention in all major nations. It _IS_ copyrighted, even if there's no license etc included. Good luck guessing what rights you have.
|
||||||
|
if (MessageBox(mainwindow, qcva("The copyright message from this progs is\n%s\n\nPlease respect the wishes and legal rights of the person who created this.", c), "Copyright", MB_OKCANCEL|MB_DEFBUTTON2|MB_ICONSTOP) == IDOK)
|
||||||
|
{
|
||||||
|
CreateOutputWindow(true);
|
||||||
|
compilecb();
|
||||||
|
DecompileProgsDat(progssrcname, buf, size);
|
||||||
|
if (SplitterGet(outputbox))
|
||||||
|
{
|
||||||
|
SendMessage(outputbox, WM_SETREDRAW, TRUE, 0);
|
||||||
|
RedrawWindow(outputbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCC_SaveVFiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
pbool fl_acc;
|
pbool fl_acc;
|
||||||
|
@ -7176,7 +7329,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
//if the project is a .dat or .zip then decompile it now (so we can access the 'source')
|
//if the project is a .dat or .zip then decompile it now (so we can access the 'source')
|
||||||
{
|
{
|
||||||
char *ext = strrchr(progssrcname, '.');
|
char *ext = strrchr(progssrcname, '.');
|
||||||
if (ext && (!QC_strcasecmp(ext, ".dat") || !QC_strcasecmp(ext, ".zip") || !QC_strcasecmp(ext, ".pk3")))
|
if (ext && (!QC_strcasecmp(ext, ".dat") || !QC_strcasecmp(ext, ".pak") || !QC_strcasecmp(ext, ".zip") || !QC_strcasecmp(ext, ".pk3")))
|
||||||
{
|
{
|
||||||
FILE *f = fopen(progssrcname, "rb");
|
FILE *f = fopen(progssrcname, "rb");
|
||||||
if (f)
|
if (f)
|
||||||
|
@ -7192,21 +7345,24 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
fclose(f);
|
fclose(f);
|
||||||
QCC_CloseAllVFiles();
|
QCC_CloseAllVFiles();
|
||||||
if (!QC_EnumerateFilesFromBlob(buf, size, QCC_EnumerateFilesResult) && !QC_strcasecmp(ext, ".dat"))
|
if (!QC_EnumerateFilesFromBlob(buf, size, QCC_EnumerateFilesResult) && !QC_strcasecmp(ext, ".dat"))
|
||||||
|
{ //its a .dat and contains no .src files
|
||||||
|
GUI_DoDecompile(buf, size);
|
||||||
|
}
|
||||||
|
else if (!QCC_FindVFile("progs.src"))
|
||||||
{
|
{
|
||||||
char *c = ReadProgsCopyright(buf, size);
|
vfile_t *f;
|
||||||
if (!c || !*c)
|
char *archivename = progssrcname;
|
||||||
c = "COPYRIGHT OWNER NOT KNOWN"; //all work is AUTOMATICALLY copyrighted under the terms of the Berne Convention in all major nations. It _IS_ copyrighted, even if there's no license etc included. Good luck guessing what rights you have.
|
while(strchr(archivename, '\\'))
|
||||||
if (MessageBox(mainwindow, qcva("The copyright message from this progs is\n%s\n\nPlease respect the wishes and legal rights of the person who created this.", c), "Copyright", MB_OKCANCEL|MB_DEFBUTTON2|MB_ICONSTOP) == IDOK)
|
archivename = strchr(archivename, '\\')+1;
|
||||||
{
|
AddSourceFile(NULL, archivename);
|
||||||
CreateOutputWindow(true);
|
for (f = qcc_vfiles; f; f = f->next)
|
||||||
compilecb();
|
AddSourceFile(archivename, f->filename);
|
||||||
DecompileProgsDat(progssrcname, buf, size);
|
|
||||||
if (SplitterGet(outputbox))
|
f = QCC_FindVFile("progs.dat");
|
||||||
{
|
if (f)
|
||||||
SendMessage(outputbox, WM_SETREDRAW, TRUE, 0);
|
GUI_DoDecompile(f->file, f->size);
|
||||||
RedrawWindow(outputbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
else
|
||||||
}
|
resetprogssrc = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
strcpy(progssrcname, "progs.src");
|
strcpy(progssrcname, "progs.src");
|
||||||
|
@ -7227,8 +7383,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
|
|
||||||
if (fl_compileonstart)
|
if (fl_compileonstart)
|
||||||
{
|
{
|
||||||
CreateOutputWindow(false);
|
if (resetprogssrc)
|
||||||
RunCompiler(lpCmdLine, false);
|
{
|
||||||
|
CreateOutputWindow(false);
|
||||||
|
RunCompiler(lpCmdLine, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7242,8 +7401,9 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
RunCompiler("-?", false);
|
RunCompiler("-?", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (resetprogssrc)
|
||||||
|
UpdateFileList();
|
||||||
resetprogssrc = false;
|
resetprogssrc = false;
|
||||||
UpdateFileList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorsRun();
|
EditorsRun();
|
||||||
|
|
|
@ -769,7 +769,7 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
|
||||||
if (zipembed)
|
if (zipembed)
|
||||||
{
|
{
|
||||||
size_t end;
|
size_t end;
|
||||||
char header[32+sizeof(f->filename)];
|
char header[32];
|
||||||
size_t fnamelen = strlen(f->filename);
|
size_t fnamelen = strlen(f->filename);
|
||||||
f->zcrc = QC_encodecrc(f->size, f->file);
|
f->zcrc = QC_encodecrc(f->size, f->file);
|
||||||
misint (header, 0, 0x04034b50);
|
misint (header, 0, 0x04034b50);
|
||||||
|
@ -783,10 +783,10 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
|
||||||
misint (header, 22, f->size);//uncompressed size
|
misint (header, 22, f->size);//uncompressed size
|
||||||
misshort(header, 26, fnamelen);//filename length
|
misshort(header, 26, fnamelen);//filename length
|
||||||
misshort(header, 28, 0);//extradata length
|
misshort(header, 28, 0);//extradata length
|
||||||
strcpy(header+30, f->filename);
|
|
||||||
|
|
||||||
f->zhdrofs = SafeSeek(h, 0, SEEK_CUR);
|
f->zhdrofs = SafeSeek(h, 0, SEEK_CUR);
|
||||||
SafeWrite(h, header, 30+fnamelen);
|
SafeWrite(h, header, 30);
|
||||||
|
SafeWrite(h, f->filename, fnamelen);
|
||||||
|
|
||||||
strcpy(idf[num].filename, f->filename);
|
strcpy(idf[num].filename, f->filename);
|
||||||
idf[num].size = f->size;
|
idf[num].size = f->size;
|
||||||
|
@ -803,13 +803,13 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
|
||||||
|
|
||||||
end = SafeSeek(h, 0, SEEK_CUR);
|
end = SafeSeek(h, 0, SEEK_CUR);
|
||||||
SafeSeek(h, f->zhdrofs, SEEK_SET);
|
SafeSeek(h, f->zhdrofs, SEEK_SET);
|
||||||
SafeWrite(h, header, 30+strlen(f->filename));
|
SafeWrite(h, header, 30);
|
||||||
SafeSeek(h, end, SEEK_SET);
|
SafeSeek(h, end, SEEK_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (f->type == FT_CODE && !sourceaswell)
|
if (strlen(f->filename) >= sizeof(idf[num].filename))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strcpy(idf[num].filename, f->filename);
|
strcpy(idf[num].filename, f->filename);
|
||||||
|
@ -827,7 +827,7 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
|
||||||
|
|
||||||
if (zipembed)
|
if (zipembed)
|
||||||
{
|
{
|
||||||
char centralheader[46+sizeof(f->filename)];
|
char centralheader[46];
|
||||||
int centraldirsize;
|
int centraldirsize;
|
||||||
ofs = SafeSeek(h, 0, SEEK_CUR);
|
ofs = SafeSeek(h, 0, SEEK_CUR);
|
||||||
for (f = filelist,num=0; f ; f=f->next)
|
for (f = filelist,num=0; f ; f=f->next)
|
||||||
|
@ -853,8 +853,8 @@ int WriteSourceFiles(qcc_cachedsourcefile_t *filelist, int h, pbool sourceaswell
|
||||||
misshort(centralheader, 36, 0);//internal file attribs
|
misshort(centralheader, 36, 0);//internal file attribs
|
||||||
misint (centralheader, 38, 0);//external file attribs
|
misint (centralheader, 38, 0);//external file attribs
|
||||||
misint (centralheader, 42, f->zhdrofs);//local header offset
|
misint (centralheader, 42, f->zhdrofs);//local header offset
|
||||||
strcpy(centralheader+46, f->filename);
|
SafeWrite(h, centralheader, 46);
|
||||||
SafeWrite(h, centralheader, 46 + fnamelen);
|
SafeWrite(h, f->filename, fnamelen);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3614,19 +3614,6 @@ DIRECTORY COPYING / PACKFILE CREATION
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[56];
|
|
||||||
int filepos, filelen;
|
|
||||||
} packfile_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char id[4];
|
|
||||||
int dirofs;
|
|
||||||
int dirlen;
|
|
||||||
} packheader_t;
|
|
||||||
|
|
||||||
packfile_t pfiles[4096], *pf;
|
packfile_t pfiles[4096], *pf;
|
||||||
int packhandle;
|
int packhandle;
|
||||||
int packbytes;
|
int packbytes;
|
||||||
|
|
|
@ -191,6 +191,18 @@ int QC_EnumerateFilesFromBlob(const void *blob, size_t blobsize, void (*cb)(cons
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (blobsize < 22)
|
if (blobsize < 22)
|
||||||
return ret;
|
return ret;
|
||||||
|
if (!strncmp(blob, "PACK", 4))
|
||||||
|
{
|
||||||
|
const packheader_t *head = blob;
|
||||||
|
const packfile_t *f = (packfile_t*)((char*)blob + head->dirofs);
|
||||||
|
for (ret = 0; ret < head->dirlen/sizeof(*f); ret++, f++)
|
||||||
|
{
|
||||||
|
cb(f->name, (const char*)blob+f->filepos, f->filelen, 0, f->filelen);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//treat it as a zip
|
||||||
eocd = blob;
|
eocd = blob;
|
||||||
eocd += blobsize-22;
|
eocd += blobsize-22;
|
||||||
if (QC_ReadRawInt(eocd+0) != 0x06054b50)
|
if (QC_ReadRawInt(eocd+0) != 0x06054b50)
|
||||||
|
|
|
@ -647,11 +647,11 @@ void NPP_SetInfo(client_t *cl, char *key, char *value)
|
||||||
if (!strcmp(key, "colours"))
|
if (!strcmp(key, "colours"))
|
||||||
{
|
{
|
||||||
i = atoi(value);
|
i = atoi(value);
|
||||||
Info_SetValueForKey (cl->userinfo, "bottomcolor", va("%i", i&15), sizeof(cl->userinfo));
|
InfoBuf_SetKey (&cl->userinfo, "bottomcolor", va("%i", i&15));
|
||||||
Info_SetValueForKey (cl->userinfo, "topcolor", va("%i", i>>4), sizeof(cl->userinfo));
|
InfoBuf_SetKey (&cl->userinfo, "topcolor", va("%i", i>>4));
|
||||||
}
|
}
|
||||||
Info_SetValueForKey (cl->userinfo, key, value, sizeof(cl->userinfo));
|
InfoBuf_SetKey (&cl->userinfo, key, value);
|
||||||
if (!*Info_ValueForKey (cl->userinfo, "name"))
|
if (!*InfoBuf_ValueForKey (&cl->userinfo, "name"))
|
||||||
cl->name[0] = '\0';
|
cl->name[0] = '\0';
|
||||||
else // process any changed values
|
else // process any changed values
|
||||||
SV_ExtractFromUserinfo (cl, false);
|
SV_ExtractFromUserinfo (cl, false);
|
||||||
|
@ -662,19 +662,19 @@ void NPP_SetInfo(client_t *cl, char *key, char *value)
|
||||||
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
||||||
MSG_WriteByte (&sv.reliable_datagram, i);
|
MSG_WriteByte (&sv.reliable_datagram, i);
|
||||||
MSG_WriteString (&sv.reliable_datagram, "bottomcolor");
|
MSG_WriteString (&sv.reliable_datagram, "bottomcolor");
|
||||||
MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(cl->userinfo, "bottomcolor"));
|
MSG_WriteString (&sv.reliable_datagram, InfoBuf_ValueForKey(&cl->userinfo, "bottomcolor"));
|
||||||
|
|
||||||
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
||||||
MSG_WriteByte (&sv.reliable_datagram, i);
|
MSG_WriteByte (&sv.reliable_datagram, i);
|
||||||
MSG_WriteString (&sv.reliable_datagram, "topcolor");
|
MSG_WriteString (&sv.reliable_datagram, "topcolor");
|
||||||
MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(cl->userinfo, "topcolor"));
|
MSG_WriteString (&sv.reliable_datagram, InfoBuf_ValueForKey(&cl->userinfo, "topcolor"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
|
||||||
MSG_WriteByte (&sv.reliable_datagram, i);
|
MSG_WriteByte (&sv.reliable_datagram, i);
|
||||||
MSG_WriteString (&sv.reliable_datagram, key);
|
MSG_WriteString (&sv.reliable_datagram, key);
|
||||||
MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(cl->userinfo, key));
|
MSG_WriteString (&sv.reliable_datagram, InfoBuf_ValueForKey(&cl->userinfo, key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1851,8 +1851,8 @@ void NPP_QWFlush(void)
|
||||||
unsigned int j = buffer[1];
|
unsigned int j = buffer[1];
|
||||||
if (j < sv.allocated_client_slots)
|
if (j < sv.allocated_client_slots)
|
||||||
{
|
{
|
||||||
Q_strncpyz(svs.clients[j].userinfo, (buffer+6), sizeof(svs.clients[j].userinfo));
|
InfoBuf_FromString(&svs.clients[j].userinfo, buffer+6, false);
|
||||||
if (*Info_ValueForKey(svs.clients[j].userinfo, "name"))
|
if (*InfoBuf_ValueForKey(&svs.clients[j].userinfo, "name"))
|
||||||
SV_ExtractFromUserinfo(&svs.clients[j], false);
|
SV_ExtractFromUserinfo(&svs.clients[j], false);
|
||||||
else
|
else
|
||||||
*svs.clients[j].name = '\0';
|
*svs.clients[j].name = '\0';
|
||||||
|
@ -1864,7 +1864,7 @@ void NPP_QWFlush(void)
|
||||||
if (j < sv.allocated_client_slots)
|
if (j < sv.allocated_client_slots)
|
||||||
{
|
{
|
||||||
*svs.clients[j].name = '\0';
|
*svs.clients[j].name = '\0';
|
||||||
*svs.clients[j].userinfo = '\0';
|
InfoBuf_Clear(&svs.clients[j].userinfo, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,6 +206,47 @@ static qcstate_t *PR_CreateThread(pubprogfuncs_t *prinst, float retval, float re
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *PR_GetWriteQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize)
|
||||||
|
{
|
||||||
|
// void *r;
|
||||||
|
if (qcsize < 0)
|
||||||
|
return NULL;
|
||||||
|
if (!qcptr)
|
||||||
|
return NULL;
|
||||||
|
if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize)
|
||||||
|
{
|
||||||
|
if (qcptr + qcsize <= prinst->stringtablemaxsize)
|
||||||
|
return prinst->stringtable+qcptr; //its in bounds
|
||||||
|
}
|
||||||
|
/*else
|
||||||
|
{
|
||||||
|
r = PR_GetString(prinst, qcptr);
|
||||||
|
if (qcsize < strlen(r))
|
||||||
|
return r;
|
||||||
|
}*/
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const void *PR_GetReadQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize)
|
||||||
|
{
|
||||||
|
const char *r;
|
||||||
|
if (qcsize < 0)
|
||||||
|
return NULL;
|
||||||
|
if (!qcptr)
|
||||||
|
return NULL;
|
||||||
|
if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize)
|
||||||
|
{
|
||||||
|
if (qcptr + qcsize <= prinst->stringtablemaxsize)
|
||||||
|
return prinst->stringtable+qcptr; //its in bounds
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = PR_GetString(prinst, qcptr);
|
||||||
|
if (qcsize < strlen(r))
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void PDECL ED_Spawned (struct edict_s *ent, int loading)
|
void PDECL ED_Spawned (struct edict_s *ent, int loading)
|
||||||
{
|
{
|
||||||
#ifdef VM_Q1
|
#ifdef VM_Q1
|
||||||
|
@ -1778,7 +1819,7 @@ void Q_InitProgs(void)
|
||||||
int j, maps;
|
int j, maps;
|
||||||
char *f;
|
char *f;
|
||||||
|
|
||||||
f = COM_LoadTempFile("maplist.txt", NULL);
|
f = COM_LoadTempFile("maplist.txt", 0, NULL);
|
||||||
f = COM_Parse(f);
|
f = COM_Parse(f);
|
||||||
maps = atoi(com_token);
|
maps = atoi(com_token);
|
||||||
for (j = 0; j < maps; j++)
|
for (j = 0; j < maps; j++)
|
||||||
|
@ -3853,7 +3894,7 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
|
||||||
case 13: tname = "blue"; break;
|
case 13: tname = "blue"; break;
|
||||||
default: tname = va("t%i", team); break; //good job our va has multiple buffers
|
default: tname = va("t%i", team); break; //good job our va has multiple buffers
|
||||||
}
|
}
|
||||||
PF_ForceInfoKey_Internal(entnum, "team", tname);
|
PF_ForceInfoKey_Internal(entnum, "team", tname, strlen(tname));
|
||||||
|
|
||||||
ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen("color "));
|
ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen("color "));
|
||||||
ClientReliableWrite_String (cl, "color ");
|
ClientReliableWrite_String (cl, "color ");
|
||||||
|
@ -4721,14 +4762,14 @@ void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
i = NUM_FOR_EDICT(prinst, ent);
|
i = NUM_FOR_EDICT(prinst, ent);
|
||||||
if (i>0 && i<sv.allocated_client_slots)
|
if (i>0 && i<sv.allocated_client_slots)
|
||||||
{
|
{
|
||||||
noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "noaim");
|
noaim = InfoBuf_ValueForKey (&svs.clients[i-1].userinfo, "noaim");
|
||||||
if (atoi(noaim) > 0)
|
if (atoi(noaim) > 0)
|
||||||
{
|
{
|
||||||
VectorCopy (P_VEC(v_forward), G_VECTOR(OFS_RETURN));
|
VectorCopy (P_VEC(v_forward), G_VECTOR(OFS_RETURN));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "aim");
|
noaim = InfoBuf_ValueForKey (&svs.clients[i-1].userinfo, "aim");
|
||||||
if (noaim)
|
if (noaim)
|
||||||
{
|
{
|
||||||
dist = atof(noaim);
|
dist = atof(noaim);
|
||||||
|
@ -5842,8 +5883,8 @@ char *PF_infokey_Internal (int entnum, const char *key)
|
||||||
value = "2.40";
|
value = "2.40";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((value = Info_ValueForKey (svs.info, key)) == NULL || !*value)
|
if ((value = InfoBuf_ValueForKey(&svs.info, key)) == NULL || !*value)
|
||||||
value = Info_ValueForKey(localinfo, key);
|
value = InfoBuf_ValueForKey(&svs.localinfo, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (entnum <= sv.allocated_client_slots)
|
else if (entnum <= sv.allocated_client_slots)
|
||||||
|
@ -5950,7 +5991,7 @@ char *PF_infokey_Internal (int entnum, const char *key)
|
||||||
else if (!strcmp(key, "*islagged"))
|
else if (!strcmp(key, "*islagged"))
|
||||||
value = (svs.clients[entnum-1].penalties & BAN_LAGGED)?"1":"";
|
value = (svs.clients[entnum-1].penalties & BAN_LAGGED)?"1":"";
|
||||||
else
|
else
|
||||||
value = Info_ValueForKey (svs.clients[entnum-1].userinfo, key);
|
value = InfoBuf_ValueForKey (&svs.clients[entnum-1].userinfo, key);
|
||||||
} else
|
} else
|
||||||
value = "";
|
value = "";
|
||||||
|
|
||||||
|
@ -5985,18 +6026,96 @@ static void QCBUILTIN PF_infokey_f (pubprogfuncs_t *prinst, struct globalvars_s
|
||||||
static void QCBUILTIN PF_sv_serverkeystring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_sv_serverkeystring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
const char *value = Info_ValueForKey (svs.info, key);
|
const char *value = InfoBuf_ValueForKey (&svs.info, key);
|
||||||
G_INT(OFS_RETURN) = *value?PR_TempString(prinst, value):0;
|
G_INT(OFS_RETURN) = *value?PR_TempString(prinst, value):0;
|
||||||
}
|
}
|
||||||
static void QCBUILTIN PF_sv_serverkeyfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_sv_serverkeyfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
const char *value = Info_ValueForKey (svs.info, key);
|
const char *value = InfoBuf_ValueForKey (&svs.info, key);
|
||||||
if (*value)
|
if (*value)
|
||||||
G_FLOAT(OFS_RETURN) = strtod(value, NULL);
|
G_FLOAT(OFS_RETURN) = strtod(value, NULL);
|
||||||
else
|
else
|
||||||
G_FLOAT(OFS_RETURN) = (prinst->callargc>=2)?G_FLOAT(OFS_PARM1):0;
|
G_FLOAT(OFS_RETURN) = (prinst->callargc>=2)?G_FLOAT(OFS_PARM1):0;
|
||||||
}
|
}
|
||||||
|
static void QCBUILTIN PF_sv_serverkeyblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
size_t blobsize = 0;
|
||||||
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
const char *blobvalue = InfoBuf_BlobForKey(&svs.info, key, &blobsize);
|
||||||
|
|
||||||
|
if ((prinst->callargc<2) || G_INT(OFS_PARM1) == 0)
|
||||||
|
G_INT(OFS_RETURN) = blobsize; //no pointer to write to, just return the length.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t size = min(blobsize, G_INT(OFS_PARM2));
|
||||||
|
void *ptr = PR_GetWriteQCPtr(prinst, G_INT(OFS_PARM1), size);
|
||||||
|
if (!ptr)
|
||||||
|
PR_BIError(prinst, "PF_sv_serverkeyblob: invalid pointer/size\n");
|
||||||
|
G_INT(OFS_RETURN) = size;
|
||||||
|
memcpy(ptr, blobvalue, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void QCBUILTIN PF_setserverkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
const char *value;
|
||||||
|
size_t size;
|
||||||
|
if (prinst->callargc > 2)
|
||||||
|
{
|
||||||
|
size = G_INT(OFS_PARM2);
|
||||||
|
value = PR_GetReadQCPtr(prinst, G_INT(OFS_PARM1), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
|
size = strlen(value);
|
||||||
|
}
|
||||||
|
if (!value)
|
||||||
|
PR_BIError(prinst, "PF_setserverkey: invalid pointer/size\n");
|
||||||
|
|
||||||
|
InfoBuf_SetStarBlobKey(&svs.info, key, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void QCBUILTIN PF_getlocalinfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
size_t blobsize = 0;
|
||||||
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
const char *blobvalue = InfoBuf_BlobForKey(&svs.localinfo, key, &blobsize);
|
||||||
|
|
||||||
|
if ((prinst->callargc<2) || G_INT(OFS_PARM1) == 0)
|
||||||
|
G_INT(OFS_RETURN) = blobsize; //no pointer to write to, just return the length.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t size = min(blobsize, G_INT(OFS_PARM2));
|
||||||
|
void *ptr = PR_GetWriteQCPtr(prinst, G_INT(OFS_PARM1), size);
|
||||||
|
if (!ptr)
|
||||||
|
PR_BIError(prinst, "PF_getlocalinfo: invalid pointer/size\n");
|
||||||
|
G_INT(OFS_RETURN) = size;
|
||||||
|
memcpy(ptr, blobvalue, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void QCBUILTIN PF_setlocalinfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
const char *key = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
|
const char *value;
|
||||||
|
size_t size;
|
||||||
|
if (prinst->callargc > 2)
|
||||||
|
{
|
||||||
|
size = G_INT(OFS_PARM2);
|
||||||
|
value = PR_GetReadQCPtr(prinst, G_INT(OFS_PARM1), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
|
size = strlen(value);
|
||||||
|
}
|
||||||
|
if (!value)
|
||||||
|
PR_BIError(prinst, "PF_setlocalinfo: invalid pointer/size\n");
|
||||||
|
|
||||||
|
InfoBuf_SetStarBlobKey(&svs.localinfo, key, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
==============
|
||||||
|
@ -7384,7 +7503,7 @@ void PRH2_SetPlayerClass(client_t *cl, int classnum, qboolean fromqc)
|
||||||
sprintf(temp,"%i",(int)classnum);
|
sprintf(temp,"%i",(int)classnum);
|
||||||
else
|
else
|
||||||
*temp = 0;
|
*temp = 0;
|
||||||
Info_SetValueForKey (cl->userinfo, "cl_playerclass", temp, sizeof(cl->userinfo));
|
InfoBuf_SetKey (&cl->userinfo, "cl_playerclass", temp);
|
||||||
if (cl->playerclass != classnum)
|
if (cl->playerclass != classnum)
|
||||||
{
|
{
|
||||||
cl->edict->xv->playerclass = classnum;
|
cl->edict->xv->playerclass = classnum;
|
||||||
|
@ -7427,7 +7546,7 @@ static void QCBUILTIN PF_h2setclass (pubprogfuncs_t *prinst, struct globalvars_s
|
||||||
client->playerclass = NewClass;
|
client->playerclass = NewClass;
|
||||||
|
|
||||||
sprintf(temp,"%d",(int)NewClass);
|
sprintf(temp,"%d",(int)NewClass);
|
||||||
Info_SetValueForKey (client->userinfo, "cl_playerclass", temp, sizeof(client->userinfo));
|
InfoBuf_SetValueForKey (&client->userinfo, "cl_playerclass", temp);
|
||||||
client->sendinfo = true;
|
client->sendinfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9091,29 +9210,25 @@ static void QCBUILTIN PF_te_plasmaburn(pubprogfuncs_t *prinst, struct globalvars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *value)
|
int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *value, size_t valsize)
|
||||||
{
|
{
|
||||||
if (entnum == 0)
|
if (entnum == 0)
|
||||||
{ //localinfo
|
{ //serverinfo
|
||||||
Info_SetValueForKey (localinfo, key, value, MAX_LOCALINFO_STRING);
|
InfoBuf_SetStarBlobKey(&svs.info, key, value, valsize);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else if (entnum <= sv.allocated_client_slots)
|
else if (entnum <= sv.allocated_client_slots)
|
||||||
{ //woo. we found a client.
|
{ //woo. we found a client.
|
||||||
char *oldvalue;
|
|
||||||
if (svs.clients[entnum-1].state == cs_free)
|
if (svs.clients[entnum-1].state == cs_free)
|
||||||
{
|
{
|
||||||
Con_DPrintf("PF_ForceInfoKey: inactive client\n");
|
Con_DPrintf("PF_ForceInfoKey: inactive client\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
oldvalue = Info_ValueForKey(svs.clients[entnum-1].userinfo, key);
|
if (InfoBuf_SetStarBlobKey(&svs.clients[entnum-1].userinfo, key, value, valsize))
|
||||||
if (strcmp(oldvalue, value))
|
|
||||||
{
|
{
|
||||||
Info_SetValueForStarKey(svs.clients[entnum-1].userinfo, key, value, sizeof(svs.clients[entnum-1].userinfo));
|
|
||||||
|
|
||||||
SV_ExtractFromUserinfo (&svs.clients[entnum-1], false);
|
SV_ExtractFromUserinfo (&svs.clients[entnum-1], false);
|
||||||
|
|
||||||
value = Info_ValueForKey(svs.clients[entnum-1].userinfo, key);
|
value = InfoBuf_ValueForKey(&svs.clients[entnum-1].userinfo, key);
|
||||||
|
|
||||||
if (!strcmp(key, "*spectator"))
|
if (!strcmp(key, "*spectator"))
|
||||||
{
|
{
|
||||||
|
@ -9155,7 +9270,33 @@ static void QCBUILTIN PF_ForceInfoKey(pubprogfuncs_t *prinst, struct globalvars_
|
||||||
key = PR_GetStringOfs(prinst, OFS_PARM1);
|
key = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
value = PR_GetStringOfs(prinst, OFS_PARM2);
|
value = PR_GetStringOfs(prinst, OFS_PARM2);
|
||||||
|
|
||||||
G_FLOAT(OFS_RETURN) = PF_ForceInfoKey_Internal(e->entnum, key, value);
|
G_FLOAT(OFS_RETURN) = PF_ForceInfoKey_Internal(e->entnum, key, value, strlen(value));
|
||||||
|
}
|
||||||
|
static void QCBUILTIN PF_ForceInfoKeyBlob(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{
|
||||||
|
edict_t *e;
|
||||||
|
const char *value;
|
||||||
|
const char *key;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
e = G_EDICT(prinst, OFS_PARM0);
|
||||||
|
key = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
|
value = PR_GetStringOfs(prinst, OFS_PARM2);
|
||||||
|
size = G_INT(OFS_PARM3);
|
||||||
|
if (size < 0)
|
||||||
|
size = 0;
|
||||||
|
if (G_INT(OFS_PARM2) >= 0 && G_INT(OFS_PARM2) < prinst->stringtablesize)
|
||||||
|
{
|
||||||
|
if (value+size > prinst->stringtable+prinst->stringtablesize)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (size > strlen(value)+1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_FLOAT(OFS_RETURN) = PF_ForceInfoKey_Internal(e->entnum, key, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -9189,16 +9330,16 @@ static void QCBUILTIN PF_setcolors (pubprogfuncs_t *prinst, struct globalvars_s
|
||||||
client->edict->v->team = (i & 15) + 1;
|
client->edict->v->team = (i & 15) + 1;
|
||||||
|
|
||||||
Q_snprintfz(number, sizeof(number), "%i", i>>4);
|
Q_snprintfz(number, sizeof(number), "%i", i>>4);
|
||||||
if (strcmp(number, Info_ValueForKey(client->userinfo, "topcolor")))
|
if (strcmp(number, InfoBuf_ValueForKey(&client->userinfo, "topcolor")))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(client->userinfo, "topcolor", number, sizeof(client->userinfo));
|
InfoBuf_SetValueForKey(&client->userinfo, "topcolor", number);
|
||||||
key = "topcolor";
|
key = "topcolor";
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_snprintfz(number, sizeof(number), "%i", i&15);
|
Q_snprintfz(number, sizeof(number), "%i", i&15);
|
||||||
if (strcmp(number, Info_ValueForKey(client->userinfo, "bottomcolor")))
|
if (strcmp(number, InfoBuf_ValueForKey(&client->userinfo, "bottomcolor")))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(client->userinfo, "bottomcolor", number, sizeof(client->userinfo));
|
InfoBuf_SetValueForKey(&client->userinfo, "bottomcolor", number);
|
||||||
key = key?"*bothcolours":"bottomcolor";
|
key = key?"*bothcolours":"bottomcolor";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10282,6 +10423,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"abort", PF_Abort, 0, 0, 0, 211, D("void(optional __variant ret)", "QC execution is aborted. Parent QC functions on the stack will be skipped, effectively this forces all QC functions to 'return ret' until execution returns to the engine. If ret is ommited, it is assumed to be 0.")},
|
{"abort", PF_Abort, 0, 0, 0, 211, D("void(optional __variant ret)", "QC execution is aborted. Parent QC functions on the stack will be skipped, effectively this forces all QC functions to 'return ret' until execution returns to the engine. If ret is ommited, it is assumed to be 0.")},
|
||||||
{"sleep", PF_Sleep, 0, 0, 0, 212, D("void(float sleeptime)", "Suspends the current QC execution thread for 'sleeptime' seconds.\nOther QC functions can and will be executed in the interim, including changing globals and field state (but not simultaneously).\nThe self and other globals will be restored when the thread wakes up (or set to world if they were removed since the thread started sleeping). Locals will be preserved, but will not be protected from remove calls.\nIf the engine is expecting the QC to return a value (even in the parent/root function), the value 0 shall be used instead of waiting for the qc to resume.")},
|
{"sleep", PF_Sleep, 0, 0, 0, 212, D("void(float sleeptime)", "Suspends the current QC execution thread for 'sleeptime' seconds.\nOther QC functions can and will be executed in the interim, including changing globals and field state (but not simultaneously).\nThe self and other globals will be restored when the thread wakes up (or set to world if they were removed since the thread started sleeping). Locals will be preserved, but will not be protected from remove calls.\nIf the engine is expecting the QC to return a value (even in the parent/root function), the value 0 shall be used instead of waiting for the qc to resume.")},
|
||||||
{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213, D("void(entity player, string key, string value)", "Directly changes a user's info without pinging off the client. Also allows explicitly setting * keys, including *spectator. Does not affect the user's config or other servers.")},
|
{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213, D("void(entity player, string key, string value)", "Directly changes a user's info without pinging off the client. Also allows explicitly setting * keys, including *spectator. Does not affect the user's config or other servers.")},
|
||||||
|
{"forceinfokeyblob",PF_ForceInfoKeyBlob,0, 0, 0, 0, D("void(entity player, string key, void *data, int size)", "Directly changes a user's info without pinging off the client. Also allows explicitly setting * keys, including *spectator. Does not affect the user's config or other servers.")},
|
||||||
#ifdef SVCHAT
|
#ifdef SVCHAT
|
||||||
{"chat", PF_chat, 0, 0, 0, 214, "void(string filename, float starttag, entity edict)"}, //(FTE_NPCCHAT)
|
{"chat", PF_chat, 0, 0, 0, 214, "void(string filename, float starttag, entity edict)"}, //(FTE_NPCCHAT)
|
||||||
#endif
|
#endif
|
||||||
|
@ -10486,8 +10628,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"drawline", PF_Fixme, 0, 0, 0, 315, D("void(float width, vector pos1, vector pos2, vector rgb, float alpha, optional float drawflag)", "Draws a 2d line between the two 2d points.")},// (EXT_CSQC)
|
{"drawline", PF_Fixme, 0, 0, 0, 315, D("void(float width, vector pos1, vector pos2, vector rgb, float alpha, optional float drawflag)", "Draws a 2d line between the two 2d points.")},// (EXT_CSQC)
|
||||||
{"iscachedpic", PF_Fixme, 0, 0, 0, 316, D("float(string name)", "Checks to see if the image is currently loaded. Engines might lie, or cache between maps.")},// (EXT_CSQC)
|
{"iscachedpic", PF_Fixme, 0, 0, 0, 316, D("float(string name)", "Checks to see if the image is currently loaded. Engines might lie, or cache between maps.")},// (EXT_CSQC)
|
||||||
{"precache_pic", PF_Fixme, 0, 0, 0, 317, D("string(string name, optional float trywad)", "Forces the engine to load the named image. If trywad is specified, the specified name must any lack path and extension.")},// (EXT_CSQC)
|
{"precache_pic", PF_Fixme, 0, 0, 0, 317, D("string(string name, optional float trywad)", "Forces the engine to load the named image. If trywad is specified, the specified name must any lack path and extension.")},// (EXT_CSQC)
|
||||||
{"r_uploadimage", PF_Fixme, 0, 0, 0, 0, D("void(string imagename, int width, int height, int *pixeldata)", "Updates a texture with the specified rgba data. Will be created if needed.")},
|
{"r_uploadimage", PF_Fixme, 0, 0, 0, 0, D("void(string imagename, int width, int height, void *pixeldata, optional int datasize, optional int format)", "Updates a texture with the specified rgba data. Will be created if needed. If blobsize is specified then the image is decoded (eg .ktx or .dds data) instead of being raw R8G8B8A data. You'll typically want shaderforname to also generate a shader to use the texture.")},
|
||||||
{"r_readimage", PF_Fixme, 0, 0, 0, 0, D("int*(string filename, __out int width, __out int height)", "Reads and decodes an image from disk, providing raw pixel data. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it.")},
|
{"r_readimage", PF_Fixme, 0, 0, 0, 0, D("int*(string filename, __out int width, __out int height)", "Reads and decodes an image from disk, providing raw R8G8B8A pixel data. Should not be used for dds or ktx etc formats. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it.")},
|
||||||
{"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, D("#define draw_getimagesize drawgetimagesize\nvector(string picname)", "Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution.")},// (EXT_CSQC)
|
{"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, D("#define draw_getimagesize drawgetimagesize\nvector(string picname)", "Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution.")},// (EXT_CSQC)
|
||||||
{"freepic", PF_Fixme, 0, 0, 0, 319, D("void(string name)", "Tells the engine that the image is no longer needed. The image will appear to be new the next time its needed.")},// (EXT_CSQC)
|
{"freepic", PF_Fixme, 0, 0, 0, 319, D("void(string name)", "Tells the engine that the image is no longer needed. The image will appear to be new the next time its needed.")},// (EXT_CSQC)
|
||||||
//320
|
//320
|
||||||
|
@ -10540,6 +10682,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"runstandardplayerphysics",PF_runclientphys,0,0,0, 347, D("void(entity ent)", "Perform the engine's standard player movement prediction upon the given entity using the input_* globals to describe movement.")},
|
{"runstandardplayerphysics",PF_runclientphys,0,0,0, 347, D("void(entity ent)", "Perform the engine's standard player movement prediction upon the given entity using the input_* globals to describe movement.")},
|
||||||
{"getplayerkeyvalue", PF_Fixme,0, 0, 0, 348, D("string(float playernum, string keyname)", "Look up a player's userinfo, to discover things like their name, topcolor, bottomcolor, skin, team, *ver.\nAlso includes scoreboard info like frags, ping, pl, userid, entertime, as well as voipspeaking and voiploudness.")},// (EXT_CSQC)
|
{"getplayerkeyvalue", PF_Fixme,0, 0, 0, 348, D("string(float playernum, string keyname)", "Look up a player's userinfo, to discover things like their name, topcolor, bottomcolor, skin, team, *ver.\nAlso includes scoreboard info like frags, ping, pl, userid, entertime, as well as voipspeaking and voiploudness.")},// (EXT_CSQC)
|
||||||
{"getplayerkeyfloat", PF_Fixme,0, 0, 0, 0, D("float(float playernum, string keyname, optional float assumevalue)", "Cheaper version of getplayerkeyvalue that avoids the need for so many tempstrings.")},
|
{"getplayerkeyfloat", PF_Fixme,0, 0, 0, 0, D("float(float playernum, string keyname, optional float assumevalue)", "Cheaper version of getplayerkeyvalue that avoids the need for so many tempstrings.")},
|
||||||
|
{"getplayerkeyblob", PF_Fixme,0, 0, 0, 0, D("int(float playernum, string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
|
||||||
|
|
||||||
|
{"getlocalinfo", PF_getlocalinfo,0, 0, 0, 0, D("int(string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
|
||||||
|
{"setlocalinfo", PF_setlocalinfo,0, 0, 0, 0, D("void(string keyname, optional void *outptr, int size)", "Changes the server's localinfo. This data will be available for the following map, and will *usually* reload with saved games.")},
|
||||||
|
|
||||||
{"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not")},// (EXT_CSQC)
|
{"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not")},// (EXT_CSQC)
|
||||||
{"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns if the client is acting as the server (aka: listen server)")},//(EXT_CSQC)
|
{"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns if the client is acting as the server (aka: listen server)")},//(EXT_CSQC)
|
||||||
|
@ -10549,6 +10695,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
|
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
|
||||||
{"serverkey", PF_sv_serverkeystring,0,0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string")},//
|
{"serverkey", PF_sv_serverkeystring,0,0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string")},//
|
||||||
{"serverkeyfloat", PF_sv_serverkeyfloat,0,0, 0, 0, D("float(string key, optional float assumevalue)", "Version of serverkey that returns the value as a float (which avoids tempstrings).")},//
|
{"serverkeyfloat", PF_sv_serverkeyfloat,0,0, 0, 0, D("float(string key, optional float assumevalue)", "Version of serverkey that returns the value as a float (which avoids tempstrings).")},//
|
||||||
|
{"serverkeyblob", PF_sv_serverkeyblob,0,0, 0, 0, D("int(int buf, string key, optional void *ptr, int size)", "Version of serverkey that can obtain entire serverinfo, localinfo, or (local)userinfo blobs. Returns blob size")},//
|
||||||
|
{"setserverkey", PF_setserverkey,0, 0, 0, 0, D("void(int buf, string key, void *ptr, optional int size)", "Changes the server's serverinfo.")},//
|
||||||
{"getentitytoken", PF_Fixme, 0, 0, 0, 355, D("string(optional string resetstring)", "Grab the next token in the map's entity lump.\nIf resetstring is not specified, the next token will be returned with no other sideeffects.\nIf empty, will reset from the map before returning the first token, probably {.\nIf not empty, will tokenize from that string instead.\nAlways returns tempstrings.")},//;
|
{"getentitytoken", PF_Fixme, 0, 0, 0, 355, D("string(optional string resetstring)", "Grab the next token in the map's entity lump.\nIf resetstring is not specified, the next token will be returned with no other sideeffects.\nIf empty, will reset from the map before returning the first token, probably {.\nIf not empty, will tokenize from that string instead.\nAlways returns tempstrings.")},//;
|
||||||
{"findfont", PF_Fixme, 0, 0, 0, 356, D("float(string s)", "Looks up a named font slot. Matches the actual font name as a last resort.")},//;
|
{"findfont", PF_Fixme, 0, 0, 0, 356, D("float(string s)", "Looks up a named font slot. Matches the actual font name as a last resort.")},//;
|
||||||
{"loadfont", PF_Fixme, 0, 0, 0, 357, D("float(string fontname, string fontmaps, string sizes, float slot, optional float fix_scale, optional float fix_voffset)", "too convoluted for me to even try to explain correct usage. Try drawfont = loadfont(\"\", \"cour\", \"16\", -1, 0, 0); to switch to the courier font (optimised for 16 virtual pixels high), if you have the freetype2 library in windows..")},
|
{"loadfont", PF_Fixme, 0, 0, 0, 357, D("float(string fontname, string fontmaps, string sizes, float slot, optional float fix_scale, optional float fix_voffset)", "too convoluted for me to even try to explain correct usage. Try drawfont = loadfont(\"\", \"cour\", \"16\", -1, 0, 0); to switch to the courier font (optimised for 16 virtual pixels high), if you have the freetype2 library in windows..")},
|
||||||
|
@ -10869,6 +11017,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"crypto_getmyidfp",PF_Fixme, 0, 0, 0, 637, "string(float addr)" STUB},
|
{"crypto_getmyidfp",PF_Fixme, 0, 0, 0, 637, "string(float addr)" STUB},
|
||||||
// {"VM_CL_RotateMoves",PF_Fixme, 0, 0, 0, 638, ""},
|
// {"VM_CL_RotateMoves",PF_Fixme, 0, 0, 0, 638, ""},
|
||||||
{"digest_hex", PF_digest_hex, 0, 0, 0, 639, "string(string digest, string data, ...)"},
|
{"digest_hex", PF_digest_hex, 0, 0, 0, 639, "string(string digest, string data, ...)"},
|
||||||
|
{"digest_ptr", PF_digest_ptr, 0, 0, 0, 0, D("string(string digest, void *data, int length)", "Calculates the digest of a single contiguous block of memory (including nulls) using the specified hash function.")},
|
||||||
// {"V_CalcRefdef", PF_Fixme, 0, 0, 0, 640, "void(entity e)"},
|
// {"V_CalcRefdef", PF_Fixme, 0, 0, 0, 640, "void(entity e)"},
|
||||||
{"crypto_getmyidstatus",PF_Fixme, 0, 0, 0, 641, "float(float i)" STUB},
|
{"crypto_getmyidstatus",PF_Fixme, 0, 0, 0, 641, "float(float i)" STUB},
|
||||||
|
|
||||||
|
@ -11075,7 +11224,7 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any
|
||||||
{
|
{
|
||||||
char *builtinmap;
|
char *builtinmap;
|
||||||
int binum;
|
int binum;
|
||||||
builtinmap = COM_LoadTempFile("fte_bimap.txt", NULL);
|
builtinmap = COM_LoadTempFile("fte_bimap.txt", 0, NULL);
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
builtinmap = COM_Parse(builtinmap);
|
builtinmap = COM_Parse(builtinmap);
|
||||||
|
|
|
@ -1100,7 +1100,7 @@ static int bi_lua_setinfokey(lua_State *L)
|
||||||
key = lua_tolstring(L, 2, NULL);
|
key = lua_tolstring(L, 2, NULL);
|
||||||
value = lua_tolstring(L, 3, NULL);
|
value = lua_tolstring(L, 3, NULL);
|
||||||
|
|
||||||
result = PF_ForceInfoKey_Internal(entnum, key, value);
|
result = PF_ForceInfoKey_Internal(entnum, key, value, strlen(value));
|
||||||
lua_pushinteger(L, result);
|
lua_pushinteger(L, result);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1532,11 +1532,11 @@ static qintptr_t QVM_Add_Bot (void *offset, quintptr_t mask, const qintptr_t *ar
|
||||||
|
|
||||||
cl->edict = EDICT_NUM_PB(sv.world.progs, i+1);
|
cl->edict = EDICT_NUM_PB(sv.world.progs, i+1);
|
||||||
|
|
||||||
Info_SetValueForKey(cl->userinfo, "name", name, sizeof(cl->userinfo));
|
InfoBuf_SetKey(&cl->userinfo, "name", name);
|
||||||
Info_SetValueForKey(cl->userinfo, "topcolor", va("%i", top), sizeof(cl->userinfo));
|
InfoBuf_SetKey(&cl->userinfo, "topcolor", va("%i", top));
|
||||||
Info_SetValueForKey(cl->userinfo, "bottomcolor", va("%i", bottom), sizeof(cl->userinfo));
|
InfoBuf_SetKey(&cl->userinfo, "bottomcolor", va("%i", bottom));
|
||||||
Info_SetValueForKey(cl->userinfo, "skin", skin, sizeof(cl->userinfo));
|
InfoBuf_SetKey(&cl->userinfo, "skin", skin);
|
||||||
Info_SetValueForStarKey(cl->userinfo, "*bot", "1", sizeof(cl->userinfo));
|
InfoBuf_SetStarKey(&cl->userinfo, "*bot", "1");
|
||||||
SV_ExtractFromUserinfo(cl, true);
|
SV_ExtractFromUserinfo(cl, true);
|
||||||
SV_SetUpClientEdict (cl, cl->edict);
|
SV_SetUpClientEdict (cl, cl->edict);
|
||||||
|
|
||||||
|
@ -1598,14 +1598,20 @@ static qintptr_t QVM_SetBotCMD (void *offset, quintptr_t mask, const qintptr_t *
|
||||||
}
|
}
|
||||||
static qintptr_t QVM_SetUserInfo (void *offset, quintptr_t mask, const qintptr_t *arg)
|
static qintptr_t QVM_SetUserInfo (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||||
{
|
{
|
||||||
char *key = VM_POINTER(arg[1]);
|
int ent = VM_LONG(arg[0]);
|
||||||
|
const char *key = VM_POINTER(arg[1]);
|
||||||
|
const char *val = VM_POINTER(arg[2]);
|
||||||
if (*key == '*' && (VM_LONG(arg[3])&1))
|
if (*key == '*' && (VM_LONG(arg[3])&1))
|
||||||
return -1; //denied!
|
return -1; //denied!
|
||||||
return PF_ForceInfoKey_Internal(VM_LONG(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]));
|
return PF_ForceInfoKey_Internal(ent, key, val, strlen(val));
|
||||||
}
|
}
|
||||||
static qintptr_t QVM_SetBotUserInfo (void *offset, quintptr_t mask, const qintptr_t *arg)
|
static qintptr_t QVM_SetBotUserInfo (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||||
{
|
{
|
||||||
return PF_ForceInfoKey_Internal(VM_LONG(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]));
|
int ent = VM_LONG(arg[0]);
|
||||||
|
const char *key = VM_POINTER(arg[1]);
|
||||||
|
const char *val = VM_POINTER(arg[2]);
|
||||||
|
|
||||||
|
return PF_ForceInfoKey_Internal(ent, key, val, strlen(val));
|
||||||
}
|
}
|
||||||
static qintptr_t QVM_MoveToGoal (void *offset, quintptr_t mask, const qintptr_t *arg)
|
static qintptr_t QVM_MoveToGoal (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||||
{
|
{
|
||||||
|
@ -2509,7 +2515,7 @@ qboolean Q1QVM_ClientSay(edict_t *player, qboolean team)
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean Q1QVM_UserInfoChanged(edict_t *player)
|
qboolean Q1QVM_UserInfoChanged(edict_t *player)
|
||||||
{
|
{ //mod will use G_CMD_ARGV to get argv1+argv2 to read the info that is changing.
|
||||||
if (!q1qvm)
|
if (!q1qvm)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -1207,7 +1207,6 @@ void SV_Savegame (const char *savename, qboolean mapchange)
|
||||||
vfsfile_t *f;
|
vfsfile_t *f;
|
||||||
int len;
|
int len;
|
||||||
levelcache_t *cache;
|
levelcache_t *cache;
|
||||||
char str[MAX_LOCALINFO_STRING+1];
|
|
||||||
char *savefilename;
|
char *savefilename;
|
||||||
|
|
||||||
#ifndef QUAKETC
|
#ifndef QUAKETC
|
||||||
|
@ -1291,13 +1290,9 @@ void SV_Savegame (const char *savename, qboolean mapchange)
|
||||||
//write floats too so you can use it to debug.
|
//write floats too so you can use it to debug.
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_strncpyz(str, svs.info, sizeof(str));
|
InfoBuf_WriteToFile(f, &svs.info, NULL, 0);
|
||||||
Info_RemovePrefixedKeys(str, '*');
|
VFS_PUTS(f, "\n");
|
||||||
VFS_PRINTF (f, "%s\n", str);
|
InfoBuf_WriteToFile(f, &svs.localinfo, NULL, 0);
|
||||||
|
|
||||||
Q_strncpyz(str, localinfo, sizeof(str));
|
|
||||||
Info_RemovePrefixedKeys(str, '*');
|
|
||||||
VFS_PUTS(f, str);
|
|
||||||
|
|
||||||
VFS_PRINTF (f, "\n{\n"); //all game vars. FIXME: Should save the ones that have been retrieved/set by progs.
|
VFS_PRINTF (f, "\n{\n"); //all game vars. FIXME: Should save the ones that have been retrieved/set by progs.
|
||||||
VFS_PRINTF (f, "skill \"%s\"\n", skill.string);
|
VFS_PRINTF (f, "skill \"%s\"\n", skill.string);
|
||||||
|
@ -1703,9 +1698,8 @@ void SV_Loadgame_f (void)
|
||||||
for (trim = str; *trim <= ' ' && *trim; trim++)
|
for (trim = str; *trim <= ' ' && *trim; trim++)
|
||||||
;
|
;
|
||||||
Info_RemovePrefixedKeys(str, '*'); //just in case
|
Info_RemovePrefixedKeys(str, '*'); //just in case
|
||||||
Info_RemoveNonStarKeys(svs.info);
|
InfoBuf_Clear(&svs.info, false);
|
||||||
len = strlen(svs.info);
|
InfoBuf_FromString(&svs.info, str, true);
|
||||||
Q_strncpyz(svs.info+len, str, sizeof(svs.info)-len);
|
|
||||||
|
|
||||||
VFS_GETS(f, str, sizeof(str)-1);
|
VFS_GETS(f, str, sizeof(str)-1);
|
||||||
for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--)
|
for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--)
|
||||||
|
@ -1713,9 +1707,8 @@ void SV_Loadgame_f (void)
|
||||||
for (trim = str; *trim <= ' ' && *trim; trim++)
|
for (trim = str; *trim <= ' ' && *trim; trim++)
|
||||||
;
|
;
|
||||||
Info_RemovePrefixedKeys(str, '*'); //just in case
|
Info_RemovePrefixedKeys(str, '*'); //just in case
|
||||||
Info_RemoveNonStarKeys(localinfo);
|
InfoBuf_Clear(&svs.localinfo, false);
|
||||||
len = strlen(localinfo);
|
InfoBuf_FromString(&svs.localinfo, str, true);
|
||||||
Q_strncpyz(localinfo+len, str, sizeof(localinfo)-len);
|
|
||||||
|
|
||||||
VFS_GETS(f, str, sizeof(str)-1);
|
VFS_GETS(f, str, sizeof(str)-1);
|
||||||
for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--)
|
for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--)
|
||||||
|
|
|
@ -458,9 +458,10 @@ typedef struct client_s
|
||||||
qboolean drop; // lose this guy next opportunity
|
qboolean drop; // lose this guy next opportunity
|
||||||
int lossage; // loss percentage
|
int lossage; // loss percentage
|
||||||
|
|
||||||
int challenge;
|
int challenge;
|
||||||
int userid; // identifying number
|
int userid; // identifying number
|
||||||
char userinfo[EXTENDED_INFO_STRING]; // infostring
|
infobuf_t userinfo; // all of the user's various settings
|
||||||
|
infosync_t infosync; // information about the infos that the client still doesn't know (server and multiple clients).
|
||||||
char *transfer;
|
char *transfer;
|
||||||
|
|
||||||
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
||||||
|
@ -908,7 +909,8 @@ typedef struct
|
||||||
int heartbeat_sequence;
|
int heartbeat_sequence;
|
||||||
svstats_t stats;
|
svstats_t stats;
|
||||||
|
|
||||||
char info[MAX_SERVERINFO_STRING];
|
infobuf_t info;
|
||||||
|
infobuf_t localinfo;
|
||||||
|
|
||||||
// log messages are used so that fraglog processes can get stats
|
// log messages are used so that fraglog processes can get stats
|
||||||
int logsequence; // the message currently being filled
|
int logsequence; // the message currently being filled
|
||||||
|
@ -1069,8 +1071,6 @@ extern edict_t *sv_player;
|
||||||
|
|
||||||
//extern char localmodels[MAX_MODELS][5]; // inline model names for precache
|
//extern char localmodels[MAX_MODELS][5]; // inline model names for precache
|
||||||
|
|
||||||
extern char localinfo[MAX_LOCALINFO_STRING+1];
|
|
||||||
|
|
||||||
extern vfsfile_t *sv_fraglogfile;
|
extern vfsfile_t *sv_fraglogfile;
|
||||||
|
|
||||||
//===========================================================
|
//===========================================================
|
||||||
|
@ -1123,7 +1123,6 @@ void SV_ArgumentOverrides(void);
|
||||||
|
|
||||||
int SV_CalcPing (client_t *cl, qboolean forcecalc);
|
int SV_CalcPing (client_t *cl, qboolean forcecalc);
|
||||||
void SV_FullClientUpdate (client_t *client, client_t *to);
|
void SV_FullClientUpdate (client_t *client, client_t *to);
|
||||||
void SV_GeneratePublicUserInfo(int pext, client_t *cl, char *info, int infolength);
|
|
||||||
char *SV_PlayerPublicAddress(client_t *cl);
|
char *SV_PlayerPublicAddress(client_t *cl);
|
||||||
|
|
||||||
qboolean SVC_GetChallenge (qboolean respond_dp);
|
qboolean SVC_GetChallenge (qboolean respond_dp);
|
||||||
|
@ -1273,7 +1272,6 @@ void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t text, ...);
|
||||||
void VARGS SV_BroadcastPrintf (int level, const char *fmt, ...) LIKEPRINTF(2);
|
void VARGS SV_BroadcastPrintf (int level, const char *fmt, ...) LIKEPRINTF(2);
|
||||||
void VARGS SV_BroadcastTPrintf (int level, translation_t fmt, ...);
|
void VARGS SV_BroadcastTPrintf (int level, translation_t fmt, ...);
|
||||||
void VARGS SV_BroadcastCommand (const char *fmt, ...) LIKEPRINTF(1);
|
void VARGS SV_BroadcastCommand (const char *fmt, ...) LIKEPRINTF(1);
|
||||||
void SV_SendServerInfoChange(const char *key, const char *value);
|
|
||||||
void SV_SendMessagesToAll (void);
|
void SV_SendMessagesToAll (void);
|
||||||
void SV_FindModelNumbers (void);
|
void SV_FindModelNumbers (void);
|
||||||
|
|
||||||
|
|
|
@ -579,7 +579,7 @@ void SV_Map_f (void)
|
||||||
if (!startspot)
|
if (!startspot)
|
||||||
{
|
{
|
||||||
//revert the startspot if its not overridden
|
//revert the startspot if its not overridden
|
||||||
Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot));
|
Q_strncpyz(spot, InfoBuf_ValueForKey(&svs.info, "*startspot"), sizeof(spot));
|
||||||
startspot = spot;
|
startspot = spot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -664,7 +664,7 @@ void SV_Map_f (void)
|
||||||
if (!isDedicated) //otherwise, info used on map loading isn't present
|
if (!isDedicated) //otherwise, info used on map loading isn't present
|
||||||
{
|
{
|
||||||
cl.haveserverinfo = true;
|
cl.haveserverinfo = true;
|
||||||
Q_strncpyz (cl.serverinfo, svs.info, sizeof(cl.serverinfo));
|
InfoBuf_Clone(&cl.serverinfo, &svs.info);
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1100,9 +1100,9 @@ void SV_EvaluatePenalties(client_t *cl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta & BAN_VIP)
|
if (delta & BAN_VIP)
|
||||||
Info_SetValueForStarKey(cl->userinfo, "*VIP", (cl->penalties & BAN_VIP)?"1":"", sizeof(cl->userinfo));
|
InfoBuf_SetStarKey(&cl->userinfo, "*VIP", (cl->penalties & BAN_VIP)?"1":"");
|
||||||
if (delta & BAN_MAPPER)
|
if (delta & BAN_MAPPER)
|
||||||
Info_SetValueForStarKey(cl->userinfo, "*mapper", (cl->penalties & BAN_MAPPER)?"1":"", sizeof(cl->userinfo));
|
InfoBuf_SetStarKey(&cl->userinfo, "*mapper", (cl->penalties & BAN_MAPPER)?"1":"");
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t reevaluatebantime;
|
static time_t reevaluatebantime;
|
||||||
|
@ -1623,7 +1623,7 @@ static void SV_ForceName_f (void)
|
||||||
|
|
||||||
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
|
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(cl->userinfo, "name", Cmd_Argv(2), EXTENDED_INFO_STRING);
|
InfoBuf_SetKey(&cl->userinfo, "name", Cmd_Argv(2));
|
||||||
SV_LogPlayer(cl, "name forced");
|
SV_LogPlayer(cl, "name forced");
|
||||||
SV_ExtractFromUserinfo(cl, true);
|
SV_ExtractFromUserinfo(cl, true);
|
||||||
Q_strncpyz(cl->name, Cmd_Argv(2), sizeof(cl->namebuf));
|
Q_strncpyz(cl->name, Cmd_Argv(2), sizeof(cl->namebuf));
|
||||||
|
@ -2192,51 +2192,6 @@ static void SV_Heartbeat_f (void)
|
||||||
SV_Master_ReResolve();
|
SV_Master_ReResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOREACHCLIENT(i,cl) \
|
|
||||||
for (i = sv.mvdrecording?-1:0; i < sv.allocated_client_slots; i++) \
|
|
||||||
if ((cl = (i==-1?&demo.recorder:&svs.clients[i]))) \
|
|
||||||
if ((i == -1) || cl->state >= cs_connected)
|
|
||||||
|
|
||||||
void SV_SendServerInfoChange(const char *key, const char *value)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
client_t *cl;
|
|
||||||
|
|
||||||
if (!sv.state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef Q2SERVER
|
|
||||||
if (svs.gametype == GT_QUAKE2)
|
|
||||||
return; //FIXME!!!
|
|
||||||
#endif
|
|
||||||
#ifdef Q3SERVER
|
|
||||||
if (svs.gametype == GT_QUAKE3)
|
|
||||||
return; //FIXME!!!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FOREACHCLIENT(i, cl)
|
|
||||||
{
|
|
||||||
if (cl->controller)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ISQWCLIENT(cl))
|
|
||||||
{
|
|
||||||
ClientReliableWrite_Begin(cl, svc_serverinfo, strlen(key) + strlen(value)+3);
|
|
||||||
ClientReliableWrite_String(cl, key);
|
|
||||||
ClientReliableWrite_String(cl, value);
|
|
||||||
}
|
|
||||||
else if (ISNQCLIENT(cl) && (cl->fteprotocolextensions2 & PEXT2_PREDINFO))
|
|
||||||
{
|
|
||||||
ClientReliableWrite_Begin(cl, svc_stufftext, 1+6+strlen(key)+2+strlen(value)+3);
|
|
||||||
ClientReliableWrite_SZ(cl, "//svi ", 6);
|
|
||||||
ClientReliableWrite_SZ(cl, key, strlen(key));
|
|
||||||
ClientReliableWrite_SZ(cl, " \"", 2);
|
|
||||||
ClientReliableWrite_SZ(cl, value, strlen(value));
|
|
||||||
ClientReliableWrite_String(cl, "\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===========
|
===========
|
||||||
SV_Serverinfo_f
|
SV_Serverinfo_f
|
||||||
|
@ -2253,7 +2208,7 @@ void SV_Serverinfo_f (void)
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
Con_TPrintf ("Server info settings:\n");
|
Con_TPrintf ("Server info settings:\n");
|
||||||
Info_Print (svs.info, "");
|
InfoBuf_Print (&svs.info, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2268,18 +2223,18 @@ void SV_Serverinfo_f (void)
|
||||||
if (!strcmp(Cmd_Argv(1), "*"))
|
if (!strcmp(Cmd_Argv(1), "*"))
|
||||||
if (!strcmp(Cmd_Argv(2), ""))
|
if (!strcmp(Cmd_Argv(2), ""))
|
||||||
{ //clear it out
|
{ //clear it out
|
||||||
char *k;
|
const char *k;
|
||||||
for(i=0;;)
|
for(i=0;;)
|
||||||
{
|
{
|
||||||
k = Info_KeyForNumber(svs.info, i);
|
k = InfoBuf_KeyForNumber(&svs.info, i);
|
||||||
if (!*k)
|
if (!k)
|
||||||
break; //no more.
|
break; //no more.
|
||||||
else if (*k == '*')
|
else if (*k == '*')
|
||||||
i++; //can't remove * keys
|
i++; //can't remove * keys
|
||||||
else if ((var = Cvar_FindVar(k)) && var->flags&CVAR_SERVERINFO)
|
else if ((var = Cvar_FindVar(k)) && var->flags&CVAR_SERVERINFO)
|
||||||
i++; //this one is a cvar.
|
i++; //this one is a cvar.
|
||||||
else
|
else
|
||||||
Info_RemoveKey(svs.info, k); //we can remove this one though, so yay.
|
InfoBuf_RemoveKey(&svs.info, k); //we can remove this one though, so yay.
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -2287,15 +2242,34 @@ void SV_Serverinfo_f (void)
|
||||||
Con_Printf ("Can't set * keys\n");
|
Con_Printf ("Can't set * keys\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_strncpyz(value, Cmd_Argv(2), sizeof(value));
|
|
||||||
value[sizeof(value)-1] = '\0';
|
|
||||||
for (i = 3; i < Cmd_Argc(); i++)
|
|
||||||
{
|
|
||||||
strncat(value, " ", sizeof(value)-1);
|
|
||||||
strncat(value, Cmd_Argv(i), sizeof(value)-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Info_SetValueForKey (svs.info, Cmd_Argv(1), value, MAX_SERVERINFO_STRING);
|
if (!strcmp(Cmd_Argv(0), "serverinfoblob"))
|
||||||
|
{
|
||||||
|
qofs_t fsize;
|
||||||
|
char *data = FS_MallocFile(Cmd_Argv(2), FS_GAME, &fsize);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
Con_Printf ("Unable to read %s\n", Cmd_Argv(2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fsize > 64*1024*1024)
|
||||||
|
Con_Printf ("File is over 64mb\n");
|
||||||
|
else
|
||||||
|
InfoBuf_SetStarBlobKey(&svs.info, Cmd_Argv(1), data, fsize);
|
||||||
|
FS_FreeFile(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_strncpyz(value, Cmd_Argv(2), sizeof(value));
|
||||||
|
value[sizeof(value)-1] = '\0';
|
||||||
|
for (i = 3; i < Cmd_Argc(); i++)
|
||||||
|
{
|
||||||
|
strncat(value, " ", sizeof(value)-1);
|
||||||
|
strncat(value, Cmd_Argv(i), sizeof(value)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
InfoBuf_SetValueForKey (&svs.info, Cmd_Argv(1), value);
|
||||||
|
}
|
||||||
|
|
||||||
// if this is a cvar, change it too
|
// if this is a cvar, change it too
|
||||||
var = Cvar_FindVar (Cmd_Argv(1));
|
var = Cvar_FindVar (Cmd_Argv(1));
|
||||||
|
@ -2306,8 +2280,6 @@ void SV_Serverinfo_f (void)
|
||||||
var->string = Z_StrDup (value);
|
var->string = Z_StrDup (value);
|
||||||
var->value = Q_atof (var->string);
|
var->value = Q_atof (var->string);
|
||||||
*/ }
|
*/ }
|
||||||
|
|
||||||
SV_SendServerInfoChange(Cmd_Argv(1), value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2325,7 +2297,7 @@ static void SV_Localinfo_f (void)
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
Con_TPrintf ("Local info settings:\n");
|
Con_TPrintf ("Local info settings:\n");
|
||||||
Info_Print (localinfo, "");
|
InfoBuf_Print (&svs.localinfo, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2340,14 +2312,14 @@ static void SV_Localinfo_f (void)
|
||||||
if (!strcmp(Cmd_Argv(1), "*"))
|
if (!strcmp(Cmd_Argv(1), "*"))
|
||||||
if (!strcmp(Cmd_Argv(2), ""))
|
if (!strcmp(Cmd_Argv(2), ""))
|
||||||
{ //clear it out
|
{ //clear it out
|
||||||
Info_RemoveNonStarKeys(localinfo);
|
InfoBuf_Clear(&svs.localinfo, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Con_Printf ("Can't set * keys\n");
|
Con_Printf ("Can't set * keys\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
old = Info_ValueForKey(localinfo, Cmd_Argv(1));
|
old = InfoBuf_ValueForKey(&svs.localinfo, Cmd_Argv(1));
|
||||||
Info_SetValueForKey (localinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_LOCALINFO_STRING);
|
InfoBuf_SetValueForKey (&svs.localinfo, Cmd_Argv(1), Cmd_Argv(2));
|
||||||
|
|
||||||
PR_LocalInfoChanged(Cmd_Argv(1), old, Cmd_Argv(2));
|
PR_LocalInfoChanged(Cmd_Argv(1), old, Cmd_Argv(2));
|
||||||
|
|
||||||
|
@ -2358,10 +2330,10 @@ void SV_SaveInfos(vfsfile_t *f)
|
||||||
{
|
{
|
||||||
VFS_WRITE(f, "\n", 1);
|
VFS_WRITE(f, "\n", 1);
|
||||||
VFS_WRITE(f, "serverinfo * \"\"\n", 16);
|
VFS_WRITE(f, "serverinfo * \"\"\n", 16);
|
||||||
Info_WriteToFile(f, svs.info, "serverinfo", CVAR_SERVERINFO);
|
InfoBuf_WriteToFile(f, &svs.info, "serverinfo", CVAR_SERVERINFO);
|
||||||
VFS_WRITE(f, "\n", 1);
|
VFS_WRITE(f, "\n", 1);
|
||||||
VFS_WRITE(f, "localinfo * \"\"\n", 15);
|
VFS_WRITE(f, "localinfo * \"\"\n", 15);
|
||||||
Info_WriteToFile(f, localinfo, "localinfo", 0);
|
InfoBuf_WriteToFile(f, &svs.localinfo, "localinfo", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2390,7 +2362,7 @@ void SV_User_f (void)
|
||||||
"fatness", "hlbsp", "bullet", "hullsize", "modeldbl", "entitydbl", "entitydbl2", "floatcoords",
|
"fatness", "hlbsp", "bullet", "hullsize", "modeldbl", "entitydbl", "entitydbl2", "floatcoords",
|
||||||
"OLD vweap", "q2bsp", "q3bsp", "colormod", "splitscreen", "hexen2", "spawnstatic2", "customtempeffects",
|
"OLD vweap", "q2bsp", "q3bsp", "colormod", "splitscreen", "hexen2", "spawnstatic2", "customtempeffects",
|
||||||
"packents", "UNKNOWN", "showpic", "setattachment","UNKNOWN", "chunkeddls", "csqc", "dpflags"};
|
"packents", "UNKNOWN", "showpic", "setattachment","UNKNOWN", "chunkeddls", "csqc", "dpflags"};
|
||||||
static const char *pext2names[32] = { "prydoncursor", "voip", "setangledelta", "rplcdeltas", "maxplayers", "predinfo", "sizeenc", "UNKNOWN",
|
static const char *pext2names[32] = { "prydoncursor", "voip", "setangledelta", "rplcdeltas", "maxplayers", "predinfo", "sizeenc", "infoblobs",
|
||||||
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
|
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
|
||||||
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
|
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
|
||||||
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"};
|
"UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"};
|
||||||
|
@ -2405,14 +2377,17 @@ void SV_User_f (void)
|
||||||
Con_Printf("Userinfo:\n");
|
Con_Printf("Userinfo:\n");
|
||||||
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
|
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
|
||||||
{
|
{
|
||||||
Info_Print (cl->userinfo, " ");
|
InfoBuf_Print (&cl->userinfo, " ");
|
||||||
switch(cl->protocol)
|
switch(cl->protocol)
|
||||||
{
|
{
|
||||||
case SCP_BAD:
|
case SCP_BAD:
|
||||||
Con_Printf("protocol: bot/invalid\n");
|
Con_Printf("protocol: bot/invalid\n");
|
||||||
break;
|
break;
|
||||||
case SCP_QUAKEWORLD:
|
case SCP_QUAKEWORLD: //branding is everything...
|
||||||
Con_Printf("protocol: quakeworld\n");
|
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||||
|
Con_Printf("protocol: fteqw-nack\n");
|
||||||
|
else
|
||||||
|
Con_Printf("protocol: quakeworld\n");
|
||||||
break;
|
break;
|
||||||
case SCP_QUAKE2:
|
case SCP_QUAKE2:
|
||||||
Con_Printf("protocol: quake2\n");
|
Con_Printf("protocol: quake2\n");
|
||||||
|
@ -2421,13 +2396,19 @@ void SV_User_f (void)
|
||||||
Con_Printf("protocol: quake3\n");
|
Con_Printf("protocol: quake3\n");
|
||||||
break;
|
break;
|
||||||
case SCP_NETQUAKE:
|
case SCP_NETQUAKE:
|
||||||
Con_Printf("protocol: (net)quake\n");
|
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||||
|
Con_Printf("protocol: ftenq-nack\n");
|
||||||
|
else
|
||||||
|
Con_Printf("protocol: (net)quake\n");
|
||||||
break;
|
break;
|
||||||
case SCP_BJP3:
|
case SCP_BJP3:
|
||||||
Con_Printf("protocol: bjp3\n");
|
Con_Printf("protocol: bjp3\n");
|
||||||
break;
|
break;
|
||||||
case SCP_FITZ666:
|
case SCP_FITZ666:
|
||||||
Con_Printf("protocol: fitzquake 666\n");
|
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||||
|
Con_Printf("protocol: fte666-nack\n");
|
||||||
|
else
|
||||||
|
Con_Printf("protocol: fitzquake 666\n");
|
||||||
break;
|
break;
|
||||||
case SCP_DARKPLACES6:
|
case SCP_DARKPLACES6:
|
||||||
Con_Printf("protocol: dpp6\n");
|
Con_Printf("protocol: dpp6\n");
|
||||||
|
@ -2442,9 +2423,12 @@ void SV_User_f (void)
|
||||||
|
|
||||||
if (cl->fteprotocolextensions)
|
if (cl->fteprotocolextensions)
|
||||||
{
|
{
|
||||||
|
unsigned int effective = cl->fteprotocolextensions;
|
||||||
|
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) //these flags were made obsolete. don't list them.
|
||||||
|
effective &= ~(PEXT_SCALE|PEXT_TRANS|PEXT_ACCURATETIMINGS|PEXT_FATNESS|PEXT_HULLSIZE|PEXT_MODELDBL|PEXT_ENTITYDBL|PEXT_ENTITYDBL2|PEXT_COLOURMOD|PEXT_SPAWNSTATIC2|PEXT_SETATTACHMENT|PEXT_DPFLAGS);
|
||||||
Con_Printf("pext1:");
|
Con_Printf("pext1:");
|
||||||
for (u = 0; u < 32; u++)
|
for (u = 0; u < 32; u++)
|
||||||
if (cl->fteprotocolextensions & (1u<<u))
|
if (effective & (1u<<u))
|
||||||
Con_Printf(" %s", pext1names[u]);
|
Con_Printf(" %s", pext1names[u]);
|
||||||
Con_Printf("\n");
|
Con_Printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -2520,7 +2504,7 @@ static void SV_Gamedir (void)
|
||||||
|
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
Con_TPrintf ("Current gamedir: %s\n", Info_ValueForKey (svs.info, "*gamedir"));
|
Con_TPrintf ("Current gamedir: %s\n", InfoBuf_ValueForKey (&svs.info, "*gamedir"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2539,7 +2523,7 @@ static void SV_Gamedir (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey (&svs.info, "*gamedir", dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int QDECL CompleteGamedirPath (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
static int QDECL CompleteGamedirPath (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||||
|
@ -2630,7 +2614,7 @@ static void SV_Gamedir_f (void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
COM_Gamedir (dir, NULL);
|
COM_Gamedir (dir, NULL);
|
||||||
Info_SetValueForStarKey (svs.info, "*gamedir", dir, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey (&svs.info, "*gamedir", dir);
|
||||||
}
|
}
|
||||||
Z_Free(dir);
|
Z_Free(dir);
|
||||||
}
|
}
|
||||||
|
@ -3004,6 +2988,7 @@ void SV_InitOperatorCommands (void)
|
||||||
Cmd_AddCommand ("sayone", SV_ConSayOne_f);
|
Cmd_AddCommand ("sayone", SV_ConSayOne_f);
|
||||||
Cmd_AddCommand ("tell", SV_ConSayOne_f);
|
Cmd_AddCommand ("tell", SV_ConSayOne_f);
|
||||||
Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); //commands that conflict with client commands.
|
Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); //commands that conflict with client commands.
|
||||||
|
Cmd_AddCommand ("serverinfoblob", SV_Serverinfo_f); //commands that conflict with client commands.
|
||||||
Cmd_AddCommand ("user", SV_User_f);
|
Cmd_AddCommand ("user", SV_User_f);
|
||||||
|
|
||||||
Cmd_AddCommand ("god", SV_God_f);
|
Cmd_AddCommand ("god", SV_God_f);
|
||||||
|
|
|
@ -585,7 +585,7 @@ unsigned SV_CheckModel(char *mdl)
|
||||||
unsigned short crc;
|
unsigned short crc;
|
||||||
// int len;
|
// int len;
|
||||||
|
|
||||||
buf = (qbyte *)COM_LoadFile (mdl, 5, &fsize);
|
buf = (qbyte *)FS_LoadMallocFile (mdl, &fsize);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
crc = QCRC_Block(buf, fsize);
|
crc = QCRC_Block(buf, fsize);
|
||||||
|
@ -645,6 +645,7 @@ void SV_UnspawnServer (void) //terminate the running server.
|
||||||
svs.clients[i].state = 0;
|
svs.clients[i].state = 0;
|
||||||
*svs.clients[i].namebuf = '\0';
|
*svs.clients[i].namebuf = '\0';
|
||||||
svs.clients[i].name = NULL;
|
svs.clients[i].name = NULL;
|
||||||
|
InfoBuf_Clear(&svs.clients[i].userinfo, true);
|
||||||
}
|
}
|
||||||
free(svs.clients);
|
free(svs.clients);
|
||||||
svs.clients = NULL;
|
svs.clients = NULL;
|
||||||
|
@ -693,6 +694,13 @@ void SV_UpdateMaxPlayers(int newmax)
|
||||||
svs.clients[i].controller = svs.clients + (svs.clients[i].controller - old);
|
svs.clients[i].controller = svs.clients + (svs.clients[i].controller - old);
|
||||||
}
|
}
|
||||||
svs.allocated_client_slots = sv.allocated_client_slots = newmax;
|
svs.allocated_client_slots = sv.allocated_client_slots = newmax;
|
||||||
|
|
||||||
|
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||||
|
{
|
||||||
|
InfoSync_Clear(&svs.clients[i].infosync);
|
||||||
|
svs.clients[i].userinfo.ChangeCB = svs.info.ChangeCB;
|
||||||
|
svs.clients[i].userinfo.ChangeCTX = &svs.clients[i].userinfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sv.allocated_client_slots = svs.allocated_client_slots;
|
sv.allocated_client_slots = svs.allocated_client_slots;
|
||||||
}
|
}
|
||||||
|
@ -874,7 +882,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
{
|
{
|
||||||
svs.clients[i].nextservertimeupdate = 0;
|
svs.clients[i].nextservertimeupdate = 0;
|
||||||
if (!svs.clients[i].state) //bots with the net_preparse module.
|
if (!svs.clients[i].state) //bots with the net_preparse module.
|
||||||
svs.clients[i].userinfo[0] = '\0'; //clear the userinfo to clear the name
|
InfoBuf_Clear(&svs.clients[i].userinfo, true); //clear the userinfo to clear the name
|
||||||
|
|
||||||
if (svs.clients[i].netchan.remote_address.type == NA_LOOPBACK)
|
if (svs.clients[i].netchan.remote_address.type == NA_LOOPBACK)
|
||||||
{ //forget this client's message buffers, so that any shared client/server network state persists (eg: float coords)
|
{ //forget this client's message buffers, so that any shared client/server network state persists (eg: float coords)
|
||||||
|
@ -943,17 +951,17 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
if (sv_cheats.ival)
|
if (sv_cheats.ival)
|
||||||
{
|
{
|
||||||
sv_allow_cheats = true;
|
sv_allow_cheats = true;
|
||||||
Info_SetValueForStarKey(svs.info, "*cheats", "ON", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*cheats", "ON");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sv_allow_cheats = 2;
|
sv_allow_cheats = 2;
|
||||||
Info_SetValueForStarKey(svs.info, "*cheats", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*cheats", "");
|
||||||
}
|
}
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
//This fixes a bug where the server advertises cheats, the internal client connects, and doesn't think cheats are allowed.
|
//This fixes a bug where the server advertises cheats, the internal client connects, and doesn't think cheats are allowed.
|
||||||
//this applies to anything that can affect the content that is loaded by the server, but cheats is the only special one (because of the *)
|
//this applies to anything that can affect the content that is loaded by the server, but cheats is the only special one (because of the *)
|
||||||
Q_strncpyz(cl.serverinfo, svs.info, sizeof(cl.serverinfo));
|
InfoBuf_Clone(&cl.serverinfo, &svs.info);
|
||||||
if (!isDedicated)
|
if (!isDedicated)
|
||||||
CL_CheckServerInfo();
|
CL_CheckServerInfo();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1029,16 +1037,16 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sv.world.worldmodel->fromgame == fg_doom)
|
if (sv.world.worldmodel->fromgame == fg_doom)
|
||||||
Info_SetValueForStarKey(svs.info, "*bspversion", "1", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*bspversion", "1");
|
||||||
else if (sv.world.worldmodel->fromgame == fg_halflife)
|
else if (sv.world.worldmodel->fromgame == fg_halflife)
|
||||||
Info_SetValueForStarKey(svs.info, "*bspversion", "30", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*bspversion", "30");
|
||||||
else if (sv.world.worldmodel->fromgame == fg_quake2)
|
else if (sv.world.worldmodel->fromgame == fg_quake2)
|
||||||
Info_SetValueForStarKey(svs.info, "*bspversion", "38", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*bspversion", "38");
|
||||||
else if (sv.world.worldmodel->fromgame == fg_quake3)
|
else if (sv.world.worldmodel->fromgame == fg_quake3)
|
||||||
Info_SetValueForStarKey(svs.info, "*bspversion", "46", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*bspversion", "46");
|
||||||
else
|
else
|
||||||
Info_SetValueForStarKey(svs.info, "*bspversion", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*bspversion", "");
|
||||||
Info_SetValueForStarKey(svs.info, "*startspot", (startspot?startspot:""), MAX_SERVERINFO_STRING);
|
InfoBuf_SetStarKey(&svs.info, "*startspot", (startspot?startspot:""));
|
||||||
|
|
||||||
//
|
//
|
||||||
// init physics interaction links
|
// init physics interaction links
|
||||||
|
@ -1049,7 +1057,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
#ifdef PEXT_CSQC
|
#ifdef PEXT_CSQC
|
||||||
fsz = 0;
|
fsz = 0;
|
||||||
if (*sv_csqc_progname.string)
|
if (*sv_csqc_progname.string)
|
||||||
file = COM_LoadTempFile(sv_csqc_progname.string, &fsz);
|
file = COM_LoadTempFile(sv_csqc_progname.string, 0, &fsz);
|
||||||
else
|
else
|
||||||
file = NULL;
|
file = NULL;
|
||||||
if (file)
|
if (file)
|
||||||
|
@ -1057,27 +1065,27 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
char text[64];
|
char text[64];
|
||||||
sv.csqcchecksum = Com_BlockChecksum(file, fsz);
|
sv.csqcchecksum = Com_BlockChecksum(file, fsz);
|
||||||
sprintf(text, "0x%x", sv.csqcchecksum);
|
sprintf(text, "0x%x", sv.csqcchecksum);
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogs", text, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogs", text);
|
||||||
sprintf(text, "0x%x", (unsigned int)fsz);
|
sprintf(text, "0x%x", (unsigned int)fsz);
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogssize", text, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogssize", text);
|
||||||
if (strcmp(sv_csqc_progname.string, "csprogs.dat"))
|
if (strcmp(sv_csqc_progname.string, "csprogs.dat"))
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogsname", sv_csqc_progname.string, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", sv_csqc_progname.string);
|
||||||
else
|
else
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogsname", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sv.csqcchecksum = 0;
|
sv.csqcchecksum = 0;
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogs", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogs", "");
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogssize", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogssize", "");
|
||||||
Info_SetValueForStarKey(svs.info, "*csprogsname", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csprogsname", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
sv.csqcdebug = sv_csqcdebug.value;
|
sv.csqcdebug = sv_csqcdebug.value;
|
||||||
if (sv.csqcdebug)
|
if (sv.csqcdebug)
|
||||||
Info_SetValueForStarKey(svs.info, "*csqcdebug", "1", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*csqcdebug", "1");
|
||||||
else
|
else
|
||||||
Info_RemoveKey(svs.info, "*csqcdebug");
|
InfoBuf_RemoveKey(&svs.info, "*csqcdebug");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (svs.gametype == GT_PROGS)
|
if (svs.gametype == GT_PROGS)
|
||||||
|
@ -1272,6 +1280,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
svs.clients[i].edict = NULL;
|
svs.clients[i].edict = NULL;
|
||||||
svs.clients[i].name = svs.clients[i].namebuf;
|
svs.clients[i].name = svs.clients[i].namebuf;
|
||||||
svs.clients[i].team = svs.clients[i].teambuf;
|
svs.clients[i].team = svs.clients[i].teambuf;
|
||||||
|
InfoSync_Clear(&svs.clients[i].infosync); //we'll mark all the info as dirty at some point while connecting.
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (svs.gametype)
|
switch (svs.gametype)
|
||||||
|
@ -1368,8 +1377,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
|
|
||||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||||
{
|
{
|
||||||
Q_strncpyz(svs.clients[i].name, Info_ValueForKey(svs.clients[i].userinfo, "name"), sizeof(svs.clients[i].namebuf));
|
Q_strncpyz(svs.clients[i].name, InfoBuf_ValueForKey(&svs.clients[i].userinfo, "name"), sizeof(svs.clients[i].namebuf));
|
||||||
Q_strncpyz(svs.clients[i].team, Info_ValueForKey(svs.clients[i].userinfo, "team"), sizeof(svs.clients[i].teambuf));
|
Q_strncpyz(svs.clients[i].team, InfoBuf_ValueForKey(&svs.clients[i].userinfo, "team"), sizeof(svs.clients[i].teambuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
|
@ -1484,10 +1493,10 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
{
|
{
|
||||||
char crc[12];
|
char crc[12];
|
||||||
sprintf(crc, "%i", sv.world.worldmodel->entitiescrc);
|
sprintf(crc, "%i", sv.world.worldmodel->entitiescrc);
|
||||||
Info_SetValueForStarKey(svs.info, "*entfile", crc, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*entfile", crc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Info_SetValueForStarKey(svs.info, "*entfile", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*entfile", "");
|
||||||
|
|
||||||
file = Mod_GetEntitiesString(sv.world.worldmodel);
|
file = Mod_GetEntitiesString(sv.world.worldmodel);
|
||||||
if (!file)
|
if (!file)
|
||||||
|
@ -1599,7 +1608,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
||||||
SV_GibFilterInit();
|
SV_GibFilterInit();
|
||||||
SV_FilterImpulseInit();
|
SV_FilterImpulseInit();
|
||||||
|
|
||||||
Info_SetValueForKey (svs.info, "map", svs.name, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForKey (&svs.info, "map", svs.name);
|
||||||
if (sv.allocated_client_slots != 1)
|
if (sv.allocated_client_slots != 1)
|
||||||
Con_TPrintf ("Server spawned.\n"); //misc filenotfounds can be misleading.
|
Con_TPrintf ("Server spawned.\n"); //misc filenotfounds can be misleading.
|
||||||
|
|
||||||
|
|
|
@ -271,6 +271,10 @@ void SV_Shutdown (void)
|
||||||
Cmd_Shutdown();
|
Cmd_Shutdown();
|
||||||
PM_Shutdown();
|
PM_Shutdown();
|
||||||
|
|
||||||
|
|
||||||
|
InfoBuf_Clear(&svs.info, true);
|
||||||
|
InfoBuf_Clear(&svs.localinfo, true);
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
#ifdef WEBSERVER
|
||||||
IWebShutdown();
|
IWebShutdown();
|
||||||
#endif
|
#endif
|
||||||
|
@ -643,7 +647,8 @@ void SV_DropClient (client_t *drop)
|
||||||
#endif
|
#endif
|
||||||
drop->namebuf[0] = 0;
|
drop->namebuf[0] = 0;
|
||||||
drop->name = drop->namebuf;
|
drop->name = drop->namebuf;
|
||||||
memset (drop->userinfo, 0, sizeof(drop->userinfo));
|
InfoBuf_Clear(&drop->userinfo, true);
|
||||||
|
InfoSync_Clear(&drop->infosync);
|
||||||
|
|
||||||
while ((lp = drop->laggedpacket))
|
while ((lp = drop->laggedpacket))
|
||||||
{
|
{
|
||||||
|
@ -943,39 +948,6 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate whatever public userinfo is supported by the client.
|
|
||||||
//private keys like _ prefixes and the password key are stripped out here.
|
|
||||||
//password needs to be stripped in case the password key doesn't actually relate to this server.
|
|
||||||
void SV_GeneratePublicUserInfo(int pext, client_t *cl, char *info, int infolength)
|
|
||||||
{
|
|
||||||
char *key, *s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
//FIXME: we should probably use some sort of priority system instead if I'm honest about it
|
|
||||||
if (pext & PEXT_BIGUSERINFOS)
|
|
||||||
Q_strncpyz (info, cl->userinfo, infolength);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (infolength >= BASIC_INFO_STRING)
|
|
||||||
infolength = BASIC_INFO_STRING;
|
|
||||||
*info = 0;
|
|
||||||
for (i = 0; (key = Info_KeyForNumber(cl->userinfo, i)); i++)
|
|
||||||
{
|
|
||||||
if (!*key)
|
|
||||||
break;
|
|
||||||
if (!SV_UserInfoIsBasic(key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
s = Info_ValueForKey(cl->userinfo, key);
|
|
||||||
Info_SetValueForStarKey (info, key, s, infolength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
|
|
||||||
Info_RemoveKey(info, "password");
|
|
||||||
Info_RemoveKey(info, "*ip");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===================
|
===================
|
||||||
SV_FullClientUpdate
|
SV_FullClientUpdate
|
||||||
|
@ -1011,6 +983,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
||||||
|
|
||||||
if (ISQWCLIENT(to))
|
if (ISQWCLIENT(to))
|
||||||
{
|
{
|
||||||
|
unsigned int pext = to->fteprotocolextensions;
|
||||||
int ping = SV_CalcPing (client, false);
|
int ping = SV_CalcPing (client, false);
|
||||||
if (ping > 0xffff)
|
if (ping > 0xffff)
|
||||||
ping = 0xffff;
|
ping = 0xffff;
|
||||||
|
@ -1031,8 +1004,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
||||||
ClientReliableWrite_Byte (to, i);
|
ClientReliableWrite_Byte (to, i);
|
||||||
ClientReliableWrite_Float (to, realtime - client->connection_started);
|
ClientReliableWrite_Float (to, realtime - client->connection_started);
|
||||||
|
|
||||||
SV_GeneratePublicUserInfo(to->fteprotocolextensions, client, info, sizeof(info));
|
InfoBuf_ToString(&client->userinfo, info, (pext&PEXT_BIGUSERINFOS)?BASIC_INFO_STRING:sizeof(info), basicuserinfos, privateuserinfos, (pext&PEXT_BIGUSERINFOS)?NULL:basicuserinfos, NULL, NULL);
|
||||||
|
|
||||||
ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info));
|
ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info));
|
||||||
ClientReliableWrite_Byte (to, i);
|
ClientReliableWrite_Byte (to, i);
|
||||||
ClientReliableWrite_Long (to, client->userid);
|
ClientReliableWrite_Long (to, client->userid);
|
||||||
|
@ -1041,7 +1013,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
||||||
else if (ISNQCLIENT(to))
|
else if (ISNQCLIENT(to))
|
||||||
{
|
{
|
||||||
int top, bottom, playercolor;
|
int top, bottom, playercolor;
|
||||||
char *nam = Info_ValueForKey(client->userinfo, "name");
|
char *nam = InfoBuf_ValueForKey(&client->userinfo, "name");
|
||||||
|
|
||||||
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
|
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
|
||||||
ClientReliableWrite_Byte (to, i);
|
ClientReliableWrite_Byte (to, i);
|
||||||
|
@ -1051,8 +1023,8 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
||||||
ClientReliableWrite_Byte (to, i);
|
ClientReliableWrite_Byte (to, i);
|
||||||
ClientReliableWrite_String(to, nam);
|
ClientReliableWrite_String(to, nam);
|
||||||
|
|
||||||
top = atoi(Info_ValueForKey(client->userinfo, "topcolor"));
|
top = atoi(InfoBuf_ValueForKey(&client->userinfo, "topcolor"));
|
||||||
bottom = atoi(Info_ValueForKey(client->userinfo, "bottomcolor"));
|
bottom = atoi(InfoBuf_ValueForKey(&client->userinfo, "bottomcolor"));
|
||||||
top &= 15;
|
top &= 15;
|
||||||
if (top > 13)
|
if (top > 13)
|
||||||
top = 13;
|
top = 13;
|
||||||
|
@ -1067,8 +1039,9 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
|
||||||
|
|
||||||
if (to->fteprotocolextensions2 & PEXT2_PREDINFO)
|
if (to->fteprotocolextensions2 & PEXT2_PREDINFO)
|
||||||
{
|
{
|
||||||
char quotedval[8192];
|
char *s;
|
||||||
char *s = va("//fui %i %s\n", i, COM_QuotedString(client->userinfo, quotedval, sizeof(quotedval), false));
|
InfoBuf_ToString(&client->userinfo, info, sizeof(info), basicuserinfos, privateuserinfos, NULL, NULL, NULL);
|
||||||
|
s = va("//fui %i \"%s\"\n", i, info);
|
||||||
ClientReliableWrite_Begin(to, svc_stufftext, 2+strlen(s));
|
ClientReliableWrite_Begin(to, svc_stufftext, 2+strlen(s));
|
||||||
ClientReliableWrite_String(to, s);
|
ClientReliableWrite_String(to, s);
|
||||||
}
|
}
|
||||||
|
@ -1124,21 +1097,27 @@ static void SVC_Status (void)
|
||||||
Cmd_TokenizeString ("status", false, false);
|
Cmd_TokenizeString ("status", false, false);
|
||||||
SV_BeginRedirect (RD_PACKET, TL_FindLanguage(""));
|
SV_BeginRedirect (RD_PACKET, TL_FindLanguage(""));
|
||||||
if (displayflags&STATUS_SERVERINFO)
|
if (displayflags&STATUS_SERVERINFO)
|
||||||
Con_Printf ("%s\n", svs.info);
|
{
|
||||||
|
char infostr[1024]; //FIXME: vanilla limit is 512. we should probably have a list of known cvars for lower priority sending.
|
||||||
|
const char *ignorekeys[] = {"mapname", "*z_ext", NULL}; //ignore some pointless stuff
|
||||||
|
const char *prioritykeys[] = {"hostname", "admin", "*gamedir", "*version", "deathmatch", "timelimit", "fraglimit", "maxclients", "maxspectators", "status", NULL}; //make sure we include these before we start overflowing
|
||||||
|
InfoBuf_ToString(&svs.info, infostr, sizeof(infostr), prioritykeys, ignorekeys, NULL, NULL, NULL);
|
||||||
|
Con_Printf ("%s\n", infostr);
|
||||||
|
}
|
||||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||||
{
|
{
|
||||||
cl = &svs.clients[i];
|
cl = &svs.clients[i];
|
||||||
if ((cl->state == cs_connected || cl->state == cs_spawned || cl->name[0]) && ((cl->spectator && displayflags&STATUS_SPECTATORS) || (!cl->spectator && displayflags&STATUS_PLAYERS)))
|
if ((cl->state == cs_connected || cl->state == cs_spawned || cl->name[0]) && ((cl->spectator && displayflags&STATUS_SPECTATORS) || (!cl->spectator && displayflags&STATUS_PLAYERS)))
|
||||||
{
|
{
|
||||||
top = atoi(Info_ValueForKey (cl->userinfo, "topcolor"));
|
top = atoi(InfoBuf_ValueForKey (&cl->userinfo, "topcolor"));
|
||||||
bottom = atoi(Info_ValueForKey (cl->userinfo, "bottomcolor"));
|
bottom = atoi(InfoBuf_ValueForKey (&cl->userinfo, "bottomcolor"));
|
||||||
top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
|
top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
|
||||||
bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
|
bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
|
||||||
ping = SV_CalcPing (cl, false);
|
ping = SV_CalcPing (cl, false);
|
||||||
name = cl->name;
|
name = cl->name;
|
||||||
|
|
||||||
skin = Info_ValueForKey (cl->userinfo, "skin");
|
skin = InfoBuf_ValueForKey (&cl->userinfo, "skin");
|
||||||
team = Info_ValueForKey (cl->userinfo, "team");
|
team = InfoBuf_ValueForKey (&cl->userinfo, "team");
|
||||||
|
|
||||||
if (!cl->state || cl->protocol == SCP_BAD) //show bots differently. Just to be courteous.
|
if (!cl->state || cl->protocol == SCP_BAD) //show bots differently. Just to be courteous.
|
||||||
botpre = "BOT:";
|
botpre = "BOT:";
|
||||||
|
@ -1235,26 +1214,31 @@ static void SVC_GetInfo (char *challenge, int fullstatus)
|
||||||
resp += strlen(resp);
|
resp += strlen(resp);
|
||||||
*resp++ = '\n';
|
*resp++ = '\n';
|
||||||
|
|
||||||
//first line is the serverinfo
|
//first line contains the serverinfo, or some form of it
|
||||||
Q_strncpyz(resp, svs.info, sizeof(response) - (resp-response));
|
{
|
||||||
//this is a DP protocol query, so some QW fields are not needed
|
const char *ignorekeys[] = {
|
||||||
Info_RemoveKey(resp, "maxclients"); //replaced with sv_maxclients
|
"maxclients", "map", "*gamedir", "*z_ext", //this is a DP protocol query, so some QW fields are not needed
|
||||||
Info_RemoveKey(resp, "map"); //replaced with mapname
|
"gamename", "modname", "protocol", "clients", "sv_maxclients", "mapname", "qcstatus", "challenge", NULL}; //and we need to add some
|
||||||
Info_RemoveKey(resp, "*gamedir"); //replaced with modname
|
const char *prioritykeys[] = {"hostname", NULL}; //make sure we include these before we start overflowing
|
||||||
Info_RemoveKey(resp, "*z_ext"); //uninteresting and spammy.
|
|
||||||
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
|
||||||
// Info_SetValueForKey(resp, "gamedir", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "protocol", va("%d", com_protocolversion.ival), sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "mapname", Info_ValueForKey(svs.info, "map"), sizeof(response) - (resp-response));
|
|
||||||
if (*gamestatus)
|
|
||||||
Info_SetValueForKey(resp, "qcstatus", gamestatus, sizeof(response) - (resp-response));
|
|
||||||
Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response));
|
|
||||||
resp += strlen(resp);
|
|
||||||
|
|
||||||
*resp++ = 0; //there's already a null, but hey
|
*resp = 0;
|
||||||
|
Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response)); //the challenge can be important for the master protocol to prevent poisoning
|
||||||
|
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));//distinguishes it from other types of games
|
||||||
|
Info_SetValueForKey(resp, "protocol", com_protocolversion.string, sizeof(response) - (resp-response)); //should be an int.
|
||||||
|
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
||||||
|
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
|
||||||
|
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
|
||||||
|
Info_SetValueForKey(resp, "mapname", InfoBuf_ValueForKey(&svs.info, "map"), sizeof(response) - (resp-response));
|
||||||
|
resp += strlen(resp);
|
||||||
|
//now include the full/regular serverinfo
|
||||||
|
resp += InfoBuf_ToString(&svs.info, resp, sizeof(response) - (resp-response), prioritykeys, ignorekeys, NULL, NULL, NULL);
|
||||||
|
*resp = 0;
|
||||||
|
//and any possibly-long qc status string
|
||||||
|
if (*gamestatus)
|
||||||
|
Info_SetValueForKey(resp, "qcstatus", gamestatus, sizeof(response) - (resp-response));
|
||||||
|
resp += strlen(resp);
|
||||||
|
}
|
||||||
|
*resp++ = 0;
|
||||||
|
|
||||||
if (fullstatus)
|
if (fullstatus)
|
||||||
{
|
{
|
||||||
|
@ -2225,21 +2209,18 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
|
||||||
case GT_QUAKE2:
|
case GT_QUAKE2:
|
||||||
cl->q2edict = Q2EDICT_NUM(i+1);
|
cl->q2edict = Q2EDICT_NUM(i+1);
|
||||||
|
|
||||||
if (!ge->ClientConnect(cl->q2edict, cl->userinfo))
|
if (!ge->ClientConnect(cl->q2edict, info))
|
||||||
{
|
{
|
||||||
const char *reject = Info_ValueForKey(cl->userinfo, "rejmsg");
|
const char *reject = Info_ValueForKey(info, "rejmsg");
|
||||||
if (*reject)
|
if (*reject)
|
||||||
SV_ClientPrintf(controller, PRINT_HIGH, "Splitscreen Refused: %s\n", reject);
|
SV_ClientPrintf(controller, PRINT_HIGH, "Splitscreen Refused: %s\n", reject);
|
||||||
else
|
else
|
||||||
SV_ClientPrintf(controller, PRINT_HIGH, "Splitscreen Refused\n");
|
SV_ClientPrintf(controller, PRINT_HIGH, "Splitscreen Refused\n");
|
||||||
Con_DPrintf ("Game rejected a connection.\n");
|
Con_DPrintf ("Game rejected a connection.\n");
|
||||||
|
|
||||||
*cl->userinfo = 0;
|
|
||||||
cl->namebuf[0] = 0;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ge->ClientUserinfoChanged(cl->q2edict, cl->userinfo);
|
ge->ClientUserinfoChanged(cl->q2edict, info);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -2252,13 +2233,11 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
|
||||||
cl->controller = controller;
|
cl->controller = controller;
|
||||||
cl->controlled = NULL;
|
cl->controlled = NULL;
|
||||||
|
|
||||||
Q_strncpyS (cl->userinfo, info, sizeof(cl->userinfo)-1);
|
InfoBuf_FromString(&cl->userinfo, info, false);
|
||||||
cl->userinfo[sizeof(cl->userinfo)-1] = '\0';
|
InfoBuf_RemoveKey (&cl->userinfo, "spectator");
|
||||||
|
|
||||||
Info_RemoveKey (cl->userinfo, "spectator");
|
|
||||||
//this is a hint rather than a game breaker should it fail.
|
//this is a hint rather than a game breaker should it fail.
|
||||||
if (cl->spectator)
|
if (cl->spectator)
|
||||||
Info_SetValueForStarKey (cl->userinfo, "*spectator", va("%i", cl->spectator), sizeof(cl->userinfo));
|
InfoBuf_SetValueForStarKey (&cl->userinfo, "*spectator", va("%i", cl->spectator));
|
||||||
cl->state = controller->state;
|
cl->state = controller->state;
|
||||||
|
|
||||||
// host_client = NULL;
|
// host_client = NULL;
|
||||||
|
@ -2759,20 +2738,6 @@ client_t *SVC_DirectConnect(void)
|
||||||
if (sv.msgfromdemo)
|
if (sv.msgfromdemo)
|
||||||
newcl->wasrecorded = true;
|
newcl->wasrecorded = true;
|
||||||
|
|
||||||
// works properly
|
|
||||||
if (!sv_highchars.value)
|
|
||||||
{
|
|
||||||
qbyte *p, *q;
|
|
||||||
|
|
||||||
for (p = (qbyte *)newcl->userinfo, q = (qbyte *)userinfo;
|
|
||||||
*q && p < (qbyte *)newcl->userinfo + sizeof(newcl->userinfo)-1; q++)
|
|
||||||
if (*q > 31 && *q <= 127)
|
|
||||||
*p++ = *q;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Q_strncpyS (newcl->userinfo, userinfo[0], sizeof(newcl->userinfo)-1);
|
|
||||||
newcl->userinfo[sizeof(newcl->userinfo)-1] = '\0';
|
|
||||||
|
|
||||||
// Con_TPrintf("%s:%s:connect\n", sv.name, NET_AdrToString (adrbuf, sizeof(adrbuf), &adr));
|
// Con_TPrintf("%s:%s:connect\n", sv.name, NET_AdrToString (adrbuf, sizeof(adrbuf), &adr));
|
||||||
|
|
||||||
// if there is already a slot for this ip, drop it
|
// if there is already a slot for this ip, drop it
|
||||||
|
@ -2814,13 +2779,13 @@ client_t *SVC_DirectConnect(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name = Info_ValueForKey (temp.userinfo, "name");
|
name = Info_ValueForKey (userinfo[0], "name");
|
||||||
|
|
||||||
if (sv.world.worldmodel && protocol == SCP_QUAKEWORLD &&!atoi(Info_ValueForKey (temp.userinfo, "iknow")))
|
if (sv.world.worldmodel && protocol == SCP_QUAKEWORLD &&!atoi(Info_ValueForKey (userinfo[0], "iknow")))
|
||||||
{
|
{
|
||||||
if (sv.world.worldmodel->fromgame == fg_halflife && !(newcl->fteprotocolextensions & PEXT_HLBSP))
|
if (sv.world.worldmodel->fromgame == fg_halflife && !(newcl->fteprotocolextensions & PEXT_HLBSP))
|
||||||
{
|
{
|
||||||
if (atof(Info_ValueForKey (temp.userinfo, "*FuhQuake")) < 0.3)
|
if (atof(Info_ValueForKey (userinfo[0], "*FuhQuake")) < 0.3)
|
||||||
{
|
{
|
||||||
SV_RejectMessage (protocol, "The server is using a halflife level and we don't think your client supports this\nuse 'setinfo iknow 1' to ignore this check\nYou can go to "ENGINEWEBSITE" to get a compatible client\n\nYou may need to enable an option\n\n");
|
SV_RejectMessage (protocol, "The server is using a halflife level and we don't think your client supports this\nuse 'setinfo iknow 1' to ignore this check\nYou can go to "ENGINEWEBSITE" to get a compatible client\n\nYou may need to enable an option\n\n");
|
||||||
// Con_Printf("player %s was dropped due to incompatible client\n", name);
|
// Con_Printf("player %s was dropped due to incompatible client\n", name);
|
||||||
|
@ -3045,9 +3010,9 @@ client_t *SVC_DirectConnect(void)
|
||||||
temp.edict = NULL;
|
temp.edict = NULL;
|
||||||
temp.q2edict = q2ent;
|
temp.q2edict = q2ent;
|
||||||
|
|
||||||
if (!ge->ClientConnect(q2ent, temp.userinfo))
|
if (!ge->ClientConnect(q2ent, userinfo[0]))
|
||||||
{
|
{
|
||||||
const char *reject = Info_ValueForKey(temp.userinfo, "rejmsg");
|
const char *reject = Info_ValueForKey(userinfo[0], "rejmsg");
|
||||||
if (*reject)
|
if (*reject)
|
||||||
SV_RejectMessage(protocol, "%s\nConnection Refused.", reject);
|
SV_RejectMessage(protocol, "%s\nConnection Refused.", reject);
|
||||||
else
|
else
|
||||||
|
@ -3056,7 +3021,7 @@ client_t *SVC_DirectConnect(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ge->ClientUserinfoChanged(q2ent, temp.userinfo);
|
ge->ClientUserinfoChanged(q2ent, userinfo[0]);
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -3074,13 +3039,18 @@ client_t *SVC_DirectConnect(void)
|
||||||
|
|
||||||
temp.name = newcl->name;
|
temp.name = newcl->name;
|
||||||
temp.team = newcl->team;
|
temp.team = newcl->team;
|
||||||
|
|
||||||
|
InfoSync_Clear(&newcl->infosync);
|
||||||
*newcl = temp;
|
*newcl = temp;
|
||||||
|
newcl->userinfo.ChangeCB = svs.info.ChangeCB;
|
||||||
|
newcl->userinfo.ChangeCTX = &svs.clients[i].userinfo;
|
||||||
|
InfoBuf_FromString(&newcl->userinfo, userinfo[0], false);
|
||||||
|
|
||||||
// NET_AdrToStringResolve(&adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid);
|
// NET_AdrToStringResolve(&adr, SV_UserDNSResolved, NULL, newcl-svs.clients, newcl->userid);
|
||||||
|
|
||||||
newcl->challenge = challenge;
|
newcl->challenge = challenge;
|
||||||
newcl->zquake_extensions = atoi(Info_ValueForKey(newcl->userinfo, "*z_ext"));
|
newcl->zquake_extensions = atoi(InfoBuf_ValueForKey(&newcl->userinfo, "*z_ext"));
|
||||||
if (*Info_ValueForKey(newcl->userinfo, "*fuhquake")) //fuhquake doesn't claim to support z_ext but does look at our z_ext serverinfo key.
|
if (*InfoBuf_ValueForKey(&newcl->userinfo, "*fuhquake")) //fuhquake doesn't claim to support z_ext but does look at our z_ext serverinfo key.
|
||||||
{ //so switch on the bits that it should be sending.
|
{ //so switch on the bits that it should be sending.
|
||||||
newcl->zquake_extensions |= Z_EXT_PM_TYPE|Z_EXT_PM_TYPE_NEW;
|
newcl->zquake_extensions |= Z_EXT_PM_TYPE|Z_EXT_PM_TYPE_NEW;
|
||||||
}
|
}
|
||||||
|
@ -3089,7 +3059,7 @@ client_t *SVC_DirectConnect(void)
|
||||||
//ezquake's download mechanism is so smegging buggy.
|
//ezquake's download mechanism is so smegging buggy.
|
||||||
//its causing far far far too many connectivity issues. seriously. its beyond a joke. I cannot stress that enough.
|
//its causing far far far too many connectivity issues. seriously. its beyond a joke. I cannot stress that enough.
|
||||||
//as the client needs to listen for the serverinfo to know which extensions will actually be used (yay demos), we can just forget that it supports svc-level extensions, at least for anything that isn't spammed via clc_move etc before the serverinfo.
|
//as the client needs to listen for the serverinfo to know which extensions will actually be used (yay demos), we can just forget that it supports svc-level extensions, at least for anything that isn't spammed via clc_move etc before the serverinfo.
|
||||||
s = Info_ValueForKey(newcl->userinfo, "*client");
|
s = InfoBuf_ValueForKey(&newcl->userinfo, "*client");
|
||||||
if (!strncmp(s, "ezQuake", 7) && (newcl->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS))
|
if (!strncmp(s, "ezQuake", 7) && (newcl->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS))
|
||||||
{
|
{
|
||||||
if (pext_ezquake_nochunks.ival)
|
if (pext_ezquake_nochunks.ival)
|
||||||
|
@ -3184,7 +3154,7 @@ client_t *SVC_DirectConnect(void)
|
||||||
SV_RejectMessage (protocol, "Rankings/Account system failed\n");
|
SV_RejectMessage (protocol, "Rankings/Account system failed\n");
|
||||||
Con_TPrintf("banned player %s is trying to connect\n", newcl->name);
|
Con_TPrintf("banned player %s is trying to connect\n", newcl->name);
|
||||||
newcl->name[0] = 0;
|
newcl->name[0] = 0;
|
||||||
memset (newcl->userinfo, 0, sizeof(newcl->userinfo));
|
InfoBuf_Clear(&newcl->userinfo, true);
|
||||||
newcl->state = cs_free;
|
newcl->state = cs_free;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3312,7 +3282,7 @@ client_t *SVC_DirectConnect(void)
|
||||||
if (spectators >= maxspectators.ival)
|
if (spectators >= maxspectators.ival)
|
||||||
newcl->drop = true; //oops.
|
newcl->drop = true; //oops.
|
||||||
newcl->spectator = spectator = true;
|
newcl->spectator = spectator = true;
|
||||||
Info_SetValueForStarKey (cl->userinfo, "*spectator", "1", sizeof(cl->userinfo));
|
InfoBuf_SetValueForStarKey (&cl->userinfo, "*spectator", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
//only advertise PEXT_SPLITSCREEN when splitscreen is allowed, to avoid spam. this might mean people need to reconnect after its enabled. oh well.
|
//only advertise PEXT_SPLITSCREEN when splitscreen is allowed, to avoid spam. this might mean people need to reconnect after its enabled. oh well.
|
||||||
|
@ -4076,18 +4046,18 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
SZ_Clear (&sb);
|
SZ_Clear (&sb);
|
||||||
MSG_WriteLong (&sb, 0);
|
MSG_WriteLong (&sb, 0);
|
||||||
{
|
{
|
||||||
char *rname, *rval, *kname;
|
const char *rname, *rval, *kname;
|
||||||
rname = MSG_ReadString();
|
rname = MSG_ReadString();
|
||||||
|
|
||||||
if (!*rname)
|
if (!*rname)
|
||||||
rname = Info_KeyForNumber(svs.info, 0);
|
rname = InfoBuf_KeyForNumber(&svs.info, 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
kname = Info_KeyForNumber(svs.info, i);
|
kname = InfoBuf_KeyForNumber(&svs.info, i);
|
||||||
if (!*kname)
|
if (!kname)
|
||||||
{
|
{
|
||||||
rname = NULL;
|
rname = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -4095,12 +4065,15 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
i++;
|
i++;
|
||||||
if (!strcmp(kname, rname))
|
if (!strcmp(kname, rname))
|
||||||
{
|
{
|
||||||
rname = Info_KeyForNumber(svs.info, i);
|
rname = InfoBuf_KeyForNumber(&svs.info, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rval = Info_ValueForKey(svs.info, rname);
|
if (rname)
|
||||||
|
rval = InfoBuf_ValueForKey(&svs.info, rname);
|
||||||
|
else
|
||||||
|
rval = rname = "";
|
||||||
MSG_WriteByte (&sb, CCREP_RULE_INFO);
|
MSG_WriteByte (&sb, CCREP_RULE_INFO);
|
||||||
MSG_WriteString (&sb, rname);
|
MSG_WriteString (&sb, rname);
|
||||||
MSG_WriteString (&sb, rval);
|
MSG_WriteString (&sb, rval);
|
||||||
|
@ -4627,9 +4600,9 @@ void SV_CheckVars (void)
|
||||||
|
|
||||||
Con_DPrintf ("Updated needpass.\n");
|
Con_DPrintf ("Updated needpass.\n");
|
||||||
if (!v)
|
if (!v)
|
||||||
Info_SetValueForKey (svs.info, "needpass", "", MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForKey (&svs.info, "needpass", "");
|
||||||
else
|
else
|
||||||
Info_SetValueForKey (svs.info, "needpass", va("%i",v), MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForKey (&svs.info, "needpass", va("%i",v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q2SERVER
|
#ifdef Q2SERVER
|
||||||
|
@ -4815,8 +4788,7 @@ float SV_Frame (void)
|
||||||
newspeed = "";
|
newspeed = "";
|
||||||
else
|
else
|
||||||
newspeed = va("%g", sv.gamespeed*100);
|
newspeed = va("%g", sv.gamespeed*100);
|
||||||
Info_SetValueForStarKey(svs.info, "*gamespeed", newspeed, MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey(&svs.info, "*gamespeed", newspeed);
|
||||||
SV_SendServerInfoChange("*gamespeed", newspeed);
|
|
||||||
|
|
||||||
//correct sv.starttime
|
//correct sv.starttime
|
||||||
sv.starttime = Sys_DoubleTime() - (sv.time/sv.gamespeed);
|
sv.starttime = Sys_DoubleTime() - (sv.time/sv.gamespeed);
|
||||||
|
@ -5048,6 +5020,23 @@ float SV_Frame (void)
|
||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SV_InfoChanged(void *context, const char *key)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (context != &svs.info && *key == '_')
|
||||||
|
return; //these keys are considered private to originating client/server, and are not broadcast to anyone else
|
||||||
|
|
||||||
|
if (svs.demorecording)
|
||||||
|
InfoSync_Add(&demo.recorder.infosync, context, key); //make sure it gets written into mvds too.
|
||||||
|
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||||
|
{
|
||||||
|
if (svs.clients[i].state >= cs_connected)
|
||||||
|
{
|
||||||
|
InfoSync_Add(&svs.clients[i].infosync, context, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
SV_InitLocal
|
SV_InitLocal
|
||||||
|
@ -5232,9 +5221,10 @@ void SV_InitLocal (void)
|
||||||
|
|
||||||
SV_MVDInit();
|
SV_MVDInit();
|
||||||
|
|
||||||
Info_SetValueForStarKey (svs.info, "*version", version_string(), MAX_SERVERINFO_STRING);
|
svs.info.ChangeCB = SV_InfoChanged;
|
||||||
|
svs.info.ChangeCTX = &svs.info;
|
||||||
Info_SetValueForStarKey (svs.info, "*z_ext", va("%i", SUPPORTED_Z_EXTENSIONS), MAX_SERVERINFO_STRING);
|
InfoBuf_SetValueForStarKey (&svs.info, "*version", version_string());
|
||||||
|
InfoBuf_SetValueForStarKey (&svs.info, "*z_ext", va("%i", SUPPORTED_Z_EXTENSIONS));
|
||||||
|
|
||||||
// init fraglog stuff
|
// init fraglog stuff
|
||||||
svs.logsequence = 1;
|
svs.logsequence = 1;
|
||||||
|
@ -5251,17 +5241,18 @@ void SV_InitLocal (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define iswhite(c) ((c) == ' ' || (unsigned char)(c) == (unsigned char)INVIS_CHAR1 || (unsigned char)(c) == (unsigned char)INVIS_CHAR2 || (unsigned char)(c) == (unsigned char)INVIS_CHAR3)
|
#define iswhite(c) ((c) == ' ' || (unsigned char)(c) == (unsigned char)INVIS_CHAR1 || (unsigned char)(c) == (unsigned char)INVIS_CHAR2 || (unsigned char)(c) == (unsigned char)INVIS_CHAR3)
|
||||||
#define isinvalid(c) ((c) == ':' || (c) == '\r' || (c) == '\n' || (unsigned char)(c) == (unsigned char)0xff || (c) == '\"')
|
#define isinvalid(c) ((c) == ':' || (c) == '\\' || (c) == '\r' || (c) == '\n' || (unsigned char)(c) == (unsigned char)0xff || (c) == '\"')
|
||||||
//colon is so clients can't get confused while parsing chats
|
//colon is so clients can't get confused while parsing chats
|
||||||
//255 is so fuhquake/ezquake don't end up with nameless players
|
//255 is so fuhquake/ezquake don't end up with nameless players
|
||||||
//" is so mods that use player names in tokenizing/frik_files don't mess up. mods are still expected to be able to cope with space.
|
//" is so mods that use player names in tokenizing/frik_files don't mess up. mods are still expected to be able to cope with space.
|
||||||
|
//\ is blocked because it messes up our ^[NAME\player\NUM^] links, and because vanilla would hate it.
|
||||||
|
|
||||||
//is allowed to shorten, out must be as long as in and min of "unnamed"+1
|
//is allowed to shorten, out must be as long as in and min of "unnamed"+1
|
||||||
void SV_FixupName(const char *in, char *out, unsigned int outlen)
|
void SV_FixupName(const char *in, char *out, unsigned int outlen)
|
||||||
{
|
{
|
||||||
char *s, *p;
|
char *s, *p;
|
||||||
unsigned int len;
|
unsigned int len, codepoint, codeflags;
|
||||||
conchar_t testbuf[1024], *t, *e;
|
conchar_t testbuf[1024], *t, *n, *e;
|
||||||
|
|
||||||
if (outlen == 0)
|
if (outlen == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -5274,7 +5265,7 @@ void SV_FixupName(const char *in, char *out, unsigned int outlen)
|
||||||
while(*in && len > 1)
|
while(*in && len > 1)
|
||||||
{
|
{
|
||||||
if (isinvalid(*in))
|
if (isinvalid(*in))
|
||||||
{
|
{ //chars that cause a problem.
|
||||||
in++;
|
in++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -5285,16 +5276,21 @@ void SV_FixupName(const char *in, char *out, unsigned int outlen)
|
||||||
|
|
||||||
/*note: clients are not guarenteed to parse things the same as the server. utf-8 surrogates may be awkward here*/
|
/*note: clients are not guarenteed to parse things the same as the server. utf-8 surrogates may be awkward here*/
|
||||||
e = COM_ParseFunString(CON_WHITEMASK, out, testbuf, sizeof(testbuf), false);
|
e = COM_ParseFunString(CON_WHITEMASK, out, testbuf, sizeof(testbuf), false);
|
||||||
for (t = testbuf; t < e; t++)
|
for (t = testbuf; t < e; t = n)
|
||||||
{
|
{
|
||||||
|
n = Font_Decode(t, &codeflags, &codepoint);
|
||||||
/*reject anything hidden in names*/
|
/*reject anything hidden in names*/
|
||||||
if (*t & CON_HIDDEN)
|
if ((codeflags & CON_HIDDEN) || (codeflags&(CON_LINKSPECIAL|CON_RICHFORECOLOUR))==CON_LINKSPECIAL)
|
||||||
break;
|
break;
|
||||||
/*reject pictograms*/
|
/*reject pictograms*/
|
||||||
if ((*t & CON_CHARMASK) >= 0xe100 && (*t & CON_CHARMASK) < 0xe200)
|
if (codepoint >= 0xe100 && codepoint < 0xe200)
|
||||||
|
break;
|
||||||
|
if (!sv_highchars.ival && (codeflags & CON_2NDCHARSETTEXT))
|
||||||
break;
|
break;
|
||||||
/*FIXME: should we try to ensure that the chars are in most fonts? that might annoy speakers of more exotic languages I suppose. cvar it?*/
|
/*FIXME: should we try to ensure that the chars are in most fonts? that might annoy speakers of more exotic languages I suppose. cvar it?*/
|
||||||
}
|
}
|
||||||
|
//and spit it out again, which makes sure there's no weird markup that might screw up other strings.
|
||||||
|
COM_DeFunString(testbuf, t, out, outlen, false, false);
|
||||||
|
|
||||||
if (!*out || (t < e) || e == testbuf)
|
if (!*out || (t < e) || e == testbuf)
|
||||||
{ //reached end and it was all whitespace
|
{ //reached end and it was all whitespace
|
||||||
|
@ -5316,9 +5312,9 @@ qboolean ReloadRanking(client_t *cl, const char *newname)
|
||||||
int newid;
|
int newid;
|
||||||
int j;
|
int j;
|
||||||
rankstats_t rs;
|
rankstats_t rs;
|
||||||
newid = Rank_GetPlayerID(cl->guid, newname, atoi(Info_ValueForKey (cl->userinfo, "_pwd")), true, false); //'_' keys are always stripped. On any server. So try and use that so persistant data won't give out the password when connecting to a different server
|
newid = Rank_GetPlayerID(cl->guid, newname, atoi(InfoBuf_ValueForKey (&cl->userinfo, "_pwd")), true, false); //'_' keys are always stripped. On any server. So try and use that so persistant data won't give out the password when connecting to a different server
|
||||||
if (!newid)
|
if (!newid)
|
||||||
newid = Rank_GetPlayerID(cl->guid, newname, atoi(Info_ValueForKey (cl->userinfo, "password")), true, false);
|
newid = Rank_GetPlayerID(cl->guid, newname, atoi(InfoBuf_ValueForKey (&cl->userinfo, "password")), true, false);
|
||||||
if (newid)
|
if (newid)
|
||||||
{
|
{
|
||||||
if (cl->rankid && cl->state >= cs_spawned)//apply current stats
|
if (cl->rankid && cl->state >= cs_spawned)//apply current stats
|
||||||
|
@ -5383,23 +5379,23 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
||||||
extern cvar_t rank_filename;
|
extern cvar_t rank_filename;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bottom = atoi(Info_ValueForKey(cl->userinfo, "bottomcolor"));
|
int bottom = atoi(InfoBuf_ValueForKey(&cl->userinfo, "bottomcolor"));
|
||||||
|
|
||||||
if (progstype == PROG_NQ)
|
if (progstype == PROG_NQ)
|
||||||
p = va("t%u", bottom);
|
p = va("t%u", bottom);
|
||||||
else
|
else
|
||||||
p = Info_ValueForKey(localinfo, va("team%u", bottom));
|
p = InfoBuf_ValueForKey(&svs.localinfo, va("team%u", bottom));
|
||||||
val = Info_ValueForKey (cl->userinfo, "team");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "team");
|
||||||
if (*p && strcmp(p, val))
|
if (*p && strcmp(p, val))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(cl->userinfo, "team", p, sizeof(cl->userinfo));
|
InfoBuf_SetValueForKey(&cl->userinfo, "team", p);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
SV_BroadcastUserinfoChange(cl, true, "team", p);
|
SV_BroadcastUserinfoChange(cl, true, "team", p);
|
||||||
}
|
}
|
||||||
Q_strncpyz (cl->team, val, sizeof(cl->teambuf));
|
Q_strncpyz (cl->team, val, sizeof(cl->teambuf));
|
||||||
|
|
||||||
// name for C code
|
// name for C code
|
||||||
val = Info_ValueForKey (cl->userinfo, "name");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "name");
|
||||||
|
|
||||||
if (cl->protocol != SCP_BAD || *val)
|
if (cl->protocol != SCP_BAD || *val)
|
||||||
{
|
{
|
||||||
|
@ -5473,18 +5469,6 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//try and actually set that new name, if it differs from what they asked for.
|
|
||||||
if (strcmp(val, newname))
|
|
||||||
{
|
|
||||||
Info_SetValueForKey (cl->userinfo, "name", newname, sizeof(cl->userinfo));
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "name");
|
|
||||||
if (!*val)
|
|
||||||
{
|
|
||||||
SV_BroadcastTPrintf (PRINT_HIGH, "corrupt userinfo for player %s\n", cl->name);
|
|
||||||
cl->drop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cl->drop && strncmp(val, cl->name, sizeof(cl->namebuf)-1) && cl->state > cs_zombie)
|
if (!cl->drop && strncmp(val, cl->name, sizeof(cl->namebuf)-1) && cl->state > cs_zombie)
|
||||||
{
|
{
|
||||||
if (*cl->name && cl->state >= cs_spawned && !cl->spectator && verbose)
|
if (*cl->name && cl->state >= cs_spawned && !cl->spectator && verbose)
|
||||||
|
@ -5506,30 +5490,41 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "lang");
|
//make CERTAIN that the name we think they're using is actually the name everyone else sees too.
|
||||||
|
{
|
||||||
|
InfoBuf_SetValueForKey (&cl->userinfo, "name", newname);
|
||||||
|
val = InfoBuf_ValueForKey (&cl->userinfo, "name");
|
||||||
|
if (!*val)
|
||||||
|
{
|
||||||
|
SV_BroadcastTPrintf (PRINT_HIGH, "corrupt userinfo for player %s\n", cl->name);
|
||||||
|
cl->drop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val = InfoBuf_ValueForKey (&cl->userinfo, "lang");
|
||||||
cl->language = *val?TL_FindLanguage(val):svs.language;
|
cl->language = *val?TL_FindLanguage(val):svs.language;
|
||||||
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "nogib");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "nogib");
|
||||||
cl->gibfilter = !!atoi(val);
|
cl->gibfilter = !!atoi(val);
|
||||||
|
|
||||||
// rate command
|
// rate command
|
||||||
val = Info_ValueForKey (cl->userinfo, "rate");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "rate");
|
||||||
if (strlen(val))
|
if (strlen(val))
|
||||||
cl->rate = atoi(val);
|
cl->rate = atoi(val);
|
||||||
else
|
else
|
||||||
cl->rate = 0;//0 means no specific limit, limited only by sv_maxrate.
|
cl->rate = 0;//0 means no specific limit, limited only by sv_maxrate.
|
||||||
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "dupe");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "dupe");
|
||||||
cl->netchan.dupe = bound(0, atoi(val), 5);
|
cl->netchan.dupe = bound(0, atoi(val), 5);
|
||||||
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "drate");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "drate");
|
||||||
if (strlen(val))
|
if (strlen(val))
|
||||||
cl->drate = atoi(val);
|
cl->drate = atoi(val);
|
||||||
else
|
else
|
||||||
cl->drate = 0; //0 disables rate limiting while downloading
|
cl->drate = 0; //0 disables rate limiting while downloading
|
||||||
|
|
||||||
#ifdef HEXEN2
|
#ifdef HEXEN2
|
||||||
val = Info_ValueForKey (cl->userinfo, "cl_playerclass");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "cl_playerclass");
|
||||||
if (val)
|
if (val)
|
||||||
{
|
{
|
||||||
PRH2_SetPlayerClass(cl, atoi(val), false);
|
PRH2_SetPlayerClass(cl, atoi(val), false);
|
||||||
|
@ -5537,13 +5532,13 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// msg command
|
// msg command
|
||||||
val = Info_ValueForKey (cl->userinfo, "msg");
|
val = InfoBuf_ValueForKey (&cl->userinfo, "msg");
|
||||||
if (strlen(val))
|
if (strlen(val))
|
||||||
{
|
{
|
||||||
cl->messagelevel = atoi(val);
|
cl->messagelevel = atoi(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
val = Info_ValueForKey (cl->userinfo, "sp"); //naming for compat with mvdsv
|
val = InfoBuf_ValueForKey (&cl->userinfo, "sp"); //naming for compat with mvdsv
|
||||||
if (*val)
|
if (*val)
|
||||||
cl->spec_print = atoi(val);
|
cl->spec_print = atoi(val);
|
||||||
else
|
else
|
||||||
|
@ -5551,7 +5546,7 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
||||||
|
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
{
|
{
|
||||||
int top = atoi(Info_ValueForKey(cl->userinfo, "topcolor"));
|
int top = atoi(InfoBuf_ValueForKey(&cl->userinfo, "topcolor"));
|
||||||
top &= 15;
|
top &= 15;
|
||||||
if (top > 13)
|
if (top > 13)
|
||||||
top = 13;
|
top = 13;
|
||||||
|
|
|
@ -823,7 +823,7 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
|
||||||
MSG_WriteByte (msg, player - svs.clients);
|
MSG_WriteByte (msg, player - svs.clients);
|
||||||
MSG_WriteFloat (msg, realtime - player->connection_started);
|
MSG_WriteFloat (msg, realtime - player->connection_started);
|
||||||
|
|
||||||
SV_GeneratePublicUserInfo(demo.recorder.fteprotocolextensions, player, info, sizeof(info));
|
InfoBuf_ToString(&player->userinfo, info, sizeof(info), basicuserinfos, privateuserinfos, NULL, &demo.recorder.infosync, player);
|
||||||
|
|
||||||
if (dosizes)
|
if (dosizes)
|
||||||
msg = MVDWrite_Begin (dem_all, 0, 7 + strlen(info));
|
msg = MVDWrite_Begin (dem_all, 0, 7 + strlen(info));
|
||||||
|
@ -1205,12 +1205,12 @@ static char *SV_PrintTeams(void)
|
||||||
|
|
||||||
clients[numcl++] = &svs.clients[i];
|
clients[numcl++] = &svs.clients[i];
|
||||||
for (j = 0; j < numt; j++)
|
for (j = 0; j < numt; j++)
|
||||||
if (!strcmp(Info_ValueForKey(svs.clients[i].userinfo, "team"), teams[j]))
|
if (!strcmp(InfoBuf_ValueForKey(&svs.clients[i].userinfo, "team"), teams[j]))
|
||||||
break;
|
break;
|
||||||
if (j != numt)
|
if (j != numt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
teams[numt++] = Info_ValueForKey(svs.clients[i].userinfo, "team");
|
teams[numt++] = InfoBuf_ValueForKey(&svs.clients[i].userinfo, "team");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create output
|
// create output
|
||||||
|
@ -1231,7 +1231,7 @@ static char *SV_PrintTeams(void)
|
||||||
{
|
{
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "team %s:\n", teams[j]);
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "team %s:\n", teams[j]);
|
||||||
for (i = 0; i < numcl; i++)
|
for (i = 0; i < numcl; i++)
|
||||||
if (!strcmp(Info_ValueForKey(clients[i]->userinfo, "team"), teams[j]))
|
if (!strcmp(InfoBuf_ValueForKey(&clients[i]->userinfo, "team"), teams[j]))
|
||||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %s\n", clients[i]->name);
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %s\n", clients[i]->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1668,7 +1668,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
|
||||||
|
|
||||||
// send the serverdata
|
// send the serverdata
|
||||||
|
|
||||||
gamedir = Info_ValueForKey (svs.info, "*gamedir");
|
gamedir = InfoBuf_ValueForKey (&svs.info, "*gamedir");
|
||||||
if (!gamedir[0])
|
if (!gamedir[0])
|
||||||
gamedir = FS_GetGamedir(true);
|
gamedir = FS_GetGamedir(true);
|
||||||
|
|
||||||
|
@ -2088,11 +2088,11 @@ char *Dem_Team(int num)
|
||||||
if (!client->name[0] || client->spectator)
|
if (!client->name[0] || client->spectator)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (first || strcmp(lastteam[index], Info_ValueForKey(client->userinfo, "team")))
|
if (first || strcmp(lastteam[index], InfoBuf_ValueForKey(&client->userinfo, "team")))
|
||||||
{
|
{
|
||||||
first = false;
|
first = false;
|
||||||
num--;
|
num--;
|
||||||
lastteam[index] = Info_ValueForKey(client->userinfo, "team");
|
lastteam[index] = InfoBuf_ValueForKey(&client->userinfo, "team");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2136,7 +2136,7 @@ char *Dem_PlayerNameTeam(char *t)
|
||||||
if (!client->name[0] || client->spectator)
|
if (!client->name[0] || client->spectator)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp(t, Info_ValueForKey(client->userinfo, "team"))==0)
|
if (strcmp(t, InfoBuf_ValueForKey(&client->userinfo, "team"))==0)
|
||||||
{
|
{
|
||||||
if (sep >= 1)
|
if (sep >= 1)
|
||||||
Q_strncatz (n, "_", sizeof(n));
|
Q_strncatz (n, "_", sizeof(n));
|
||||||
|
@ -2158,7 +2158,7 @@ int Dem_CountTeamPlayers (char *t)
|
||||||
for (i = 0; i < sv.allocated_client_slots ; i++)
|
for (i = 0; i < sv.allocated_client_slots ; i++)
|
||||||
{
|
{
|
||||||
if (svs.clients[i].name[0] && !svs.clients[i].spectator)
|
if (svs.clients[i].name[0] && !svs.clients[i].spectator)
|
||||||
if (strcmp(Info_ValueForKey(svs.clients[i].userinfo, "team"), t)==0)
|
if (strcmp(InfoBuf_ValueForKey(&svs.clients[i].userinfo, "team"), t)==0)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2683,7 +2683,7 @@ qboolean SV_CanTrack(client_t *client, int entity)
|
||||||
return false;
|
return false;
|
||||||
if (svs.clients[entity-1].spectator)
|
if (svs.clients[entity-1].spectator)
|
||||||
return false;
|
return false;
|
||||||
if (svs.clients[entity-1].state == cs_spawned || (svs.clients[entity-1].state == cs_free && *svs.clients[entity-1].userinfo))
|
if (svs.clients[entity-1].state == cs_spawned || (svs.clients[entity-1].state == cs_free && svs.clients[entity-1].userinfo.numkeys))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2924,6 +2924,100 @@ void SV_FlushBroadcasts (void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qboolean SV_SyncInfoBuf(client_t *client)
|
||||||
|
{
|
||||||
|
const char *key = client->infosync.keys[0].name;
|
||||||
|
infobuf_t *info = client->infosync.keys[0].context;
|
||||||
|
size_t bloboffset = client->infosync.keys[0].syncpos;
|
||||||
|
//unsigned int seat = info - cls.userinfo;
|
||||||
|
size_t blobsize;
|
||||||
|
const char *blobdata = InfoBuf_BlobForKey(info, key, &blobsize);
|
||||||
|
size_t sendsize;
|
||||||
|
size_t bufferspace;
|
||||||
|
|
||||||
|
qboolean final;
|
||||||
|
char enckey[2048];
|
||||||
|
char encval[2048];
|
||||||
|
|
||||||
|
if (client->protocol == SCP_QUAKE2)
|
||||||
|
{ //q2 gamecode is fully responsible for networking this via configstrings.
|
||||||
|
InfoSync_Clear(&client->infosync);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host_client->num_backbuf)
|
||||||
|
return false;
|
||||||
|
if (client->netchan.message.cursize >= MAX_BACKBUFLEN/2)
|
||||||
|
return false; //don't bother trying to send anything.
|
||||||
|
|
||||||
|
if (!InfoBuf_EncodeString(key, strlen(key), enckey, sizeof(enckey)))
|
||||||
|
{
|
||||||
|
InfoSync_Remove(&client->infosync, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendsize = blobsize - bloboffset;
|
||||||
|
bufferspace = MAX_BACKBUFLEN - client->netchan.message.cursize;
|
||||||
|
bufferspace -= 7 - strlen(enckey) - 2; //extra overhead
|
||||||
|
bufferspace = (bufferspace/4)*3; //encoding overhead
|
||||||
|
sendsize = min(bufferspace, sendsize);
|
||||||
|
final = (bloboffset+sendsize >= blobsize);
|
||||||
|
|
||||||
|
if (!InfoBuf_EncodeString(blobdata+bloboffset, sendsize, encval, sizeof(encval)))
|
||||||
|
{
|
||||||
|
InfoSync_Remove(&client->infosync, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final && !bloboffset && *enckey != '\xff' && *encval != '\xff')
|
||||||
|
{ //vanilla-compatible info.
|
||||||
|
if (ISNQCLIENT(client))
|
||||||
|
{ //except that nq never had any userinfo
|
||||||
|
const char *s = va("//ui %i \"%s\" \"%s\"\n", (client_t*)info-svs.clients, enckey, encval);
|
||||||
|
ClientReliableWrite_Begin(client, svc_stufftext, strlen(s)+2);
|
||||||
|
ClientReliableWrite_String(client, s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (info == &svs.info)
|
||||||
|
ClientReliableWrite_Begin(client, svc_serverinfo, 1+strlen(enckey)+1+strlen(encval)+1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClientReliableWrite_Begin(client, svc_setinfo, 2+strlen(enckey)+1+strlen(encval)+1);
|
||||||
|
ClientReliableWrite_Byte(client, (client_t*)info-svs.clients);
|
||||||
|
}
|
||||||
|
ClientReliableWrite_String(client, enckey);
|
||||||
|
ClientReliableWrite_String(client, encval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (client->fteprotocolextensions2 & PEXT2_INFOBLOBS)
|
||||||
|
{
|
||||||
|
int pl;
|
||||||
|
if (info == &svs.info)
|
||||||
|
pl = 255; //colourmaps being 1-based with these being 0-based means that only 0-254 are valid players, and 255 is unused, so lets use it for serverinfo blobs.
|
||||||
|
else
|
||||||
|
pl = (client_t*)info-svs.clients;
|
||||||
|
|
||||||
|
ClientReliableWrite_Begin(client, svc_setinfo, 7+strlen(enckey)+1+strlen(encval)+1);
|
||||||
|
ClientReliableWrite_Byte(client, 255); //special meaning to say that this is a partial update
|
||||||
|
ClientReliableWrite_Byte(client, pl);
|
||||||
|
ClientReliableWrite_Long(client, (final?0x80000000:0)|bloboffset);
|
||||||
|
ClientReliableWrite_String(client, enckey);
|
||||||
|
ClientReliableWrite_String(client, encval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //client can't receive this info, stop trying to send it.
|
||||||
|
InfoSync_Remove(&client->infosync, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bloboffset+sendsize == blobsize)
|
||||||
|
InfoSync_Remove(&client->infosync, 0);
|
||||||
|
else
|
||||||
|
client->infosync.keys[0].syncpos += sendsize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=======================
|
=======================
|
||||||
SV_UpdateToReliableMessages
|
SV_UpdateToReliableMessages
|
||||||
|
@ -2949,8 +3043,8 @@ void SV_UpdateToReliableMessages (void)
|
||||||
//DP_SV_CLIENTCOLORS
|
//DP_SV_CLIENTCOLORS
|
||||||
if (host_client->edict->xv->clientcolors != host_client->playercolor)
|
if (host_client->edict->xv->clientcolors != host_client->playercolor)
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(host_client->userinfo, "topcolor", va("%i", (int)host_client->edict->xv->clientcolors/16), sizeof(host_client->userinfo));
|
InfoBuf_SetValueForKey(&host_client->userinfo, "topcolor", va("%i", (int)host_client->edict->xv->clientcolors/16));
|
||||||
Info_SetValueForKey(host_client->userinfo, "bottomcolor", va("%i", (int)host_client->edict->xv->clientcolors&15), sizeof(host_client->userinfo));
|
InfoBuf_SetValueForKey(&host_client->userinfo, "bottomcolor", va("%i", (int)host_client->edict->xv->clientcolors&15));
|
||||||
{
|
{
|
||||||
SV_ExtractFromUserinfo (host_client, true); //this will take care of nq for us anyway.
|
SV_ExtractFromUserinfo (host_client, true); //this will take care of nq for us anyway.
|
||||||
SV_BroadcastUserinfoChange(host_client, true, "*bothcolours", NULL);
|
SV_BroadcastUserinfoChange(host_client, true, "*bothcolours", NULL);
|
||||||
|
@ -2974,7 +3068,7 @@ void SV_UpdateToReliableMessages (void)
|
||||||
Q_strncpyz(oname, host_client->name, sizeof(oname));
|
Q_strncpyz(oname, host_client->name, sizeof(oname));
|
||||||
|
|
||||||
Con_DPrintf("Client %s programatically renamed to %s\n", host_client->name, name);
|
Con_DPrintf("Client %s programatically renamed to %s\n", host_client->name, name);
|
||||||
Info_SetValueForKey(host_client->userinfo, "name", name, sizeof(host_client->userinfo));
|
InfoBuf_SetValueForKey(&host_client->userinfo, "name", name);
|
||||||
SV_ExtractFromUserinfo (host_client, true);
|
SV_ExtractFromUserinfo (host_client, true);
|
||||||
|
|
||||||
if (strcmp(oname, host_client->name))
|
if (strcmp(oname, host_client->name))
|
||||||
|
@ -3135,6 +3229,12 @@ void SV_UpdateToReliableMessages (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (host_client->infosync.numkeys)
|
||||||
|
{
|
||||||
|
if (!SV_SyncInfoBuf(host_client))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sv.reliable_datagram.overflowed)
|
if (sv.reliable_datagram.overflowed)
|
||||||
|
@ -3173,7 +3273,7 @@ static void SV_SendUserinfoChange(client_t *to, client_t *about, qboolean isbasi
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!newval)
|
if (!newval)
|
||||||
newval = Info_ValueForKey(about->userinfo, key);
|
newval = InfoBuf_ValueForKey(&about->userinfo, key);
|
||||||
|
|
||||||
if (ISQWCLIENT(to))
|
if (ISQWCLIENT(to))
|
||||||
{
|
{
|
||||||
|
@ -3181,13 +3281,13 @@ static void SV_SendUserinfoChange(client_t *to, client_t *about, qboolean isbasi
|
||||||
{
|
{
|
||||||
if (ISQWCLIENT(to) && !strcmp(key, "*bothcolours"))
|
if (ISQWCLIENT(to) && !strcmp(key, "*bothcolours"))
|
||||||
{
|
{
|
||||||
newval = Info_ValueForKey(about->userinfo, "topcolor");
|
newval = InfoBuf_ValueForKey(&about->userinfo, "topcolor");
|
||||||
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
|
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
|
||||||
ClientReliableWrite_Byte(to, playernum);
|
ClientReliableWrite_Byte(to, playernum);
|
||||||
ClientReliableWrite_String(to, "topcolor");
|
ClientReliableWrite_String(to, "topcolor");
|
||||||
ClientReliableWrite_String(to, Info_ValueForKey(about->userinfo, "topcolor"));
|
ClientReliableWrite_String(to, InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
|
||||||
|
|
||||||
newval = Info_ValueForKey(about->userinfo, "bottomcolor");
|
newval = InfoBuf_ValueForKey(&about->userinfo, "bottomcolor");
|
||||||
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
|
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
|
||||||
ClientReliableWrite_Byte(to, playernum);
|
ClientReliableWrite_Byte(to, playernum);
|
||||||
ClientReliableWrite_String(to, "bottomcolor");
|
ClientReliableWrite_String(to, "bottomcolor");
|
||||||
|
@ -3223,8 +3323,8 @@ static void SV_SendUserinfoChange(client_t *to, client_t *about, qboolean isbasi
|
||||||
}
|
}
|
||||||
else if (!strcmp(key, "topcolor") || !strcmp(key, "bottomcolor") || !strcmp(key, "*bothcolours"))
|
else if (!strcmp(key, "topcolor") || !strcmp(key, "bottomcolor") || !strcmp(key, "*bothcolours"))
|
||||||
{ //due to these being combined, nq players get double colour change notifications...
|
{ //due to these being combined, nq players get double colour change notifications...
|
||||||
int tc = atoi(Info_ValueForKey(about->userinfo, "topcolor"));
|
int tc = atoi(InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
|
||||||
int bc = atoi(Info_ValueForKey(about->userinfo, "bottomcolor"));
|
int bc = atoi(InfoBuf_ValueForKey(&about->userinfo, "bottomcolor"));
|
||||||
if (tc < 0 || tc > 13)
|
if (tc < 0 || tc > 13)
|
||||||
tc = 0;
|
tc = 0;
|
||||||
if (bc < 0 || bc > 13)
|
if (bc < 0 || bc > 13)
|
||||||
|
@ -3250,7 +3350,7 @@ void SV_BroadcastUserinfoChange(client_t *about, qboolean isbasic, const char *k
|
||||||
client_t *client;
|
client_t *client;
|
||||||
int j;
|
int j;
|
||||||
if (!newval)
|
if (!newval)
|
||||||
newval = Info_ValueForKey(about->userinfo, key);
|
newval = InfoBuf_ValueForKey(&about->userinfo, key);
|
||||||
for (j = 0; j < svs.allocated_client_slots; j++)
|
for (j = 0; j < svs.allocated_client_slots; j++)
|
||||||
{
|
{
|
||||||
client = svs.clients+j;
|
client = svs.clients+j;
|
||||||
|
|
|
@ -121,6 +121,9 @@ cvar_t sv_realiphostname_ipv4 = CVARD("sv_realiphostname_ipv4", "", "This is the
|
||||||
cvar_t sv_realiphostname_ipv6 = CVARD("sv_realiphostname_ipv6", "", "This is the server's public ip:port. This is needed for realip to work when the autodetected/local ip is not globally routable");
|
cvar_t sv_realiphostname_ipv6 = CVARD("sv_realiphostname_ipv6", "", "This is the server's public ip:port. This is needed for realip to work when the autodetected/local ip is not globally routable");
|
||||||
cvar_t sv_realip_timeout = CVAR("sv_realip_timeout", "10");
|
cvar_t sv_realip_timeout = CVAR("sv_realip_timeout", "10");
|
||||||
|
|
||||||
|
cvar_t sv_userinfo_keylimit = CVARD("sv_userinfo_keylimit", "128", "This is the maximum number of userinfo keys each user may create.");
|
||||||
|
cvar_t sv_userinfo_bytelimit = CVARD("sv_userinfo_bytelimit", "8192", "This is the maximum number of bytes that may be stored into each user's userinfo. Note that this includes key names too.");
|
||||||
|
|
||||||
#ifdef VOICECHAT
|
#ifdef VOICECHAT
|
||||||
cvar_t sv_voip = CVARD("sv_voip", "1", "Enable reception of voice packets.");
|
cvar_t sv_voip = CVARD("sv_voip", "1", "Enable reception of voice packets.");
|
||||||
cvar_t sv_voip_record = CVARD("sv_voip_record", "0", "Record voicechat into mvds. Requires player support. 0=noone, 1=everyone, 2=spectators only");
|
cvar_t sv_voip_record = CVARD("sv_voip_record", "0", "Record voicechat into mvds. Requires player support. 0=noone, 1=everyone, 2=spectators only");
|
||||||
|
@ -255,7 +258,7 @@ void SV_New_f (void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *srv = Info_ValueForKey(host_client->userinfo, "*redirect");
|
const char *srv = InfoBuf_ValueForKey(&host_client->userinfo, "*redirect");
|
||||||
if (*srv)
|
if (*srv)
|
||||||
{
|
{
|
||||||
char *msg = va("connect \"%s\"\n", srv);
|
char *msg = va("connect \"%s\"\n", srv);
|
||||||
|
@ -284,7 +287,7 @@ void SV_New_f (void)
|
||||||
// SV_FullClientUpdate (host_client, &sv.reliable_datagram);
|
// SV_FullClientUpdate (host_client, &sv.reliable_datagram);
|
||||||
// host_client->sendinfo = true;
|
// host_client->sendinfo = true;
|
||||||
|
|
||||||
gamedir = Info_ValueForKey (svs.info, "*gamedir");
|
gamedir = InfoBuf_ValueForKey (&svs.info, "*gamedir");
|
||||||
if (!gamedir[0])
|
if (!gamedir[0])
|
||||||
{
|
{
|
||||||
if (ISQWCLIENT(host_client) || ISQ2CLIENT(host_client))
|
if (ISQWCLIENT(host_client) || ISQ2CLIENT(host_client))
|
||||||
|
@ -650,7 +653,7 @@ void SVNQ_New_f (void)
|
||||||
Q_snprintfz(build, sizeof(build), "%s", __DATE__);
|
Q_snprintfz(build, sizeof(build), "%s", __DATE__);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gamedir = Info_ValueForKey (svs.info, "*gamedir");
|
gamedir = InfoBuf_ValueForKey (&svs.info, "*gamedir");
|
||||||
if (!gamedir[0])
|
if (!gamedir[0])
|
||||||
{
|
{
|
||||||
gamedir = FS_GetGamedir(true);
|
gamedir = FS_GetGamedir(true);
|
||||||
|
@ -694,7 +697,7 @@ void SVNQ_New_f (void)
|
||||||
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
|
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
|
||||||
MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n");
|
MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n");
|
||||||
|
|
||||||
f = COM_LoadTempFile("csprogs.dat", &sz);
|
f = COM_LoadTempFile("csprogs.dat", 0, &sz);
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
|
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
|
||||||
|
@ -1009,13 +1012,15 @@ void SV_SendClientPrespawnInfo(client_t *client)
|
||||||
{
|
{
|
||||||
if (!ISNQCLIENT(client) || (client->fteprotocolextensions2 & PEXT2_PREDINFO))
|
if (!ISNQCLIENT(client) || (client->fteprotocolextensions2 & PEXT2_PREDINFO))
|
||||||
{ //nq does not normally get serverinfo sent to it.
|
{ //nq does not normally get serverinfo sent to it.
|
||||||
ClientReliableWrite_Begin(client, svc_stufftext, 20 + strlen(svs.info));
|
i = InfoBuf_ToString(&svs.info, buffer, sizeof(buffer), NULL, NULL, NULL, &client->infosync, &svs.info);
|
||||||
ClientReliableWrite_String (client, va("fullserverinfo \"%s\"\n", svs.info) );
|
ClientReliableWrite_Begin(client, svc_stufftext, 20 + i);
|
||||||
|
ClientReliableWrite_String (client, va("fullserverinfo \"%s\"\n", buffer) );
|
||||||
}
|
}
|
||||||
else if (sv.csqcdebug)
|
else if (sv.csqcdebug)
|
||||||
{
|
{
|
||||||
ClientReliableWrite_Begin(client, svc_stufftext, 22 + strlen(svs.info));
|
i = InfoBuf_ToString(&svs.info, buffer, sizeof(buffer), NULL, NULL, NULL, &client->infosync, &svs.info);
|
||||||
ClientReliableWrite_String (client, va("//fullserverinfo \"%s\"\n", svs.info) );
|
ClientReliableWrite_Begin(client, svc_stufftext, 22 + i);
|
||||||
|
ClientReliableWrite_String (client, va("//fullserverinfo \"%s\"\n", buffer) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (client->prespawn_idx == 1)
|
else if (client->prespawn_idx == 1)
|
||||||
|
@ -1946,7 +1951,9 @@ void SV_Begin_Core(client_t *split)
|
||||||
#ifdef Q2SERVER
|
#ifdef Q2SERVER
|
||||||
if (ge)
|
if (ge)
|
||||||
{
|
{
|
||||||
ge->ClientUserinfoChanged (split->q2edict, split->userinfo); //tell the gamecode
|
char userinfo[8192];
|
||||||
|
InfoBuf_ToString(&split->userinfo, userinfo, sizeof(userinfo), NULL, NULL, NULL, NULL, NULL);
|
||||||
|
ge->ClientUserinfoChanged (split->q2edict, userinfo); //tell the gamecode
|
||||||
SV_ExtractFromUserinfo(split, true); //let the server routines know
|
SV_ExtractFromUserinfo(split, true); //let the server routines know
|
||||||
|
|
||||||
ge->ClientBegin(split->q2edict);
|
ge->ClientBegin(split->q2edict);
|
||||||
|
@ -1980,11 +1987,11 @@ void SV_Begin_Core(client_t *split)
|
||||||
|
|
||||||
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "playermodel", ev_string, NULL);
|
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "playermodel", ev_string, NULL);
|
||||||
if (eval)
|
if (eval)
|
||||||
svprogfuncs->SetStringField(svprogfuncs, ent, &eval->string, Info_ValueForKey(split->userinfo, "model"), false);
|
svprogfuncs->SetStringField(svprogfuncs, ent, &eval->string, InfoBuf_ValueForKey(&split->userinfo, "model"), false);
|
||||||
|
|
||||||
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "playerskin", ev_string, NULL);
|
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "playerskin", ev_string, NULL);
|
||||||
if (eval)
|
if (eval)
|
||||||
svprogfuncs->SetStringField(svprogfuncs, ent, &eval->string, Info_ValueForKey(split->userinfo, "skin"), false);
|
svprogfuncs->SetStringField(svprogfuncs, ent, &eval->string, InfoBuf_ValueForKey(&split->userinfo, "skin"), false);
|
||||||
|
|
||||||
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "netaddress", ev_string, NULL);
|
eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "netaddress", ev_string, NULL);
|
||||||
if (eval)
|
if (eval)
|
||||||
|
@ -2176,8 +2183,8 @@ void SV_Begin_f (void)
|
||||||
//check he's not cheating
|
//check he's not cheating
|
||||||
if (progstype == PROG_QW)
|
if (progstype == PROG_QW)
|
||||||
{
|
{
|
||||||
pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel"));
|
pmodel = atoi(InfoBuf_ValueForKey (&host_client->userinfo, "pmodel"));
|
||||||
emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel"));
|
emodel = atoi(InfoBuf_ValueForKey (&host_client->userinfo, "emodel"));
|
||||||
|
|
||||||
if (pmodel != sv.model_player_checksum ||
|
if (pmodel != sv.model_player_checksum ||
|
||||||
emodel != sv.eyes_player_checksum)
|
emodel != sv.eyes_player_checksum)
|
||||||
|
@ -3694,7 +3701,7 @@ void SV_Say (qboolean team)
|
||||||
|
|
||||||
if (team)
|
if (team)
|
||||||
{
|
{
|
||||||
Q_strncpyz (t1, Info_ValueForKey (host_client->userinfo, "team"), sizeof(t1));
|
Q_strncpyz (t1, InfoBuf_ValueForKey(&host_client->userinfo, "team"), sizeof(t1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host_client->spectator && (!sv_spectalk.value || team))
|
if (host_client->spectator && (!sv_spectalk.value || team))
|
||||||
|
@ -3790,7 +3797,7 @@ void SV_Say (qboolean team)
|
||||||
if (!client->spectator)
|
if (!client->spectator)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
t2 = Info_ValueForKey (client->userinfo, "team");
|
t2 = InfoBuf_ValueForKey (&client->userinfo, "team");
|
||||||
if (strcmp(t1, t2) || client->spectator)
|
if (strcmp(t1, t2) || client->spectator)
|
||||||
continue; // on different teams
|
continue; // on different teams
|
||||||
}
|
}
|
||||||
|
@ -4222,7 +4229,7 @@ void SV_Rate_f (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Info_SetValueForKey (host_client->userinfo, "rate", Cmd_Argv(1), sizeof(host_client->userinfo));
|
InfoBuf_SetKey (&host_client->userinfo, "rate", Cmd_Argv(1));
|
||||||
SV_ExtractFromUserinfo (host_client, true);
|
SV_ExtractFromUserinfo (host_client, true);
|
||||||
|
|
||||||
if (host_client->state > cs_connected)
|
if (host_client->state > cs_connected)
|
||||||
|
@ -4254,20 +4261,9 @@ void SV_Msg_f (void)
|
||||||
qboolean SV_UserInfoIsBasic(const char *infoname)
|
qboolean SV_UserInfoIsBasic(const char *infoname)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *basicinfos[] = {
|
for (i = 1; basicuserinfos[i]; i++)
|
||||||
|
|
||||||
"name",
|
|
||||||
"team",
|
|
||||||
"skin",
|
|
||||||
"topcolor",
|
|
||||||
"bottomcolor",
|
|
||||||
"chat", //ezquake's afk indicators
|
|
||||||
|
|
||||||
NULL};
|
|
||||||
|
|
||||||
for (i = 0; basicinfos[i]; i++)
|
|
||||||
{
|
{
|
||||||
if (*infoname == '*' || !strcmp(infoname, basicinfos[i]))
|
if (*infoname == '*' || !strcmp(infoname, basicuserinfos[i]))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -4277,6 +4273,8 @@ qboolean SV_UserInfoIsBasic(const char *infoname)
|
||||||
static void SV_SetInfo_PrintCB (void *ctx, const char *key, const char *value)
|
static void SV_SetInfo_PrintCB (void *ctx, const char *key, const char *value)
|
||||||
{
|
{
|
||||||
client_t *cl = ctx;
|
client_t *cl = ctx;
|
||||||
|
if (cl->num_backbuf > MAX_BACK_BUFFERS/2)
|
||||||
|
return; //stop printing if there's too many...
|
||||||
SV_ClientPrintf(cl, PRINT_HIGH, "\t%-20s%s\n", key, value);
|
SV_ClientPrintf(cl, PRINT_HIGH, "\t%-20s%s\n", key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4290,89 +4288,102 @@ Allow clients to change userinfo
|
||||||
void SV_SetInfo_f (void)
|
void SV_SetInfo_f (void)
|
||||||
{
|
{
|
||||||
char oldval[MAX_INFO_KEY];
|
char oldval[MAX_INFO_KEY];
|
||||||
char *key, *val;
|
char *key, *val, *t;
|
||||||
|
size_t offset, keysize, valsize, k;
|
||||||
|
qboolean final;
|
||||||
|
|
||||||
if (Cmd_Argc() == 1)
|
if (Cmd_Argc() == 1)
|
||||||
{
|
{
|
||||||
SV_ClientPrintf(host_client, PRINT_HIGH, "User info settings:\n");
|
SV_ClientPrintf(host_client, PRINT_HIGH, "User info settings:\n");
|
||||||
Info_Enumerate(host_client->userinfo, (void*)host_client, SV_SetInfo_PrintCB);
|
InfoBuf_Enumerate(&host_client->userinfo, (void*)host_client, SV_SetInfo_PrintCB);
|
||||||
|
SV_ClientPrintf(host_client, PRINT_HIGH, "[%u/%i, %u/%i]\n", (unsigned int)host_client->userinfo.numkeys, sv_userinfo_keylimit.ival, (unsigned int)host_client->userinfo.totalsize, sv_userinfo_bytelimit.ival);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cmd_Argc() != 3)
|
if (Cmd_Argc() == 4)
|
||||||
|
{
|
||||||
|
offset = strtoul(Cmd_Argv(3), &t, 0);
|
||||||
|
final = (*t != '+');
|
||||||
|
}
|
||||||
|
else if (Cmd_Argc() == 3)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
final = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
SV_ClientPrintf(host_client, PRINT_HIGH, "usage: setinfo [ <key> <value> ]\n");
|
SV_ClientPrintf(host_client, PRINT_HIGH, "usage: setinfo [ <key> <value> ]\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = Cmd_Argv(1);
|
|
||||||
|
|
||||||
if (key[0] == '*')
|
|
||||||
return; // don't set priveledged values
|
|
||||||
|
|
||||||
if (strstr(key, "\\") || strstr(Cmd_Argv(2), "\\"))
|
|
||||||
return; // illegal char
|
|
||||||
|
|
||||||
Q_strncpyz(oldval, Info_ValueForKey(host_client->userinfo, key), sizeof(oldval));
|
|
||||||
|
|
||||||
#ifdef VM_Q1
|
#ifdef VM_Q1
|
||||||
if (Q1QVM_UserInfoChanged(sv_player))
|
if (Q1QVM_UserInfoChanged(sv_player))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Info_SetValueForKey (host_client->userinfo, key, Cmd_Argv(2), sizeof(host_client->userinfo));
|
key = Cmd_Argv(1);
|
||||||
// name is extracted below in ExtractFromUserInfo
|
val = Cmd_Argv(2);
|
||||||
// strncpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name")
|
if (strstr(key, "\\") || strstr(val, "\\"))
|
||||||
// , sizeof(host_client->name)-1);
|
return; // illegal char, at least at this point.
|
||||||
// SV_FullClientUpdate (host_client, &sv.reliable_datagram);
|
key = InfoBuf_DecodeString(key, key+strlen(key), &keysize);
|
||||||
// host_client->sendinfo = true;
|
val = InfoBuf_DecodeString(val, val+strlen(val), &valsize);
|
||||||
|
|
||||||
if (!strcmp(Info_ValueForKey(host_client->userinfo, key), oldval))
|
|
||||||
return; // key hasn't changed
|
|
||||||
|
|
||||||
|
if (key[0] == '*')
|
||||||
|
SV_ClientPrintf(host_client, PRINT_HIGH, "setinfo: %s may not be changed mid-game\n", key);
|
||||||
|
else if (sv_userinfo_keylimit.ival >= 0 && host_client->userinfo.numkeys >= sv_userinfo_keylimit.ival && !offset && *val && !InfoBuf_FindKey(&host_client->userinfo, key, &k)) //when the limit is hit, allow people to freely change existing keys, but not new ones. they can also silently remove any that don't exist yet, too.
|
||||||
|
SV_ClientPrintf(host_client, PRINT_MEDIUM, "setinfo: userinfo is limited to %i keys. Ignoring setting %s\n", sv_userinfo_keylimit.ival, key);
|
||||||
|
else if (sv_userinfo_bytelimit.ival >= 0 && host_client->userinfo.totalsize >= sv_userinfo_bytelimit.ival && *val)
|
||||||
|
{
|
||||||
|
SV_ClientPrintf(host_client, PRINT_MEDIUM, "setinfo: userinfo is limited to %i bytes. Ignoring setting %s\n", sv_userinfo_bytelimit.ival, key);
|
||||||
|
if (offset) //kill it if they're part way through sending one, so that they're not penalised by the presence of partials that will never complete.
|
||||||
|
InfoBuf_RemoveKey(&host_client->userinfo, key);
|
||||||
|
}
|
||||||
|
else if (InfoBuf_SyncReceive(&host_client->userinfo, key, keysize, val, valsize, offset, final))
|
||||||
|
{
|
||||||
#ifdef Q2SERVER
|
#ifdef Q2SERVER
|
||||||
if (svs.gametype == GT_QUAKE2)
|
if (svs.gametype == GT_QUAKE2)
|
||||||
{
|
{
|
||||||
ge->ClientUserinfoChanged (host_client->q2edict, host_client->userinfo); //tell the gamecode
|
char tempbuffer[32768];
|
||||||
SV_ExtractFromUserinfo(host_client, true); //let the server routines know
|
InfoBuf_ToString(&host_client->userinfo, tempbuffer, sizeof(tempbuffer), NULL, NULL, NULL, NULL, NULL);
|
||||||
return;
|
ge->ClientUserinfoChanged (host_client->q2edict, tempbuffer); //tell the gamecode
|
||||||
}
|
SV_ExtractFromUserinfo(host_client, true); //let the server routines know
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
if (progstype != PROG_QW && !strcmp(key, "bottomcolor"))
|
if (progstype != PROG_QW && !strcmp(key, "bottomcolor"))
|
||||||
{ //team fortress has a nasty habit of booting people without this
|
{ //team fortress has a nasty habit of booting people without this
|
||||||
sv_player->v->team = atoi(Cmd_Argv(2))+1;
|
sv_player->v->team = atoi(Cmd_Argv(2))+1;
|
||||||
}
|
}
|
||||||
#ifndef NOLEGACY
|
#ifndef NOLEGACY
|
||||||
if (progstype != PROG_QW && !strcmp(key, "model"))
|
if (progstype != PROG_QW && !strcmp(key, "model"))
|
||||||
{
|
{
|
||||||
eval_t *eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, sv_player, "playermodel", ev_string, NULL);
|
eval_t *eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, sv_player, "playermodel", ev_string, NULL);
|
||||||
if (eval)
|
if (eval)
|
||||||
svprogfuncs->SetStringField(svprogfuncs, sv_player, &eval->string, Cmd_Argv(2), false);
|
svprogfuncs->SetStringField(svprogfuncs, sv_player, &eval->string, Cmd_Argv(2), false);
|
||||||
}
|
}
|
||||||
if (progstype != PROG_QW && !strcmp(key, "skin"))
|
if (progstype != PROG_QW && !strcmp(key, "skin"))
|
||||||
{
|
{
|
||||||
eval_t *eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, sv_player, "playerskin", ev_string, NULL);
|
eval_t *eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, sv_player, "playerskin", ev_string, NULL);
|
||||||
if (eval)
|
if (eval)
|
||||||
svprogfuncs->SetStringField(svprogfuncs, sv_player, &eval->string, Cmd_Argv(2), false);
|
svprogfuncs->SetStringField(svprogfuncs, sv_player, &eval->string, Cmd_Argv(2), false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// process any changed values
|
// process any changed values
|
||||||
SV_ExtractFromUserinfo (host_client, true);
|
// chat happens far too often and makes debugging annoying, as well as making logs spammy
|
||||||
|
if (strcmp(key, "chat"))
|
||||||
|
{
|
||||||
|
SV_ExtractFromUserinfo (host_client, true);
|
||||||
|
SV_LogPlayer(host_client, "userinfo changed");
|
||||||
|
}
|
||||||
|
|
||||||
if (*key != '_')
|
PR_ClientUserInfoChanged(key, oldval, InfoBuf_ValueForKey(&host_client->userinfo, key));
|
||||||
{
|
}
|
||||||
val = Info_ValueForKey(host_client->userinfo, key);
|
|
||||||
|
|
||||||
SV_BroadcastUserinfoChange(host_client, SV_UserInfoIsBasic(key), key, val);
|
|
||||||
}
|
}
|
||||||
|
Z_Free(key);
|
||||||
//doh't spam chat changes. they're not interesting, and just spammy.
|
Z_Free(val);
|
||||||
if (strcmp(key, "chat"))
|
|
||||||
SV_LogPlayer(host_client, "userinfo changed");
|
|
||||||
|
|
||||||
PR_ClientUserInfoChanged(key, oldval, Info_ValueForKey(host_client->userinfo, key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4385,7 +4396,7 @@ Dumps the serverinfo info string
|
||||||
void SV_ShowServerinfo_f (void)
|
void SV_ShowServerinfo_f (void)
|
||||||
{
|
{
|
||||||
SV_BeginRedirect(RD_CLIENT, host_client->language);
|
SV_BeginRedirect(RD_CLIENT, host_client->language);
|
||||||
Info_Print (svs.info, "");
|
InfoBuf_Print (&svs.info, "");
|
||||||
SV_EndRedirect();
|
SV_EndRedirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4950,8 +4961,8 @@ void SV_SetUpClientEdict (client_t *cl, edict_t *ent)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int tc = atoi(Info_ValueForKey(cl->userinfo, "topcolor"));
|
int tc = atoi(InfoBuf_ValueForKey(&cl->userinfo, "topcolor"));
|
||||||
int bc = atoi(Info_ValueForKey(cl->userinfo, "bottomcolor"));
|
int bc = atoi(InfoBuf_ValueForKey(&cl->userinfo, "bottomcolor"));
|
||||||
if (tc < 0 || tc > 13)
|
if (tc < 0 || tc > 13)
|
||||||
tc = 0;
|
tc = 0;
|
||||||
if (bc < 0 || bc > 13)
|
if (bc < 0 || bc > 13)
|
||||||
|
@ -5152,7 +5163,7 @@ void Cmd_Join_f (void)
|
||||||
|
|
||||||
// turn the spectator into a player
|
// turn the spectator into a player
|
||||||
host_client->spectator = false;
|
host_client->spectator = false;
|
||||||
Info_RemoveKey (host_client->userinfo, "*spectator");
|
InfoBuf_RemoveKey (&host_client->userinfo, "*spectator");
|
||||||
|
|
||||||
// FIXME, bump the client's userid?
|
// FIXME, bump the client's userid?
|
||||||
|
|
||||||
|
@ -5287,7 +5298,7 @@ void Cmd_Observe_f (void)
|
||||||
|
|
||||||
// turn the player into a spectator
|
// turn the player into a spectator
|
||||||
host_client->spectator = true;
|
host_client->spectator = true;
|
||||||
Info_SetValueForStarKey (host_client->userinfo, "*spectator", "1", sizeof(host_client->userinfo));
|
InfoBuf_SetValueForStarKey (&host_client->userinfo, "*spectator", "1");
|
||||||
|
|
||||||
// FIXME, bump the client's userid?
|
// FIXME, bump the client's userid?
|
||||||
|
|
||||||
|
@ -5555,8 +5566,8 @@ static void SVNQ_Begin_f (void)
|
||||||
|
|
||||||
if (sv_playermodelchecks.value)
|
if (sv_playermodelchecks.value)
|
||||||
{
|
{
|
||||||
pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel"));
|
pmodel = atoi(InfoBuf_ValueForKey (&host_client->userinfo, "pmodel"));
|
||||||
emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel"));
|
emodel = atoi(InfoBuf_ValueForKey (&host_client->userinfo, "emodel"));
|
||||||
|
|
||||||
if (pmodel != sv.model_player_checksum ||
|
if (pmodel != sv.model_player_checksum ||
|
||||||
emodel != sv.eyes_player_checksum)
|
emodel != sv.eyes_player_checksum)
|
||||||
|
@ -5672,18 +5683,12 @@ static void SVNQ_NQColour_f (void)
|
||||||
host_client->edict->v->team = bottom + 1;
|
host_client->edict->v->team = bottom + 1;
|
||||||
|
|
||||||
val = va("%i", top);
|
val = va("%i", top);
|
||||||
if (strcmp(val, Info_ValueForKey(host_client->userinfo, "topcolor")))
|
if (InfoBuf_SetValueForKey(&host_client->userinfo, "topcolor", val))
|
||||||
{
|
|
||||||
Info_SetValueForKey(host_client->userinfo, "topcolor", val, sizeof(host_client->userinfo));
|
|
||||||
SV_BroadcastUserinfoChange(host_client, true, "topcolor", NULL);
|
SV_BroadcastUserinfoChange(host_client, true, "topcolor", NULL);
|
||||||
}
|
|
||||||
|
|
||||||
val = va("%i", bottom);
|
val = va("%i", bottom);
|
||||||
if (strcmp(val, Info_ValueForKey(host_client->userinfo, "bottomcolor")))
|
if (InfoBuf_SetValueForKey(&host_client->userinfo, "bottomcolor", val))
|
||||||
{
|
|
||||||
Info_SetValueForKey(host_client->userinfo, "bottomcolor", val, sizeof(host_client->userinfo));
|
|
||||||
SV_BroadcastUserinfoChange(host_client, true, "bottomcolor", NULL);
|
SV_BroadcastUserinfoChange(host_client, true, "bottomcolor", NULL);
|
||||||
}
|
|
||||||
|
|
||||||
switch(bottom)
|
switch(bottom)
|
||||||
{
|
{
|
||||||
|
@ -5697,9 +5702,9 @@ static void SVNQ_NQColour_f (void)
|
||||||
val = va("t%i", bottom+1);
|
val = va("t%i", bottom+1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strcmp(val, Info_ValueForKey(host_client->userinfo, "team")))
|
if (strcmp(val, InfoBuf_ValueForKey(&host_client->userinfo, "team")))
|
||||||
{
|
{
|
||||||
Info_SetValueForKey(host_client->userinfo, "team", val, sizeof(host_client->userinfo));
|
InfoBuf_SetValueForKey(&host_client->userinfo, "team", val);
|
||||||
SV_BroadcastUserinfoChange(host_client, true, "team", NULL);
|
SV_BroadcastUserinfoChange(host_client, true, "team", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6066,6 +6071,7 @@ ucmd_t nqucmds[] =
|
||||||
{"download", SV_BeginDownload_f},
|
{"download", SV_BeginDownload_f},
|
||||||
{"sv_startdownload", SVDP_StartDownload_f},
|
{"sv_startdownload", SVDP_StartDownload_f},
|
||||||
|
|
||||||
|
{"serverinfo", SV_ShowServerinfo_f},
|
||||||
/*userinfo stuff*/
|
/*userinfo stuff*/
|
||||||
{"setinfo", SV_SetInfo_f},
|
{"setinfo", SV_SetInfo_f},
|
||||||
{"name", SVNQ_NQInfo_f},
|
{"name", SVNQ_NQInfo_f},
|
||||||
|
@ -8067,9 +8073,11 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case clcq2_userinfo:
|
case clcq2_userinfo:
|
||||||
strncpy (cl->userinfo, MSG_ReadString (), sizeof(cl->userinfo)-1);
|
//FIXME: allows the client to set * keys mid-game.
|
||||||
ge->ClientUserinfoChanged (cl->q2edict, cl->userinfo); //tell the gamecode
|
s = MSG_ReadString();
|
||||||
|
InfoBuf_FromString(&cl->userinfo, s, false);
|
||||||
SV_ExtractFromUserinfo(cl, true); //let the server routines know
|
SV_ExtractFromUserinfo(cl, true); //let the server routines know
|
||||||
|
ge->ClientUserinfoChanged (cl->q2edict, s); //tell the gamecode
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case clcq2_stringcmd:
|
case clcq2_stringcmd:
|
||||||
|
@ -8459,6 +8467,9 @@ void SV_UserInit (void)
|
||||||
Cvar_Register (&sv_realiphostname_ipv6, cvargroup_servercontrol);
|
Cvar_Register (&sv_realiphostname_ipv6, cvargroup_servercontrol);
|
||||||
Cvar_Register (&sv_realip_timeout, cvargroup_servercontrol);
|
Cvar_Register (&sv_realip_timeout, cvargroup_servercontrol);
|
||||||
|
|
||||||
|
Cvar_Register (&sv_userinfo_keylimit, cvargroup_servercontrol);
|
||||||
|
Cvar_Register (&sv_userinfo_bytelimit, cvargroup_servercontrol);
|
||||||
|
|
||||||
Cvar_Register (&sv_pushplayers, cvargroup_servercontrol);
|
Cvar_Register (&sv_pushplayers, cvargroup_servercontrol);
|
||||||
Cvar_Register (&sv_protocol_nq, cvargroup_servercontrol);
|
Cvar_Register (&sv_protocol_nq, cvargroup_servercontrol);
|
||||||
|
|
||||||
|
|
|
@ -1013,7 +1013,9 @@ static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn,
|
||||||
{
|
{
|
||||||
char *dest = VM_POINTER(arg[0]);
|
char *dest = VM_POINTER(arg[0]);
|
||||||
int length = VM_LONG(arg[1]);
|
int length = VM_LONG(arg[1]);
|
||||||
Q_strncpyz(dest, svs.info, length);
|
if (VM_OOB(arg[1], arg[2]))
|
||||||
|
return 0;
|
||||||
|
InfoBuf_ToString(&svs.info, dest, length, NULL, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case G_GET_USERINFO://int num, char *buffer, int bufferSize 20
|
case G_GET_USERINFO://int num, char *buffer, int bufferSize 20
|
||||||
|
@ -1021,11 +1023,13 @@ static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn,
|
||||||
return 0;
|
return 0;
|
||||||
if ((unsigned)VM_LONG(arg[0]) >= sv.allocated_client_slots)
|
if ((unsigned)VM_LONG(arg[0]) >= sv.allocated_client_slots)
|
||||||
return 0;
|
return 0;
|
||||||
Q_strncpyz(VM_POINTER(arg[1]), svs.clients[VM_LONG(arg[0])].userinfo, VM_LONG(arg[2]));
|
InfoBuf_ToString(&svs.clients[VM_LONG(arg[0])].userinfo, VM_POINTER(arg[1]), VM_LONG(arg[2]), NULL, NULL, NULL, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case G_SET_USERINFO://int num, char *buffer 20
|
case G_SET_USERINFO://int num, char *buffer 20
|
||||||
Q_strncpyz(svs.clients[VM_LONG(arg[0])].userinfo, VM_POINTER(arg[1]), sizeof(svs.clients[0].userinfo));
|
if (VM_OOB(arg[1], 1))
|
||||||
|
return 0;
|
||||||
|
InfoBuf_FromString(&svs.clients[VM_LONG(arg[0])].userinfo, VM_POINTER(arg[1]), false);
|
||||||
SV_ExtractFromUserinfo(&svs.clients[VM_LONG(arg[0])], false);
|
SV_ExtractFromUserinfo(&svs.clients[VM_LONG(arg[0])], false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1894,13 +1898,13 @@ qboolean SVQ3_InitGame(void)
|
||||||
|
|
||||||
q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES);
|
q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES);
|
||||||
|
|
||||||
/*qw serverinfo settings are not normally visible in the q3 serverinfo*/
|
{ /*qw serverinfo settings are not normally visible in the q3 serverinfo, so strip them from the configstring*/
|
||||||
strcpy(buffer, svs.info);
|
static const char *ignores[] = {"maxclients", "map", "sv_maxclients", "*z_ext", "*bspversion", "*gamedir", NULL};
|
||||||
Info_SetValueForKey(buffer, "map", "", sizeof(buffer));
|
extern cvar_t maxclients;
|
||||||
Info_SetValueForKey(buffer, "maxclients", "", sizeof(buffer));
|
InfoBuf_ToString(&svs.info, buffer, sizeof(buffer), NULL, ignores, NULL, NULL, NULL);
|
||||||
Info_SetValueForKey(buffer, "mapname", svs.name, sizeof(buffer));
|
//add in maxclients.. the q3 version
|
||||||
Info_SetValueForKey(buffer, "sv_maxclients", "32", sizeof(buffer));
|
Q_strncatz(buffer, va("\\sv_maxclients\\%s", maxclients.string), sizeof(buffer));
|
||||||
Info_SetValueForKey(buffer, "sv_pure", "", sizeof(buffer));
|
}
|
||||||
SVQ3_SetConfigString(0, buffer);
|
SVQ3_SetConfigString(0, buffer);
|
||||||
|
|
||||||
Cvar_Set(Cvar_Get("sv_running", "0", 0, "Q3 compatability"), "1");
|
Cvar_Set(Cvar_Get("sv_running", "0", 0, "Q3 compatability"), "1");
|
||||||
|
@ -3069,8 +3073,7 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
|
||||||
|
|
||||||
void SVQ3_UpdateUserinfo_f(client_t *cl)
|
void SVQ3_UpdateUserinfo_f(client_t *cl)
|
||||||
{
|
{
|
||||||
Q_strncpyz(cl->userinfo, Cmd_Argv(1), sizeof(cl->userinfo));
|
InfoBuf_FromString(&cl->userinfo, Cmd_Argv(1), false);
|
||||||
|
|
||||||
SV_ExtractFromUserinfo (cl, true);
|
SV_ExtractFromUserinfo (cl, true);
|
||||||
|
|
||||||
if (svs.gametype == GT_QUAKE3)
|
if (svs.gametype == GT_QUAKE3)
|
||||||
|
@ -3386,9 +3389,9 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and
|
||||||
reason = "Invalid challenge";
|
reason = "Invalid challenge";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Q_strncpyz(cl->userinfo, userinfo, sizeof(cl->userinfo));
|
InfoBuf_FromString(&cl->userinfo, userinfo, false);
|
||||||
reason = NET_AdrToString(adr, sizeof(adr), &net_from);
|
reason = NET_AdrToString(adr, sizeof(adr), &net_from);
|
||||||
Info_SetValueForStarKey(cl->userinfo, "ip", reason, sizeof(cl->userinfo));
|
InfoBuf_SetKey(&cl->userinfo, "ip", reason);
|
||||||
|
|
||||||
ret = VM_Call(q3gamevm, GAME_CLIENT_CONNECT, (int)(cl-svs.clients), false, false);
|
ret = VM_Call(q3gamevm, GAME_CLIENT_CONNECT, (int)(cl-svs.clients), false, false);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
char shaders[][64] =
|
char shaders[][64] =
|
||||||
{
|
{
|
||||||
"fixedemu",
|
"fixedemu",
|
||||||
|
"q3terrain",
|
||||||
"altwater",
|
"altwater",
|
||||||
"bloom_blur",
|
"bloom_blur",
|
||||||
"bloom_filter",
|
"bloom_filter",
|
||||||
|
@ -129,7 +130,7 @@ int main(void)
|
||||||
if (!c)
|
if (!c)
|
||||||
{
|
{
|
||||||
printf("unable to open a file\n");
|
printf("unable to open a file\n");
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
|
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
|
||||||
|
@ -166,4 +167,6 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(c);
|
fclose(c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
!!permu REFLECTCUBEMASK
|
!!permu REFLECTCUBEMASK
|
||||||
!!cvarf r_glsl_offsetmapping_scale
|
!!cvarf r_glsl_offsetmapping_scale
|
||||||
!!cvardf r_tessellation_level=5
|
!!cvardf r_tessellation_level=5
|
||||||
!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3
|
!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3
|
||||||
|
|
||||||
#include "sys/defs.h"
|
#include "sys/defs.h"
|
||||||
|
|
||||||
|
@ -271,16 +271,16 @@ void main ()
|
||||||
#else
|
#else
|
||||||
vec3 lightmaps = vc.rgb;
|
vec3 lightmaps = vc.rgb;
|
||||||
#endif
|
#endif
|
||||||
#define delux vec3(0.0,0.0,1.0)
|
#define deluxe vec3(0.0,0.0,1.0)
|
||||||
#else
|
#else
|
||||||
#ifdef LIGHTSTYLED
|
#ifdef LIGHTSTYLED
|
||||||
#define delux vec3(0.0,0.0,1.0)
|
#define deluxe vec3(0.0,0.0,1.0)
|
||||||
vec3 lightmaps;
|
vec3 lightmaps;
|
||||||
#ifdef DELUXE
|
#ifdef DELUXE
|
||||||
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxmap0, lm0).rgb-0.5);
|
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxemap0, lm0).rgb-0.5);
|
||||||
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxmap1, lm1).rgb-0.5);
|
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxemap1, lm1).rgb-0.5);
|
||||||
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxmap2, lm2).rgb-0.5);
|
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxemap2, lm2).rgb-0.5);
|
||||||
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxmap3, lm3).rgb-0.5);
|
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxemap3, lm3).rgb-0.5);
|
||||||
#else
|
#else
|
||||||
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;
|
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;
|
||||||
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;
|
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;
|
||||||
|
@ -291,15 +291,15 @@ void main ()
|
||||||
vec3 lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
|
vec3 lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
|
||||||
//modulate by the bumpmap dot light
|
//modulate by the bumpmap dot light
|
||||||
#ifdef DELUXE
|
#ifdef DELUXE
|
||||||
vec3 delux = (texture2D(s_deluxmap, lm0).rgb-0.5);
|
vec3 deluxe = (texture2D(s_deluxemap, lm0).rgb-0.5);
|
||||||
#ifdef BUMPMODELSPACE
|
#ifdef BUMPMODELSPACE
|
||||||
delux = normalize(delux*invsurface);
|
deluxe = normalize(deluxe*invsurface);
|
||||||
#else
|
#else
|
||||||
lightmaps *= 2.0 / max(0.25, delux.z); //counter the darkening from deluxmaps
|
lightmaps *= 2.0 / max(0.25, deluxe.z); //counter the darkening from deluxemaps
|
||||||
#endif
|
#endif
|
||||||
lightmaps *= dot(norm, delux);
|
lightmaps *= dot(norm, deluxe);
|
||||||
#else
|
#else
|
||||||
#define delux vec3(0.0,0.0,1.0)
|
#define deluxe vec3(0.0,0.0,1.0)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -307,7 +307,7 @@ void main ()
|
||||||
//add in specular, if applicable.
|
//add in specular, if applicable.
|
||||||
#ifdef SPECULAR
|
#ifdef SPECULAR
|
||||||
vec4 specs = texture2D(s_specular, tc);
|
vec4 specs = texture2D(s_specular, tc);
|
||||||
vec3 halfdir = normalize(normalize(eyevector) + delux); //this norm should be the deluxemap info instead
|
vec3 halfdir = normalize(normalize(eyevector) + deluxe); //this norm should be the deluxemap info instead
|
||||||
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * specs.a);
|
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * specs.a);
|
||||||
spec *= FTE_SPECULAR_MULTIPLIER;
|
spec *= FTE_SPECULAR_MULTIPLIER;
|
||||||
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
|
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
|
||||||
|
|
|
@ -5069,7 +5069,6 @@ void VKBE_RT_End(struct vk_rendertarg *targ)
|
||||||
|
|
||||||
static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
||||||
{
|
{
|
||||||
extern cvar_t r_refractreflect_scale;
|
|
||||||
float oldil;
|
float oldil;
|
||||||
int oldbem;
|
int oldbem;
|
||||||
// struct vk_rendertarg *targ;
|
// struct vk_rendertarg *targ;
|
||||||
|
@ -5093,8 +5092,8 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
||||||
|
|
||||||
r_refdef.vrect.x = 0;
|
r_refdef.vrect.x = 0;
|
||||||
r_refdef.vrect.y = 0;
|
r_refdef.vrect.y = 0;
|
||||||
r_refdef.vrect.width = max(1, vid.fbvwidth*r_refractreflect_scale.value);
|
r_refdef.vrect.width = max(1, vid.fbvwidth*bs->portalfboscale);
|
||||||
r_refdef.vrect.height = max(1, vid.fbvheight*r_refractreflect_scale.value);
|
r_refdef.vrect.height = max(1, vid.fbvheight*bs->portalfboscale);
|
||||||
VKBE_RT_Gen(&shaderstate.rt_reflection, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
|
VKBE_RT_Gen(&shaderstate.rt_reflection, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
|
||||||
VKBE_RT_Begin(&shaderstate.rt_reflection);
|
VKBE_RT_Begin(&shaderstate.rt_reflection);
|
||||||
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
|
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
|
||||||
|
|
|
@ -3746,7 +3746,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkApplicationInfo app;
|
VkApplicationInfo app;
|
||||||
VkInstanceCreateInfo inst_info;
|
VkInstanceCreateInfo inst_info;
|
||||||
int gpuidx;
|
int gpuidx = 0;
|
||||||
const char *extensions[8];
|
const char *extensions[8];
|
||||||
uint32_t extensions_count = 0;
|
uint32_t extensions_count = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue