make sure the capture command doesn't switch between gamedirs while capturing.

added dimension_default global to provide default dimensions. expected to be a (var) constant.
support setcustomskin in menuqc.
implement some considerations for win95, so it can actually run on that horrendously outdated system.
provide scr_autoid and r_showbbox-field info when running csqc.
ignore vid_restarts at the end of config.cfg files from other engines. in fte, these are at best redundant and at worst overrides user settings.
fix issue with latched cvars not flagging the config as modified.
path command always shows filenames properly.
fix some fteqcc inlining bugs.
added precaches command to display all active precaches.
added docs for mapcluster.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4881 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-04 06:15:14 +00:00
parent 4bfb34a8c0
commit f4d3df7bf5
62 changed files with 1042 additions and 431 deletions

View file

@ -1624,11 +1624,6 @@ help:
@-echo "vc - Attempts to use msvc8+ to compile. Note: uses profile guided optimisations. You must build+run the relevent profile target before a release target will compile properly. Debug doesn't care."
@-echo "android, npfte, nacl targets explicitly cross compile, and should generally not be given an FTE_TARGET."
install:
-cp debug/*.* /opt/quake/
-cp release/*.* /opt/quake/
-cp profile/*.* /opt/quake
clean:
-rm -f -r $(RELEASE_DIR)
-rm -f -r $(DEBUG_DIR)
@ -1847,3 +1842,16 @@ else
test -f libvorbis-$(VORBISVER).tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-$(VORBISVER).tar.gz
-test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-$(VORBISVER).tar.gz && cd libvorbis-$(VORBISVER) && $(TOOLOVERRIDES) ./configure PKG_CONFIG= $(CONFIGARGS) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(NATIVE_ABSBASE_DIR)/libs-$(ARCH)/libogg-$(OGGVER)/include && $(TOOLOVERRIDES) $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ )
endif
prefix ?= /usr/local
exec_prefix ?= $(prefix)
bindir ?= $(exec_prefix)/bin
sbindir ?= $(exec_prefix)/sbin
INSTALL ?= install
INSTALL_PROGRAM ?= $(INSTALL)
INSTALL_DATA ?= ${INSTALL} -m 644
install: sv-rel gl-rel mingl-rel qcc-rel
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqw $(DESTDIR)$(bindir)/fteqw
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqwsv $(DESTDIR)$(bindir)/fteqwsv
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc

View file

@ -1101,10 +1101,10 @@ float CL_FilterTime (double time, float wantfps, qboolean ignoreserver) //now re
fps = bound (6.7, wantfps, fpscap); //we actually cap ourselves to 150msecs (1000/7 = 142)
}
if (time < 1000 / fps)
if (time < ceil(1000 / fps))
return 0;
return time - (1000 / fps);
return time - ceil(1000 / fps);
}
qboolean allowindepphys;

View file

@ -333,6 +333,9 @@ CL_Quit_f
*/
void CL_Quit_f (void)
{
if (!host_initialized)
return;
if (forcesaveprompt && strcmp(Cmd_Argv(1), "force"))
{
forcesaveprompt = false;
@ -4586,7 +4589,7 @@ double Host_Frame (double time)
#endif
Key_Dest_Has(kdm_menu) ||
Key_Dest_Has(kdm_editor) ||
cl.paused;
cl.paused || !ActiveApp;
// TODO: check if minimized or unfocused
//read packets early and always, so we don't have stuff waiting for reception quite so often.
@ -5238,6 +5241,8 @@ void Host_Shutdown(void)
}
host_initialized = false;
HTTP_CL_Terminate();
#ifdef PLUGINS
Plug_Shutdown(false);
#endif

View file

@ -1959,12 +1959,12 @@ typedef struct _TargaHeader {
#if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG)
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight);
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight);
#endif
#ifdef AVAIL_PNGLIB
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height);
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height);
#endif
void WriteBMPFile(char *filename, qbyte *in, int width, int height);
void WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, int width, int height);
/*
Find closest color in the palette for named color
@ -1999,7 +1999,7 @@ int MipColor(int r, int g, int b)
return best;
}
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height)
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height)
{
int i, c, temp;
#if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB)
@ -2016,14 +2016,14 @@ qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height
#ifdef AVAIL_PNGLIB
if (!Q_strcasecmp(ext, "png"))
{
return Image_WritePNG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
return Image_WritePNG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
}
else
#endif
#ifdef AVAIL_JPEGLIB
if (!Q_strcasecmp(ext, "jpeg") || !Q_strcasecmp(ext, "jpg"))
{
return screenshotJPEG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
return screenshotJPEG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
}
else
#endif
@ -2049,13 +2049,13 @@ qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height
}
}
WritePCXfile (filename, newbuf, width, height, width, host_basepal, false);
WritePCXfile (filename, fsroot, newbuf, width, height, width, host_basepal, false);
}
else if (!Q_strcasecmp(ext, "tga")) //tga
{
vfsfile_t *vfs;
FS_CreatePath(filename, FS_GAMEONLY);
vfs = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs)
{
unsigned char header[18];
@ -2144,7 +2144,7 @@ void SCR_ScreenShot_f (void)
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer)
{
if (SCR_ScreenShot(pcxname, rgbbuffer, width, height))
if (SCR_ScreenShot(pcxname, FS_GAMEONLY, rgbbuffer, width, height))
{
Con_Printf ("Wrote %s\n", sysname);
BZ_Free(rgbbuffer);
@ -2217,7 +2217,7 @@ void SCR_ScreenShot_Mega_f(void)
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer)
{
if (SCR_ScreenShot(filename, rgbbuffer, width, height))
if (SCR_ScreenShot(filename, FS_GAMEONLY, rgbbuffer, width, height))
{
char sysname[1024];
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
@ -2385,7 +2385,7 @@ qboolean SCR_RSShot (void)
Q_strncpyz(st, name.string, sizeof(st));
SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w);
WritePCXfile ("snap.pcx", newbuf, w, h, w, host_basepal, true);
WritePCXfile ("snap.pcx", FS_GAMEONLY, newbuf, w, h, w, host_basepal, true);
BZ_Free(newbuf);

View file

@ -977,7 +977,7 @@ error:
#ifndef NPFTE
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height)
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height)
{
char name[MAX_OSPATH];
int i;
@ -987,7 +987,7 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i
png_byte **row_pointers;
struct pngerr errctx;
if (!FS_NativePath(filename, FS_GAMEONLY, name, sizeof(name)))
if (!FS_NativePath(filename, fsroot, name, sizeof(name)))
return false;
if (!LibPNG_Init())
@ -1533,7 +1533,7 @@ METHODDEF(void) jpeg_error_exit (j_common_ptr cinfo)
{
longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1);
}
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
{
qbyte *buffer;
vfsfile_t *outfile;
@ -1544,10 +1544,10 @@ qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int
if (!LIBJPEG_LOADED())
return false;
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
if (!(outfile = FS_OpenVFS(filename, "wb", fsroot)))
{
FS_CreatePath (filename, FS_GAMEONLY);
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
FS_CreatePath (filename, fsroot);
if (!(outfile = FS_OpenVFS(filename, "wb", fsroot)))
{
Con_Printf("Error opening %s\n", filename);
return false;
@ -1632,7 +1632,7 @@ qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int
WritePCXfile
==============
*/
void WritePCXfile (const char *filename, qbyte *data, int width, int height,
void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height,
int rowbytes, qbyte *palette, qboolean upload) //data is 8bit.
{
int i, j, length;
@ -1695,7 +1695,7 @@ void WritePCXfile (const char *filename, qbyte *data, int width, int height,
if (upload)
CL_StartUpload((void *)pcx, length);
else
COM_WriteFile (filename, pcx, length);
COM_WriteFile (filename, fsroot, pcx, length);
}
#endif

View file

@ -30,7 +30,6 @@ void Editor_Key(int key, int unicode);
void Key_ConsoleInsert(char *instext);
void Key_ClearTyping (void);
#define KEY_MODIFIERSTATES 8
unsigned char *key_lines[CON_EDIT_LINES_MASK+1];
int key_linepos;
int shift_down=false;
@ -1561,11 +1560,11 @@ int Key_StringToKeynum (const char *str, int *modifier)
if (!underscore || !underscore[1])
break; //nothing afterwards or no underscore.
if (!strnicmp(str, "shift_", 6))
*modifier |= 1;
*modifier |= KEY_MODIFIER_SHIFT;
else if (!strnicmp(str, "alt_", 4))
*modifier |= 2;
*modifier |= KEY_MODIFIER_ALT;
else if (!strnicmp(str, "ctrl_", 5))
*modifier |= 4;
*modifier |= KEY_MODIFIER_CTRL;
else
break;
str = underscore+1; //next char.
@ -1616,7 +1615,7 @@ char *Key_KeynumToString (int keynum)
if (keynum == -1)
return "<KEY NOT FOUND>";
if (keynum > 32 && keynum < 127)
if (keynum > 32 && keynum < 127 && keynum != '\'' && keynum != '\"')
{ // printable ascii
tinystr[0] = keynum;
tinystr[1] = 0;
@ -1853,11 +1852,11 @@ void Key_WriteBindings (vfsfile_t *f)
if (strcmp(binding, base) || (m==0 && keybindings[i][0]) || bindcmdlevel[i][m] != bindcmdlevel[i][0])
{
*prefix = '\0';
if (m & 4)
if (m & KEY_MODIFIER_CTRL)
strcat(prefix, "CTRL_");
if (m & 2)
if (m & KEY_MODIFIER_ALT)
strcat(prefix, "ALT_");
if (m & 1)
if (m & KEY_MODIFIER_SHIFT)
strcat(prefix, "SHIFT_");
s = va("%s%s", prefix, Key_KeynumToString(i));

View file

@ -166,6 +166,11 @@ K_PRINTSCREEN = 248,
K_MAX = 256
};
#define KEY_MODIFIER_SHIFT (1<<0)
#define KEY_MODIFIER_ALT (1<<1)
#define KEY_MODIFIER_CTRL (1<<2)
#define KEY_MODIFIERSTATES (1<<3)
#define K_SHIFT K_LSHIFT
#define K_CTRL K_LCTRL
#define K_ALT K_LALT

View file

@ -6,7 +6,7 @@
#ifdef DOWNLOADMENU
#define ROOTDOWNLOADABLESSOURCE "http://fteqw.com/downloadables.txt"
#define ROOTDOWNLOADABLESSOURCE "http://fte.triptohell.info/downloadables.txt"
#define INSTALLEDFILES "installed.lst" //the file that resides in the quakedir (saying what's installed).
#define DPF_HAVEAVERSION 1 //any old version

View file

@ -2530,6 +2530,7 @@ void *currentcapture_ctx;
struct capture_raw_ctx
{
int frames;
enum fs_relative fsroot;
char videonameprefix[MAX_QPATH];
char videonameextension[16];
vfsfile_t *audio;
@ -2544,7 +2545,12 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
else
Q_strncpyz(ctx->videonameextension, "tga", sizeof(ctx->videonameextension));
Q_strncpyz(ctx->videonameprefix, streamname, sizeof(ctx->videonameprefix));
if (!FS_NativePath(va("%s", streamname), FS_GAMEONLY, ctx->videonameprefix, sizeof(ctx->videonameprefix)))
{
Z_Free(ctx);
return NULL;
}
ctx->fsroot = FS_SYSTEM;
ctx->audio = NULL;
if (*sndkhz)
{
@ -2558,8 +2564,8 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
if (*sndchannels < 1)
*sndchannels = 1;
Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits);
FS_CreatePath(filename, FS_GAMEONLY);
ctx->audio = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
FS_CreatePath(filename, ctx->fsroot);
ctx->audio = FS_OpenVFS(filename, "wb", ctx->fsroot);
}
if (!ctx->audio)
{
@ -2575,7 +2581,7 @@ static void QDECL capture_raw_video (void *vctx, void *data, int frame, int widt
char filename[MAX_OSPATH];
ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, data, width, height);
SCR_ScreenShot(filename, ctx->fsroot, data, width, height);
}
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
{

View file

@ -105,31 +105,51 @@ void M_DrawTextBox (int x, int y, int width, int lines)
M_DrawScalePic (cx, cy+8, 8, 8, p);
}
int M_FindKeysForBind (char *command, int *keylist, int total)
int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total)
{
int count;
int j;
int l;
int j, m;
int l, p;
char *b;
for (count = 0; count < total; count++)
keylist[count] = -1;
l = strlen(command);
count = 0;
for (j=0 ; j<256 ; j++)
{
b = keybindings[j][0];
for (m = 0; m < KEY_MODIFIERSTATES; m++)
{
b = keybindings[j][m];
if (!b)
continue;
if (!strncmp (b, command, l) && (!b[l] || b[l] == ' ' || b[l] == ';'))
{
//if ctrl_a and ctrl_shift_a do the same thing, don't report ctrl_shift_a because its redundant.
for (p = 0; p < m; p++)
{
if (p&~m) //ignore shift_a if we're checking ctrl_a
continue;
if (!strcmp(keybindings[j][p], b))
break; //break+continue
}
if (p != m)
continue;
keylist[count] = j;
if (keymods)
keymods[count] = j;
count++;
if (count == total)
break;
return count;
}
}
}
for (j = count; j < total; j++)
{
keylist[j] = -1;
if (keymods)
keymods[j] = 0;
}
return count;
}
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys)
@ -160,7 +180,7 @@ void M_FindKeysForCommand (int pnum, const char *command, int *twokeys)
prefix[3] = 0;
}
}
M_FindKeysForBind(va("%s%s", prefix, command), twokeys, 2);
M_FindKeysForBind(va("%s%s", prefix, command), twokeys, NULL, 2);
}
#ifndef NOBUILTINMENUS

View file

@ -468,6 +468,7 @@ void M_Keyup (int key, int unicode);
void M_Draw (int uimenu);
#endif
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys);
int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total);
void M_Media_Draw (void);
void M_Media_Key (int key);

View file

@ -1170,7 +1170,7 @@ static void P_ParticleEffect_f(void)
ptype->alpha = atof(value);
else if (!strcmp(var, "alphachange"))
{
Con_DPrintf("alphachange is deprechiated, use alphadelta\n");
Con_DPrintf("alphachange is deprecated, use alphadelta\n");
ptype->alphachange = atof(value);
}
else if (!strcmp(var, "alphadelta"))
@ -1195,7 +1195,7 @@ static void P_ParticleEffect_f(void)
}
else if (!strcmp(var, "diesubrand"))
{
Con_DPrintf("diesubrand is deprechiated, use die with two arguments\n");
Con_DPrintf("diesubrand is deprecated, use die with two arguments\n");
ptype->randdie = atof(value);
}
@ -1550,7 +1550,7 @@ static void P_ParticleEffect_f(void)
}
else if (!strcmp(var, "isbeam"))
{
Con_DPrintf("isbeam is deprechiated, use type beam\n");
Con_DPrintf("isbeam is deprecated, use type beam\n");
ptype->looks.type = PT_BEAM;
}
else if (!strcmp(var, "spawntime"))
@ -1589,22 +1589,22 @@ static void P_ParticleEffect_f(void)
// old names
else if (!strcmp(var, "areaspread"))
{
Con_DPrintf("areaspread is deprechiated, use spawnorg\n");
Con_DPrintf("areaspread is deprecated, use spawnorg\n");
ptype->areaspread = atof(value);
}
else if (!strcmp(var, "areaspreadvert"))
{
Con_DPrintf("areaspreadvert is deprechiated, use spawnorg\n");
Con_DPrintf("areaspreadvert is deprecated, use spawnorg\n");
ptype->areaspreadvert = atof(value);
}
else if (!strcmp(var, "offsetspread"))
{
Con_DPrintf("offsetspread is deprechiated, use spawnvel\n");
Con_DPrintf("offsetspread is deprecated, use spawnvel\n");
ptype->spawnvel = atof(value);
}
else if (!strcmp(var, "offsetspreadvert"))
{
Con_DPrintf("offsetspreadvert is deprechiated, use spawnvel\n");
Con_DPrintf("offsetspreadvert is deprecated, use spawnvel\n");
ptype->spawnvelvert = atof(value);
}
@ -1640,7 +1640,7 @@ static void P_ParticleEffect_f(void)
ptype->rampmode = RAMP_NONE;
else if (!strcmp(value, "absolute"))
{
Con_DPrintf("'rampmode absolute' is deprechiated, use 'rampmode nearest'\n");
Con_DPrintf("'rampmode absolute' is deprecated, use 'rampmode nearest'\n");
ptype->rampmode = RAMP_NEAREST;
}
else if (!strcmp(value, "nearest"))
@ -2902,7 +2902,7 @@ static void P_ExportBuiltinSet_f(void)
file = *partset_list[i].data;
if (file)
{
COM_WriteFile(va("particles/%s.cfg", efname), file, strlen(file));
COM_WriteFile(va("particles/%s.cfg", efname), FS_GAMEONLY, file, strlen(file));
Con_Printf("Written particles/%s.cfg\n", efname);
}
else

View file

@ -285,6 +285,7 @@ int MP_TranslateQCtoFTECodes(int code)
void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0);
//float bindmap = G_FLOAT(OFS_PARM1);
int keynums[2];
char keyname[512];
@ -298,6 +299,26 @@ void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalva
RETURN_TSTRING(keyname);
}
void QCBUILTIN PF_cl_findkeysforcommandex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0);
int keynums[256];
int keymods[countof(keynums)];
char keyname[512];
int i, count;
count = M_FindKeysForBind(cmdname, keynums, keymods, countof(keynums));
keyname[0] = '\0';
for (i = 0; i < count; i++)
{
Q_strncatz (keyname, va("%s%s%s%s ", (keymods[i]&KEY_MODIFIER_CTRL)?"CTRL_":"", (keymods[i]&KEY_MODIFIER_ALT)?"ALT_":"", (keymods[i]&KEY_MODIFIER_SHIFT)?"SHIFT_":"", Key_KeynumToString(keynums[i])), sizeof(keyname));
}
RETURN_TSTRING(keyname);
}
void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)));

View file

@ -184,6 +184,7 @@ extern sfx_t *cl_sfx_r_exp3;
globalvector(input_cursor_impact, "input_cursor_trace_endpos"); /*float filled by getinputstate*/ \
globalfloat(input_cursor_entitynumber, "input_cursor_entitynumber"); /*float filled by getinputstate*/ \
\
globalfloat(dimension_default, "dimension_default"); /*float default value for dimension_hit+dimension_solid*/ \
globalfloat(autocvar_vid_conwidth, "autocvar_vid_conwidth"); /*float hackfix for dp mods*/ \
globalfloat(autocvar_vid_conheight, "autocvar_vid_conheight"); /*float hackfix for dp mods*/ \
@ -278,6 +279,7 @@ static void CSQC_ChangeLocalPlayer(int seat)
static void CSQC_FindGlobals(void)
{
static float csphysicsmode = 0;
static float dimension_default = 255;
#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalint(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
@ -320,6 +322,9 @@ static void CSQC_FindGlobals(void)
csqc_world.g.physics_mode = &csphysicsmode;
}
if (!csqcg.dimension_default)
csqcg.dimension_default = &dimension_default;
if (csqcg.maxclients)
*csqcg.maxclients = cl.allocated_client_slots;
}
@ -492,6 +497,7 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t
}
//and the normal frames.
out->g[FS_REG].endbone = 0x7fffffff;
out->g[FS_REG].frame[0] = in->v->frame;
out->g[FS_REG].frame[1] = in->xv->frame2;
out->g[FS_REG].frame[2] = in->xv->frame3;
@ -1757,6 +1763,7 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
}
void R2D_PolyBlend (void);
void R_DrawNameTags(void);
static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (csqc_worldchanged)
@ -1775,6 +1782,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
V_ApplyRefdef();
R_RenderView();
R2D_PolyBlend ();
R_DrawNameTags();
{
srect_t srect;
@ -4062,8 +4070,6 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
ent->v->colormap = src->colormap;
ent->v->skin = src->skinnum;
// ent->v->glowsize = src->glowsize;
// ent->v->glowcolor = src->glowcolour;
ent->xv->scale = src->scale/16.0f;
ent->xv->fatness = src->fatness/16.0f;
// ent->xv->drawflags = src->hexen2flags;
@ -4072,16 +4078,23 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
ent->xv->colormod[0] = src->colormod[0]*(8/256.0f);
ent->xv->colormod[1] = src->colormod[1]*(8/256.0f);
ent->xv->colormod[2] = src->colormod[2]*(8/256.0f);
ent->xv->glowmod[0] = src->glowmod[0]*(8/256.0f);
ent->xv->glowmod[1] = src->glowmod[1]*(8/256.0f);
ent->xv->glowmod[2] = src->glowmod[2]*(8/256.0f);
// ent->xv->glow_size = src->glowsize*4;
// ent->xv->glow_color = src->glowcolour;
// ent->xv->glow_trail = !!(state->dpflags & RENDER_GLOWTRAIL);
ent->xv->alpha = src->trans/255.0f;
// ent->v->solid = src->solid;
// ent->v->color[0] = src->light[0]/255.0;
// ent->v->color[1] = src->light[1]/255.0;
// ent->v->color[2] = src->light[2]/255.0;
// ent->v->light_lev = src->light[3];
// ent->xv->style = src->lightstyle;
// ent->xv->pflags = src->lightpflags;
// ent->v->solid = src->solid;
// ent->v->color[0] = src->light[0];
// ent->v->color[1] = src->light[1];
// ent->v->color[2] = src->light[2];
// ent->v->light_lev = src->light[3];
// ent->xv->tagentity = src->tagentity;
// ent->xv->tagindex = src->tagindex;
ent->xv->tag_entity = src->tagentity;
ent->xv->tag_index = src->tagindex;
if (src->solid == ES_SOLID_BSP)
{
@ -5346,6 +5359,7 @@ static struct {
{"keynumtostring_omgwtf", PF_cl_keynumtostring, 520},
{"findkeysforcommand", PF_cl_findkeysforcommand, 521},
{"findkeysforcommandex", PF_cl_findkeysforcommandex, 0},
{"loadfromdata", PF_loadfromdata, 529},
{"loadfromfile", PF_loadfromfile, 530},
@ -5373,7 +5387,7 @@ static struct {
{"getresolution", PF_cl_getresolution, 608},
{"keynumtostring_menu", PF_cl_keynumtostring, 609}, //while present in dp's menuqc, dp doesn't actually support keynumtostring=609 in csqc. Which is probably a good thing because csqc would have 3 separate versions if it did.
{"findkeysforcommand_dp", PF_cl_findkeysforcommand, 610},
{"findkeysforcommand_menu", PF_cl_findkeysforcommand, 610},
{"gethostcachevalue", PF_cl_gethostcachevalue, 611},
{"gethostcachestring", PF_cl_gethostcachestring, 612},
{"parseentitydata", PF_parseentitydata, 613},
@ -5474,7 +5488,7 @@ void VARGS CSQC_Abort (char *format, ...) //an error occured.
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3);
COM_WriteFile("csqccore.txt", buffer, size);
COM_WriteFile("csqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}
@ -5506,11 +5520,11 @@ void PDECL CSQC_EntSpawn (struct edict_s *e, int loading)
if (1)
{
// ent->xv->dimension_see = 255;
// ent->xv->dimension_seen = 255;
// ent->xv->dimension_see = csqc_world.dimension_default;
// ent->xv->dimension_seen = csqc_world.dimension_default;
// ent->xv->dimension_ghost = 0;
ent->xv->dimension_solid = 255;
ent->xv->dimension_hit = 255;
ent->xv->dimension_solid = *csqcg.dimension_default;
ent->xv->dimension_hit = *csqcg.dimension_default;
}
}
@ -5710,7 +5724,7 @@ qbyte *PDECL CSQC_PRLoadFile (const char *path, void *buffer, int bufsize, size_
#ifndef FTE_TARGET_WEB
//back it up
COM_WriteFile(newname, file, *sz);
COM_WriteFile(newname, FS_GAMEONLY, file, *sz);
#endif
}
}
@ -6147,7 +6161,7 @@ void CSQC_CoreDump(void)
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3);
COM_WriteFile("csqccore.txt", buffer, size);
COM_WriteFile("csqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}

View file

@ -1038,6 +1038,7 @@ static struct
evalc_t frame1time;
evalc_t frame2time;
evalc_t renderflags;
evalc_t skinobject;
} menuc_eval;
static playerview_t menuview;
@ -1670,6 +1671,29 @@ static void QCBUILTIN PF_m_setmodel(pubprogfuncs_t *prinst, struct globalvars_s
if (mod && maxsval)
VectorCopy(mod->maxs, maxsval->_vector);
}
static void QCBUILTIN PF_m_setcustomskin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
menuedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
const char *fname = PR_GetStringOfs(prinst, OFS_PARM1);
const char *skindata = PF_VarString(prinst, 2, pr_globals);
eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "skinobject", &menuc_eval.skinobject);
if (!val)
return;
if (val->_float > 0)
{
Mod_WipeSkin(val->_float);
val->_float = 0;
}
if (*fname || *skindata)
{
if (*skindata)
val->_float = Mod_ReadSkinFile(fname, skindata);
else
val->_float = -(int)Mod_RegisterSkinFile(fname);
}
}
//trivially basic
static void QCBUILTIN PF_m_setorigin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -1707,6 +1731,7 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
eval_t *frame2timeval = prinst->GetEdictFieldValue(prinst, (void*)in, "frame2time", &menuc_eval.frame2time);
eval_t *colormapval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormap", &menuc_eval.colormap);
eval_t *renderflagsval = prinst->GetEdictFieldValue(prinst, (void*)in, "renderflags", &menuc_eval.renderflags);
eval_t *skinobjectval = prinst->GetEdictFieldValue(prinst, (void*)in, "skinobject", &menuc_eval.skinobject);
int ival;
int rflags;
@ -1730,6 +1755,8 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
out->framestate.g[FS_REG].frametime[0] = frame1timeval?frame1timeval->_float:0;
out->framestate.g[FS_REG].frametime[1] = frame2timeval?frame2timeval->_float:0;
out->customskin = skinobjectval?skinobjectval->_float:0;
//FIXME: colourmap
ival = colormapval?colormapval->_float:0;
out->playerindex = -1;
@ -1969,6 +1996,10 @@ static struct {
{"findfont", PF_CL_findfont, 356},
{"loadfont", PF_CL_loadfont, 357},
//gap
// {"dynamiclight_get", PF_R_DynamicLight_Get, 372},
// {"dynamiclight_set", PF_R_DynamicLight_Set, 373},
{"setcustomskin", PF_m_setcustomskin, 376},
//gap
{"memalloc", PF_memalloc, 384},
{"memfree", PF_memfree, 385},
{"memcpy", PF_memcpy, 386},
@ -2245,7 +2276,7 @@ void VARGS Menu_Abort (char *format, ...)
int size = 1024*1024*8;
buffer = Z_Malloc(size);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
COM_WriteFile("menucore.txt", buffer, size);
COM_WriteFile("menucore.txt", FS_GAMEONLY, buffer, size);
Z_Free(buffer);
}
@ -2422,7 +2453,7 @@ void MP_CoreDump_f(void)
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
COM_WriteFile("menucore.txt", buffer, size);
COM_WriteFile("menucore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}
}

View file

@ -199,9 +199,10 @@ static void R_Clutter_Insert_Mesh(clutter_build_ctx_t *ctx, model_t *mod, float
if (!mod)
return;
if (mod->type == mod_alias)
{
//fill in the parts of the entity_t that Alias_GAliasBuildMesh needs.
memset(&re, 0, sizeof(re));
// memset(&re.framestate, 0, sizeof(re.framestate));
re.framestate.g[FS_REG].lerpweight[0] = 1;
re.model = mod;
@ -221,6 +222,7 @@ static void R_Clutter_Insert_Mesh(clutter_build_ctx_t *ctx, model_t *mod, float
inf = inf->nextsurf;
}
Alias_FlushCache(); //it got built using an entity on the stack, make sure other stuff doesn't get hurt.
}
}
static void R_Clutter_Insert(void *vctx, vec3_t *fte_restrict points, size_t numtris, shader_t *surface)
{

View file

@ -517,7 +517,7 @@ void CLQ2_FlyEffect(struct q2centity_s *ent, vec3_t org);
void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects);
void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg);
void WritePCXfile (const char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height);
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey);
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);

View file

@ -204,7 +204,7 @@ cvar_t vid_conwidth = CVARF ("vid_conwidth", "0",
cvar_t vid_renderer = CVARFD ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering).");
cvar_t vid_bpp = CVARFD ("vid_bpp", "32",
cvar_t vid_bpp = CVARFD ("vid_bpp", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context");
cvar_t vid_desktopsettings = CVARFD ("vid_desktopsettings", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Ignore the values of vid_width and vid_height, and just use the same settings that are used for the desktop.");

View file

@ -79,7 +79,8 @@ void SCR_ShowPic_Script_f(void);
//a header is better than none...
void Draw_TextBox (int x, int y, int width, int lines);
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height);
enum fs_relative;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height);
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);

View file

@ -585,7 +585,9 @@ qboolean MyRegGetStringValue(HKEY base, const char *keyname, const char *valuena
DWORD type = REG_NONE;
if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS)
{
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &datalen);
DWORD dl = datalen;
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dl);
datalen = dl;
RegCloseKey (subkey);
}

View file

@ -360,22 +360,38 @@ void Sys_CloseLibrary(dllhandle_t *lib)
{
FreeLibrary((HMODULE)lib);
}
HMODULE LoadLibraryU(const char *name)
{
if (WinNT)
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), name);
return LoadLibraryW(wide);
}
else
{
wchar_t wide[MAX_OSPATH];
char ansi[MAX_OSPATH];
widen(wide, sizeof(wide), name);
ansi[WideCharToMultiByte(CP_ACP, 0, wide, wcslen(wide), ansi, sizeof(ansi)-1, NULL, NULL)] = 0;
return LoadLibraryA(ansi);
}
}
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{
int i;
HMODULE lib;
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), name);
lib = LoadLibraryW(wide);
lib = LoadLibraryU(name);
if (!lib)
{
if (!strstr(COM_SkipPath(name), ".dll"))
{ //.dll implies that it is a system dll, or something that is otherwise windows-specific already.
#ifdef _WIN64
lib = LoadLibrary(va("%s_64", name));
lib = LoadLibraryU(va("%s_64", name));
#elif defined(_WIN32)
lib = LoadLibrary(va("%s_32", name));
lib = LoadLibraryU(va("%s_32", name));
#endif
}
if (!lib)
@ -1537,7 +1553,15 @@ void VARGS Sys_Printf (char *fmt, ...)
if (debugout)
OutputDebugStringW(wide);
if (houtput)
{
if (WinNT)
WriteConsoleW(houtput, wide, wlen, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck. this conversion might loose stuff if the multibytes are too long.
WriteConsole(houtput, text, WideCharToMultiByte(CP_ACP, 0, wide, wlen, text, sizeof(text), NULL, NULL), &dummy, NULL);
}
}
}
void Sys_Quit (void)
@ -1941,7 +1965,13 @@ char *Sys_ConsoleInput (void)
} else if (ch >= ' ')
{
wchar_t wch = ch;
if (WinNT)
WriteConsoleW(houtput, &wch, 1, &dummy, NULL);
else
{
char mb[8]; //hopefully ucs-2-only will be sufficient...
WriteConsoleA(houtput, mb, WideCharToMultiByte(CP_ACP, 0, &wch, 1, mb, sizeof(mb), NULL, NULL), &dummy, NULL);
}
len += utf8_encode(text+len, ch, sizeof(text)-1-len);
}
@ -2170,8 +2200,6 @@ HWND hwnd_dialog;
#define COBJMACROS
#include <shlobj.h>
typedef struct qSHARDAPPIDINFOLINK {
@ -2413,15 +2441,24 @@ typedef struct {
} qOPENASINFO;
HRESULT (WINAPI *pSHOpenWithDialog)(HWND hwndParent, const qOPENASINFO *poainfo);
LPITEMIDLIST (STDAPICALLTYPE *pSHBrowseForFolderW)(LPBROWSEINFOW lpbi);
BOOL (STDAPICALLTYPE *pSHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath);
BOOL (STDAPICALLTYPE *pSHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
BOOL (STDAPICALLTYPE *pShell_NotifyIconW)(DWORD dwMessage, PNOTIFYICONDATAW lpData);
void Win7_Init(void)
{
HANDLE h;
HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
h = LoadLibraryW(L"shell32.dll");
h = LoadLibraryU("shell32.dll");
if (h)
{
pSHBrowseForFolderW = (void*)GetProcAddress(h, "SHBrowseForFolderW");
pSHGetPathFromIDListW = (void*)GetProcAddress(h, "SHGetPathFromIDListW");
pSHGetSpecialFolderPathW = (void*)GetProcAddress(h, "SHGetSpecialFolderPathW");
pShell_NotifyIconW = (void*)GetProcAddress(h, "Shell_NotifyIconW");
pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog");
pSetCurrentProcessExplicitAppUserModelID = (void*)GetProcAddress(h, "SetCurrentProcessExplicitAppUserModelID");
@ -2507,6 +2544,13 @@ void Win7_TaskListInit(void)
}
}
BOOL CopyFileU(const char *src, const char *dst, BOOL bFailIfExists)
{
wchar_t wide1[2048];
wchar_t wide2[2048];
return CopyFileW(widen(wide1, sizeof(wide1), src), widen(wide2, sizeof(wide2), dst), bFailIfExists);
}
//#define SVNREVISION 1
#if defined(SVNREVISION) && !defined(MINIMAL)
#define SVNREVISIONSTR STRINGIFY(SVNREVISION)
@ -3115,7 +3159,7 @@ static int Sys_ProcessCommandline(char **argv, int maxargc, char *argv0)
//using this like posix' access function, but with much more code, microsoftisms, and no errno codes/info
//no, I don't really have a clue why it needs to be so long.
#include <svrapi.h>
static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
static BOOL microsoft_accessW(LPWSTR pszFolder, DWORD dwAccessDesired)
{
HANDLE hToken;
PRIVILEGE_SET PrivilegeSet;
@ -3126,11 +3170,9 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
SECURITY_INFORMATION si = (SECURITY_INFORMATION)( OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION);
PSECURITY_DESCRIPTOR psdSD = NULL;
DWORD dwNeeded;
wchar_t wpath[MAX_OSPATH];
widen(wpath, sizeof(wpath), pszFolder);
GetFileSecurityW(wpath,si,NULL,0,&dwNeeded);
GetFileSecurityW(pszFolder,si,NULL,0,&dwNeeded);
psdSD = malloc(dwNeeded);
GetFileSecurityW(wpath,si,psdSD,dwNeeded,&dwNeeded);
GetFileSecurityW(pszFolder,si,psdSD,dwNeeded,&dwNeeded);
ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken);
memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING));
@ -3144,8 +3186,13 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
free(psdSD);
return fAccessGranted;
}
static BOOL microsoft_accessU(LPCSTR pszFolder, DWORD dwAccessDesired)
{
wchar_t wpath[MAX_OSPATH];
return microsoft_accessW(widen(wpath, sizeof(wpath), pszFolder), dwAccessDesired);
}
static int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
{
wchar_t widecaption[256];
wchar_t widetext[2048];
@ -3175,8 +3222,8 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
gah.ptDrag.x = gah.ptDrag.y = 0;
gah.hdr = fu->hdr;
gah.hdr.code = TVN_SELCHANGEDW;
r = CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProc(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
r = CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProcW(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
return r;
}
break;
@ -3191,8 +3238,8 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
gah.ptDrag.x = gah.ptDrag.y = 0;
gah.hdr = fu->hdr;
gah.hdr.code = TVN_SELCHANGEDA;
r = CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProc(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
r = CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProcW(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
return r;
}
break;
@ -3202,7 +3249,7 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
}
break;
}
return CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp);
return CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
}
struct egadsthisisretarded
@ -3213,11 +3260,20 @@ struct egadsthisisretarded
char statustext[MAX_OSPATH];
};
void FS_Directorize(char *fname, size_t fnamesize)
{
size_t l = strlen(fname);
if (!l) //technically already a directory
return;
if (fname[l-1] == '\\' || fname[l-1] == '/')
return; //already a directory
Q_strncatz(fname, "/", fnamesize);
}
static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pDatafoo)
{ //'stolen' from microsoft's knowledge base.
//required to work around microsoft being annoying.
struct egadsthisisretarded *pData = (struct egadsthisisretarded*)pDatafoo;
TCHAR szDir[MAX_PATH];
// char *foo;
HWND edit = FindWindowEx(hwnd, NULL, "EDIT", NULL);
HWND list;
@ -3226,8 +3282,6 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
switch(uMsg)
{
case BFFM_INITIALIZED:
OutputDebugStringA("initialised\n");
//combat windows putting new windows behind everything else if it takes a while for UAC prompts to go away
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
@ -3236,53 +3290,68 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
if (list)
omgwtfwhyohwhy = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (LONG_PTR)stoopidstoopidstoopid);
{
wchar_t szDir[MAX_PATH];
#ifndef _DEBUG
//the standard location iiuc
if (com_homepathenabled && SHGetSpecialFolderPath(NULL, szDir, CSIDL_PROGRAM_FILES, TRUE) && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
if (com_homepathenabled && pSHGetSpecialFolderPathW(NULL, szDir, CSIDL_PROGRAM_FILES, TRUE) && microsoft_accessW(szDir, ACCESS_READ | ACCESS_WRITE))
;
else if (microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
Q_strncpyz(szDir, "C:\\Games\\", sizeof(szDir));
else if (microsoft_access("C:\\", ACCESS_READ | ACCESS_WRITE))
Q_strncpyz(szDir, "C:\\", sizeof(szDir));
else if (microsoft_accessU("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
widen(szDir, sizeof(szDir), "C:\\Games\\");
else if (microsoft_accessU("C:\\", ACCESS_READ | ACCESS_WRITE))
widen(szDir, sizeof(szDir), "C:\\");
//if we're not an admin, install it somewhere else.
else if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_LOCAL_APPDATA, TRUE) && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
else if (pSHGetSpecialFolderPathW(NULL, szDir, CSIDL_LOCAL_APPDATA, TRUE) && microsoft_accessW(szDir, ACCESS_READ | ACCESS_WRITE))
;
else
#endif
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir))// && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
if (GetCurrentDirectoryW(countof(szDir), szDir))// && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir);
// SendMessage(hwnd, BFFM_SETEXPANDED, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETOKTEXT, TRUE, (LPARAM)L"Install");
SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETEXPANDED, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETOKTEXT, TRUE, (LPARAM)widen(szDir, sizeof(szDir), "Install"));
}
break;
case BFFM_VALIDATEFAILEDA:
if (!microsoft_access(pData->parentdir, ACCESS_READ | ACCESS_WRITE))
return 1;
if (edit)
GetWindowText(edit, pData->subdir, sizeof(pData->subdir));
if (microsoft_access(va("%s\\%s", pData->parentdir, pData->subdir), ACCESS_READ))
return MessageBoxU(hwnd, va("%s\\%s already exists!\nThis installer will (generally) not overwrite.\nIf you want to re-install, you must manually uninstall it first.\n\nContinue?", pData->parentdir, pData->subdir), fs_gamename.string, MB_ICONWARNING|MB_OKCANCEL|MB_TOPMOST) == IDCANCEL;
else
return MessageBoxU(hwnd, va("Install to %s\\%s ?", pData->parentdir, pData->subdir), fs_gamename.string, MB_OKCANCEL) == IDCANCEL;
case BFFM_VALIDATEFAILEDW:
return 1;//!microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
case BFFM_SELCHANGED:
OutputDebugStringA("selchanged\n");
if (SHGetPathFromIDList((LPITEMIDLIST)lp, pData->parentdir))
if (!microsoft_accessU(pData->parentdir, ACCESS_READ | ACCESS_WRITE))
{
// OutputDebugString(va("selchanged: %s\n", szDir));
// while(foo = strchr(pData->parentdir, '\\'))
// *foo = '/';
//fixme: verify that id1 is a subdir perhaps?
MessageBoxU(hwnd, va("%s is not writable.", pData->parentdir), fs_gamename.string, 0);
return 1;
}
if (edit)
{
wchar_t wide[256];
GetWindowTextW(edit, wide, countof(wide));
narrowen(pData->subdir, sizeof(pData->subdir), wide);
}
if (microsoft_accessU(va("%s%s", pData->parentdir, pData->subdir), ACCESS_READ))
return MessageBoxU(hwnd, va("%s%s already exists!\nThis installer will (generally) not overwrite existing data files.\nIf you want to re-install, you must manually uninstall it first.\n\nContinue?", pData->parentdir, pData->subdir), fs_gamename.string, MB_ICONWARNING|MB_OKCANCEL|MB_TOPMOST) == IDCANCEL;
else
return MessageBoxU(hwnd, va("Install to %s%s ?", pData->parentdir, pData->subdir), fs_gamename.string, MB_OKCANCEL) == IDCANCEL;
case BFFM_SELCHANGED:
{
wchar_t wide[MAX_PATH*2+2];
char *foo;
if (pSHGetPathFromIDListW((LPITEMIDLIST)lp, wide))
{
narrowen(pData->parentdir, sizeof(pData->parentdir), wide);
FS_Directorize(pData->parentdir, sizeof(pData->parentdir));
//this'll make microsoft happy.
while(foo = strchr(pData->parentdir, '/'))
*foo = '\\';
if (edit)
{
wchar_t wide[128];
SetWindowTextW(edit, widen(wide, sizeof(wide), fs_gamename.string));
SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s", pData->parentdir));
SendMessageW(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)widen(wide, sizeof(wide), va("%s", pData->parentdir)));
}
else
SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s/%s", pData->parentdir, fs_gamename.string));
SendMessageW(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)widen(wide, sizeof(wide), va("%s%s", pData->parentdir, fs_gamename.string)));
}
}
break;
case BFFM_IUNKNOWN:
@ -3298,16 +3367,6 @@ LRESULT CALLBACK NoCloseWindowProc(HWND w, UINT m, WPARAM wp, LPARAM lp)
return DefWindowProc(w, m, wp, lp);
}
void FS_Directorize(char *fname, size_t fnamesize)
{
size_t l = strlen(fname);
if (!l) //technically already a directory
return;
if (fname[l-1] == '\\' || fname[l-1] == '/')
return; //already a directory
Q_strncatz(fname, "/", fnamesize);
}
void FS_CreateBasedir(const char *path);
qboolean Sys_DoInstall(void)
{
@ -3315,22 +3374,31 @@ qboolean Sys_DoInstall(void)
char exepath[MAX_OSPATH];
char newexepath[MAX_OSPATH];
wchar_t wide[MAX_PATH];
wchar_t wide2[MAX_PATH];
char resultpath[MAX_OSPATH];
BROWSEINFOW bi;
LPITEMIDLIST il;
struct egadsthisisretarded diediedie;
if (!pSHGetSpecialFolderPathW)
{
MessageBoxU(NULL, "SHGetSpecialFolderPathW is not supported\n", fs_gamename.string, 0);
return TRUE;
}
if (fs_manifest && fs_manifest->eula)
{
if (MessageBoxU(NULL, fs_manifest->eula, fs_gamename.string, MB_OKCANCEL|MB_TOPMOST|MB_DEFBUTTON2) != IDOK)
return TRUE;
}
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir));
_snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
GetCurrentDirectoryW(countof(wide)-1, wide);
memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL;
_snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
GetCurrentDirectoryW(countof(wide)-1, wide);
bi.pszDisplayName = wide;
bi.lpszTitle = diediedie.title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE;
@ -3338,12 +3406,10 @@ qboolean Sys_DoInstall(void)
bi.lParam = (LPARAM)&diediedie;
bi.iImage = 0;
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir));
il = SHBrowseForFolderW(&bi);
il = pSHBrowseForFolderW?pSHBrowseForFolderW(&bi):NULL;
if (il)
{
SHGetPathFromIDListW(il, wide);
pSHGetPathFromIDListW(il, wide);
CoTaskMemFree(il);
}
else
@ -3359,9 +3425,10 @@ qboolean Sys_DoInstall(void)
FS_CreateBasedir(resultpath);
GetModuleFileName(NULL, exepath, sizeof(exepath));
GetModuleFileNameW(NULL, wide, countof(wide));
narrowen(exepath, sizeof(exepath), wide);
FS_NativePath(va("%s.exe", fs_gamename.string), FS_ROOT, newexepath, sizeof(newexepath));
CopyFile(exepath, newexepath, FALSE);
CopyFileU(exepath, newexepath, FALSE);
/*the game can now be run (using regular autoupdate stuff), but most installers are expected to install the data instead of just more downloaders, so lets do that with a 'nice' progress box*/
{
@ -3453,13 +3520,15 @@ qboolean Sys_DoInstall(void)
widen(wsz, sizeof(wsz), resultpath);
psl->lpVtbl->SetWorkingDirectory(psl, wsz);
hres = psl->lpVtbl->QueryInterface(psl, &qIID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres) && SHGetSpecialFolderPath(NULL, startmenu, CSIDL_COMMON_PROGRAMS, TRUE))
if (SUCCEEDED(hres) && pSHGetSpecialFolderPathW(NULL, wsz, CSIDL_COMMON_PROGRAMS, TRUE))
{
WCHAR wsz[MAX_PATH];
narrowen(startmenu, sizeof(startmenu), wsz);
widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string));
hres = ppf->lpVtbl->Save(ppf, wsz, TRUE);
if (hres == E_ACCESSDENIED && SHGetSpecialFolderPath(NULL, startmenu, CSIDL_PROGRAMS, TRUE))
if (hres == E_ACCESSDENIED && pSHGetSpecialFolderPathW(NULL, wsz, CSIDL_PROGRAMS, TRUE))
{
narrowen(startmenu, sizeof(startmenu), wsz);
widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string));
hres = ppf->lpVtbl->Save(ppf, wsz, TRUE);
}
@ -3470,7 +3539,7 @@ qboolean Sys_DoInstall(void)
}
//now start it up properly.
ShellExecute(mainwindow, "open", newexepath, Q_strcasecmp(fs_manifest->installation, "quake")?"":"+sys_register_file_associations", resultpath, SW_SHOWNORMAL);
ShellExecuteW(mainwindow, L"open", widen(wide, sizeof(wide), newexepath), Q_strcasecmp(fs_manifest->installation, "quake")?L"":L"+sys_register_file_associations", widen(wide2, sizeof(wide2), resultpath), SW_SHOWNORMAL);
return true;
}
qboolean Sys_RunInstaller(void)
@ -3742,11 +3811,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
memset(&parms, 0, sizeof(parms));
#ifndef MINGW
#if _MSC_VER > 1200
// #ifndef MINGW
// #if _MSC_VER > 1200
Win7_Init();
#endif
#endif
// #endif
// #endif
#ifdef _MSC_VER
#if _M_IX86_FP >= 1
@ -3781,11 +3850,16 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#endif
#ifdef CATCHCRASH
LoadLibraryA ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance.
LoadLibraryU ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance.
#ifdef _MSC_VER
__try
#else
AddVectoredExceptionHandler(true, nonmsvc_CrashExceptionHandler);
{
PVOID (WINAPI *pAddVectoredExceptionHandler)(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
dllfunction_t dbgfuncs[] = {{(void*)&pAddVectoredExceptionHandler, "AddVectoredExceptionHandler"}, {NULL,NULL}};
if (Sys_LoadLibrary("kernel32.dll", dbgfuncs) && pAddVectoredExceptionHandler)
pAddVectoredExceptionHandler(0, nonmsvc_CrashExceptionHandler);
}
#endif
#endif
{

View file

@ -252,7 +252,7 @@ static qboolean EditorSaveFile(char *s) //returns true if succesful
pos++;
}
COM_WriteFile(s, data, len);
COM_WriteFile(s, FS_GAMEONLY, data, len);
madechanges = false;
editenabled = true;

View file

@ -4,7 +4,7 @@
#include "shader.h"
#ifdef _WIN32
#include <windows.h>
#include "winquake.h"
#include "resource.h"
#else
#include <unistd.h>
@ -68,6 +68,9 @@ LRESULT CALLBACK HeadlessWndProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lpara
}
return 0;
default:
if (WinNT)
return DefWindowProcW(wnd, msg, wparam, lparam);
else
return DefWindowProcA(wnd, msg, wparam, lparam);
}
}
@ -79,6 +82,8 @@ static qboolean Headless_VID_Init (rendererstate_t *info, unsigned char *pale
//tray icon crap, so the user can still restore the game.
extern HWND mainwindow;
extern HINSTANCE global_hInstance;
if (WinNT)
{
WNDCLASSW wc;
NOTIFYICONDATAW data;
@ -103,7 +108,38 @@ static qboolean Headless_VID_Init (rendererstate_t *info, unsigned char *pale
data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon;
wcscpy(data.szTip, L"Right-click to restore");
Shell_NotifyIconW(NIM_ADD, &data);
if (pShell_NotifyIconW)
pShell_NotifyIconW(NIM_ADD, &data);
}
else
{
WNDCLASSA wc;
NOTIFYICONDATAA data;
//Shell_NotifyIcon requires a window to provide events etc.
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)HeadlessWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "FTEHeadlessClass";
RegisterClassA(&wc);
mainwindow = CreateWindowExA(0L, wc.lpszClassName, "FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL);
data.cbSize = sizeof(data);
data.hWnd = mainwindow;
data.uID = 0;
data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon;
//fixme: proper multibyte
Q_strncpyz(data.szTip, "Right-click to restore", sizeof(data.szTip));
Shell_NotifyIconA(NIM_ADD, &data);
}
#endif
return true;
}
@ -111,6 +147,7 @@ static void Headless_VID_DeInit (void)
{
#ifdef _WIN32
//tray icon crap, so the user can still restore the game.
//FIXME: remove tray icon. win95 won't do this automagically.
extern HWND mainwindow;
DestroyWindow(mainwindow);
mainwindow = NULL;

View file

@ -574,12 +574,22 @@ When you run over an item, the server sends this command
void V_BonusFlash_f (void)
{
if (v_bonusflash.value || !Cmd_FromGamecode())
{
if (Cmd_Argc() > 1)
{ //this is how I understand DP expects them.
cl.cshifts[CSHIFT_BONUS].destcolor[0] = atof(Cmd_Argv(1));
cl.cshifts[CSHIFT_BONUS].destcolor[1] = atof(Cmd_Argv(2));
cl.cshifts[CSHIFT_BONUS].destcolor[2] = atof(Cmd_Argv(3));
cl.cshifts[CSHIFT_BONUS].percent = atof(Cmd_Argv(4))*255*v_bonusflash.value;
}
else
{
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
cl.cshifts[CSHIFT_BONUS].percent = 50*v_bonusflash.value;
}
}
}
void V_DarkFlash_f (void)
{
@ -1544,7 +1554,8 @@ void R_DrawNameTags(void)
e = WEDICT_NUM(w->progs, i);
if (e->isfree)
continue;
VectorInterpolate(e->v->absmin, 0.5, e->v->absmax, org);
VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
VectorAdd(org, e->v->origin, org);
VectorSubtract(org, r_refdef.vieworg, diff);
if (DotProduct(diff, diff) > 256*256)
continue;

View file

@ -74,6 +74,16 @@ LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
//shell32 stuff that doesn't exist in win95
#define COBJMACROS
#include <shlobj.h>
#include <shellapi.h>
extern LPITEMIDLIST (STDAPICALLTYPE *pSHBrowseForFolderW)(LPBROWSEINFOW lpbi);
extern BOOL (STDAPICALLTYPE *pSHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath);
extern BOOL (STDAPICALLTYPE *pSHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
extern BOOL (STDAPICALLTYPE *pShell_NotifyIconW)(DWORD dwMessage, PNOTIFYICONDATAW lpData);
//void VID_LockBuffer (void);
//void VID_UnlockBuffer (void);

View file

@ -528,8 +528,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ARCH_DL_POSTFIX ".so"
#endif
#if defined(__amd64__)
#define ARCH_CPU_POSTFIX "amd"
#if defined(_M_AMD64) || defined(__amd64__)
#ifdef _WIN32
#define ARCH_CPU_POSTFIX "x64"
#else
#define ARCH_CPU_POSTFIX "amd64"
#endif
#elif defined(_M_IX86) || defined(__i386__)
#define ARCH_CPU_POSTFIX "x86"
#elif defined(__powerpc__) || defined(__ppc__)

View file

@ -581,6 +581,20 @@ void Cmd_Exec_f (void)
int defdepth = COM_FDepthFile("default.cfg", true);
if (defdepth < cfgdepth)
Cbuf_InsertText("exec default.cfg\n", ((Cmd_FromGamecode() || untrusted) ? RESTRICT_INSECURE : Cmd_ExecLevel), false);
//hack to work around the more insideous hacks of other engines.
//namely: vid_restart at the end of config.cfg is evil, and NOT desired in FTE as it generally means any saved video settings are wrong.
if (l >= 13 && !strcmp(f+l-13, "\nvid_restart\n"))
{
Con_Printf(CON_WARNING "WARNING: %s came from a different engine\n", loc.rawname);
l -= 12;
}
else if (l >= 14 && !strcmp(f+l-14, "\nvid_restart\r\n"))
{
Con_Printf(CON_WARNING "WARNING: %s came from a different engine\n", loc.rawname);
l -= 13;
}
f[l] = 0;
}
// don't execute anything if it was from server (either the stuffcmd/localcmd, or the file)
if (!strcmp(name, "default.cfg") && !(Cmd_FromGamecode() || untrusted))

View file

@ -5065,6 +5065,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
int bonemap[MAX_BONES];
char *e;
size_t psasize;
void *psabuffer;
pskpnts_t *pnts = NULL;
pskvtxw_t *vtxw = NULL;
@ -5205,13 +5206,14 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
/*attempt to load a psa file. don't die if we can't find one*/
COM_StripExtension(mod->name, psaname, sizeof(psaname));
Q_strncatz(psaname, ".psa", sizeof(psaname));
buffer = COM_LoadFile(psaname, 5, &psasize);
if (buffer)
buffer = NULL;//test
psabuffer = COM_LoadFile(psaname, 5, &psasize);
if (psabuffer)
{
pos = 0;
while (pos < psasize && !fail)
{
chunk = (pskchunk_t*)((char*)buffer + pos);
chunk = (pskchunk_t*)((char*)psabuffer + pos);
chunk->version = LittleLong(chunk->version);
chunk->recordsize = LittleLong(chunk->recordsize);
chunk->numrecords = LittleLong(chunk->numrecords);
@ -5224,7 +5226,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("BONENAMES", chunk->id) && chunk->recordsize == sizeof(pskboneinfo_t))
{
/*parsed purely to ensure that the bones match the main model*/
pskboneinfo_t *animbones = (pskboneinfo_t*)((char*)buffer + pos);
pskboneinfo_t *animbones = (pskboneinfo_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords;
if (num_boneinfo != chunk->numrecords)
{
@ -5262,7 +5264,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t))
{
num_animinfo = chunk->numrecords;
animinfo = (pskaniminfo_t*)((char*)buffer + pos);
animinfo = (pskaniminfo_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords;
for (i = 0; i < num_animinfo; i++)
@ -5277,7 +5279,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("ANIMKEYS", chunk->id) && chunk->recordsize == sizeof(pskanimkeys_t))
{
num_animkeys = chunk->numrecords;
animkeys = (pskanimkeys_t*)((char*)buffer + pos);
animkeys = (pskanimkeys_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords;
for (i = 0; i < num_animkeys; i++)
@ -5317,11 +5319,11 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
num_animkeys = 0;
fail = false;
}
BZ_Free(buffer);
}
if (fail)
{
BZ_Free(psabuffer);
return false;
}
@ -5613,6 +5615,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
gmdl[i].nextsurf = (i != num_matt-1)?&gmdl[i+1]:NULL;
}
BZ_Free(psabuffer);
if (fail)
{
return false;

View file

@ -2271,7 +2271,8 @@ unsigned int qchar_encode(char *out, unsigned int unicode, int maxlen, qboolean
{
static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
//FIXME: is it a bug that we can't distinguish between true ascii and 0xe0XX ?
if (((unicode >= 32 || unicode == '\n' || unicode == '\t' || unicode == '\r') && unicode < 128) || (unicode >= 0xe000 && unicode <= 0xe0ff))
//ntrv are considered special by parsefunstring and are not remapped back to the quake glyphs, so try to keep them as quake glyphs where possible
if (((unicode >= 32 || unicode == '\n' || unicode == '\t' || unicode == '\r') && unicode < 128) || (unicode >= 0xe000 && unicode <= 0xe0ff && unicode != (0xe000|'\n') && unicode != (0xe000|'\t') && unicode != (0xe000|'\r') && unicode != (0xe000|'\v')))
{ //quake compatible chars
if (maxlen < 1)
return 0;
@ -2965,7 +2966,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
while(*str)
{
if (*str & 0x80 && utf8 > 0)
if ((*str & 0x80) && utf8 > 0)
{ //check for utf-8
int decodeerror;
char *end;

View file

@ -344,8 +344,6 @@ extern char com_homepath[MAX_OSPATH];
extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in
//extern char *com_basedir;
void COM_WriteFile (const char *filename, const void *data, int len);
//qofs_Make is used to 'construct' a variable of qofs_t type. this is so the code can merge two 32bit ints on old systems and use a long long type internally without generating warnings about bit shifts when qofs_t is only 32bit instead.
#if defined(__amd64__) || defined(_AMD64_) || __WORDSIZE == 64
#define FS_64BIT
@ -443,6 +441,8 @@ enum fs_relative{
FS_SYSTEM //a system path. absolute paths are explicitly allowed and expected.
};
void COM_WriteFile (const char *filename, enum fs_relative fsroot, const void *data, int len);
void FS_FlushFSHashReally(qboolean domutexes);
void FS_FlushFSHashWritten(void);
void FS_FlushFSHashRemoved(void);
@ -458,9 +458,9 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
vfsfile_t *FS_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
#define countof(array) (sizeof(array)/sizeof(array[0]))
#ifdef _WIN32
//windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything.
#define countof(array) (sizeof(array)/sizeof(array[0]))
char *narrowen(char *out, size_t outlen, wchar_t *wide);
wchar_t *widen(wchar_t *out, size_t outbytes, const char *utf8);
#define __L(x) L ## x

View file

@ -740,6 +740,7 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
if (var->latched_string && !strcmp(var->latched_string, value)) //no point, this would force the same
return NULL;
Cvar_ConfigChanged();
if (var->latched_string)
Z_Free(var->latched_string);
if (!strcmp(var->string, value)) //latch to the original value? remove the latch.

View file

@ -581,7 +581,7 @@ COM_Path_f
*/
static void COM_PathLine(searchpath_t *s)
{
Con_Printf("%s %s%s%s%s%s%s\n", s->logicalpath,
Con_Printf(U8("%s")" %s%s%s%s%s%s\n", s->logicalpath,
(s->flags & SPF_REFERENCED)?"^[(ref)\\tip\\Referenced\\desc\\Package will auto-download to clients^]":"",
(s->flags & SPF_TEMPORARY)?"^[(temp)\\tip\\Temporary\\desc\\Flushed on map change^]":"",
(s->flags & SPF_COPYPROTECTED)?"^[(c)\\tip\\Copyrighted\\desc\\Copy-Protected and is not downloadable^]":"",
@ -672,15 +672,18 @@ COM_Locate_f
void COM_Locate_f (void)
{
flocation_t loc;
if (FS_FLocateFile(Cmd_Argv(1), FSLFRT_LENGTH, &loc)>=0)
char *f = Cmd_Argv(1);
if (strchr(f, '^')) //fte's filesystem is assumed to be utf-8, but that doesn't mean that console input is. and I'm too lazy to utf-8ify the string (in part because markup can be used to exploit ascii assumptions).
Con_Printf("Warning: filename contains markup. If this is because of unicode, set com_parseutf8 1\n");
if (FS_FLocateFile(f, FSLFRT_LENGTH, &loc)>=0)
{
if (!*loc.rawname)
{
Con_Printf("File is %u bytes compressed inside %s\n", (unsigned)loc.len, loc.search->logicalpath);
Con_Printf("File is %u bytes compressed inside "U8("%s")"\n", (unsigned)loc.len, loc.search->logicalpath);
}
else
{
Con_Printf("Inside %s (%u bytes)\n %s\n", loc.rawname, (unsigned)loc.len, loc.search->logicalpath);
Con_Printf("Inside "U8("%s")" (%u bytes)\n "U8("%s")"\n", loc.rawname, (unsigned)loc.len, loc.search->logicalpath);
}
}
else
@ -694,14 +697,14 @@ COM_WriteFile
The filename will be prefixed by the current game directory
============
*/
void COM_WriteFile (const char *filename, const void *data, int len)
void COM_WriteFile (const char *filename, enum fs_relative fsroot, const void *data, int len)
{
vfsfile_t *vfs;
Sys_Printf ("COM_WriteFile: %s\n", filename);
FS_CreatePath(filename, FS_GAMEONLY);
vfs = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs)
{
VFS_WRITE(vfs, data, len);
@ -928,7 +931,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
{
int depth=0;
searchpath_t *search;
char cleanpath[MAX_QPATH];
char cleanpath[MAX_OSPATH];
flocation_t allownoloc;
void *pf;
@ -3158,7 +3161,6 @@ void FS_ReloadPackFiles_f(void)
#ifdef MINGW
#define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile.
#endif
#include <shlobj.h>
static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname)
{
/*
@ -3209,7 +3211,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
case BFFM_VALIDATEFAILEDW:
break; //FIXME: validate that the gamedir contains what its meant to
case BFFM_SELCHANGED:
if (SHGetPathFromIDListW((LPITEMIDLIST) lp, szDir))
if (pSHGetPathFromIDListW((LPITEMIDLIST) lp, szDir))
{
wchar_t statustxt[MAX_OSPATH];
while(foo = wcschr(szDir, '\\'))
@ -3225,6 +3227,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
}
return 0;
}
int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType);
#endif
qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname)
@ -3242,6 +3245,10 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
widen(resultpath, sizeof(resultpath), poshname);
_snwprintf(title, countof(title), L"Please locate your existing %s installation", resultpath);
//force mouse to deactivate, so that we can actually see it.
INS_UpdateGrabs(false, false);
bi.lpszTitle = title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
@ -3249,33 +3256,16 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
bi.lParam = 0;//(LPARAM)poshname;
bi.iImage = 0;
//force mouse to deactivate, so that we can actually see it.
INS_UpdateGrabs(false, false);
il = SHBrowseForFolderW(&bi);
il = pSHBrowseForFolderW?pSHBrowseForFolderW(&bi):NULL;
if (il)
{
SHGetPathFromIDListW(il, resultpath);
pSHGetPathFromIDListW(il, resultpath);
CoTaskMemFree(il);
narrowen(basepath, basepathsize, resultpath);
if (savedname)
{
HKEY key = NULL;
//and save it into the windows registry
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\" _L(FULLENGINENAME) L"\\GamePaths",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
NULL) == ERROR_SUCCESS)
{
wchar_t wsavedname[MAX_OSPATH];
widen(wsavedname, sizeof(wsavedname), savedname);
RegSetValueExW(key, wsavedname, 0, REG_SZ, (BYTE*)resultpath, sizeof(wchar_t)*wcslen(resultpath));
RegCloseKey(key);
}
if (MessageBoxU(mainwindow, va("Would you like to save the location of %s as:\n%s", poshname, resultpath), "Save Instaltion path", MB_YESNO|MB_DEFBUTTON2) == IDYES)
MyRegSetValue(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", savedname, REG_SZ, basepath, strlen(basepath));
}
return true;
}

View file

@ -328,12 +328,13 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
if (!WinNT)
{
//FILE_SHARE_DELETE is not supported in 9x, sorry.
if ((write && read) || append)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (write)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (read)
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
else
h = INVALID_HANDLE_VALUE;
}
@ -341,7 +342,6 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), osname);
h = INVALID_HANDLE_VALUE;
if (write || append)
{

View file

@ -116,10 +116,12 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
bmaxs[i] = ceil(maxs[i]/(1<<s->lmshift));
s->texturemins[i] = bmins[i] << s->lmshift;
s->extents[i] = (bmaxs[i] - bmins[i]) << s->lmshift;
s->extents[i] = (bmaxs[i] - bmins[i]);
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 8176 ) //q2 uses 512. probably for skys.
// Con_Printf ("Bad surface extents (texture %s)\n", s->texinfo->texture->name);
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 17 ) //vanilla used 16(+1), glquake used 17(+1). FTE uses 255(+1), but we omit lightmapping instead of crashing if its larger than our limit, so we omit the check here. different engines use different limits here, many of them make no sense.
// Con_Printf ("Bad surface extents (texture %s, more than %i lightmap samples)\n", s->texinfo->texture->name, s->extents[i]);
s->extents[i] <<= s->lmshift;
}
}

View file

@ -902,7 +902,7 @@ void PM_CategorizePosition (void)
pmove.onground = false;
else
{
pmove.onground = true;
pmove.onground = !trace.startsolid;
pmove.groundent = trace.entnum;
groundplane = trace.plane;
pmove.waterjumptime = 0;
@ -1273,8 +1273,8 @@ were contacted during the move.
*/
void PM_PlayerMove (float gamespeed)
{
int i;
int tmp; //for rounding
// int i;
// int tmp; //for rounding
frametime = pmove.cmd.msec * 0.001*gamespeed;
pmove.numtouch = 0;
@ -1337,7 +1337,7 @@ void PM_PlayerMove (float gamespeed)
else
PM_AirMove ();
//round to network precision
/* //round to network precision
for (i = 0; i < 3; i++)
{
tmp = floor(pmove.velocity[i]*8 + 0.5);
@ -1346,7 +1346,7 @@ void PM_PlayerMove (float gamespeed)
pmove.origin[i] = tmp/8.0;
}
PM_NudgePosition ();
*/
// set onground, watertype, and waterlevel for final spot
PM_CategorizePosition ();

View file

@ -514,7 +514,7 @@ pbool QDECL QC_WriteFile(const char *name, void *data, int len)
{
char buffer[256];
Q_snprintfz(buffer, sizeof(buffer), "%s", name);
COM_WriteFile(buffer, data, len);
COM_WriteFile(buffer, FS_GAMEONLY, data, len);
return true;
}
@ -1879,7 +1879,7 @@ void PF_fclose_i (int fnum)
switch(pf_fopen_files[fnum].accessmode)
{
case FRIK_FILE_MMAP_RW:
COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
COM_WriteFile(pf_fopen_files[fnum].name, FS_GAMEONLY, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
/*fall through*/
case FRIK_FILE_MMAP_READ:
pf_fopen_files[fnum].prinst->AddressableFree(pf_fopen_files[fnum].prinst, pf_fopen_files[fnum].data);
@ -1891,7 +1891,7 @@ void PF_fclose_i (int fnum)
break;
case 1:
case 2:
COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
COM_WriteFile(pf_fopen_files[fnum].name, FS_GAMEONLY, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
BZ_Free(pf_fopen_files[fnum].data);
break;
case 3:
@ -2859,7 +2859,7 @@ void QCBUILTIN PF_chr2str (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
{
ch = G_FLOAT(OFS_PARM0 + i*3);
if (VMUTF8 || ch > 0xff)
s += unicode_encode(s, ch, (string+sizeof(string)-1)-s, VMUTF8MARKUP);
s += unicode_encode(s, ch, (string+sizeof(string)-1)-s, VMUTF8MARKUP||(ch>0xff));
else
*s++ = G_FLOAT(OFS_PARM0 + i*3);
}
@ -4818,7 +4818,7 @@ void QCBUILTIN PF_coredump (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
prinst->save_ents(prinst, buffer, &size, size, 3);
COM_WriteFile("core.txt", buffer, size);
COM_WriteFile("core.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}
void QCBUILTIN PF_eprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)

View file

@ -382,6 +382,7 @@ void QCBUILTIN PF_cl_GetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr
void QCBUILTIN PF_cl_SetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommandex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View file

@ -102,7 +102,7 @@ void VM_fclose (int fnum, int owner)
case VM_FS_WRITE:
case VM_FS_APPEND:
case VM_FS_APPEND2:
COM_WriteFile(vm_fopen_files[fnum].name, vm_fopen_files[fnum].data, vm_fopen_files[fnum].len);
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;
}

View file

@ -85,7 +85,12 @@ unsigned int WINAPI threadwrapper(void *args)
Sys_SetThreadName(GetCurrentThreadId(), ((threadwrap_t *)args)->name);
#endif
#ifdef CATCHCRASH
AddVectoredExceptionHandler(true, nonmsvc_CrashExceptionHandler);
{
PVOID (WINAPI *pAddVectoredExceptionHandler)(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
dllfunction_t dbgfuncs[] = {{(void*)&pAddVectoredExceptionHandler, "AddVectoredExceptionHandler"}, {NULL,NULL}};
if (Sys_LoadLibrary("kernel32.dll", dbgfuncs) && pAddVectoredExceptionHandler)
pAddVectoredExceptionHandler(0, nonmsvc_CrashExceptionHandler);
}
#endif
free(args);
@ -177,7 +182,7 @@ void *Sys_CreateMutex(void)
return (void *)mutex;
}
qboolean Sys_TryLockMutex(void *mutex)
/*qboolean Sys_TryLockMutex(void *mutex)
{
#ifdef _DEBUG
if (!mutex)
@ -196,7 +201,7 @@ qboolean Sys_TryLockMutex(void *mutex)
return true;
}
return false;
}
}*/
qboolean Sys_LockMutex(void *mutex)
{

View file

@ -595,13 +595,13 @@ static void initD3D9(HWND hWnd, rendererstate_t *info)
d3d9dll = LoadLibrary("d3d9.dll");
if (!d3d9dll)
{
Con_Printf("Direct3d 9 does not appear to be installed\n");
Con_Printf(CON_ERROR "Direct3d 9 does not appear to be installed\n");
return;
}
pDirect3DCreate9 = (void*)GetProcAddress(d3d9dll, "Direct3DCreate9");
if (!pDirect3DCreate9)
{
Con_Printf("Direct3d 9 does not appear to be installed properly\n");
Con_Printf(CON_ERROR "Direct3d 9 does not appear to be installed properly\n");
return;
}

View file

@ -582,9 +582,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (!sk->qwskin && *sk->qwskinname)
sk->qwskin = Skin_Lookup(sk->qwskinname);
if (sk->q1lower != Q1UNSPECIFIED)
bc = sk->q1lower;
bc = e->bottomcolour = sk->q1lower;
if (sk->q1upper != Q1UNSPECIFIED)
bc = sk->q1upper;
bc = e->topcolour = sk->q1upper;
plskin = sk->qwskin;
}
}
@ -610,7 +610,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (!gl_nocolors.ival || forced)
{
if (!plskin || plskin->loadstate == SKIN_FAILED)
if (plskin && plskin->loadstate == SKIN_LOADING)
plskin = NULL;
else if (!plskin || plskin->loadstate != SKIN_LOADED)
{
if (e->playerindex >= 0 && e->playerindex <= MAX_CLIENTS)
{

View file

@ -6620,7 +6620,7 @@ void Mod_Terrain_Create_f(void)
"origin \"0 0 1024\"\n"
"}\n"
, Cmd_Argv(2));
COM_WriteFile(mname, mdata, strlen(mdata));
COM_WriteFile(mname, FS_GAMEONLY, mdata, strlen(mdata));
//FIXME: create 4 sections around the origin
}

View file

@ -79,7 +79,8 @@ typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey,
extern cvar_t vid_conwidth, vid_conautoscale;
#define WINDOW_CLASS_NAME L"FTEGLQuake"
#define WINDOW_CLASS_NAME_W L"FTEGLQuake"
#define WINDOW_CLASS_NAME_A "FTEGLQuake"
#define MAX_MODE_LIST 128
#define VID_ROW_SIZE 3
@ -470,8 +471,10 @@ qboolean GLInitialise (char *renderer)
if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32"))
{
unsigned int emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/
Con_DPrintf ("Loading renderer dll \"%s\"", renderer);
hInstGL = Sys_LoadLibrary(opengldllname, NULL);
SetErrorMode(emode);
if (hInstGL)
{
usingminidriver = true;
@ -531,7 +534,7 @@ qboolean GLInitialise (char *renderer)
}
else
{
qwglSwapLayerBuffers = (void *)getwglfunc("wglSwapLayerBuffers");
qwglSwapLayerBuffers = NULL;//(void *)getwglfunc("wglSwapLayerBuffers");
qSwapBuffers = SwapBuffers;
qChoosePixelFormat = ChoosePixelFormat;
qSetPixelFormat = SetPixelFormat;
@ -765,9 +768,11 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight);
// Create the DIB window
if (WinNT)
{
dibwindow = CreateWindowExW (
ExWindowStyle,
WINDOW_CLASS_NAME,
WINDOW_CLASS_NAME_W,
_L(FULLENGINENAME),
WindowStyle,
WindowRect.left, WindowRect.top,
@ -777,6 +782,22 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
NULL,
global_hInstance,
NULL);
}
else
{
dibwindow = CreateWindowExA (
ExWindowStyle,
WINDOW_CLASS_NAME_A,
FULLENGINENAME,
WindowStyle,
WindowRect.left, WindowRect.top,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
sys_parentwindow,
NULL,
global_hInstance,
NULL);
}
if (!dibwindow)
{
@ -889,7 +910,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
gdevmode.dmBitsPerPel = info->bpp;
if (info->bpp && (gdevmode.dmBitsPerPel < 15))
{
Con_Printf("Forcing at least 16bpp\n");
Con_Printf("Forcing at least 15bpp\n");
gdevmode.dmBitsPerPel = 16;
}
gdevmode.dmDisplayFrequency = info->rate;
@ -899,7 +920,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
Con_SafePrintf((gdevmode.dmFields&DM_DISPLAYFREQUENCY)?"Windows rejected mode %i*%i*%i*%i\n":"Windows rejected mode %i*%i*%i\n", (int)gdevmode.dmPelsWidth, (int)gdevmode.dmPelsHeight, (int)gdevmode.dmBitsPerPel, (int)gdevmode.dmDisplayFrequency);
Con_SafePrintf((gdevmode.dmFields&DM_DISPLAYFREQUENCY)?"Windows rejected mode %i*%i*%ibpp@%ihz\n":"Windows rejected mode %i*%i*%ibpp\n", (int)gdevmode.dmPelsWidth, (int)gdevmode.dmPelsHeight, (int)gdevmode.dmBitsPerPel, (int)gdevmode.dmDisplayFrequency);
return false;
}
}
@ -927,9 +948,11 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
wheight = rect.bottom - rect.top;
// Create the DIB window
if(WinNT)
{
dibwindow = CreateWindowExW (
ExWindowStyle,
WINDOW_CLASS_NAME,
WINDOW_CLASS_NAME_W,
_L(FULLENGINENAME),
WindowStyle,
rect.left, rect.top,
@ -939,6 +962,22 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
NULL,
global_hInstance,
NULL);
}
else
{
dibwindow = CreateWindowExA (
ExWindowStyle,
WINDOW_CLASS_NAME_A,
FULLENGINENAME,
WindowStyle,
rect.left, rect.top,
wwidth,
wheight,
NULL,
NULL,
global_hInstance,
NULL);
}
if (!dibwindow)
Sys_Error ("Couldn't create DIB window");
@ -1002,6 +1041,8 @@ static void Win_Touch_Init(HWND wnd);
static qboolean CreateMainWindow(rendererstate_t *info)
{
qboolean stat;
if (WinNT)
{
WNDCLASSW wc;
/* Register the frame class */
wc.style = CS_OWNDC;
@ -1013,9 +1054,27 @@ static qboolean CreateMainWindow(rendererstate_t *info)
wc.hCursor = hArrowCursor;
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME;
wc.lpszClassName = WINDOW_CLASS_NAME_W;
if (!RegisterClassW (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
Con_Printf("RegisterClass failed\n");
}
else
{
WNDCLASSA wc;
/* Register the frame class */
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = hIcon;
wc.hCursor = hArrowCursor;
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME_A;
if (!RegisterClassA (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
Con_Printf("RegisterClass failed\n");
}
if (!info->fullscreen)
{
@ -2464,7 +2523,10 @@ LONG WINAPI GLMainWndProc (
default:
/* pass all unhandled messages to DefWindowProc */
if (WinNT)
lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
else
lRet = DefWindowProcA (hWnd, uMsg, wParam, lParam);
break;
}
@ -2521,7 +2583,10 @@ void GLVID_DeInit (void)
Cvar_Unhook(&vid_wndalpha);
Cmd_RemoveCommand("vid_recenter");
UnregisterClassW(WINDOW_CLASS_NAME, global_hInstance);
if (WinNT)
UnregisterClassW(WINDOW_CLASS_NAME_W, global_hInstance);
else
UnregisterClassA(WINDOW_CLASS_NAME_A, global_hInstance);
}
/*

View file

@ -491,7 +491,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
nl = strchr(msg, '\n');
if (nl)
*nl = '\0';
Con_Printf("HTTP: %s %s\n", buffer, COM_TrimString(msg, trimmed, sizeof(trimmed)));
Con_Printf("HTTP: %s %s (%s)\n", buffer, COM_TrimString(msg, trimmed, sizeof(trimmed)), Location);
if (!*Location)
Con_Printf("Server redirected to null location\n");
else
@ -1324,6 +1324,21 @@ void HTTP_CL_Think(void)
#endif
}
}
void HTTP_CL_Terminate(void)
{
struct dl_download *dl = activedownloads;
struct dl_download *next = NULL;
next = activedownloads;
activedownloads = NULL;
while (next)
{
dl = next;
next = dl->next;
DL_Close(dl);
}
HTTP_CL_Think();
}
#endif
#endif /*WEBCLIENT*/

View file

@ -150,6 +150,7 @@ struct dl_download
vfsfile_t *VFSPIPE_Open(void);
void HTTP_CL_Think(void);
void HTTP_CL_Terminate(void); //kills all active downloads
struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl));
struct dl_download *HTTP_CL_Put(const char *url, const char *mime, const char *data, size_t datalen, void (*NotifyFunction)(struct dl_download *dl));

View file

@ -559,6 +559,11 @@ extern pbool keyword_inline; //don't write the def to the output.
extern pbool keyword_strip; //don't write the def to the output.
extern pbool keyword_union; //you surly know what a union is!
extern pbool keyword_unused;
extern pbool keyword_used;
extern pbool keyword_static;
extern pbool keyword_nonstatic;
extern pbool keyword_ignore;
extern pbool keywords_coexist;
extern pbool output_parms;

View file

@ -50,6 +50,11 @@ pbool keyword_struct;
pbool keyword_var; //allow it to be initialised and set around the place.
pbool keyword_vector; //for skipping the local
pbool keyword_static;
pbool keyword_nonstatic;
pbool keyword_used;
pbool keyword_unused;
pbool keyword_enum; //kinda like in c, but typedef not supported.
pbool keyword_enumflags; //like enum, but doubles instead of adds 1.
@ -69,6 +74,7 @@ pbool keyword_noref; //nowhere else references this, don't strip it.
pbool keyword_nosave; //don't write the def to the output.
pbool keyword_inline;
pbool keyword_strip;
pbool keyword_ignore;
pbool keyword_union; //you surly know what a union is!
#define keyword_not 1 //hexenc support needs this, and fteqcc can optimise without it, but it adds an extra token after the if, so it can cause no namespace conflicts
@ -2038,6 +2044,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
case OP_LOADA_I:
{
QCC_sref_t nd = var_a;
QCC_FreeTemp(var_b);
nd.ofs += eval_b->_int;
//FIXME: case away the array...
return nd;
@ -2884,7 +2891,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
//a - (n * floor(a/n));
//(except using v|v instead of floor)
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], var_a, var_b, NULL, STFL_CONVERTA|STFL_CONVERTB|STFL_PRESERVEA|STFL_PRESERVEB);
var_c = QCC_PR_Statement(&pr_opcodes[OP_BITOR_F], var_c, var_c, NULL);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_c, var_c, NULL, STFL_PRESERVEA);
var_c = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], var_b, var_c, NULL);
return QCC_PR_Statement(&pr_opcodes[OP_SUB_F], var_a, var_c, NULL);
@ -2960,7 +2967,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a);
if (eval_a)
{
QCC_FreeTemp(var_a);
var_a = QCC_MakeFloatConst(eval_a->_int);
}
else
{
var_c = QCC_PR_GetSRef(NULL, "itof", NULL, false, 0, 0);
@ -2983,7 +2993,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a);
if (eval_a)
{
QCC_FreeTemp(var_a);
var_a = QCC_MakeIntConst(eval_a->_float);
}
else
{
var_c = QCC_PR_GetSRef(NULL, "ftoi", NULL, false, 0, 0);
@ -3972,6 +3985,7 @@ struct inlinectx_s
{
QCC_def_t *def;
QCC_def_t *srcsym;
int bias;
} locals[64];
int numlocals;
};
@ -3993,6 +4007,7 @@ static pbool QCC_PR_InlinePushResult(struct inlinectx_s *ctx, QCC_sref_t src, QC
else if (ctx->locals[i].def)
QCC_FreeDef(ctx->locals[i].def);
ctx->locals[i].def = mappedto.sym;
ctx->locals[i].bias = mappedto.ofs - src.ofs; //FIXME: this feels unsafe (needed for array[immediate] fixups)
return true;
}
@ -4015,10 +4030,11 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
{
QCC_FreeDef(ctx->locals[p].def);
ctx->locals[p].def = NULL;
ctx->locals[p].bias = 0;
d = NULL;
return QCC_MakeSRefForce(NULL, 0, NULL);
}
return QCC_MakeSRefForce(d, src.ofs, src.cast);
return QCC_MakeSRefForce(d, src.ofs + ctx->locals[p].bias, src.cast);
}
}
@ -4030,7 +4046,7 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
{
if (src.sym->symbolheader == local)
{
return QCC_MakeSRefForce(ctx->arglist[p].sym->symbolheader, ctx->arglist[p].sym->ofs+src.ofs, src.cast);
return QCC_MakeSRefForce(ctx->arglist[p].sym->symbolheader, src.ofs, src.cast);
}
}
@ -4082,9 +4098,14 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
//returns a string saying why inlining failed.
static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
{
/*FIXME: what happens with:
t = foo;
foo = 5;
return t;
*/
QCC_sref_t a, b, c;
QCC_statement_t *st;
// const QCC_eval_t *eval;
const QCC_eval_t *eval;
// float af,bf;
// int i;
@ -4099,6 +4120,10 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
case OP_IFNOT_I:
case OP_IF_S:
case OP_IFNOT_S:
if (st->b.ofs > 0 && st[st->b.ofs].op == OP_DONE)
{
//logically, an if statement around the entire function is safe because the locals are safe
}
case OP_GOTO:
case OP_SWITCH_F:
case OP_SWITCH_I:
@ -4138,20 +4163,18 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
return "OP_RETURN no a";
}
return NULL;
#ifdef IAMNOTLAZY
case OP_BOUNDCHECK:
a = QCC_PR_InlineFindDef(ctx, st->a);
a = QCC_PR_InlineFindDef(ctx, st->a, false);
QCC_PR_InlinePushResult(ctx, st->a, a);
eval = QCC_SRef_EvalConst(st->a);
eval = QCC_SRef_EvalConst(a);
if (eval)
{
if (eval->_int < st->c || eval->_int >= st->b)
if (eval->_int < (int)st->c.ofs || eval->_int >= (int)st->b.ofs)
QCC_PR_ParseWarning(0, "constant value exceeds bounds failed bounds check while inlining\n");
}
else
QCC_PR_SimpleStatement(OP_BOUNDCHECK, a->ofs, st->b, st->c, false);
QCC_PR_SimpleStatement(&pr_opcodes[OP_BOUNDCHECK], a, st->b, st->c, false);
break;
#endif
default:
if ((st->op >= OP_CALL0 && st->op <= OP_CALL8) || (st->op >= OP_CALL1H && st->op <= OP_CALL8H))
{
@ -4910,6 +4933,7 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
if (!func.sym->initialized)
func.sym->initialized = 3;
func.sym->referenced = true;
QCC_FreeTemp(func);
e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
QCC_PR_Expect(")");
@ -4917,6 +4941,7 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
d = QCC_PR_GetSRef(NULL, "nextent", NULL, false, 0, false);
if (!d.cast)
QCC_PR_ParseError(0, "the nextent builtin is not defined");
QCC_UnFreeTemp(e);
d = QCC_PR_GenerateFunctionCall (nullsref, d, &e, &type_float, 1);
d = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), NULL, 0);
e = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], e, d, NULL, 0);
@ -5600,7 +5625,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype)
pr.local_head.nextlocal = NULL;
pr.local_tail = &pr.local_head;
scope->initialized = true;
scope->symboldata[scope->ofs].function = pr_scope - functions;
ed = QCC_PR_GetSRef(type_entity, "self", NULL, true, 0, false);
@ -6295,6 +6320,8 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
}
}
d.sym->referenced = true;
//class code uses self as though it was 'this'. its a hack, but this is QC.
if (assumeclass && pr_classtype && !strcmp(name, "self"))
{
@ -7340,11 +7367,11 @@ QCC_sref_t QCC_StoreToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable, pb
TypeName(source.cast, typea, sizeof(typea));
TypeName(dest->cast, typeb, sizeof(typeb));
if (dest->type == REF_FIELD)
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s %s.%s", typea, typeb, dest->base.cast->name, QCC_GetSRefName(dest->index));
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s %s.%s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
else if (dest->index.cast)
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s[%s]", typea, typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s[%s]", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
else
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s %s", typea, typeb, QCC_GetSRefName(dest->base));
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s %s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base));
}
}
}
@ -10646,6 +10673,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false);
scope->initialized = true;
scope->symboldata[scope->ofs]._int = pr_scope - functions;
/* if (fasttrackpossible)
@ -10828,6 +10856,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false);
scope->initialized = true;
scope->symboldata[scope->ofs]._int = pr_scope - functions;
if (fasttrackpossible.cast)
@ -11272,6 +11301,8 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as constant", name);
else if (flags & GDF_STATIC)
QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as static", name);
if (!(flags & GDF_STRIP))
flags |= GDF_USED;
}
def = QCC_PR_DummyDef(type, name, scope, arraysize, NULL, ofs, true, flags);
@ -11829,7 +11860,7 @@ void QCC_PR_ParseDefs (char *classname)
pbool inlinefunction = false;
pbool allowinline = false;
pbool dostrip = false;
pbool ignored = false;
pbool forceused = false;
int arraysize;
unsigned int gd_flags;
@ -12046,20 +12077,24 @@ void QCC_PR_ParseDefs (char *classname)
isconstant = true;
else if (QCC_PR_CheckKeyword(keyword_var, "var"))
isvar = true;
else if (QCC_PR_CheckKeyword(keyword_var, "static"))
else if (QCC_PR_CheckKeyword(keyword_static, "static"))
isstatic = true;
else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "nonstatic"))
else if (!pr_scope && QCC_PR_CheckKeyword(keyword_nonstatic, "nonstatic"))
isstatic = false;
else if (QCC_PR_CheckKeyword(keyword_noref, "noref"))
noref=true;
else if (QCC_PR_CheckKeyword(keyword_unused, "unused"))
noref=true;
else if (QCC_PR_CheckKeyword(keyword_used, "used"))
forceused=true;
else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave"))
nosave = true;
else if (QCC_PR_CheckKeyword(keyword_strip, "strip"))
dostrip = true;
else if (QCC_PR_CheckKeyword(keyword_inline, "inline"))
allowinline = true;
else if (QCC_PR_CheckKeyword(keyword_inline, "ignore"))
ignored = true;
else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore"))
dostrip = true;
else
break;
}
@ -12085,7 +12120,7 @@ void QCC_PR_ParseDefs (char *classname)
def = QCC_PR_GetDef (type, name, NULL, true, 0, false);
if (autoprototype || ignored)
if (autoprototype || dostrip)
{ //ignore the code and stuff
if (QCC_PR_CheckKeyword(keyword_external, "external"))
@ -12283,7 +12318,7 @@ void QCC_PR_ParseDefs (char *classname)
gd_flags |= GDF_INLINE;
if (dostrip)
gd_flags |= GDF_STRIP;
if (isvar && !ignored) //FIXME: make proper pragma(used) thingie
else if (forceused) //FIXME: make proper pragma(used) thingie
gd_flags |= GDF_USED;
#if IAMNOTLAZY
@ -12366,10 +12401,12 @@ void QCC_PR_ParseDefs (char *classname)
// QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
}
if (autoprototype || ignored)
if (autoprototype || dostrip)
{ //ignore the code and stuff
if (ignored && !def->initialized)
if (dostrip && !def->initialized)
def->initialized = 3;
if (dostrip)
def->referenced = true;
if (QCC_PR_CheckToken("["))
{
while (!QCC_PR_CheckToken("]"))
@ -12425,7 +12462,12 @@ void QCC_PR_ParseDefs (char *classname)
if (type->type == ev_function)
isconstant = !isvar;
if (type->type == ev_field)
if (dostrip)
{
def->constant = isconstant;
def->referenced = true;
}
else if (type->type == ev_field)
{
//fields are const by default, even when not initialised (as they are initialised behind the scenes)
if (isconstant)

View file

@ -4642,6 +4642,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
pbool isvirt = false;
pbool isnonvirt = false;
pbool isstatic = false;
pbool isignored = false;
while(1)
{
if (QCC_PR_CheckKeyword(1, "nonvirtual"))
@ -4650,6 +4651,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
isstatic = true;
else if (QCC_PR_CheckKeyword(1, "virtual"))
isvirt = true;
else if (QCC_PR_CheckKeyword(1, "ignore"))
isignored = true;
else if (QCC_PR_CheckKeyword(1, "strip"))
isignored = true;
else
break;
}
@ -4720,20 +4725,28 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
isnull = (QCC_PR_CheckImmediate("0") || QCC_PR_CheckImmediate("0i"));
QC_snprintfz(membername, sizeof(membername), "%s::%s", classname, parmname);
if (isnull)
{
if (isignored)
def = NULL;
else
{
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, 0);
def->symboldata[def->ofs].function = 0;
def->initialized = 1;
}
}
else
{
if (isignored)
def = NULL;
else
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST);
if (newparm->type != ev_function)
QCC_Error(ERR_INTERNAL, "Can only initialise member functions");
else
{
if (autoprototype)
if (autoprototype || isignored)
{
QCC_PR_Expect("{");
@ -4765,9 +4778,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
}
}
}
if (def)
QCC_FreeDef(def);
if (!isvirt)
if (!isvirt && !isignored)
{
QCC_def_t *fdef;
QCC_type_t *pc;
@ -4799,6 +4813,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_PR_Expect(";");
if (isignored) //member doesn't really exist
continue;
//static members are technically just funny-named globals, and do not generate fields.
if (isnonvirt || isstatic || (newparm->type == ev_function && !arraysize))
{

View file

@ -282,7 +282,13 @@ compiler_flag_t compiler_flag[] = {
{&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."},
{&keyword_int, defaultkeyword, "int", "Keyword: int", "Disables the 'int' keyword."},
{&keyword_integer, defaultkeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."},
{&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't strip it.
{&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't warn about it.
{&keyword_unused, nondefaultkeyword, "unused", "Keyword: unused", "Disables the 'unused' keyword. 'unused' means that the variable is unused, you're aware that its unused, and you'd rather not know about all the warnings this results in."},
{&keyword_used, nondefaultkeyword, "used", "Keyword: used", "Disables the 'used' keyword. 'used' means that the variable is used even if the qcc can't see how - thus preventing it from ever being stripped."},
{&keyword_static, defaultkeyword, "static", "Keyword: static", "Disables the 'static' keyword. 'static' means that a variable has altered scope. On globals, the variable is visible only to the current .qc file. On locals, the variable's value does not change between calls to the function. On class variables, specifies that the field is a scoped global instead of a local. On class functions, specifies that 'this' is expected to be invalid and that the function will access any memembers via it."},
{&keyword_nonstatic, defaultkeyword, "nonstatic", "Keyword: nonstatic", "Disables the 'nonstatic' keyword. 'nonstatic' acts upon globals+functions, reverting the defaultstatic pragma on a per-variable basis. For use by people who prefer to keep their APIs explicit."},
{&keyword_ignore, nondefaultkeyword, "ignore", "Keyword: ignore", "Disables the 'ignore' keyword. 'ignore' is expected to typically be hidden behind a 'csqconly' define, and in such a context can be used to conditionally compile functions a little more gracefully. The opposite of the 'used' keyword. These variables/functions/members are ALWAYS stripped, and effectively ignored."},
{&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output.
{&keyword_inline, defaultkeyword, "inline", "Keyword: inline", "Disables the 'inline' keyword."}, //don't write the def to the output.
{&keyword_strip, defaultkeyword, "strip", "Keyword: strip", "Disables the 'strip' keyword."}, //don't write the def to the output.
@ -1307,9 +1313,9 @@ pbool QCC_WriteData (int crc)
for (i = 0; i < nummodels; i++)
{
if (!precache_model[i].used)
QCC_PR_Warning(WARN_EXTRAPRECACHE, precache_model[i].filename, precache_model[i].fileline, "Model %s was precached but not directly used", precache_model[i].name);
QCC_PR_Warning(WARN_EXTRAPRECACHE, precache_model[i].filename, precache_model[i].fileline, "Model \"%s\" was precached but not directly used", precache_model[i].name);
else if (!precache_model[i].block)
QCC_PR_Warning(WARN_NOTPRECACHED, precache_model[i].filename, precache_model[i].fileline, "Model %s was used but not precached", precache_model[i].name);
QCC_PR_Warning(WARN_NOTPRECACHED, precache_model[i].filename, precache_model[i].fileline, "Model \"%s\" was used but not precached", precache_model[i].name);
}
//PrintStrings ();
//PrintFunctions ();

View file

@ -205,11 +205,11 @@ void PDECL ED_Spawned (struct edict_s *ent, int loading)
if (!loading || !ent->xv->Version)
{
ent->xv->dimension_see = 255;
ent->xv->dimension_seen = 255;
ent->xv->dimension_see = pr_global_struct->dimension_default;
ent->xv->dimension_seen = pr_global_struct->dimension_default;
ent->xv->dimension_ghost = 0;
ent->xv->dimension_solid = 255;
ent->xv->dimension_hit = 255;
ent->xv->dimension_solid = pr_global_struct->dimension_default;
ent->xv->dimension_hit = pr_global_struct->dimension_default;
if (progstype != PROG_H2)
ent->xv->drawflags = SCALE_ORIGIN_ORIGIN; //if not running hexen2, default the scale origin to the actual origin.
@ -666,6 +666,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static float svphysicsmode = 2;
static float writeonly;
static float dimension_send_default;
static float dimension_default = 255;
static float zero_default;
static float input_buttons_default;
static float input_timelength_default;
@ -725,6 +726,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalfunc (false, SetChangeParms);
globalfloat (false, cycle_wrapped);
globalfloat (false, dimension_send);
globalfloat (false, dimension_default);
globalfloat (false, clientcommandframe);
@ -747,6 +749,7 @@ void PR_LoadGlabalStruct(qboolean muted)
// make sure these entries are always valid pointers
ensureglobal(dimension_send, dimension_send_default);
ensureglobal(dimension_default, dimension_default);
ensureglobal(trace_endcontents, writeonly);
ensureglobal(trace_surfaceflags, writeonly);
@ -804,8 +807,8 @@ void PR_LoadGlabalStruct(qboolean muted)
//this can be a map start or a loadgame. don't hurt stuff.
if (!pr_global_struct->dimension_send)
pr_global_struct->dimension_send = 255;
/* pr_global_struct->dimension_send = 255;
pr_global_struct->dimension_send = pr_global_struct->dimension_default;
/*
pr_global_struct->serverflags = 0;
pr_global_struct->total_secrets = 0;
pr_global_struct->total_monsters = 0;
@ -1218,7 +1221,7 @@ void PR_SSCoreDump_f(void)
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
COM_WriteFile("ssqccore.txt", buffer, size);
COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}
}
@ -9681,7 +9684,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"keynumtostring_csqc",PF_Fixme,0, 0, 0, 340, D("string(float keynum)", "Returns a hunam-readable name for the given keycode, as a tempstring.")},// (found in menuqc)
{"stringtokeynum", PF_Fixme, 0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (EXT_CSQC)
{"stringtokeynum_csqc", PF_Fixme,0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (found in menuqc)
{"getkeybind", PF_Fixme, 0, 0, 0, 342, D("string(float keynum)", "Finds the current binding for the given key (ignores modifiers like shift/alt/ctrl).")},// (EXT_CSQC)
{"getkeybind", PF_Fixme, 0, 0, 0, 342, D("string(float keynum)", "Returns the current binding for the given key (returning only the command executed when no modifiers are pressed).")},// (EXT_CSQC)
{"setcursormode", PF_Fixme, 0, 0, 0, 343, D("void(float usecursor, optional string cursorimage, optional vector hotspot, optional float scale)", "Pass TRUE if you want the engine to release the mouse cursor (absolute input events + touchscreen mode). Pass FALSE if you want the engine to grab the cursor (relative input events + standard looking). If the image name is specified, the engine will use that image for a cursor (use an empty string to clear it again), in a way that will not conflict with the console. Images specified this way will be hardware accelerated, if supported by the platform/port.")},
{"getmousepos", PF_Fixme, 0, 0, 0, 344, D("vector()", "Nasty convoluted DP extension. Typically returns deltas instead of positions. Use CSQC_InputEvent for such things in csqc mods.")}, // #344 This is a DP extension
@ -9918,7 +9921,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"uri_escape", PF_uri_escape, 0, 0, 0, 510, "string(string in)"},//DP_QC_URI_ESCAPE
{"uri_unescape", PF_uri_unescape, 0, 0, 0, 511, "string(string in)"},//DP_QC_URI_ESCAPE
{"num_for_edict", PF_num_for_edict, 0, 0, 0, 512, "float(entity ent)"},//DP_QC_NUM_FOR_EDICT
{"uri_get", PF_uri_get, 0, 0, 0, 513, D("#define uri_post uri_get\nfloat(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string")},//DP_QC_URI_GET
{"uri_get", PF_uri_get, 0, 0, 0, 513, D("#define uri_post uri_get\nfloat(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string\nFor a POST request, you will typically want the postmimetype set to application/x-www-form-urlencoded.\nFor a GET request, omit the mime+data entirely.\nConsult your webserver/php/etc documentation for best-practise.")},//DP_QC_URI_GET
{"uri_post", PF_uri_get, 0, 0, 0, 513, D("float(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string"), true},//DP_QC_URI_POST
{"tokenize_console",PF_tokenize_console,0, 0, 0, 514, D("float(string str)", "Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches.")},
{"argv_start_index",PF_argv_start_index,0, 0, 0, 515, D("float(float idx)", "Returns the character index that the tokenized arg started at.")},
@ -9927,7 +9930,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"cvar_description",PF_cvar_description,0, 0, 0, 518, D("string(string cvarname)", "Retrieves the description of a cvar, which might be useful for tooltips or help files. This may still not be useful.")},
{"gettime", PF_gettime, 0, 0, 0, 519, "float(optional float timetype)"},
{"keynumtostring_omgwtf",PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, //excessive third version in dp's csqc.
{"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, "string(string command, optional float bindmap)"},
{"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, D("string(string command, optional float bindmap)", "Returns a list of keycodes that perform the given console command in a format that can only be parsed via tokenize (NOT tokenize_console). This only and always returns two values - if only one key is actually bound, -1 will be returned. The bindmap argument is listed for compatibility with dp-specific defs, but is ignored in FTE.")},
{"findkeysforcommandex",PF_Fixme, 0, 0, 0, 0, D("string(string command)", "Returns a list of key bindings in keyname format instead of keynums. Use tokenize to parse. This list may contain modifiers. May return large numbers of keys.")},
// {"initparticlespawner",PF_Fixme, 0, 0, 0, 522, "void(float max_themes)"},
// {"resetparticle", PF_Fixme, 0, 0, 0, 523, "void()"},
// {"particletheme", PF_Fixme, 0, 0, 0, 524, "void(float theme)"},
@ -10698,6 +10702,8 @@ void PR_DumpPlatform_f(void)
{"parm17, parm18, parm19, parm20, parm21, parm22, parm23, parm24, parm25, parm26, parm27, parm28, parm29, parm30, parm31, parm32", "float", QW|NQ},
{"parm33, parm34, parm35, parm36, parm37, parm38, parm39, parm40, parm41, parm42, parm43, parm44, parm45, parm46, parm47, parm48", "float", QW|NQ},
{"parm49, parm50, parm51, parm52, parm53, parm54, parm55, parm56, parm57, parm58, parm59, parm60, parm61, parm62, parm63, parm64", "float", QW|NQ},
{"dimension_send", "var float", QW|NQ, "Used by multicast functionality. Multicasts (and related builtins that multicast internally) will only be sent to players where (player.dimension_see & dimension_send) is non-zero."},
{"dimension_default", "//var float", QW|NQ, "Default dimension bitmask", 255},
{"physics_mode", "var float", QW|NQ|CS, "0: original csqc - physics are not run\n1: DP-compat. Thinks occur, but not true movetypes.\n2: movetypes occur just as they do in ssqc.", 2},
{"gamespeed", "float", CS, "Set by the engine, this is the value of the sv_gamespeed cvar"},
{"numclientseats", "float", CS, "This is the number of splitscreen clients currently running on this client."},

View file

@ -1950,6 +1950,7 @@ static void Lua_SetupGlobals(world_t *world)
memset(&lua.globals, 0, sizeof(lua.globals));
lua.globals.physics_mode = 2;
lua.globals.dimension_send = 255;
lua.globals.dimension_default = 255;
flds = 0;
bucks = 64;

View file

@ -81,6 +81,7 @@ typedef struct nqglobalvars_s
func_t *SetChangeParms;
float *cycle_wrapped;
float *dimension_send;
float *dimension_default;
float *physics_mode;
float *clientcommandframe;

View file

@ -1215,7 +1215,7 @@ void SV_Savegame (char *savename)
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer)
{
SCR_ScreenShot(savefilename, rgbbuffer, width, height);
SCR_ScreenShot(savefilename, FS_GAMEONLY, rgbbuffer, width, height);
BZ_Free(rgbbuffer);

View file

@ -2573,6 +2573,31 @@ void SV_ReallyEvilHack_f(void)
}
*/
void SV_PrecacheList_f(void)
{
unsigned int i;
for (i = 0; i < sizeof(sv.strings.vw_model_precache)/sizeof(sv.strings.vw_model_precache[0]); i++)
{
if (sv.strings.vw_model_precache[i])
Con_Printf("vweap %u: %s\n", i, sv.strings.vw_model_precache[i]);
}
for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{
if (sv.strings.model_precache[i])
Con_Printf("model %u: %s\n", i, sv.strings.model_precache[i]);
}
for (i = 0; i < MAX_PRECACHE_SOUNDS; i++)
{
if (*sv.strings.sound_precache[i])
Con_Printf("sound %u: %s\n", i, sv.strings.sound_precache[i]);
}
for (i = 0; i < MAX_SSPARTICLESPRE; i++)
{
if (*sv.strings.particle_precache[i])
Con_Printf("pticl %u: %s\n", i, sv.strings.particle_precache[i]);
}
}
/*
==================
SV_InitOperatorCommands
@ -2636,6 +2661,7 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("killserver", SV_KillServer_f);
Cmd_AddCommand ("map", SV_Map_f);
Cmd_AddCommandD ("precaches", SV_PrecacheList_f, "Displays a list of current server precaches.");
#ifdef Q3SERVER
Cmd_AddCommand ("spmap", SV_Map_f);
#endif

View file

@ -119,9 +119,11 @@ pubsubserver_t *MSV_FindSubServer(unsigned int id)
}
//"5" finds server 5 only
//"5:" is equivelent to the above
//"5:dm4" finds server 5, and will start it if not known (even if a different node is running the same map)
//"0:dm4" starts a new server running dm4, even if its already running
//":dm4" finds any server running dm4. starts a new one if needed.
//"dm4" is ambiguous, in the case of a map beginning with a number (bah). don't use.
pubsubserver_t *MSV_FindSubServerName(const char *servername)
{
pubsubserver_t *s;
@ -136,8 +138,11 @@ pubsubserver_t *MSV_FindSubServerName(const char *servername)
forcenew = true;
mapname++;
}
else
else if (*mapname)
{
Con_Printf("Invalid node name (lacks colon): %s\n", servername);
mapname = "";
}
if (id)
{
@ -216,17 +221,9 @@ void MSV_MapCluster_f(void)
//child processes return 0 and fall through
memset(&sv, 0, sizeof(sv));
if (Cmd_Argc() > 1)
if (atoi(Cmd_Argv(1)))
{
char *dbname = Cmd_Argv(1);
char *sqlparams[] =
{
"", //host
"", //username
"", //password
dbname, //db
};
Con_Printf("Opening database \"%s\"\n", dbname);
Con_Printf("Opening database \"%s\"\n", sqlparams[3]);
sv.logindatabase = SQL_NewServer("sqlite", sqlparams);
if (sv.logindatabase == -1)
{
@ -777,8 +774,21 @@ void SSV_ReadFromControlServer(void)
for (i = 0; i < sv.allocated_client_slots; i++)
{
cl = &svs.clients[i];
if (cl->state >= ca_connected)
if (!*dest || !strcmp(dest, cl->name))
{
if (!strcmp(cmd, "say"))
SV_PrintToClient(cl, PRINT_HIGH, va("^[%s^]: %s\n", from, info));
else if (!strcmp(cmd, "join"))
{
SV_PrintToClient(cl, PRINT_HIGH, va("^[%s^] is joining you\n", from));
SSV_Send(from, cl->name, "joinnode", va("%i", svs.clusterserverid));
}
else if (!strcmp(cmd, "joinnode"))
{
SSV_InitiatePlayerTransfer(cl, info);
}
else
SV_PrintToClient(cl, PRINT_HIGH, va("%s from [%s]: %s\n", cmd, from, info));
if (*dest)
break;
@ -815,7 +825,7 @@ void SSV_UpdateAddresses(void)
{
if (addr[i].type == NA_IP)
{
NET_StringToAdr(sv_serverip.string, BigShort(addr[i].port), &addr[0]);
NET_StringToAdr2(sv_serverip.string, BigShort(addr[i].port), &addr[0], sizeof(addr)/sizeof(addr[0]));
count = 1;
break;
}

View file

@ -295,7 +295,7 @@ void VARGS SV_Error (char *error, ...)
int size = 1024*1024*8;
char *buffer = BZ_Malloc(size);
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
COM_WriteFile("ssqccore.txt", buffer, size);
COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer);
}
}

View file

@ -1053,17 +1053,41 @@ void ApplyColour(unsigned int chr)
}
}
void Sys_PrintColouredChar(unsigned int chr)
//this could be much more efficient.
static void Sys_PrintColouredChars(conchar_t *start, conchar_t *end)
{
conchar_t m;
wchar_t wc[256];
int l;
DWORD dummy;
wchar_t wc;
if (chr & CON_HIDDEN)
return;
ApplyColour(chr);
while(start < end)
{
l = 0;
m = *start & CON_FLAGSMASK;
for (;;)
{
if (start == end || m != (*start & CON_FLAGSMASK) || l >= countof(wc))
{
ApplyColour(m);
if (WinNT)
WriteConsoleW(hconsoleout, wc, l, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck.
char ac[256];
l = WideCharToMultiByte(CP_ACP, 0, wc, l, ac, sizeof(ac), NULL, NULL);
WriteConsole(hconsoleout, ac, l, &dummy, NULL);
}
break;
}
if (!(*start & CON_HIDDEN))
wc[l++] = *start & CON_CHARMASK;
start++;
}
}
wc = chr & CON_CHARMASK;
WriteConsoleW(hconsoleout, &wc, 1, &dummy, NULL);
ApplyColour(CON_WHITEMASK);
}
/*
@ -1112,13 +1136,9 @@ void Sys_Printf (char *fmt, ...)
if (sys_colorconsole.value && hconsoleout)
{
conchar_t out[MAXPRINTMSG], *c, *end;
conchar_t out[MAXPRINTMSG], *end;
end = COM_ParseFunString(CON_WHITEMASK, msg, out, sizeof(out), false);
for (c = out; c < end; c++)
Sys_PrintColouredChar (*c);
ApplyColour(CON_WHITEMASK);
Sys_PrintColouredChars (out, end);
}
else
{

View file

@ -4346,7 +4346,7 @@ void Cmd_Fly_f (void)
}
#ifdef SUBSERVERS
void Cmd_Transfer_f(void)
void Cmd_SSV_Transfer_f(void)
{
char *dest = Cmd_Argv(1);
if (!SV_MayCheat())
@ -4357,6 +4357,46 @@ void Cmd_Transfer_f(void)
SSV_InitiatePlayerTransfer(host_client, dest);
}
void Cmd_SSV_AllSay_f(void)
{
char *text = Cmd_Args();
if (!SV_MayCheat())
{
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
return;
}
SSV_Send("", host_client->name, "say", text);
}
void Cmd_SSV_Join_f(void)
{
int i;
char *who = Cmd_Argv(1);
if (!SV_MayCheat())
{
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
return;
}
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (!strcmp(who, svs.clients[i].name))
{
// VectorCopy(svs.clients[i].edict->v->origin, sv_player->v->oldorigin);
VectorCopy(svs.clients[i].edict->v->origin, sv_player->v->origin);
World_LinkEdict (&sv.world, (wedict_t*)sv_player, false);
sv_player->xv->dimension_hit = (int)sv_player->xv->dimension_hit & ~128;
sv_player->xv->dimension_solid = (int)sv_player->xv->dimension_solid & 128;
svs.clients[i].edict->xv->dimension_hit = (int)svs.clients[i].edict->xv->dimension_hit & ~128;
svs.clients[i].edict->xv->dimension_solid = (int)svs.clients[i].edict->xv->dimension_solid & 128;
return;
}
}
SSV_Send(who, host_client->name, "join", "");
}
#endif
/*
@ -5272,7 +5312,9 @@ ucmd_t ucmds[] =
{"notarget", Cmd_Notarget_f},
{"setpos", Cmd_SetPos_f},
#ifdef SUBSERVERS
{"transfer", Cmd_Transfer_f}, //transfer the player to a different map/server
{"ssvtransfer", Cmd_SSV_Transfer_f},//transfer the player to a different map/server
{"ssvsay", Cmd_SSV_AllSay_f}, //transfer the player to a different map/server
{"ssvjoin", Cmd_SSV_Join_f}, //transfer the player to a different map/server
#endif
#ifdef NQPROT

View file

@ -9,7 +9,7 @@ PLUG_NATIVE_EXT=_amd.dll
PLUG_LDFLAGS=-Lavplug/lib64 -L../engine/libs/mingw64-libs -lz -Wl,--support-old-code
endif
PLUG_LDFLAGS?=-L/usr/local/lib -Wl,-R/usr/local/lib -lz
PLUG_LDFLAGS?=-L/usr/local/lib -Wl,-R/usr/local/lib -lz -lm
ifneq ($(PLUG_NATIVE_EXT),)
#if we're on windows, we'll put our windows-specific hacks here.
@ -129,7 +129,7 @@ native: $(OUT_DIR)/fteplug_irc$(PLUG_NATIVE_EXT)
#for compat with ezquake
$(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT)
native:

View file

@ -60,6 +60,12 @@ client compat:
#include <time.h>
#include "xmpp.h"
#ifdef DEFAULTDOMAIN
#define EXAMPLEDOMAIN DEFAULTDOMAIN //used in examples / default text field (but not otherwise assumed when omitted)
#else
#define EXAMPLEDOMAIN "gmail.com" //used in examples
#endif
#ifdef JINGLE
icefuncs_t *piceapi;
@ -1578,7 +1584,7 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args)
else if (!strcmp(what, "newaccount"))
{
pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true);
pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your account name");
pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN);
jclient_action_cl = jcl;
jclient_action_buddy = NULL;
jclient_action = ACT_NEWACCOUNT;
@ -1746,7 +1752,7 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args)
case ACT_NONE:
break;
case ACT_NEWACCOUNT:
if (*args)
if (!*args)
break; //they didn't enter anything! oh well.
for (i = 0; i < sizeof(jclients)/sizeof(jclients[0]); i++)
{
@ -2208,14 +2214,13 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch
}
else
{
#ifdef DEFAULTDOMAIN
domain = DEFAULTDOMAIN;
if (domain && *domain)
Con_Printf("XMPP: domain not specified, assuming %s\n", domain);
else
{
#else
Con_Printf("XMPP: domain not specified\n");
return NULL;
}
#endif
}
x = XML_CreateNode(NULL, "account", "", "");
@ -5401,7 +5406,7 @@ void XMPP_Menu_Connect(void)
y = 36;
pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \"gmail.com\"\n", y), false);y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \""EXAMPLEDOMAIN"\"\n", y), false);y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32;
pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false);
pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false);

View file

@ -22,7 +22,7 @@
#define JCL_BUILD "4"
#define DEFAULTDOMAIN ""
//#define DEFAULTDOMAIN "triptohell.info"
#define DEFAULTRESOURCE "Quake"
#define QUAKEMEDIAXMLNS "http://fteqw.com/protocol/quake"
#define DISCONODE "http://fteqw.com/ftexmpp" //some sort of client identifier

79
specs/mapcluster.txt Normal file
View file

@ -0,0 +1,79 @@
WARNING: this mode is not currently compiled in by default, in order to avoid potential unexpected resource usage.
you will need to enable it by enabling the SUBSERVERS preprocessor define at compile time.
random useful commands (bash or console):
make sv-rel CFLAGS=-DSUBSERVERS
mapcluster <enablelogins>
ssv 1 quit
ssv * say The Admin Is Awesome
sv_serverip 127.0.0.1
the mapcluster command provides support for a single host running multiple maps as a single server cluster.
this is achieved by running multiple instances of the server in multiple processes, each with their own port numbers.
the initial server acts as a login server, which communicates with the various nodes.
ssqc is able to transfer clients from one node to another within the cluster, or send messages to the node hosting clients (or, if the node's id is explicitly known, can be used to directly communicate with other nodes).
node naming rules:
a node name takes the form of id:name
if the id is empty, then it is considered unspecified, and the message/transfer will id used will be updated to any existing node with the same name (:e1m1 will pick ANY e1m1).
if the id is 0, then it will NEVER use an existing node.
if the id is invalid/0/empty, and the name is not blank, and the node is named via a transfer request, a new node will be started using that name as the new node's initial map.
note that "0:start$\\foo\\bar" can be used, in which case you will ALWAYS get a new instance, using maps/start.bsp and that infoget(startspot, "foo") will return "bar".
event destinations:
event destinations logically use player names. However, if the name takes the form "\\5" for example, then the message will be sent to the node with id 5, rather than to the node of a name player. You can use this to directly communicate server-to-server. If the node id does not exist, the event will be returned to the sender as an error - no new node will be created with this (fixme: it probably should be, but blurgh).
ssqc builtins:
forceinfokey(player, "*transfer", ":e1m1");
initiates a transfer request. the infokey will be cleared out upon failure, and the client will drop on success.
their parms will be transfered immediately, and will be available to the new server once the transfer completes.
WARNING: it is the QC's responsibility to terminate servers {localcmd("quit\n");} - the engine will not automatically do this.
If you are implementing an mmo-like game, you would presumably do this when there are no players and all monsters were respawned (such that restarting will not be noticed). Otherwise you may choose to terminate the node instantly or after some delay after the last player has left. If you only have limited maps, you might opt to never terminate any nodes - lucky you.
void(string dest, string from, string cmd, string info) clusterevent = #;
sends a message to the destination.
if dest is blank, the event will be broadcast to EVERY node.
if the destination is prefixed with a \ char, (eg: "\\1"), then the message is sent to node id 1.
if the destination is a player name, will send to whichever node that player is currently on. the receiving server is expected to handle the event on behalf of the player (perhaps by forwarding to csqc, or just doing a sprint or something).
if the destination appears invalid (and cmd is not prefixed with 'error:'), the cmd will be prefixed with error:, the dest+from args swapped, and the event will be sent back to the receiver.
info and cmd have meaning to the engine only if the receiver's ssqc does not handle the event.
float serverid
this float contains the node's unique id. no two active nodes will use the same id, and can be used in replies to identify the node as the receipient of a transfer.
float(string dest, string from, string cmd, string info) SV_ParseClusterEvent = {};
this function is called by the engine in response to a clusterevent call. the arguments match those of the prior call.
if you return false, the engine will attempt to handle it the best it can. which is limited and probably not ideal. any other result will cause the node to carry out no further action (meaning the from+cmd+info args are completely free-form if you do so).
the dest argument follows the restrictions/expectations specified for clusterevent.
this is handled by the receipient server, and as such the qc is expected to find the named player (if not direct-to-server) and handle the event itself.
the senders and receivers of these messages are all part of the same cluster, and so should all be considered trustworthy - unless you permit direct message injection. for this reason, you should *probably* ALWAYS use constants for the cmd argument, and thereby avoid surprises. this allows you to make assumptions about the dest+from+info fields more easily, simplifying your parsing.
it is possible for a client to have transfered off the server (or be in the process of transfering and thus ownership of the player's properties uncertain). in such cases, you are recommended to mimic the error: behaviour so that the sender can handle things in a consistent way.
debug/cheat commands (mods are expected to provide their own functionality for these things, and thus these are considered cheats to limit their use):
cmd ssvtransfer :e1m1
transfers the player to the named node (see node naming rules), just like forceinfokey would.
cmd ssvsay hello world
broadcasts the message to every single player on every single node (instead of merely the node the player is on).
(this does: clusterevent("", self.netname, "say", args()) )
cmd ssvjoin playername
attempts to teleport the player to the named player's server.
if the named player is already on the same node, teleports the player on top of the named player.
(this does: clusterevent(player, self.netname, "join", ""), the default join handler will reply with joinnode, and the handler of that will initiate a transfer request to the node specified by the joinnode's info string)
gotchas:
in order to invite another player, you will likely need to implement some sort of timeout serverside, in order to avoid issues with people's UIs ignoring the request (or not receiving it due to a player transfering at the time).
you probably shouldn't allow people to join others without mutual consent, to reduce trolling. probably you'll want the server of the person being joined in ultimate control of the join, if only because its nice and easy to pull another player to your node on account of the puller already knowing the destination's serverid.
due to players disconnecting or randomly transfering before your messages get to them, all of these messages should be considered unreliable.
if you block transfers of one player, you can hopefully get away with a race condition between the reply and a timeout. for non-parm based things, you can use sql transaction support to ensure atomicity.