qwsvdef.h is no more. Many files changed because of this.

enabled ssl support in windows for plugins.
updated jabber plugin.
tweaked downloading logic in an effort to end the madness.
Updated sql code to support sleeping the qc thread until query completion, as a more readable alternative to callbacks.
Client updates should be more explicit now, removing a potential bug.
networked terrain editing should now be in a better state.
updated the dir command to show paths too (so when the same file is listed twice, the pak its in will at least be different). Many files changed because of this.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4273 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-03-31 04:21:08 +00:00
parent fed1fb62a7
commit 6a831e2f99
84 changed files with 2998 additions and 2482 deletions

View file

@ -564,9 +564,21 @@ SERVERONLY_OBJS = \
WINDOWSSERVERONLY_OBJS = \
svmodel.o \
net_ssl_winsspi.o \
sv_sys_win.o \
sys_win_threads.o
WINDOWS_OBJS = \
snd_win.o \
snd_directx.o \
cd_win.o \
fs_win32.o \
in_win.o \
sys_win.o \
sys_win_threads.o \
net_ssl_winsspi.o \
$(LTO_END) resources.o $(LTO_START)
COMMON_OBJS = \
gl_alias.o \
gl_heightmap.o \
@ -839,13 +851,13 @@ ifeq ($(FTE_TARGET),vc)
GLCL_DIR=glcl_vc$(BITS)
GL_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/"
GLCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o fs_win32.o in_win.o sys_win.o sys_win_threads.o resources.o
GLCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) gl_vidnt.o $(WINDOWS_OBJS)
GL_OBJS=
MINGL_DIR=mingl_vc$(BITS)
MINGL_EXE_NAME=../fteminglqw$(BITS).exe
D3DCL_OBJS=$(D3DQUAKE_OBJS) $(SPEEX_OBJS) snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(D3DGL_OBJS) fs_win32.o $(LTO_END) resources.o $(LTO_START)
D3DCL_OBJS=$(D3DQUAKE_OBJS) $(D3DGL_OBJS) $(SPEEX_OBJS) $(WINDOWS_OBJS)
D3D_EXE_NAME=../fted3dqw$(BITS).exe
D3DCL_EXE_NAME=../fted3dclqw$(BITS).exe
D3D_LDFLAGS=$(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
@ -854,7 +866,7 @@ ifeq ($(FTE_TARGET),vc)
D3DCL_DIR=d3dcl_vc$(BITS)
M_EXE_NAME=../fteqw$(BITS).exe
MCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(D3DQUAKE_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o resources.o
MCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(D3DQUAKE_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o $(SPEEX_OBJS) $(WINDOWS_OBJS)
M_CFLAGS=$(D3DCFLAGS) $(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/"
MB_DIR=m_vc$(BITS)
M_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows
@ -889,32 +901,32 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),)
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) $(BOTLIB_OBJS) fs_win32.o $(LTO_END) resources.o $(LTO_START)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(LTO_END) resources.o $(LTO_START)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidnt.o $(WINDOWS_OBJS)
GL_EXE_NAME=../fteglqw$(BITS).exe
GLCL_EXE_NAME=../fteglqwcl$(BITS).exe
GL_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32
GL_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 -Wl,--subsystem,windows
GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD -DLIBVORBISFILE_STATIC $(SPEEXCFLAGS)
GLB_DIR=gl_mgw$(BITS)
GLCL_DIR=glcl_mgw$(BITS)
NPFTE_OBJS=httpclient.o image.o sys_win_threads.o sys_npfte.o sys_axfte.o sys_plugfte.o $(LTO_END) npplug.o ../../ftequake/npapi.def $(LTO_START)
NPFTE_DLL_NAME=../npfte$(BITS).dll
NPFTE_LDFLAGS=-Wl,--enable-stdcall-fixup $(IMAGELDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 -loleaut32 -luuid -lstdc++ -shared
NPFTE_LDFLAGS=-Wl,--enable-stdcall-fixup $(IMAGELDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 -loleaut32 -luuid -lstdc++ -shared -Wl,--subsystem,windows
NPFTE_CFLAGS=$(NPFTECFLAGS) $(W32_CFLAGS) -DMULTITHREAD
NPFTEB_DIR=npfte_mgw$(BITS)
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(D3DQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(LTO_END) resources.o $(LTO_START)
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(D3DQUAKE_OBJS) $(BOTLIB_OBJS) $(SPEEX_OBJS) gl_vidnt.o $(WINDOWS_OBJS)
M_EXE_NAME=../fteqw$(BITS).exe
MCL_EXE_NAME=../fteqwcl$(BITS).exe
M_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32
M_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 -Wl,--subsystem,windows
M_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) $(DX7SDK) -DMULTITHREAD -DLIBVORBISFILE_STATIC $(SPEEXCFLAGS)
MB_DIR=m_mgw$(BITS)
MCL_DIR=mcl_mgw$(BITS)
D3DCL_OBJS=$(D3DQUAKE_OBJS) $(SPEEX_OBJS) snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(D3DGL_OBJS) fs_win32.o $(LTO_END) resources.o $(LTO_START)
D3DCL_OBJS=$(D3DQUAKE_OBJS) $(D3DGL_OBJS) $(SPEEX_OBJS) $(WINDOWS_OBJS)
D3D_EXE_NAME=../fted3dqw$(BITS).exe
D3DCL_EXE_NAME=../fted3dclqw$(BITS).exe
D3D_LDFLAGS=$(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32
D3D_LDFLAGS=$(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 -Wl,--subsystem,windows
D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD -DLIBVORBISFILE_STATIC $(SPEEXCFLAGS)
D3DB_DIR=d3d_mgw$(BITS)
D3DCL_DIR=d3dcl_mgw$(BITS)

View file

@ -2066,7 +2066,7 @@ void CL_QTVPlay_f (void)
if (connrequest)
host = connrequest+1;
Q_strncpyz(qtvhostname, host, sizeof(qtvhostname));
newf = FS_OpenTCP(qtvhostname);
newf = FS_OpenTCP(qtvhostname, 27599);
if (!newf)
{
@ -2148,7 +2148,7 @@ void CL_QTVList_f (void)
{
char *connrequest;
vfsfile_t *newf;
newf = FS_OpenTCP(qtvhostname);
newf = FS_OpenTCP(qtvhostname, 27599);
if (!newf)
{
@ -2182,7 +2182,7 @@ void CL_QTVDemos_f (void)
{
char *connrequest;
vfsfile_t *newf;
newf = FS_OpenTCP(Cmd_Argv(1));
newf = FS_OpenTCP(Cmd_Argv(1), 27599);
if (!newf)
{

View file

@ -971,7 +971,7 @@ void CL_IRCConnect_f (void)
{
CL_Disconnect_f ();
if (FTENET_AddToCollection(cls.sockets, "TCP", Cmd_Argv(2), FTENET_IRCConnect_EstablishConnection, false))
if (FTENET_AddToCollection(cls.sockets, "TCP", Cmd_Argv(2), NA_IRC, false))
{
char *server;
server = Cmd_Argv (1);
@ -1307,7 +1307,7 @@ void CL_Disconnect (void)
#ifdef TCPCONNECT
//disconnects it, without disconnecting the others.
FTENET_AddToCollection(cls.sockets, "TCP", NULL, NULL, false);
FTENET_AddToCollection(cls.sockets, "conn", NULL, NA_INVALID, false);
#endif
Cvar_ForceSet(&cl_servername, "none");
@ -2855,11 +2855,17 @@ qboolean CL_AllowArbitaryDownload(char *localfile)
{
char *ext = COM_FileExtension(localfile);
if (!strcmp(ext, "pak") || !strcmp(ext, "pk3") || !strcmp(ext, "pk4"))
allow = true;
return true;
else
allow = false;
{
Con_Printf("Ignoring non-package download redirection to \"%s\"\n", localfile);
return false;
}
return !!allow;
}
if (allow)
return true;
Con_Printf("Ignoring download redirection to \"%s\". This server may require you to set cl_download_redirection to 2.\n", localfile);
return false;
}
/*
@ -2952,10 +2958,7 @@ void CL_DownloadSize_f(void)
redirection = Cmd_Argv(3);
if (!CL_AllowArbitaryDownload(redirection))
{
Con_Printf("Ignoring redirection of %s to %s\n", rname, redirection);
return;
}
dl = CL_DownloadFailed(rname, false);
Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", rname, redirection);

View file

@ -1650,6 +1650,8 @@ int CL_DownloadRate(void)
return cls.downloadedbytes/(Sys_DoubleTime() - cls.downloadstarttime);
}
qboolean CL_AllowArbitaryDownload(char *localfile);
void CL_ParseChunkedDownload(void)
{
qbyte *svname;
@ -1659,7 +1661,7 @@ void CL_ParseChunkedDownload(void)
char data[DLBLOCKSIZE];
chunknum = MSG_ReadLong();
if (chunknum < 0)
if (chunknum == -1)
{
totalsize = MSG_ReadLong();
svname = MSG_ReadString();
@ -1680,7 +1682,17 @@ void CL_ParseChunkedDownload(void)
if (totalsize < 0)
{
if (totalsize == -3)
if (totalsize == -4)
{
if (CL_AllowArbitaryDownload(svname))
{
Con_Printf("Download of \"%s\" redirected to \"%s\"\n", cls.downloadremotename, svname);
if (CL_CheckOrEnqueDownloadFile(svname, NULL, 0))
Con_Printf("However, \"%s\" already exists. You may need to delete it.\n", svname);
}
svname = cls.downloadremotename;
}
else if (totalsize == -3)
Con_Printf("Server reported an error when downloading file \"%s\"\n", svname);
else if (totalsize == -2)
Con_Printf("Server permissions deny downloading file \"%s\"\n", svname);
@ -1698,7 +1710,10 @@ void CL_ParseChunkedDownload(void)
Host_EndGame("Received second download - \"%s\"\n", svname);
if (stricmp(cls.downloadremotename, svname))
{
//fixme: we should allow extension changes, in the case of ogg/mp3/wav, or tga/png/jpg/pcx, or the addition of .gz or whatever
Host_EndGame("Server sent the wrong download - \"%s\" instead of \"%s\"\n", svname, cls.downloadremotename);
}
//start the new download
@ -1749,6 +1764,9 @@ void CL_ParseChunkedDownload(void)
MSG_ReadData(data, DLBLOCKSIZE);
if (chunknum*DLBLOCKSIZE > downloadsize+DLBLOCKSIZE)
return;
if (!cls.downloadqw)
return;

View file

@ -141,7 +141,7 @@ void Plug_DrawReloadImages(void)
}
}
void Plug_FreePlugImages(plugin_t *plug)
static void Plug_FreePlugImages(plugin_t *plug)
{
int i;
for (i = 0; i < pluginimagearraylen; i++)
@ -277,8 +277,8 @@ qintptr_t VARGS Plug_CL_GetStats(void *offset, quintptr_t mask, const qintptr_t
if (VM_OOB(arg[1], arg[2]*4))
return 0;
if (qrenderer == QR_NONE)
return false;
if (qrenderer == QR_NONE || !cls.state)
return 0;
max = pluginstats;
if (max > MAX_CL_STATS)
@ -536,7 +536,12 @@ void Plug_Client_Close(plugin_t *plug)
}
}
void Plug_Client_Shutdown(void)
{
BZ_Free(pluginimagearray);
pluginimagearray = NULL;
pluginimagearraylen = 0;
}

View file

@ -768,7 +768,9 @@ extern cvar_t ruleset_allow_sensative_texture_replacements;
extern cvar_t ruleset_allow_localvolume;
extern cvar_t ruleset_allow_shaders;
#ifndef SERVERONLY
extern client_state_t cl;
#endif
typedef struct
{

View file

@ -810,7 +810,7 @@ static int numbootdownloads;
#include "fs.h"
#ifdef AVAIL_ZLIB
extern searchpathfuncs_t zipfilefuncs;
static int CL_BootDownload_Extract(const char *fname, int fsize, void *ptr)
static int CL_BootDownload_Extract(const char *fname, int fsize, void *ptr, void *spath)
{
char buffer[512*1024];
int read;

View file

@ -412,7 +412,7 @@ void M_Media_Draw (void)
char compleatenamepath[MAX_OSPATH];
char compleatenamename[MAX_OSPATH];
qboolean compleatenamemultiple;
int Com_CompleatenameCallback(const char *name, int size, void *data)
int Com_CompleatenameCallback(const char *name, int size, void *data, void *spath)
{
if (*compleatenamename)
compleatenamemultiple = true;
@ -431,8 +431,8 @@ void Com_CompleateOSFileName(char *name)
ending[-1] = '\0'; //strip a slash
*compleatenamename='\0';
Sys_EnumerateFiles(NULL, va("%s*", name), Com_CompleatenameCallback, NULL);
Sys_EnumerateFiles(NULL, va("%s*.*", name), Com_CompleatenameCallback, NULL);
Sys_EnumerateFiles(NULL, va("%s*", name), Com_CompleatenameCallback, NULL, NULL);
Sys_EnumerateFiles(NULL, va("%s*.*", name), Com_CompleatenameCallback, NULL, NULL);
if (*compleatenamename)
strcpy(name, compleatenamename);

View file

@ -188,7 +188,7 @@ typedef struct {
int match;
} q2skinsearch_t;
int q2skin_enumerate(const char *name, int fsize, void *parm)
int q2skin_enumerate(const char *name, int fsize, void *parm, void *spath)
{
char blah[MAX_QPATH];
q2skinsearch_t *s = parm;

View file

@ -494,7 +494,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key)
return false;
}
static int DemoAddItem(const char *filename, int size, void *parm)
static int DemoAddItem(const char *filename, int size, void *parm, void *spath)
{
int extnum;
demomenu_t *menu = parm;
@ -667,7 +667,7 @@ static void ShowDemoMenu (menu_t *menu, char *path)
if (*path)
{
Q_snprintfz(match, sizeof(match), "%s../", path);
DemoAddItem(match, 0, menu->data);
DemoAddItem(match, 0, menu->data, NULL);
}
Q_snprintfz(match, sizeof(match), "%s*", path);

View file

@ -176,6 +176,12 @@ typedef struct part_type_s {
int nummodels;
partmodels_t *models;
char soundname[MAX_QPATH];
float soundvol;
float soundattn;
float sounddelay;
float soundpitch;
vec3_t rgb; //initial colour
float alpha;
vec3_t rgbchange; //colour delta (per second)
@ -1401,6 +1407,23 @@ static void P_ParticleEffect_f(void)
else if (!strcmp(var, "nospreadlast"))
ptype->flags |= PT_NOSPREADLAST;
else if (!strcmp(var, "sound"))
{
Q_strncpyz(ptype->soundname, value, sizeof(ptype->soundname));
ptype->soundvol = atof(Cmd_Argv(2));
if (!ptype->soundvol)
ptype->soundvol = 1;
ptype->soundattn = atof(Cmd_Argv(3));
if (!ptype->soundattn)
ptype->soundattn = 1;
ptype->soundpitch = atof(Cmd_Argv(4));
if (!ptype->soundpitch)
ptype->soundpitch = 100;
ptype->sounddelay = atof(Cmd_Argv(5));
if (!ptype->sounddelay)
ptype->sounddelay = 0;
}
else if (!strcmp(var, "lightradius"))
ptype->dl_radius = atof(value);
else if (!strcmp(var, "lightradiusfade"))
@ -1554,13 +1577,16 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen)
Q_strncatz(outstr, va("spawnvel %g %g\n", ptype->spawnvel, ptype->spawnvelvert), outstrlen);
if (ptype->assoc != P_INVALID)
Q_strncatz(outstr, va("assoc %s\n", part_type[ptype->assoc].name), outstrlen);
Q_strncatz(outstr, va("assoc \"%s\"\n", part_type[ptype->assoc].name), outstrlen);
Q_strncatz(outstr, va("tcoords %g %g %g %g %g %i %g\n", ptype->s1, ptype->t1, ptype->s2, ptype->t2, 1.0f, ptype->randsmax, ptype->texsstride), outstrlen);
Q_strncatz(outstr, va("rotationstart %g %g\n", ptype->rotationstartmin*180/M_PI, (ptype->rotationstartmin+ptype->rotationstartrand)*180/M_PI), outstrlen);
Q_strncatz(outstr, va("rotationspeed %g %g\n", ptype->rotationmin*180/M_PI, (ptype->rotationmin+ptype->rotationrand)*180/M_PI), outstrlen);
if (ptype->soundvol)
Q_strncatz(outstr, va("sound \"%s\" %g %g %g %g\n", ptype->soundname, ptype->soundvol, ptype->soundattn, ptype->soundpitch, ptype->sounddelay), outstrlen);
if (ptype->dl_radius)
{
Q_strncatz(outstr, va("lightradius %g\n", ptype->dl_radius), outstrlen);
@ -2994,6 +3020,10 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir, in
if (ptype->dl_cubemapnum)
snprintf(dl->cubemapname, sizeof(dl->cubemapname), "cubemaps/%i", ptype->dl_cubemapnum);
}
if (*ptype->soundname)
{
S_StartSound(0, 0, S_PrecacheSound(ptype->soundname), org, ptype->soundvol, ptype->soundattn, ptype->sounddelay, ptype->soundpitch);
}
if (ptype->stain_radius)
R_AddStain(org, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2], ptype->stain_radius);
}

View file

@ -1056,7 +1056,6 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (csqc_poly_flags & 4)
{
mesh_t mesh;
int i;
memset(&mesh, 0, sizeof(mesh));
mesh.colors4f_array = cl_strisvertc + csqc_poly_startvert;

View file

@ -211,7 +211,7 @@ cvar_t vid_width = CVARF ("vid_width", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t r_stereo_separation = CVARD("r_stereo_separation", "4", "How far your eyes are apart, in quake units. A non-zero value will enable stereoscoping rendering. You might need some of them retro 3d glasses. Hardware support is recommended, see r_stereo_context.");
cvar_t r_stereo_method = CVARD("r_stereo_method", "0", "Value 0 = Off.\nValue 1 = Attempt hardware acceleration. Requires vid_restart.\nValue 2 = red/cyan.\nValue 3 = red/blue. Value 4=red/green");
cvar_t r_stereo_method = CVARD("r_stereo_method", "0", "Value 0 = Off.\nValue 1 = Attempt hardware acceleration. Requires vid_restart.\nValue 2 = red/cyan.\nValue 3 = red/blue.\nValue 4=red/green.\nValue 5=eye strain.");
extern cvar_t r_dodgytgafiles;
extern cvar_t r_dodgypcxfiles;

View file

@ -775,7 +775,7 @@ qboolean S_LoadSound (sfx_t *s)
return false; //it failed to load once before, don't bother trying again.
// see if still in memory
if (s->decoder.buf)
if (s->decoder.buf || s->decoder.decodedata)
return true;
if (name[1] == ':' && name[2] == '\\')

View file

@ -468,7 +468,7 @@ void Sys_SaveClipboard(char *text)
{
}
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
DIR *dir;
char apath[MAX_OSPATH];
@ -478,8 +478,8 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
struct dirent *ent;
struct stat st;
//printf("path = %s\n", gpath);
//printf("match = %s\n", match);
//printf("path = %s\n", gpath);
//printf("match = %s\n", match);
if (!gpath)
gpath = "";
@ -501,10 +501,10 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
Q_snprintfz(truepath, sizeof(truepath), "%s/%s", gpath, apath);
//printf("truepath = %s\n", truepath);
//printf("gamepath = %s\n", gpath);
//printf("apppath = %s\n", apath);
//printf("match = %s\n", match);
//printf("truepath = %s\n", truepath);
//printf("gamepath = %s\n", gpath);
//printf("apppath = %s\n", apath);
//printf("match = %s\n", match);
dir = opendir(truepath);
if (!dir)
{
@ -526,7 +526,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
{
Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":"");
if (!func(file, st.st_size, parm))
if (!func(file, st.st_size, parm, spath))
{
closedir(dir);
return false;

View file

@ -144,7 +144,7 @@ void Sys_Quit (void)
//SDL provides no file enumeration facilities.
#if defined(_WIN32)
#include <windows.h>
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
HANDLE r;
WIN32_FIND_DATA fd;
@ -191,7 +191,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
if (wildcmp(match, fd.cFileName))
{
Q_snprintfz(file, sizeof(file), "%s%s/", apath2, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
else
@ -199,7 +199,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
if (wildcmp(match, fd.cFileName))
{
Q_snprintfz(file, sizeof(file), "%s%s", apath2, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
@ -210,7 +210,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
}
#elif defined(linux) || defined(__unix__)
#include <dirent.h>
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
DIR *dir;
char apath[MAX_OSPATH];
@ -268,7 +268,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
{
Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":"");
if (!func(file, st.st_size, parm))
if (!func(file, st.st_size, parm, spath))
{
closedir(dir);
return false;
@ -284,7 +284,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
return true;
}
#else
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
Con_Printf("Warning: Sys_EnumerateFiles not implemented\n");
return false;

View file

@ -568,6 +568,7 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception
BOOL (WINAPI *pIsDebuggerPresent)(void);
#ifdef PRINTGLARRAYS
if (qrenderer == QR_OPENGL)
DumpGLState();
#endif
@ -750,7 +751,7 @@ qboolean Sys_Rename (char *oldfname, char *newfname)
return !rename(oldfname, newfname);
}
static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (*func)(const char *, int, void *), void *parm)
static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath)
{
HANDLE r;
WIN32_FIND_DATA fd;
@ -771,7 +772,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
char file[MAX_OSPATH];
if (!wild)
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm);
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm, spath);
if (nest-neststart+1> MAX_OSPATH)
return 1;
@ -802,7 +803,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot, fd.cFileName);
newnest = strlen(file);
strcpy(file+newnest, match+nest);
go = Sys_EnumerateFiles2(file, matchstart, newnest, func, parm);
go = Sys_EnumerateFiles2(file, matchstart, newnest, func, parm, spath);
}
}
}
@ -835,7 +836,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 2 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s/", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
@ -846,7 +847,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
if (strlen(tmproot+matchstart) + strlen(fd.cFileName) + 1 < MAX_OSPATH)
{
Q_snprintfz(file, sizeof(file), "%s%s", tmproot+matchstart, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
}
@ -856,7 +857,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
return go;
}
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath)
{
char fullmatch[MAX_OSPATH];
int start;
@ -869,7 +870,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
fullmatch[start++] = '/';
fullmatch[start] = 0;
strcat(fullmatch, match);
return Sys_EnumerateFiles2(fullmatch, start, start, func, parm);
return Sys_EnumerateFiles2(fullmatch, start, start, func, parm, spath);
}
/*
@ -1077,6 +1078,10 @@ void VARGS Sys_Printf (char *fmt, ...)
char text[1024];
DWORD dummy;
conchar_t msg[1024], *end, *in;
wchar_t wide[1024], *out;
int wlen;
if (!houtput && !debugout)
return;
@ -1084,24 +1089,24 @@ void VARGS Sys_Printf (char *fmt, ...)
vsnprintf (text, sizeof(text), fmt, argptr);
va_end (argptr);
if (debugout)
{
//msvc debug output
conchar_t msg[1024], *end, *in;
wchar_t wide[1024], *out;
end = COM_ParseFunString(CON_WHITEMASK, text, msg, sizeof(msg), false);
out = wide;
in = msg;
wlen = 0;
for (in = msg; in < end; in++)
{
if (!(*in & CON_HIDDEN))
{
*out++ = dequake(*in & CON_CHARMASK);
wlen++;
}
}
*out = 0;
if (debugout)
OutputDebugStringW(wide);
}
if (houtput)
WriteFile (houtput, text, strlen(text), &dummy, NULL);
WriteConsoleW(houtput, wide, wlen, &dummy, NULL);
}
void Sys_Quit (void)
@ -1435,8 +1440,8 @@ char *Sys_ConsoleInput (void)
}
} else if (ch >= ' ')
{
i = utf8_encode(text+len, ch, sizeof(text)-1-len);
WriteFile(houtput, text+len, i, &dummy, NULL);
wchar_t wch = ch;
WriteConsoleW(houtput, &wch, 1, &dummy, NULL);
len += i;
}

View file

@ -1193,6 +1193,8 @@ entity_t *CL_EntityNum(int num)
float CalcFov (float fov_x, float width, float height);
void SCR_VRectForPlayer(vrect_t *vrect, int pnum)
{
float ws;
extern cvar_t r_stereo_method, r_stereo_separation;
#if MAX_SPLITS > 4
#pragma warning "Please change this function to cope with the new MAX_SPLITS value"
#endif
@ -1250,15 +1252,19 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum)
if (cl.playerview[pnum].stats[STAT_VIEWZOOM])
r_refdef.fov_x *= cl.playerview[pnum].stats[STAT_VIEWZOOM]/255.0f;
if (vrect->width < (vrect->height*640)/432)
ws = 1;
if (r_stereo_method.ival == 5 && r_stereo_separation.value)
ws = 0.5;
if (ws*vrect->width < (vrect->height*640)/432)
{
r_refdef.fov_y = CalcFov(r_refdef.fov_x, (vrect->width*vid.pixelwidth)/vid.width, (vrect->height*vid.pixelheight)/vid.height);
r_refdef.fov_y = CalcFov(r_refdef.fov_x, (ws*vrect->width*vid.pixelwidth)/vid.width, (vrect->height*vid.pixelheight)/vid.height);
// r_refdef.fov_x = CalcFov(r_refdef.fov_y, 432, 640);
}
else
{
r_refdef.fov_y = CalcFov(r_refdef.fov_x, 640, 432);
r_refdef.fov_x = CalcFov(r_refdef.fov_y, vrect->height, vrect->width);
r_refdef.fov_x = CalcFov(r_refdef.fov_y, vrect->height, vrect->width*ws);
}
}

View file

@ -103,6 +103,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define AVAIL_D3D
#endif
#if defined(_WIN32) && !defined(_SDL)
#define HAVE_SSL
#endif
//#define DYNAMIC_ZLIB
//#define DYNAMIC_LIBPNG
//#define DYNAMIC_LIBJPEG

View file

@ -2115,7 +2115,7 @@ static qboolean VARGS Mod_TryAddSkin(const char *skinname, ...)
return true;
}
int Mod_EnumerateSkins(const char *name, int size, void *param)
int Mod_EnumerateSkins(const char *name, int size, void *param, void *spath)
{
Mod_TryAddSkin(name);
return true;

View file

@ -2469,7 +2469,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
int decodeerror;
char *end;
uc = utf8_decode(&decodeerror, str, &end);
if (decodeerror)
if (decodeerror && !(utf8 & 2))
{
utf8 &= ~1;
//malformed encoding we just drop through and stop trying to decode.
@ -2486,7 +2486,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
continue;
}
}
if (*str == '^')
if (*str == '^' && !(flags & PFS_NOMARKUP))
{
if (str[1] >= '0' && str[1] <= '9')
{
@ -2664,7 +2664,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
continue;
}
}
else if (*str == '&' && str[1] == 'c')
else if (*str == '&' && str[1] == 'c' && !(flags & PFS_NOMARKUP))
{
// ezQuake color codes
@ -2704,7 +2704,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
}
}
}
else if (*str == '&' && str[1] == 'r')
else if (*str == '&' && str[1] == 'r' && !(flags & PFS_NOMARKUP))
{
ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~(CON_RICHFOREMASK|CON_RICHFORECOLOUR));
if (!keepmarkup)

View file

@ -292,8 +292,9 @@ void COM_ParsePlusSets (void);
typedef unsigned int conchar_t;
char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags);
#define PFS_KEEPMARKUP 1
#define PFS_FORCEUTF8 2
#define PFS_KEEPMARKUP 1 //leave markup in the final string (but do parse it)
#define PFS_FORCEUTF8 2 //force utf-8 decoding
#define PFS_NOMARKUP 4 //strip markup completely
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, int keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
unsigned int utf8_decode(int *error, const void *in, char **out);
unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen);
@ -406,7 +407,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out
qboolean FS_WriteFile (const char *filename, const void *data, int len, enum fs_relative relativeto);
vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto);
vfsfile_t *FS_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
void FS_UnloadPackFiles(void);
void FS_ReloadPackFiles(void);
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum);
@ -441,7 +442,7 @@ qbyte *COM_LoadFile (const char *path, int usehunk);
qboolean COM_LoadMapPackFile(const char *name, int offset);
void COM_FlushTempoaryPacks(void);
void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm);
void COM_EnumerateFiles (const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm);
extern struct cvar_s registered;
extern qboolean standard_quake; //fixme: remove

View file

@ -227,9 +227,19 @@ COM_Dir_f
============
*/
static int COM_Dir_List(const char *name, int size, void *parm)
static int COM_Dir_List(const char *name, int size, void *parm, void *spath)
{
Con_Printf("%s (%i)\n", name, size);
char pbuf[MAX_OSPATH] = "??";
searchpath_t *s;
for (s=com_searchpaths ; s ; s=s->next)
{
if (s->handle == spath)
{
s->funcs->GetDisplayPath(s->handle, pbuf, sizeof(pbuf));
break;
}
}
Con_Printf("%s (%i) (%s)\n", name, size, pbuf);
return 1;
}
@ -693,7 +703,7 @@ char *FS_GetPackNames(char *buffer, int buffersize, int referencedonly, qboolean
// '*' prefix is meant to mean 'referenced'.
//really all that means to the client is that it definitely wants to download it.
//if its copyrighted, the client shouldn't try to do so, as it won't be allowed.
if (search->copyprotected)
if (!search->copyprotected)
Q_strncatz(buffer, "*", buffersize);
}
@ -1214,7 +1224,7 @@ void FS_FreeFile(void *file)
void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm)
void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *, void *), void *parm)
{
searchpath_t *search;
for (search = com_searchpaths; search ; search = search->next)
@ -1338,7 +1348,7 @@ typedef struct {
const char *puredesc;
} wildpaks_t;
static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam)
static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam, struct searchpath_s *path)
{
wildpaks_t *param = vparam;
vfsfile_t *vfs;

View file

@ -8,7 +8,7 @@ extern hashtable_t filesystemhash; //this table is the one to build your hash re
extern int fs_hash_dups; //for tracking efficiency. no functional use.
extern int fs_hash_files; //for tracking efficiency. no functional use.
struct searchpath_s;
typedef struct {
void (*GetDisplayPath)(void *handle, char *outpath, unsigned int pathsize);
void (*ClosePath)(void *handle);
@ -17,7 +17,7 @@ typedef struct {
//note that if rawfile and offset are set, many Com_FileOpens will read the raw file
//otherwise ReadFile will be called instead.
void (*ReadFile)(void *handle, flocation_t *loc, char *buffer); //reads the entire file in one go (size comes from loc, so make sure the loc is valid, this is for performance with compressed archives)
int (*EnumerateFiles)(void *handle, const char *match, int (*func)(const char *, int, void *), void *parm);
int (*EnumerateFiles)(void *handle, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm);
void *(*OpenNew)(vfsfile_t *file, const char *desc); //returns a handle to a new pak/path

View file

@ -126,7 +126,7 @@ qboolean FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, voi
}
return false;
}
int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm)
{
pack_t *pak = handle;
int num;
@ -135,7 +135,7 @@ int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const cha
{
if (wildcmp(match, pak->files[num].name))
{
if (!func(pak->files[num].name, pak->files[num].filelen, parm))
if (!func(pak->files[num].name, pak->files[num].filelen, parm, handle))
return false;
}
}

View file

@ -240,7 +240,7 @@ static void *FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc)
}
return np;
}
static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data)
static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data, void *spath)
{
stdiopath_t *sp = data;
if (filename[strlen(filename)-1] == '/')
@ -248,7 +248,7 @@ static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data)
char childpath[256];
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
Sys_EnumerateFiles(sp->rootpath, childpath, FSSTDIO_RebuildFSHash, data);
Sys_EnumerateFiles(sp->rootpath, childpath, FSSTDIO_RebuildFSHash, data, spath);
return true;
}
FS_AddFileHash(sp->depth, filename, NULL, sp);
@ -258,7 +258,7 @@ static void FSSTDIO_BuildHash(void *handle, int depth)
{
stdiopath_t *sp = handle;
sp->depth = depth;
Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, handle);
Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, handle, handle);
}
static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult)
{
@ -326,10 +326,10 @@ static void FSSTDIO_ReadFile(void *handle, flocation_t *loc, char *buffer)
fclose(f);
}
static int FSSTDIO_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
static int FSSTDIO_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm)
{
stdiopath_t *sp = handle;
return Sys_EnumerateFiles(sp->rootpath, match, func, parm);
return Sys_EnumerateFiles(sp->rootpath, match, func, parm, handle);
}
searchpathfuncs_t stdiofilefuncs = {

View file

@ -243,7 +243,7 @@ static void *VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc)
}
return np;
}
static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle)
static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, void *spath)
{
vfsw32path_t *wp = handle;
if (filename[strlen(filename)-1] == '/')
@ -251,7 +251,7 @@ static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle
char childpath[256];
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, wp);
Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, wp, handle);
return true;
}
@ -262,7 +262,7 @@ static void VFSW32_BuildHash(void *handle, int hashdepth)
{
vfsw32path_t *wp = handle;
wp->hashdepth = hashdepth;
Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, handle);
Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, handle, handle);
}
static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult)
{
@ -315,10 +315,10 @@ static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer)
fread(buffer, 1, loc->len, f);
fclose(f);
}
static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm)
{
vfsw32path_t *wp = handle;
return Sys_EnumerateFiles(wp->rootpath, match, func, parm);
return Sys_EnumerateFiles(wp->rootpath, match, func, parm, handle);
}

View file

@ -337,7 +337,7 @@ static void FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer)
return;
}
static int FSZIP_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
static int FSZIP_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm)
{
zipfile_t *zip = handle;
int num;
@ -346,7 +346,7 @@ static int FSZIP_EnumerateFiles (void *handle, const char *match, int (*func)(co
{
if (wildcmp(match, zip->files[num].name))
{
if (!func(zip->files[num].name, zip->files[num].filelen, parm))
if (!func(zip->files[num].name, zip->files[num].filelen, parm, handle))
return false;
}
}

View file

@ -25,7 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define HAVE_WEBSOCKCL
#endif
typedef enum {NA_INVALID, NA_LOOPBACK, NA_IP, NA_IPV6, NA_IPX, NA_BROADCAST_IP, NA_BROADCAST_IP6, NA_BROADCAST_IPX, NA_TCP, NA_TCPV6, NA_IRC, NA_WEBSOCKET} netadrtype_t;
//FIXME: should split this into loopback/dgram/stream/irc
//with the ipv4/v6/x as a separate parameter
typedef enum {NA_INVALID, NA_LOOPBACK, NA_IP, NA_IPV6, NA_IPX, NA_BROADCAST_IP, NA_BROADCAST_IP6, NA_BROADCAST_IPX, NA_TCP, NA_TCPV6, NA_IRC, NA_WEBSOCKET, NA_NATPMP} netadrtype_t;
typedef enum {NS_CLIENT, NS_SERVER} netsrc_t;
@ -80,8 +82,10 @@ int TCP_OpenStream (netadr_t remoteaddr); //makes things easier
struct ftenet_connections_s;
void NET_Init (void);
void SVNET_RegisterCvars(void);
void NET_InitClient (void);
void NET_InitServer (void);
qboolean NET_WasSpecialPacket(void);
void NET_CloseServer (void);
void UDP_CloseSocket (int socket);
void NET_Shutdown (void);
@ -98,6 +102,7 @@ char *NET_AdrToString (char *s, int len, netadr_t a);
char *NET_BaseAdrToString (char *s, int len, netadr_t a);
qboolean NET_StringToSockaddr (const char *s, int defaultport, struct sockaddr_qstorage *sadr, int *addrfamily, int *addrsize);
qboolean NET_StringToAdr (const char *s, int defaultport, netadr_t *a);
qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a);
qboolean NET_IsClientLegal(netadr_t *adr);
qboolean NET_IsLoopBackAddress (netadr_t adr);
@ -107,9 +112,7 @@ char *NET_AdrToStringMasked (char *s, int len, netadr_t a, netadr_t amask);
void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits);
qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask);
struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboolean isserver, const char *address);
qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, struct ftenet_generic_connection_s *(*establish)(qboolean isserver, const char *address), qboolean islisten);
qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, netadrtype_t addrtype, qboolean islisten);
//============================================================================

View file

@ -0,0 +1,624 @@
#include "quakedef.h"
#if defined(_WIN32) && !defined(_SDL) && defined(HAVE_SSL)
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#include <sspi.h>
#include <schannel.h>
//hungarian ensures we hit no macros.
static struct
{
void *lib;
SECURITY_STATUS (WINAPI *pDecryptMessage) (PCtxtHandle,PSecBufferDesc,ULONG,PULONG);
SECURITY_STATUS (WINAPI *pEncryptMessage) (PCtxtHandle,ULONG,PSecBufferDesc,ULONG);
SECURITY_STATUS (WINAPI *pAcquireCredentialsHandleA) (SEC_CHAR*,SEC_CHAR*,ULONG,PLUID,PVOID,SEC_GET_KEY_FN,PVOID,PCredHandle,PTimeStamp);
SECURITY_STATUS (WINAPI *pInitializeSecurityContextA) (PCredHandle,PCtxtHandle,SEC_CHAR*,ULONG,ULONG,ULONG,PSecBufferDesc,ULONG,PCtxtHandle,PSecBufferDesc,PULONG,PTimeStamp);
SECURITY_STATUS (WINAPI *pCompleteAuthToken) (PCtxtHandle,PSecBufferDesc);
SECURITY_STATUS (WINAPI *pQueryContextAttributesA) (PCtxtHandle,ULONG,PVOID);
SECURITY_STATUS (WINAPI *pFreeCredentialsHandle) (PCredHandle);
SECURITY_STATUS (WINAPI *pDeleteSecurityContext) (PCtxtHandle);
} secur;
static struct
{
void *lib;
BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*);
BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS);
void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT);
} crypt;
static qboolean SSL_Init(void)
{
dllfunction_t secur_functable[] =
{
{(void**)&secur.pDecryptMessage, "DecryptMessage"},
{(void**)&secur.pEncryptMessage, "EncryptMessage"},
{(void**)&secur.pAcquireCredentialsHandleA, "AcquireCredentialsHandleA"},
{(void**)&secur.pInitializeSecurityContextA, "InitializeSecurityContextA"},
{(void**)&secur.pCompleteAuthToken, "CompleteAuthToken"},
{(void**)&secur.pQueryContextAttributesA, "QueryContextAttributesA"},
{(void**)&secur.pFreeCredentialsHandle, "FreeCredentialsHandle"},
{(void**)&secur.pDeleteSecurityContext, "DeleteSecurityContext"},
{NULL, NULL}
};
dllfunction_t crypt_functable[] =
{
{(void**)&crypt.pCertGetCertificateChain, "CertGetCertificateChain"},
{(void**)&crypt.pCertVerifyCertificateChainPolicy, "CertVerifyCertificateChainPolicy"},
{(void**)&crypt.pCertFreeCertificateChain, "CertFreeCertificateChain"},
{NULL, NULL}
};
if (!secur.lib)
secur.lib = Sys_LoadLibrary("secur32.dll", secur_functable);
if (!crypt.lib)
crypt.lib = Sys_LoadLibrary("crypt32.dll", crypt_functable);
return !!secur.lib && !!crypt.lib;
}
#define MessageAttribute (ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_MANUAL_CRED_VALIDATION)
struct sslbuf
{
char data[8192];
int avail;
int newd;
};
typedef struct {
vfsfile_t funcs;
vfsfile_t *stream;
wchar_t wpeername[256];
enum
{
HS_ESTABLISHED,
HS_STARTCLIENT,
HS_CLIENT,
HS_STARTSERVER,
HS_SERVER
} handshaking;
struct sslbuf outraw;
struct sslbuf outcrypt;
struct sslbuf inraw;
struct sslbuf incrypt;
CredHandle cred;
SecHandle sechnd;
int headersize, footersize;
char headerdata[1024], footerdata[1024];
} sslfile_t;
static int SSPI_CopyIntoBuffer(struct sslbuf *buf, const void *data, unsigned int bytes)
{
if (bytes > sizeof(buf->data) - buf->avail)
bytes = sizeof(buf->data) - buf->avail;
memcpy(buf->data + buf->avail, data, bytes);
buf->avail += bytes;
return bytes;
}
static void SSPI_Error(sslfile_t *f, char *error)
{
Sys_Printf("%s", error);
if (f->stream)
VFS_CLOSE(f->stream);
secur.pDeleteSecurityContext(&f->sechnd);
secur.pFreeCredentialsHandle(&f->cred);
f->stream = NULL;
}
static void SSPI_TryFlushCryptOut(sslfile_t *f)
{
int sent;
if (f->outcrypt.avail)
sent = VFS_WRITE(f->stream, f->outcrypt.data, f->outcrypt.avail);
else
return;
if (sent > 0)
{
memmove(f->outcrypt.data, f->outcrypt.data + sent, f->outcrypt.avail - sent);
f->outcrypt.avail -= sent;
}
}
static int SSPI_CheckNewInCrypt(sslfile_t *f)
{
int newd;
if (!f->stream)
return -1;
newd = VFS_READ(f->stream, f->incrypt.data+f->incrypt.avail, sizeof(f->incrypt.data) - f->incrypt.avail);
if (newd < 0)
return newd;
else
f->incrypt.avail += newd;
return 0;
}
//convert inbound crypt->data
static void SSPI_Decode(sslfile_t *f)
{
SECURITY_STATUS ss;
SecBufferDesc BuffDesc;
SecBuffer SecBuff[4];
ULONG ulQop = 0;
SecBuffer *data = NULL;
SecBuffer *extra = NULL;
int i;
if (!f->incrypt.avail)
return;
BuffDesc.ulVersion = SECBUFFER_VERSION;
BuffDesc.cBuffers = 4;
BuffDesc.pBuffers = SecBuff;
SecBuff[0].BufferType = SECBUFFER_DATA;
SecBuff[0].cbBuffer = f->incrypt.avail;
SecBuff[0].pvBuffer = f->incrypt.data;
SecBuff[1].BufferType = SECBUFFER_EMPTY; //space for header
SecBuff[2].BufferType = SECBUFFER_EMPTY; //space for footer
SecBuff[3].BufferType = SECBUFFER_EMPTY; //space for extra marker
ss = secur.pDecryptMessage(&f->sechnd, &BuffDesc, 0, &ulQop);
if (ss < 0)
{
SSPI_Error(f, "DecryptMessage failed");
return;
}
for (i = 0; i < BuffDesc.cBuffers; i++)
{
if (SecBuff[i].BufferType == SECBUFFER_DATA && !data)
data = &SecBuff[i];
if (SecBuff[i].BufferType == SECBUFFER_EXTRA && !extra)
extra = &SecBuff[i];
}
//copy the data out to the result, yay.
if (data)
SSPI_CopyIntoBuffer(&f->inraw, data->pvBuffer, data->cbBuffer);
//retain the extra. if there's no extra then mark it so.
if (extra)
{
memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - extra->cbBuffer), extra->cbBuffer);
f->incrypt.avail = extra->cbBuffer;
}
else
f->incrypt.avail = 0;
}
//convert outgoing data->crypt
static void SSPI_Encode(sslfile_t *f)
{
SECURITY_STATUS ss;
SecBufferDesc BuffDesc;
SecBuffer SecBuff[4];
ULONG ulQop = 0;
if (f->outcrypt.avail)
{
SSPI_TryFlushCryptOut(f);
if (f->outcrypt.avail)
return; //don't flood too much
}
//don't corrupt the handshake data.
if (f->handshaking)
return;
if (!f->outraw.avail)
return;
BuffDesc.ulVersion = SECBUFFER_VERSION;
BuffDesc.cBuffers = 4;
BuffDesc.pBuffers = SecBuff;
SecBuff[0].BufferType = SECBUFFER_STREAM_HEADER;
SecBuff[0].cbBuffer = f->headersize;
SecBuff[0].pvBuffer = f->headerdata;
SecBuff[1].BufferType = SECBUFFER_DATA;
SecBuff[1].cbBuffer = f->outraw.avail;
SecBuff[1].pvBuffer = f->outraw.data;
SecBuff[2].BufferType = SECBUFFER_STREAM_TRAILER;
SecBuff[2].cbBuffer = f->footersize;
SecBuff[2].pvBuffer = f->footerdata;
SecBuff[3].BufferType = SECBUFFER_EMPTY;
ss = secur.pEncryptMessage(&f->sechnd, ulQop, &BuffDesc, 0);
if (ss < 0)
{
SSPI_Error(f, "EncryptMessage failed");
return;
}
f->outraw.avail = 0;
//fixme: these should be made non-fatal.
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer) < SecBuff[0].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed");
return;
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer) < SecBuff[1].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed");
return;
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer) < SecBuff[2].cbBuffer)
{
SSPI_Error(f, "crypt buffer overflowed");
return;
}
SSPI_TryFlushCryptOut(f);
}
static DWORD VerifyServerCertificate(PCCERT_CONTEXT pServerCert, PWSTR pwszServerName, DWORD dwCertFlags)
{
HTTPSPolicyCallbackData polHttps;
CERT_CHAIN_POLICY_PARA PolicyPara;
CERT_CHAIN_POLICY_STATUS PolicyStatus;
CERT_CHAIN_PARA ChainPara;
PCCERT_CHAIN_CONTEXT pChainContext;
DWORD Status;
LPSTR rgszUsages[] =
{
szOID_PKIX_KP_SERVER_AUTH,
szOID_SERVER_GATED_CRYPTO,
szOID_SGC_NETSCAPE
};
DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
if(pServerCert == NULL)
return SEC_E_WRONG_PRINCIPAL;
if(!*pwszServerName)
return SEC_E_WRONG_PRINCIPAL;
// Build certificate chain.
memset(&ChainPara, 0, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
ChainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages;
ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;
if (!crypt.pCertGetCertificateChain(NULL, pServerCert, NULL, pServerCert->hCertStore, &ChainPara, 0, NULL, &pChainContext))
{
Status = GetLastError();
Sys_Printf("Error 0x%x returned by CertGetCertificateChain!\n", Status);
}
else
{
// Validate certificate chain.
memset(&polHttps, 0, sizeof(HTTPSPolicyCallbackData));
polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
polHttps.dwAuthType = AUTHTYPE_SERVER;
polHttps.fdwChecks = dwCertFlags;
polHttps.pwszServerName = pwszServerName;
memset(&PolicyPara, 0, sizeof(PolicyPara));
PolicyPara.cbSize = sizeof(PolicyPara);
PolicyPara.pvExtraPolicyPara = &polHttps;
memset(&PolicyStatus, 0, sizeof(PolicyStatus));
PolicyStatus.cbSize = sizeof(PolicyStatus);
if (!crypt.pCertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus))
{
Status = GetLastError();
Sys_Printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!\n", Status);
}
else
{
if (PolicyStatus.dwError)
{
char *err;
Status = PolicyStatus.dwError;
switch (Status)
{
case CERT_E_EXPIRED: err = "CERT_E_EXPIRED"; break;
case CERT_E_VALIDITYPERIODNESTING: err = "CERT_E_VALIDITYPERIODNESTING"; break;
case CERT_E_ROLE: err = "CERT_E_ROLE"; break;
case CERT_E_PATHLENCONST: err = "CERT_E_PATHLENCONST"; break;
case CERT_E_CRITICAL: err = "CERT_E_CRITICAL"; break;
case CERT_E_PURPOSE: err = "CERT_E_PURPOSE"; break;
case CERT_E_ISSUERCHAINING: err = "CERT_E_ISSUERCHAINING"; break;
case CERT_E_MALFORMED: err = "CERT_E_MALFORMED"; break;
case CERT_E_UNTRUSTEDROOT: err = "CERT_E_UNTRUSTEDROOT"; break;
case CERT_E_CHAINING: err = "CERT_E_CHAINING"; break;
case TRUST_E_FAIL: err = "TRUST_E_FAIL"; break;
case CERT_E_REVOKED: err = "CERT_E_REVOKED"; break;
case CERT_E_UNTRUSTEDTESTROOT: err = "CERT_E_UNTRUSTEDTESTROOT"; break;
case CERT_E_REVOCATION_FAILURE: err = "CERT_E_REVOCATION_FAILURE"; break;
case CERT_E_CN_NO_MATCH: err = "CERT_E_CN_NO_MATCH"; break;
case CERT_E_WRONG_USAGE: err = "CERT_E_WRONG_USAGE"; break;
default: err = "(unknown)"; break;
}
Sys_Printf("Error verifying certificate for %s: %s\n", pwszServerName, err);
}
else
Status = SEC_E_OK;
}
crypt.pCertFreeCertificateChain(pChainContext);
}
return Status;
}
static void SSPI_Handshake (sslfile_t *f)
{
SECURITY_STATUS ss;
TimeStamp Lifetime;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff[2];
ULONG ContextAttributes;
SCHANNEL_CRED SchannelCred;
if (f->outcrypt.avail)
{
//don't let things build up too much
SSPI_TryFlushCryptOut(f);
if (f->outcrypt.avail)
return;
}
OutBuffDesc.ulVersion = SECBUFFER_VERSION;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = sizeof(f->outcrypt.data) - f->outcrypt.avail;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = f->outcrypt.data + f->outcrypt.avail;
if (f->handshaking == HS_STARTCLIENT)
{
//no input data yet.
f->handshaking = HS_CLIENT;
memset(&SchannelCred, 0, sizeof(SchannelCred));
SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1 | SP_PROT_SSL3;
SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; /*don't use windows login info or anything*/
ss = secur.pAcquireCredentialsHandleA (NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &f->cred, &Lifetime);
if (ss < 0)
{
SSPI_Error(f, "AcquireCredentialsHandle failed\n");
return;
}
ss = secur.pInitializeSecurityContextA (&f->cred, NULL, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, NULL, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime);
}
else
{
//only if we actually have data.
if (!f->incrypt.avail)
return;
InBuffDesc.ulVersion = SECBUFFER_VERSION;
InBuffDesc.cBuffers = 2;
InBuffDesc.pBuffers = InSecBuff;
InSecBuff[0].BufferType = SECBUFFER_TOKEN;
InSecBuff[0].cbBuffer = f->incrypt.avail;
InSecBuff[0].pvBuffer = f->incrypt.data;
InSecBuff[1].BufferType = SECBUFFER_EMPTY;
InSecBuff[1].pvBuffer = NULL;
InSecBuff[1].cbBuffer = 0;
ss = secur.pInitializeSecurityContextA (&f->cred, &f->sechnd, NULL, MessageAttribute, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, &f->sechnd, &OutBuffDesc, &ContextAttributes, &Lifetime);
if (ss == SEC_E_INCOMPLETE_MESSAGE)
return;
//any extra data should still remain for the next time around. this might be more handshake data or payload data.
if (InSecBuff[1].BufferType == SECBUFFER_EXTRA)
{
memmove(f->incrypt.data, f->incrypt.data + (f->incrypt.avail - InSecBuff[1].cbBuffer), InSecBuff[1].cbBuffer);
f->incrypt.avail = InSecBuff[1].cbBuffer;
}
else f->incrypt.avail = 0;
}
if (ss == SEC_I_INCOMPLETE_CREDENTIALS)
{
SSPI_Error(f, "server requires credentials\n");
return;
}
if (ss < 0)
{
SSPI_Error(f, "InitializeSecurityContext failed\n");
return;
}
if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))
{
ss = secur.pCompleteAuthToken (&f->sechnd, &OutBuffDesc);
if (ss < 0)
{
SSPI_Error(f, "CompleteAuthToken failed\n");
return;
}
}
if (SSPI_CopyIntoBuffer(&f->outcrypt, OutSecBuff.pvBuffer, OutSecBuff.cbBuffer) < OutSecBuff.cbBuffer)
{
SSPI_Error(f, "crypt overflow\n");
return;
}
//send early, send often.
SSPI_TryFlushCryptOut(f);
//its all okay and established if we get this far.
if (ss == SEC_E_OK)
{
SecPkgContext_StreamSizes strsizes;
CERT_CONTEXT *remotecert;
secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_STREAM_SIZES, &strsizes);
f->headersize = strsizes.cbHeader;
f->footersize = strsizes.cbTrailer;
f->handshaking = HS_ESTABLISHED;
if (*f->wpeername)
{
ss = secur.pQueryContextAttributesA(&f->sechnd, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &remotecert);
if (ss != SEC_E_OK)
{
SSPI_Error(f, "unable to read server's certificate\n");
return;
}
if (VerifyServerCertificate(remotecert, f->wpeername, 0))
SSPI_Error(f, "Error validating certificante");
}
else
Sys_Printf("SSL/TLS Server name not specified, skipping verification\n");
SSPI_Encode(f);
}
}
static int SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
{
sslfile_t *f = (sslfile_t *)file;
int err = SSPI_CheckNewInCrypt(f);
if (f->handshaking)
{
SSPI_Handshake(f);
return err;
}
SSPI_Encode(f);
SSPI_Decode(f);
bytestoread = min(bytestoread, f->inraw.avail);
if (bytestoread)
{
memcpy(buffer, f->inraw.data, bytestoread);
f->inraw.avail -= bytestoread;
memmove(f->inraw.data, f->inraw.data + bytestoread, f->inraw.avail);
}
else
{
if (err)
return err;
}
return bytestoread;
}
static int SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite)
{
sslfile_t *f = (sslfile_t *)file;
bytestowrite = SSPI_CopyIntoBuffer(&f->outraw, buffer, bytestowrite);
if (f->handshaking)
{
SSPI_CheckNewInCrypt(f); //make sure its ticking over
SSPI_Handshake(f);
}
else
{
SSPI_Encode(f);
}
return bytestowrite;
}
static qboolean SSPI_Seek (struct vfsfile_s *file, unsigned long pos)
{
SSPI_Error((sslfile_t*)file, "unable to seek on streams");
return false;
}
static unsigned long SSPI_Tell (struct vfsfile_s *file)
{
SSPI_Error((sslfile_t*)file, "unable to seek on streams");
return 0;
}
static unsigned long SSPI_GetLen (struct vfsfile_s *file)
{
return 0;
}
static void SSPI_Close (struct vfsfile_s *file)
{
SSPI_Error((sslfile_t*)file, "");
Z_Free(file);
}
#include <wchar.h>
vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server)
{
sslfile_t *newf;
int i = 0;
int err;
unsigned int c;
if (!source || !SSL_Init())
{
VFS_CLOSE(source);
return NULL;
}
if (!hostname)
hostname = "";
if (server) //unsupported
{
VFS_CLOSE(source);
return NULL;
}
newf = Z_Malloc(sizeof(*newf));
while(*hostname)
{
c = utf8_decode(&err, hostname, (void*)&hostname);
if (c > WCHAR_MAX)
err = true; //no 16bit surrogates. they're evil.
else if (i == sizeof(newf->wpeername)/sizeof(newf->wpeername[0]) - 1)
err = true; //no space to store it
else
newf->wpeername[i++] = c;
if (err)
{
Z_Free(newf);
VFS_CLOSE(source);
return NULL;
}
}
newf->wpeername[i] = 0;
newf->handshaking = server?HS_STARTSERVER:HS_STARTCLIENT;
newf->stream = source;
newf->funcs.Close = SSPI_Close;
newf->funcs.Flush = NULL;
newf->funcs.GetLen = SSPI_GetLen;
newf->funcs.ReadBytes = SSPI_ReadBytes;
newf->funcs.Seek = SSPI_Seek;
newf->funcs.Tell = SSPI_Tell;
newf->funcs.WriteBytes = SSPI_WriteBytes;
newf->funcs.seekingisabadplan = true;
return &newf->funcs;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -344,7 +344,7 @@ plugin_t *Plug_Load(char *file)
return newplug;
}
static int Plug_Emumerated (const char *name, int size, void *param)
static int Plug_Emumerated (const char *name, int size, void *param, struct searchpath_s *spath)
{
char vmname[MAX_QPATH];
Q_strncpyz(vmname, name, sizeof(vmname));
@ -745,14 +745,14 @@ typedef enum{
STREAM_NONE,
STREAM_SOCKET,
STREAM_TLS,
STREAM_OSFILE,
STREAM_FILE
STREAM_VFS
} plugstream_e;
typedef struct {
plugin_t *plugin;
plugstream_e type;
int socket;
vfsfile_t *vfs;
struct {
char filename[MAX_QPATH];
qbyte *buffer;
@ -770,7 +770,7 @@ int pluginstreamarraylen;
static int Plug_NewStreamHandle(plugstream_e type)
{
int i;
for (i = 1; i < pluginstreamarraylen; i++)
for (i = 0; i < pluginstreamarraylen; i++)
{
if (!pluginstreamarray[i].plugin)
break;
@ -906,50 +906,49 @@ qintptr_t VARGS Plug_Net_TCPConnect(void *offset, quintptr_t mask, const qintptr
unsigned short remoteport = VM_LONG(arg[1]);
int handle;
struct sockaddr_qstorage to, from;
int sock;
int _true = 1;
netadr_t a;
if (!NET_StringToAdr(remoteip, remoteport, &a))
vfsfile_t *stream = FS_OpenTCP(remoteip, remoteport);
if (!stream)
return -1;
NetadrToSockadr(&a, &to);
if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
return -2;
}
memset(&from, 0, sizeof(from));
((struct sockaddr*)&from)->sa_family = ((struct sockaddr*)&to)->sa_family;
if (bind(sock, (struct sockaddr *)&from, sizeof(from)) == -1)
{
return -2;
}
//not yet blocking. So no frequent attempts please...
//non blocking prevents connect from returning worthwhile sensible value.
if (connect(sock, (struct sockaddr *)&to, sizeof(to)) == -1)
{
closesocket(sock);
return -2;
}
if (ioctlsocket (sock, FIONBIO, (u_long *)&_true) == -1) //now make it non blocking.
{
return -1;
}
handle = Plug_NewStreamHandle(STREAM_SOCKET);
pluginstreamarray[handle].socket = sock;
handle = Plug_NewStreamHandle(STREAM_VFS);
pluginstreamarray[handle].vfs = stream;
return handle;
}
void Plug_Net_Close_Internal(int handle);
vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server);
#ifdef HAVE_SSL
qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintptr_t *arg)
{
pluginstream_t *stream;
int handle = VM_LONG(arg[0]);
qboolean anon = false;
if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
{
Con_Printf("Plug_Net_SetTLSClient: socket does not belong to you (or is invalid)\n");
return -2;
}
stream = &pluginstreamarray[handle];
if (stream->type != STREAM_VFS)
{ //not a socket - invalid
Con_Printf("Plug_Net_SetTLSClient: Not a socket handle\n");
return -2;
}
stream->vfs = FS_OpenSSL(VM_POINTER(arg[1]), stream->vfs, false);
if (!stream->vfs)
{
Plug_Net_Close_Internal(handle);
return -1;
}
return 0;
}
#endif
#ifdef GNUTLS
qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, unsigned int mask, const qintptr_t *arg)
qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintptr_t *arg)
{
static gnutls_anon_client_credentials anoncred;
static gnutls_certificate_credentials xcred;
@ -1058,47 +1057,32 @@ qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg
int handle;
int *ret;
char *data;
//char *data;
char *mode;
vfsfile_t *f;
if (VM_OOB(arg[1], sizeof(int)))
return -2;
ret = VM_POINTER(arg[1]);
if (arg[2] == 1)
switch(arg[2])
{
FS_LoadFile(VM_POINTER(arg[0]), (void**)&data);
if (!data)
return -1;
handle = Plug_NewStreamHandle(STREAM_FILE);
pluginstreamarray[handle].file.buffer = data;
pluginstreamarray[handle].file.curpos = 0;
pluginstreamarray[handle].file.curlen = com_filesize;
pluginstreamarray[handle].file.buflen = com_filesize;
*ret = handle;
return com_filesize;
}
else if (arg[2] == 2)
{
data = BZ_Malloc(8192);
if (!data)
return -1;
handle = Plug_NewStreamHandle(STREAM_FILE);
Q_strncpyz(pluginstreamarray[handle].file.filename, VM_POINTER(arg[0]), MAX_QPATH);
pluginstreamarray[handle].file.buffer = data;
pluginstreamarray[handle].file.curpos = 0;
pluginstreamarray[handle].file.curlen = 0;
pluginstreamarray[handle].file.buflen = 8192;
*ret = handle;
return com_filesize;
}
else
case 1:
mode = "rb";
break;
case 2:
mode = "wb";
break;
default:
return -2;
}
f = FS_OpenVFS(VM_POINTER(arg[0]), mode, FS_GAME);
if (!f)
return -1;
handle = Plug_NewStreamHandle(STREAM_VFS);
pluginstreamarray[handle].vfs = f;
*ret = handle;
return VFS_GETLEN(pluginstreamarray[handle].vfs);
}
qintptr_t VARGS Plug_memset(void *offset, quintptr_t mask, const qintptr_t *arg)
@ -1171,6 +1155,34 @@ qintptr_t VARGS Plug_atan2(void *offset, quintptr_t mask, const qintptr_t *arg)
return ret;
}
void Plug_Net_Close_Internal(int handle)
{
switch(pluginstreamarray[handle].type)
{
case STREAM_NONE:
break;
case STREAM_VFS:
if (pluginstreamarray[handle].vfs)
VFS_CLOSE(pluginstreamarray[handle].vfs);
pluginstreamarray[handle].vfs = NULL;
break;
case STREAM_SOCKET:
#ifndef NACL
closesocket(pluginstreamarray[handle].socket);
#endif
break;
case STREAM_TLS:
#ifdef GNUTLS
gnutls_bye (pluginstreamarray[handle].session, GNUTLS_SHUT_RDWR);
pluginstreamarray[handle].type = STREAM_SOCKET;
Plug_Net_Close_Internal(handle);
return;
#endif
break;
}
pluginstreamarray[handle].plugin = NULL;
}
qintptr_t VARGS Plug_Net_Recv(void *offset, quintptr_t mask, const qintptr_t *arg)
{
int read;
@ -1217,16 +1229,8 @@ qintptr_t VARGS Plug_Net_Recv(void *offset, quintptr_t mask, const qintptr_t *ar
return -2; //closed by remote connection.
return read;
#endif
case STREAM_FILE:
if (pluginstreamarray[handle].file.curlen - pluginstreamarray[handle].file.curpos < destlen)
{
destlen = pluginstreamarray[handle].file.curlen - pluginstreamarray[handle].file.curpos;
if (destlen < 0)
return -2;
}
memcpy(dest, pluginstreamarray[handle].file.buffer + pluginstreamarray[handle].file.curpos, destlen);
pluginstreamarray[handle].file.curpos += destlen;
return destlen;
case STREAM_VFS:
return VFS_READ(pluginstreamarray[handle].vfs, dest, destlen);
default:
return -2;
}
@ -1273,18 +1277,8 @@ qintptr_t VARGS Plug_Net_Send(void *offset, quintptr_t mask, const qintptr_t *ar
return -2; //closed by remote connection.
return written;
#endif
case STREAM_FILE:
if (pluginstreamarray[handle].file.buflen < pluginstreamarray[handle].file.curpos + srclen)
{
pluginstreamarray[handle].file.buflen = pluginstreamarray[handle].file.curpos + srclen+8192;
pluginstreamarray[handle].file.buffer =
BZ_Realloc(pluginstreamarray[handle].file.buffer, pluginstreamarray[handle].file.buflen);
}
memcpy(pluginstreamarray[handle].file.buffer + pluginstreamarray[handle].file.curpos, src, srclen);
pluginstreamarray[handle].file.curpos += srclen;
if (pluginstreamarray[handle].file.curpos > pluginstreamarray[handle].file.curlen)
pluginstreamarray[handle].file.curlen = pluginstreamarray[handle].file.curpos;
return -2;
case STREAM_VFS:
return VFS_WRITE(pluginstreamarray[handle].vfs, src, srclen);
default:
return -2;
@ -1331,41 +1325,6 @@ qintptr_t VARGS Plug_Net_SendTo(void *offset, quintptr_t mask, const qintptr_t *
return -2;
}
}
void Plug_Net_Close_Internal(int handle)
{
switch(pluginstreamarray[handle].type)
{
case STREAM_FILE:
if (*pluginstreamarray[handle].file.filename)
{
COM_WriteFile(pluginstreamarray[handle].file.filename, pluginstreamarray[handle].file.buffer, pluginstreamarray[handle].file.curlen);
BZ_Free(pluginstreamarray[handle].file.buffer);
}
else
FS_FreeFile(pluginstreamarray[handle].file.buffer);
break;
case STREAM_NONE:
break;
case STREAM_OSFILE:
break;
case STREAM_SOCKET:
#ifndef NACL
closesocket(pluginstreamarray[handle].socket);
#endif
break;
case STREAM_TLS:
#ifdef GNUTLS
gnutls_bye (pluginstreamarray[handle].session, GNUTLS_SHUT_RDWR);
pluginstreamarray[handle].type = STREAM_SOCKET;
Plug_Net_Close_Internal(handle);
return;
#endif
break;
}
pluginstreamarray[handle].plugin = NULL;
}
qintptr_t VARGS Plug_Net_Close(void *offset, quintptr_t mask, const qintptr_t *arg)
{
int handle = VM_LONG(arg[0]);
@ -1484,6 +1443,9 @@ void Plug_Init(void)
#ifdef GNUTLS
if (Init_GNUTLS())
Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0);
#endif
#ifdef HAVE_SSL
Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0);
#endif
Plug_RegisterBuiltin("Net_Recv", Plug_Net_Recv, 0);
Plug_RegisterBuiltin("Net_Send", Plug_Net_Send, 0);
@ -1775,6 +1737,7 @@ qboolean Plug_CenterPrintMessage(char *buffer, int clientnum)
void Plug_Close(plugin_t *plug)
{
int i;
if (plug->blockcloses)
{
Con_Printf("Plugin %s provides driver features, and cannot safely be unloaded\n", plug->name);
@ -1804,6 +1767,14 @@ void Plug_Close(plugin_t *plug)
VM_Call(plug->vm, plug->shutdown);
VM_Destroy(plug->vm);
for (i = 0; i < pluginstreamarraylen; i++)
{
if (pluginstreamarray[i].plugin == plug)
{
Plug_Net_Close_Internal(i);
}
}
Plug_FreeConCommands(plug);
Plug_Client_Close(plug);
@ -1883,6 +1854,10 @@ void Plug_Shutdown(void)
Plug_Close(plugs);
}
BZ_Free(pluginstreamarray);
pluginstreamarray = NULL;
pluginstreamarraylen = 0;
numplugbuiltins = 0;
BZ_Free(plugbuiltins);
plugbuiltins = NULL;
@ -1894,6 +1869,10 @@ void Plug_Shutdown(void)
plugincommandarraylen = 0;
BZ_Free(plugincommandarray);
plugincommandarray = NULL;
#ifndef SERVERONLY
Plug_Client_Shutdown();
#endif
}
#endif

View file

@ -1426,7 +1426,7 @@ void search_close_progs(pubprogfuncs_t *prinst, qboolean complain)
prvm_nextsearchhandle = 0; //might as well.
}
int search_enumerate(const char *name, int fsize, void *parm)
int search_enumerate(const char *name, int fsize, void *parm, struct searchpath_s *spath)
{
prvmsearch_t *s = parm;

View file

@ -206,8 +206,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define svc_muzzleflash 39 // [short] entity
#define svc_updateuserinfo 40 // [qbyte] slot [long] uid
// [string] userinfo
#define svc_updateuserinfo 40 // [qbyte] slot [long] uid [string] userinfo
#define svc_download 41 // [short] size [size bytes]
#define svc_playerinfo 42 // variable
@ -260,6 +259,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define svcfte_movepic 71
#define svcfte_updatepic 72
//73
#define svcfte_effect 74 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
#define svcfte_effect2 75 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate

View file

@ -186,7 +186,7 @@ typedef struct {
int bufferleft;
int skip;
} vmsearch_t;
static int VMEnum(const char *match, int size, void *args)
static int VMEnum(const char *match, int size, void *args, void *spath)
{
char *check;
int newlen;
@ -210,13 +210,13 @@ static int VMEnum(const char *match, int size, void *args)
return true;
}
static int IfFound(const char *match, int size, void *args)
static int IfFound(const char *match, int size, void *args, void *spath)
{
*(qboolean*)args = true;
return true;
}
static int VMEnumMods(const char *match, int size, void *args)
static int VMEnumMods(const char *match, int size, void *args, void *spath)
{
char *check;
char desc[1024];
@ -238,7 +238,7 @@ static int VMEnumMods(const char *match, int size, void *args)
return true; //we don't want baseq3
foundone = false;
Sys_EnumerateFiles(va("%s%s/", ((vmsearch_t *)args)->dir, match), "*.pk3", IfFound, &foundone);
Sys_EnumerateFiles(va("%s%s/", ((vmsearch_t *)args)->dir, match), "*.pk3", IfFound, &foundone, spath);
if (foundone == false)
return true; //we only count directories with a pk3 file
@ -286,9 +286,9 @@ int VM_GetFileList(char *path, char *ext, char *output, int buffersize)
if (!strcmp(path, "$modlist"))
{
vms.skip=0;
Sys_EnumerateFiles((vms.dir=com_quakedir), "*", VMEnumMods, &vms);
Sys_EnumerateFiles((vms.dir=com_quakedir), "*", VMEnumMods, &vms, NULL);
if (*com_homedir)
Sys_EnumerateFiles((vms.dir=com_homedir), "*", VMEnumMods, &vms);
Sys_EnumerateFiles((vms.dir=com_homedir), "*", VMEnumMods, &vms, NULL);
}
else if (*(char *)ext == '.' || *(char *)ext == '/')
COM_EnumerateFiles(va("%s/*%s", path, ext), VMEnum, &vms);

View file

@ -83,7 +83,7 @@ void Sys_ServerActivity(void);
void Sys_SendKeyEvents (void);
// Perform Key_Event () callbacks until the input que is empty
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm);
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath);
void Sys_Vibrate(int count);

View file

@ -72,6 +72,10 @@
RelativePath="..\droid\src\com\fteqw\FTEDroidEngine.java"
>
</File>
<File
RelativePath="..\client\in_generic.c"
>
</File>
<File
RelativePath="..\client\snd_droid.c"
>

View file

@ -2,6 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {9767E236-8454-44E9-8999-CD5BDAFBE9BA}
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
@ -30,6 +31,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avplug", "..\..\plugins\avp
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "droid", "droid.vcproj", "{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{8CED01C6-2C61-4EC5-90B6-574D9756D773}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jabbercl", "..\..\plugins\jabber\jabbercl.vcproj", "{9767E236-8454-44E9-8999-CD5BDAFBE9BA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
D3DDebug|Win32 = D3DDebug|Win32
@ -437,10 +442,52 @@ Global
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|Win32.Build.0 = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Release|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DRelease|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DRelease|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DRelease|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Debug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLDebug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLDebug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLDebug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLRelease|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLRelease|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.GLRelease|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MDebug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MDebug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MDebug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLDebug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLRelease|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MinGLRelease|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MRelease|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MRelease|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.MRelease|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release Dedicated Server|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release|Win32.Build.0 = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4877586B-E85B-4DF8-BCCE-59D31514D240} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{32B12987-DF8C-4E40-B07C-B18586A4CA65} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{873CCE24-3549-49D4-A4B4-653F91B1532A} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {8CED01C6-2C61-4EC5-90B6-574D9756D773}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw
EndGlobalSection

File diff suppressed because it is too large Load diff

View file

@ -176,7 +176,7 @@ typedef struct heightmap_s
static void ted_dorelight(heightmap_t *hm);
static void Terr_Collect(heightmap_t *hm);
static qboolean Terr_Collect(heightmap_t *hm);
#ifndef SERVERONLY
@ -241,7 +241,7 @@ static void Terr_InitLightmap(hmsection_t *s)
lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false);
for (i = 0; i < LMCHUNKS*LMCHUNKS; i++)
{
lms = malloc(sizeof(*lms));
lms = BZ_Malloc(sizeof(*lms));
lms->lm = lm;
lms->x = (i & (LMCHUNKS-1))*SECTTEXSIZE;
lms->y = (i / LMCHUNKS)*SECTTEXSIZE;
@ -257,7 +257,7 @@ static void Terr_InitLightmap(hmsection_t *s)
s->lmx = lms->x;
s->lmy = lms->y;
free(lms);
Z_Free(lms);
}
#endif
@ -344,7 +344,7 @@ static qboolean Terr_IsSectionFName(heightmap_t *hm, char *fname, int *sx, int *
}
static hmsection_t *Terr_ReadSection(heightmap_t *hm, hmsection_t *s, int sx, int sy, dsection_t *ds, unsigned int dslen)
{
int i;
int i, j;
#ifndef SERVERONLY
dsmesh_t *dm;
unsigned char *lm;
@ -365,13 +365,12 @@ static hmsection_t *Terr_ReadSection(heightmap_t *hm, hmsection_t *s, int sx, in
if (!s)
{
s = malloc(sizeof(*s));
s = Z_Malloc(sizeof(*s));
if (!s)
{
FS_FreeFile(ds);
return NULL;
}
memset(s, 0, sizeof(*s));
InsertLinkBefore(&s->recycle, &hm->recycle);
s->sx = sx;
@ -468,12 +467,11 @@ static hmsection_t *Terr_ReadSection(heightmap_t *hm, hmsection_t *s, int sx, in
s->numents = ds->ents_num;
s->maxents = s->numents;
if (s->maxents)
s->ents = malloc(sizeof(*s->ents) * s->maxents);
s->ents = Z_Malloc(sizeof(*s->ents) * s->maxents);
else
s->ents = NULL;
if (!s->ents)
s->numents = s->maxents = 0;
memset(s->ents, 0, sizeof(*s->ents) * s->maxents);
for (i = 0, dm = (dsmesh_t*)ptr; i < s->numents; i++, dm = (dsmesh_t*)((qbyte*)dm + dm->size))
{
s->ents[i].model = Mod_ForName((char*)(dm + 1), false);
@ -499,7 +497,7 @@ static hmsection_t *Terr_ReadSection(heightmap_t *hm, hmsection_t *s, int sx, in
}
else
{
s->flags |= TSF_RELIGHT;
// s->flags |= TSF_RELIGHT;
#ifndef SERVERONLY
if (s->lightmap >= 0)
@ -508,7 +506,13 @@ static hmsection_t *Terr_ReadSection(heightmap_t *hm, hmsection_t *s, int sx, in
lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes;
for (i = 0; i < SECTTEXSIZE; i++)
{
memset(lm, 0, sizeof(byte_vec4_t)*SECTTEXSIZE);
for (j = 0; j < SECTTEXSIZE; j++)
{
lm[j*4+0] = 0;
lm[j*4+0] = 0;
lm[j*4+0] = 0;
lm[j*4+3] = 255;
}
lm += (HMLMSTRIDE)*lightmap_bytes;
}
lightmap[s->lightmap]->modified = true;
@ -644,13 +648,10 @@ qboolean Terr_DownloadedSection(char *fname)
hmcluster_t *cluster = hm->cluster[cx + cy*MAXSECTIONS];
if (!cluster)
{
cluster = malloc(sizeof(*cluster));
cluster = Z_Malloc(sizeof(*cluster));
if (cluster)
{
memset(cluster, 0, sizeof(*cluster));
hm->cluster[cx + cy*MAXSECTIONS] = cluster;
}
}
if (cluster)
cluster->section[sx + sy*MAXSECTIONS] = Terr_ReadSection(hm, cluster->section[sx + sy*MAXSECTIONS], x, y, fileptr, len);
}
@ -663,7 +664,7 @@ qboolean Terr_DownloadedSection(char *fname)
}
#endif
static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, int sy)
static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, int sy, qboolean force)
{
hmsection_t *sect;
void *diskimage;
@ -685,9 +686,7 @@ static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, in
/*queue the file for download if we don't have it yet*/
if (len < 0)
{
#ifndef CLIENTONLY
if (!sv.state) //server ignores any load errors, and will load a dummy section.
#endif
if (!force)
{
#ifndef SERVERONLY
if (!cl.downloadlist)
@ -805,7 +804,10 @@ static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy
}
/*convienience function*/
static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, qboolean doload)
#define TGS_NOLOAD 0
#define TGS_LOAD 1
#define TGS_FORCELOAD 2
static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, unsigned int flags)
{
hmcluster_t *cluster;
hmsection_t *section;
@ -816,12 +818,11 @@ static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, qboolean dolo
cluster = hm->cluster[cx + cy*MAXSECTIONS];
if (!cluster)
{
if (doload)
if (flags & (TGS_LOAD|TGS_FORCELOAD))
{
cluster = malloc(sizeof(*cluster));
cluster = Z_Malloc(sizeof(*cluster));
if (!cluster)
return NULL;
memset(cluster, 0, sizeof(*cluster));
hm->cluster[cx + cy*MAXSECTIONS] = cluster;
}
else
@ -830,13 +831,27 @@ static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, qboolean dolo
section = cluster->section[sx + sy*MAXSECTIONS];
if (!section)
{
if (doload)
if (flags & (TGS_LOAD|TGS_FORCELOAD))
{
// while (hm->activesections > TERRAINACTIVESECTIONS)
// Terr_Collect(hm);
section = cluster->section[sx + sy*MAXSECTIONS] = Terr_LoadSection(hm, section, x, y);
section = cluster->section[sx + sy*MAXSECTIONS] = Terr_LoadSection(hm, section, x, y, !!(flags & TGS_FORCELOAD));
}
}
#ifndef SERVERONLY
//when using networked terrain, the client will never load a section from disk, but only loading it from the server
if (section && (section->flags & TSF_NOTIFY) && mod_terrain_networked.ival && !sv.state)
{
//try to download it now...
if (!cl.downloadlist)
{
CL_CheckOrEnqueDownloadFile(Terr_DiskSectionName(hm, x, y), Terr_TempDiskSectionName(hm, x, y), DLLF_OVERWRITE|DLLF_TEMPORARY);
section->flags &= ~TSF_NOTIFY;
}
}
#endif
return section;
}
@ -850,7 +865,7 @@ int Heightmap_Save(heightmap_t *hm)
{
for (y = hm->firstsegy; y < hm->maxsegy; y++)
{
s = Terr_GetSection(hm, x, y, false);
s = Terr_GetSection(hm, x, y, TGS_NOLOAD);
if (!s)
continue;
if (s->flags & TSF_EDITED)
@ -868,16 +883,6 @@ int Heightmap_Save(heightmap_t *hm)
}
#ifndef CLIENTONLY
static int dehex(int i)
{
if (i >= '0' && i <= '9')
return (i-'0');
else if (i >= 'A' && i <= 'F')
return (i-'A'+10);
else
return (i-'a'+10);
}
//on servers, we can get requests to download current map sections. if so, give them it.
qboolean Terrain_LocateSection(char *name, flocation_t *loc)
{
@ -896,22 +901,11 @@ qboolean Terrain_LocateSection(char *name, flocation_t *loc)
if (!Terr_IsSectionFName(hm, name, &x, &y))
return false;
x = dehex(name[nlen-17+ 6])<<8;
x|= dehex(name[nlen-17+ 7])<<4;
x|= dehex(name[nlen-17+ 8])<<0;
y = dehex(name[nlen-17+10])<<8;
y|= dehex(name[nlen-17+11])<<4;
y|= dehex(name[nlen-17+12])<<0;
x += CHUNKBIAS;
y += CHUNKBIAS;
//verify that its valid
if (strcmp(name, Terr_DiskSectionName(hm, x, y)))
return false;
s = Terr_GetSection(hm, x, y, false);
s = Terr_GetSection(hm, x, y, TGS_NOLOAD);
if (!s || !(s->flags & TSF_EDITED))
return false; //its not been edited, might as well just use the regular file
@ -931,7 +925,7 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa
{
struct lmsect_s *lms;
lms = malloc(sizeof(*lms));
lms = BZ_Malloc(sizeof(*lms));
lms->lm = s->lightmap;
lms->x = s->lmx;
lms->y = s->lmy;
@ -950,18 +944,56 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa
}
#endif
free(s->ents);
free(s->mesh.xyz_array);
free(s->mesh.indexes);
Z_Free(s->ents);
Z_Free(s->mesh.xyz_array);
Z_Free(s->mesh.indexes);
#endif
free(s);
Z_Free(s);
hm->activesections--;
}
static void Terr_DoEditNotify(heightmap_t *hm)
{
int i;
char *cmd;
hmsection_t *s;
link_t *ln = &hm->recycle;
if (!sv.state)
return;
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (svs.clients[i].state > cs_zombie && svs.clients[i].netchan.remote_address.type != NA_LOOPBACK)
{
if (svs.clients[i].backbuf.cursize)
return;
}
}
for (ln = &hm->recycle; ln->next != &hm->recycle; ln = &s->recycle)
{
s = (hmsection_t*)ln->next;
if (s->flags & TSF_NOTIFY)
{
s->flags &= ~TSF_NOTIFY;
cmd = va("mod_terrain_reload %s %i %i\n", hm->path, s->sx - CHUNKBIAS, s->sy - CHUNKBIAS);
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (svs.clients[i].state > cs_zombie && svs.clients[i].netchan.remote_address.type != NA_LOOPBACK)
{
SV_StuffcmdToClient(&svs.clients[i], cmd);
}
}
return;
}
}
}
//garbage collect the oldest section, to make space for another
static void Terr_Collect(heightmap_t *hm)
static qboolean Terr_Collect(heightmap_t *hm)
{
hmcluster_t *c;
hmsection_t *s;
@ -986,9 +1018,10 @@ static void Terr_Collect(heightmap_t *hm)
c->section[sx+sy*MAXSECTIONS] = NULL;
Terr_DestroySection(hm, s, true);
return;
return true;
}
}
return false;
}
/*purge all sections
@ -1034,7 +1067,7 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light
if (!lightmapsonly)
{
hm->cluster[cx + cy*MAXSECTIONS] = NULL;
free(c);
BZ_Free(c);
}
}
#ifndef SERVERONLY
@ -1045,7 +1078,7 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light
struct lmsect_s *lms;
lms = hm->unusedlmsects;
hm->unusedlmsects = lms->next;
free(lms);
BZ_Free(lms);
}
}
#endif
@ -1528,11 +1561,11 @@ void Terr_DrawInBounds(struct tdibctx *ctx, int x, int y, int w, int h)
if (R_CullBox(mins, maxs))
return;
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (!s)
return;
if (s->lightmap < 0)
Terr_LoadSection(hm, s, x, y);
Terr_LoadSection(hm, s, x, y, false);
if (s->flags & TSF_RELIGHT)
{
@ -1644,8 +1677,15 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
struct tdibctx tdibctx;
if (!r_refdef.recurse)
{
Terr_DoEditNotify(hm);
// while (hm->activesections > 0)
// if (!Terr_Collect(hm))
// break;
while (hm->activesections > TERRAINACTIVESECTIONS)
Terr_Collect(hm);
if (!Terr_Collect(hm))
break;
}
if (hm->relight)
ted_dorelight(hm);
@ -1729,7 +1769,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
mins[1] = (y+0 - CHUNKBIAS)*hm->sectionsize;
maxs[1] = (y+1 - CHUNKBIAS)*hm->sectionsize;
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (!s)
continue;
if (s->lightmap < 0)
@ -1829,7 +1869,7 @@ void Terrain_ClipDecal(fragmentdecal_t *dec, float *center, float radius, model_
{
for (x = min[0]; x < max[0]; x++)
{
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (!s)
continue;
@ -1912,7 +1952,7 @@ unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t
return hm->exteriorcontents;
if (sx >= hm->maxsegx || sy >= hm->maxsegy)
return hm->exteriorcontents;
s = Terr_GetSection(hm, sx, sy, true);
s = Terr_GetSection(hm, sx, sy, TGS_LOAD);
if (!s)
{
return FTECONTENTS_SOLID;
@ -2002,7 +2042,7 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
return;
if (sx >= hm->maxsegx || sy >= hm->maxsegy)
return;
s = Terr_GetSection(hm, sx, sy, true);
s = Terr_GetSection(hm, sx, sy, TGS_LOAD);
if (!s)
return;
@ -2152,7 +2192,7 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
else if (sy < tr->hm->firstsegy || sy >= tr->hm->maxsegy)
s = NULL;
else
s = Terr_GetSection(tr->hm, sx, sy, true);
s = Terr_GetSection(tr->hm, sx, sy, TGS_LOAD);
if (!s)
{
@ -2501,7 +2541,7 @@ static unsigned char *ted_getlightmap(hmsection_t *s, int idx)
int x = idx % SECTTEXSIZE, y = idx / SECTTEXSIZE;
if (s->lightmap < 0)
{
Terr_LoadSection(s->hmmod, s, x, y);
Terr_LoadSection(s->hmmod, s, x, y, true);
if (s->lightmap < 0)
Terr_InitLightmap(s);
}
@ -2832,7 +2872,7 @@ static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float ra
{
for (sx = min[0]; sx < max[0]; sx++)
{
s = Terr_GetSection(hm, sx, sy, true);
s = Terr_GetSection(hm, sx, sy, TGS_FORCELOAD);
if (!s)
continue;
@ -2907,7 +2947,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx*4, x, hm->maxsegy*4-1);
y = bound(hm->firstsegy*4, y, hm->maxsegy*4-1);
s = Terr_GetSection(hm, x/4, y/4, true);
s = Terr_GetSection(hm, x/4, y/4, TGS_FORCELOAD);
if (!s)
return;
ted_sethole(&quant, s, (x&3) + (y&3)*4, x/4, y/4, 0);
@ -2953,7 +2993,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx, x, hm->maxsegy-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (!s)
return;
s->flags |= TSF_HASWATER|TSF_EDITED;
@ -2995,7 +3035,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx, x, hm->maxsegy-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_LOAD);
if (!s)
return;
x = bound(0, quant, 3);
@ -3012,7 +3052,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx, x, hm->maxsegy-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_FORCELOAD);
if (!s)
return;
s->flags |= TSF_EDITED;
@ -3070,7 +3110,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx, x, hm->maxsegy-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_FORCELOAD);
if (!s)
return;
@ -3106,7 +3146,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
x = bound(hm->firstsegx, x, hm->maxsegy-1);
y = bound(hm->firstsegy, y, hm->maxsegy-1);
s = Terr_GetSection(hm, x, y, true);
s = Terr_GetSection(hm, x, y, TGS_FORCELOAD);
if (!s)
return;
@ -3354,8 +3394,70 @@ void *Mod_LoadTerrainInfo(model_t *mod, char *loadname)
return hm;
}
void Mod_Terrain_Create_f(void)
{
char *mname;
char *mdata;
mname = va("maps/%s.hmp", Cmd_Argv(1));
mdata = va(
"terrain\n"
"{\n"
"classname worldspawn\n"
"_segmentsize 1024\n"
"_minxsegment -2048\n"
"_minysegment -2048\n"
"_maxxsegment 2048\n"
"_maxysegment 2048\n"
"_segmentsize 1024\n"
// "_tiles 64 64 8 8\n"
"}\n"
"{\n"
"classname info_player_start\n"
"origin \"0 0 1024\"\n"
"}\n"
, mname);
COM_WriteFile(mname, mdata, strlen(mdata));
}
void Mod_Terrain_Reload_f(void)
{
model_t *mod;
heightmap_t *hm;
if (Cmd_Argc() >= 2)
mod = Mod_FindName(va("maps/%s.hmp", Cmd_Argv(1)));
#ifndef SERVERONLY
else if (cls.state)
mod = cl.worldmodel;
#endif
else
mod = NULL;
if (!mod || mod->type == mod_dummy)
return;
hm = mod->terrain;
if (!hm)
return;
if (Cmd_Argc() >= 4)
{
hmsection_t *s;
int sx = atoi(Cmd_Argv(2)) + CHUNKBIAS;
int sy = atoi(Cmd_Argv(3)) + CHUNKBIAS;
if (hm)
{
s = Terr_GetSection(hm, sx, sy, TGS_NOLOAD);
if (s)
{
s->flags |= TSF_NOTIFY;
}
}
}
else
Terr_PurgeTerrainModel(mod, false, true);
}
void Terr_Init(void)
{
Cvar_Register(&mod_terrain_networked, "Terrain");
Cmd_AddCommand("mod_terrain_create", Mod_Terrain_Create_f);
Cmd_AddCommand("mod_terrain_reload", Mod_Terrain_Reload_f);
}
#endif

View file

@ -4686,7 +4686,7 @@ typedef struct {
short xpos;
short ypos;
} doomimage_t;
static int FindDoomSprites(const char *name, int size, void *param)
static int FindDoomSprites(const char *name, int size, void *param, void *spath)
{
if (*(int *)param + strlen(name)+1 > 16000)
Sys_Error("Too many doom sprites\n");

View file

@ -401,6 +401,16 @@ void R_SetupGL (float stereooffset)
w = x2 - x;
h = y - y2;
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
if (stereooffset && r_stereo_method.ival == 5)
{
w /= 2;
if (stereooffset > 0)
x += vid.pixelwidth/2;
}
r_refdef.pxrect.x = x;
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = w;
@ -408,9 +418,6 @@ void R_SetupGL (float stereooffset)
qglViewport (x, y2, w, h);
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
if (r_waterwarp.value<0 && (r_viewcontents & FTECONTENTS_FLUID))
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
@ -556,7 +563,8 @@ void R_RenderScene (void)
else
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
break;
case 5: //eyestrain
break;
}
if (i)
qglClear (GL_DEPTH_BUFFER_BIT);
@ -595,12 +603,20 @@ void R_RenderScene (void)
case 1:
qglDrawBuffer(GL_BACK);
break;
case 2:
case 3:
case 4:
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
qglClear(GL_COLOR_BUFFER_BIT);
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
break;
case 4:
qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
qglClear(GL_COLOR_BUFFER_BIT);
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
case 2:
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
break;
case 5:
break;
}
}
/*generates a new modelview matrix, as well as vpn vectors*/

View file

@ -2977,7 +2977,7 @@ void Shader_Free (shader_t *shader)
int Shader_InitCallback (const char *name, int size, void *param)
int Shader_InitCallback (const char *name, int size, void *param, void *spath)
{
strcpy(shaderbuf+shaderbuflen, name);
Shader_MakeCache(shaderbuf+shaderbuflen);

View file

@ -54,13 +54,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform sampler2D s_t2; //diffuse/reflection\n"
"#ifdef DEPTH\n"
"uniform sampler2D s_t3; //refraction depth\n"
"#ifdef RIPPLEMAP\n"
"uniform sampler2D s_t4; //ripplemap\n"
"#endif\n"
"#define s_ripplemap s_t4\n"
"#else\n"
"#ifdef RIPPLEMAP\n"
"uniform sampler2D s_t3; //ripplemap\n"
"#define s_ripplemap s_t3\n"
"#endif\n"
"#ifdef RIPPLEMAP\n"
"uniform sampler2D s_ripplemap; //ripplemap\n"
"#endif\n"
"uniform float e_time;\n"
@ -84,7 +83,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"n -= 1.0 - 4.0/256.0;\n"
"#ifdef RIPPLEMAP\n"
"n += texture2D(s_t4, stc).rgb*3.0;\n"
"n += texture2D(s_ripplemap, stc).rgb*3.0;\n"
"#endif\n"
//the fresnel term decides how transparent the water should be
@ -543,7 +542,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"vec4 col, sp;\n"
"#ifdef OFFSETMAPPING\n"
"vec2 tcoffsetmap = offsetmap(s_t4, tcbase, eyevector);\n"
"vec2 tcoffsetmap = offsetmap(s_t4, tc, eyevector);\n"
"#define tc tcoffsetmap\n"
"#endif\n"

View file

@ -128,7 +128,7 @@ void FTP_ServerShutdown(void)
}
//we ought to filter this to remove duplicates.
static int SendFileNameTo(const char *rawname, int size, void *param)
static int SendFileNameTo(const char *rawname, int size, void *param, struct searchpath_s *spath)
{
int socket = *(int*)param;
// int i;

View file

@ -68,9 +68,9 @@ iwboolean IWebAllowUpLoad(char *fname, char *uname);
vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength);
char *COM_ParseOut (const char *data, char *out, int outlen);
void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm);
//struct searchpath_s;
//void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *, struct searchpath_s *), void *parm);
char *Q_strcpyline(char *out, const char *in, int maxlen);

View file

@ -345,7 +345,7 @@ static void FSPPAPI_ClosePath(void *handle)
Z_Free(handle);
}
int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
int rootlen = strlen(rootpath);
char *sub;
@ -362,33 +362,33 @@ int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(con
sub++;
if (wildcmp(match, sub))
{
if (!func(sub, f->length, parm))
if (!func(sub, f->length, parm, spath))
return false;
}
}
return true;
}
static int FSPPAPI_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
static int FSPPAPI_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *), void *parm, void *spath)
{
return Sys_EnumerateFiles((char*)handle, match, func, parm);
return Sys_EnumerateFiles((char*)handle, match, func, parm, spath);
}
static int FSPPAPI_RebuildFSHash(const char *filename, int filesize, void *data)
static int FSPPAPI_RebuildFSHash(const char *filename, int filesize, void *data, void *handle)
{
if (filename[strlen(filename)-1] == '/')
{ //this is actually a directory
char childpath[256];
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
Sys_EnumerateFiles((char*)data, childpath, FSPPAPI_RebuildFSHash, data);
Sys_EnumerateFiles((char*)data, childpath, FSPPAPI_RebuildFSHash, data, handle);
return true;
}
FS_AddFileHash(0, filename, NULL, data);
FS_AddFileHash(0, filename, NULL, handle);
return true;
}
static void FSPPAPI_BuildHash(void *handle, int depth)
{
Sys_EnumerateFiles(handle, "*", FSPPAPI_RebuildFSHash, handle);
Sys_EnumerateFiles(handle, "*", FSPPAPI_RebuildFSHash, handle, handle);
}
/*

View file

@ -3847,8 +3847,8 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
//note that we don't allow passing 0.0f for null.
//WARNING: field 0 is actually a valid field, and is commonly modelindex.
}
else if (p->type == ev_field && e->type->type == ev_field && (p->aux_type->type == ev_variant || e->type->aux_type->type == ev_variant))
{ //allow passing variant fields etc
else if ((p->type == ev_field || p->type == ev_pointer) && e->type->type == p->type && (p->aux_type->type == ev_variant || e->type->aux_type->type == ev_variant || p->aux_type->type == ev_void || e->type->aux_type->type == ev_void))
{ //allow passing variant fields etc (also allow .void or *void as universal/variant field/pointer types)
}
else if ((p->type == ev_vector) && e->type->type == ev_integer && e->constant && !((int*)qcc_pr_globals)[e->ofs])
{

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
/*Testing this code should typically be done with the three following mods:

View file

@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#ifdef SQL
#include "sv_sql.h"
@ -105,6 +105,21 @@ void PF_InitTempStrings(pubprogfuncs_t *prinst);
void PR_DumpPlatform_f(void);
typedef struct qcstate_s
{
float resumetime;
qboolean waiting;
struct qcthread_s *thread;
int self;
int selfid;
int other;
int otherid;
float returnval;
struct qcstate_s *next;
} qcstate_t;
qcstate_t *qcthreads;
typedef struct {
//for func finding and swapping.
char *name;
@ -163,9 +178,22 @@ progstype_t progstype;
void PR_RegisterFields(void);
void PR_ResetBuiltins(progstype_t type);
char *QC_ProgsNameForEnt(edict_t *ent)
static qcstate_t *PR_CreateThread(pubprogfuncs_t *prinst, float retval, float resumetime, qboolean wait)
{
return "?";
qcstate_t *state;
state = prinst->parms->memalloc(sizeof(qcstate_t));
state->next = qcthreads;
qcthreads = state;
state->resumetime = resumetime;
state->self = NUM_FOR_EDICT(prinst, PROG_TO_EDICT(prinst, pr_global_struct->self));
state->selfid = PROG_TO_EDICT(prinst, state->self)->xv->uniquespawnid;
state->other = NUM_FOR_EDICT(prinst, PROG_TO_EDICT(prinst, pr_global_struct->other));
state->otherid = PROG_TO_EDICT(prinst, state->other)->xv->uniquespawnid;
state->thread = prinst->Fork(prinst);
state->waiting = wait;
state->returnval = retval;
return state;
}
void PDECL ED_Spawned (struct edict_s *ent, int loading)
@ -5550,35 +5578,83 @@ void QCBUILTIN PF_sqldisconnect (pubprogfuncs_t *prinst, struct globalvars_s *pr
}
}
static qboolean PR_SQLResultAvailable(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof)
{
edict_t *ent;
pubprogfuncs_t *prinst = svprogfuncs;
struct globalvars_s *pr_globals = PR_globals(prinst, PR_CURRENT);
if (req->user.qccallback)
{
G_FLOAT(OFS_PARM0) = req->srvid;
G_FLOAT(OFS_PARM1) = req->num;
G_FLOAT(OFS_PARM2) = numrows;
G_FLOAT(OFS_PARM3) = numcols;
G_FLOAT(OFS_PARM4) = eof;
G_FLOAT(OFS_PARM5) = firstrow;
// recall self and other references
ent = PROG_TO_EDICT(prinst, req->user.selfent);
if (ent->isfree || ent->xv->uniquespawnid != req->user.selfid)
pr_global_struct->self = pr_global_struct->world;
else
pr_global_struct->self = req->user.selfent;
ent = PROG_TO_EDICT(prinst, req->user.otherent);
if (ent->isfree || ent->xv->uniquespawnid != req->user.otherid)
pr_global_struct->other = pr_global_struct->world;
else
pr_global_struct->other = req->user.otherent;
PR_ExecuteProgram(svprogfuncs, req->user.qccallback);
}
if (eof && req->user.thread)
{
qcstate_t *thread = req->user.thread;
req->user.thread = NULL;
if (thread)
thread->waiting = false;
}
return req->user.persistant;
}
void QCBUILTIN PF_sqlopenquery (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server;
int callfunc = G_INT(OFS_PARM1);
int querytype = G_FLOAT(OFS_PARM2);
char *querystr = PF_VarString(prinst, 3, pr_globals);
int qself, qother;
float qselfid, qotherid;
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
if (server)
{
// save self and other references
if (PROG_TO_EDICT(prinst, pr_global_struct->self)->isfree)
qself = pr_global_struct->world;
else
qself = pr_global_struct->self;
qselfid = PROG_TO_EDICT(prinst, qself)->xv->uniquespawnid;
if (PROG_TO_EDICT(prinst, pr_global_struct->other)->isfree)
qother = pr_global_struct->world;
else
qother = pr_global_struct->other;
qotherid = PROG_TO_EDICT(prinst, qother)->xv->uniquespawnid;
queryrequest_t *qreq;
Con_DPrintf("SQL Query: %s\n", querystr);
G_FLOAT(OFS_RETURN) = SQL_NewQuery(server, callfunc, querytype, qself, qselfid, qother, qotherid, querystr);
G_FLOAT(OFS_RETURN) = SQL_NewQuery(server, PR_SQLResultAvailable, querystr, &qreq);
if (qreq)
{
//so our C callback knows what to do
qreq->user.persistant = querytype > 0;
qreq->user.qccallback = callfunc;
// save self and other references
qreq->user.selfent = PROG_TO_EDICT(prinst, pr_global_struct->self)->isfree?pr_global_struct->world:pr_global_struct->self;
qreq->user.selfid = PROG_TO_EDICT(prinst, qreq->user.selfent)->xv->uniquespawnid;
qreq->user.otherent = PROG_TO_EDICT(prinst, pr_global_struct->other)->isfree?pr_global_struct->world:pr_global_struct->other;
qreq->user.otherid = PROG_TO_EDICT(prinst, qreq->user.otherent)->xv->uniquespawnid;
if (querytype & 2)
{
qreq->user.thread = PR_CreateThread(prinst, G_FLOAT(OFS_RETURN), 0, true);
svprogfuncs->AbortStack(prinst);
}
}
return;
}
}
@ -5589,20 +5665,21 @@ void QCBUILTIN PF_sqlopenquery (pubprogfuncs_t *prinst, struct globalvars_s *pr_
void QCBUILTIN PF_sqlclosequery (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server;
queryresult_t *qres;
queryrequest_t *qreq;
if (SQL_Available())
{
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
if (server)
{
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
if (qres)
qreq = SQL_GetQueryRequest(server, G_FLOAT(OFS_PARM1));
if (qreq)
{
// TODO: partial resultset logic not implemented yet
SQL_CloseResult(server, qres);
SQL_CloseRequest(server, qreq, false);
return;
}
else
Con_Printf("Invalid sql request\n");
}
}
// else nothing to close
@ -5619,7 +5696,7 @@ void QCBUILTIN PF_sqlreadfield (pubprogfuncs_t *prinst, struct globalvars_s *pr_
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
if (server)
{
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
if (qres)
{
data = SQL_ReadField(server, qres, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), true);
@ -5629,6 +5706,10 @@ void QCBUILTIN PF_sqlreadfield (pubprogfuncs_t *prinst, struct globalvars_s *pr_
return;
}
}
else
{
Con_Printf("Invalid sql request/row\n");
}
}
}
// else we failed to get anything
@ -5638,6 +5719,7 @@ void QCBUILTIN PF_sqlreadfield (pubprogfuncs_t *prinst, struct globalvars_s *pr_
void QCBUILTIN PF_sqlreadfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server;
queryrequest_t *qreq;
queryresult_t *qres;
char *data;
@ -5646,9 +5728,39 @@ void QCBUILTIN PF_sqlreadfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
if (server)
{
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
if (G_FLOAT(OFS_PARM2) < 0)
{
qreq = SQL_GetQueryRequest(server, G_FLOAT(OFS_PARM1));
if (qreq->results)
{
if (G_FLOAT(OFS_PARM2) == -2)
G_FLOAT(OFS_RETURN) = qreq->results->columns;
else if (G_FLOAT(OFS_PARM2) == -3)
G_FLOAT(OFS_RETURN) = qreq->results->rows + qreq->results->firstrow;
else
{
Con_Printf("Invalid sql row\n");
G_FLOAT(OFS_RETURN) = 0;
}
return;
}
}
else
{
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
if (qres)
{
if (G_FLOAT(OFS_PARM2) == -1)
{
G_FLOAT(OFS_RETURN) = qres->columns;
return;
}
if (G_FLOAT(OFS_PARM2) == -2)
{
G_FLOAT(OFS_RETURN) = qres->rows;
return;
}
data = SQL_ReadField(server, qres, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), true);
if (data)
{
@ -5656,6 +5768,11 @@ void QCBUILTIN PF_sqlreadfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_
return;
}
}
else
{
Con_Printf("Invalid sql request/row\n");
}
}
}
}
// else we failed to get anything
@ -5676,7 +5793,7 @@ void QCBUILTIN PF_sqlerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
{ // query-specific error request
if (server->active) // didn't check this earlier so check it now
{
queryresult_t *qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
queryresult_t *qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
if (qres)
{
RETURN_TSTRING(qres->error);
@ -5738,14 +5855,9 @@ void QCBUILTIN PF_sqlversion (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
void PR_SQLCycle(void)
{
globalvars_t *pr_globals;
if (!SQL_Available() || !svprogfuncs)
if (!SQL_Available())
return;
pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
SQL_ServerCycle(svprogfuncs, pr_globals);
SQL_ServerCycle();
}
#endif
@ -7653,17 +7765,6 @@ static void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct global
#endif
}
typedef struct qcstate_s {
float resumetime;
struct qcthread_s *thread;
int self;
int other;
struct qcstate_s *next;
} qcstate_t;
qcstate_t *qcthreads;
void PRSV_RunThreads(void)
{
struct globalvars_s *pr_globals;
@ -7674,7 +7775,7 @@ void PRSV_RunThreads(void)
{
next = state->next;
if (state->resumetime > sv.time)
if (state->resumetime > sv.time || state->waiting)
{ //not time yet, reform original list.
state->next = qcthreads;
qcthreads = state;
@ -7685,7 +7786,7 @@ void PRSV_RunThreads(void)
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, state->self));
pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, state->other));
G_FLOAT(OFS_RETURN) = 1;
G_FLOAT(OFS_RETURN) = state->returnval;
svprogfuncs->RunThread(svprogfuncs, state->thread);
svprogfuncs->parms->memfree(state->thread);
@ -7713,29 +7814,17 @@ static void PRSV_ClearThreads(void)
static void QCBUILTIN PF_Sleep(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
qcstate_t *state;
struct qcthread_s *thread;
float sleeptime;
sleeptime = G_FLOAT(OFS_PARM0);
thread = svprogfuncs->Fork(svprogfuncs);
PR_CreateThread(prinst, 1, sv.time + sleeptime, false);
state = svprogfuncs->parms->memalloc(sizeof(qcstate_t));
state->next = qcthreads;
qcthreads = state;
state->resumetime = sv.time + sleeptime;
state->self = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->self));
state->other = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->other));
state->thread = thread;
svprogfuncs->AbortStack(svprogfuncs);
prinst->AbortStack(prinst);
}
static void QCBUILTIN PF_Fork(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
qcstate_t *state;
struct qcthread_s *thread;
float sleeptime;
if (svprogfuncs->callargc >= 1)
@ -7743,15 +7832,7 @@ static void QCBUILTIN PF_Fork(pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
else
sleeptime = 0;
thread = svprogfuncs->Fork(svprogfuncs);
state = svprogfuncs->parms->memalloc(sizeof(qcstate_t));
state->next = qcthreads;
qcthreads = state;
state->resumetime = sv.time + sleeptime;
state->self = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->self));
state->other = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->other));
state->thread = thread;
PR_CreateThread(prinst, 1, sv.time + sleeptime, false);
PRSV_RunThreads();

View file

@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "qwsvdef.h"
#ifdef VM_Q1

View file

@ -1,106 +0,0 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// quakedef.h -- primary header for server
#define QUAKEDEF_H__
#if 1//ndef SERVERONLY
#include "../client/quakedef.h"
#else
#define QUAKE_GAME // as opposed to utilities
//define PARANOID // speed sapping error checking
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <ctype.h>
#include "bothdefs.h"
#ifdef MSVCDISABLEWARNINGS
#pragma warning( disable : 4244 4127 4201 4214 4514 4305 4115 4018)
#endif
#include "translate.h"
#include "common.h"
#include "bspfile.h"
#include "sys.h"
#include "zone.h"
#include "mathlib.h"
#include "cvar.h"
#include "net.h"
#include "protocol.h"
#include "cmd.h"
#include "model.h"
#include "crc.h"
#include "progtype.h"
#include "progdefs.h"
#include "progs.h"
#include "q2game.h"
#include "server.h"
#include "world.h"
#include "pmove.h"
//=============================================================================
// the host system specifies the base of the directory tree, the
// command line parms passed to the program, and the amount of memory
// available for the program to use
typedef struct quakeparms_s
{
char *basedir;
int argc;
char **argv;
void *membase;
int memsize;
} quakeparms_t;
//=============================================================================
//
// host
//
extern quakeparms_t host_parms;
extern cvar_t sys_nostdout;
extern cvar_t developer;
extern qboolean host_initialized; // true if into command execution
extern double host_frametime;
extern double realtime; // not bounded in any way, changed at
// start of every frame, never reset
void SV_Error (char *error, ...) LIKEPRINTF(1);
void SV_Init (struct quakeparms_s *parms);
void Con_Printf (char *fmt, ...) LIKEPRINTF(1);
void Con_TPrintf (translation_t fmt, ...);
void Con_DPrintf (char *fmt, ...) LIKEPRINTF(1);
#endif

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY

View file

@ -941,9 +941,7 @@ struct quakeparms_s;
void SV_Init (struct quakeparms_s *parms);
int SV_CalcPing (client_t *cl, qboolean forcecalc);
void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext);
void SV_FullClientUpdateToClient (client_t *client, client_t *cl);
void SVNQ_FullClientUpdate (client_t *client, sizebuf_t *buf);
void SV_FullClientUpdate (client_t *client, client_t *to);
int SV_ModelIndex (char *name);

View file

@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
@ -374,7 +374,7 @@ void SV_Give_f (void)
}
}
int ShowMapList (const char *name, int flags, void *parm)
int ShowMapList (const char *name, int flags, void *parm, struct searchpath_s *spath)
{
if (name[5] == 'b' && name[6] == '_') //skip box models
return true;
@ -1454,6 +1454,18 @@ void SV_Status_f (void)
Con_Printf ("current map : %s\n", sv.name);
Con_Printf("entities : %i/%i\n", sv.world.num_edicts, sv.world.max_edicts);
if (svs.gametype == GT_PROGS)
{
int count = 0;
for (count = 1; count < MAX_MODELS; count++)
if (!sv.strings.model_precache[count])
break;
Con_Printf("models : %i/%i\n", count, MAX_MODELS);
for (count = 1; count < MAX_SOUNDS; count++)
if (!*sv.strings.sound_precache[count])
break;
Con_Printf("sounds : %i/%i\n", count, MAX_SOUNDS);
}
Con_Printf("gamedir : %s\n", FS_GetGamedir());
if (sv.csqcdebug)
Con_Printf("csqc debug : true\n");

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
/*
NPC chat:

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
#ifdef SERVER_DEMO_PLAYBACK

View file

@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#include "pr_common.h"
#ifndef CLIENTONLY
@ -436,7 +436,7 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
int m;
if (!client->frameunion.frames)
{
Con_Printf("BLAME %s\n", client->state?client->name:"a zombie");
Con_Printf("Server bug: No frames!\n");
return;
}

View file

@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
extern int total_loading_size, current_loading_size, loading_stage;
char *T_GetString(int num);

View file

@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#include "netinc.h"
#include <sys/types.h>
#ifndef CLIENTONLY
@ -150,22 +150,6 @@ cvar_t sv_masterport = CVAR("sv_masterport", "0");
cvar_t sv_gamespeed = CVAR("sv_gamespeed", "1");
cvar_t sv_csqcdebug = CVAR("sv_csqcdebug", "0");
cvar_t sv_csqc_progname = CVAR("sv_csqc_progname", "csprogs.dat");
#ifdef TCPCONNECT
cvar_t sv_port_tcp = CVARC("sv_port_tcp", "", SV_Tcpport_Callback);
#ifdef IPPROTO_IPV6
cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback);
#endif
#endif
#ifdef HAVE_IPV4
cvar_t sv_port_ipv4 = CVARC("sv_port", "27500", SV_Port_Callback);
#endif
#ifdef IPPROTO_IPV6
cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "", SV_PortIPv6_Callback);
#endif
#ifdef USEIPX
cvar_t sv_port_ipx = CVARC("sv_port_ipx", "", SV_PortIPX_Callback);
#endif
cvar_t pausable = CVAR("pausable", "1");
@ -646,10 +630,7 @@ void SV_DropClient (client_t *drop)
if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) //gamecode should do it all for us.
{
// send notification to all remaining clients
SV_FullClientUpdate (drop, &sv.reliable_datagram, 0);
#ifdef NQPROT
SVNQ_FullClientUpdate (drop, &sv.nqreliable_datagram);
#endif
SV_FullClientUpdate (drop, NULL);
SV_MVD_FullClientUpdate(NULL, drop);
}
@ -732,10 +713,10 @@ void PIN_SaveMessages(void)
pinnedmessages_t *p;
vfsfile_t *f;
f = FS_OpenVFS("pinned.txt", "wt", FS_GAMEONLY);
f = FS_OpenVFS("pinned.txt", "wb", FS_GAMEONLY);
if (!f)
{
Con_Printf("couldn't write anything\n");
Con_Printf("couldn't write to %s\n", "pinned.txt");
return;
}
@ -746,7 +727,11 @@ void PIN_SaveMessages(void)
}
void PIN_DeleteOldestMessage(void)
{
pinnedmessages_t *old = pinned;
pinnedmessages_t *old;
if (dopinnedload)
PIN_LoadMessages();
old = pinned;
if (old)
{
pinned = pinned->next;
@ -758,6 +743,9 @@ void PIN_MakeMessage(char *from, char *msg)
pinnedmessages_t *p;
pinnedmessages_t *newp;
if (dopinnedload)
PIN_LoadMessages();
newp = BZ_Malloc(sizeof(pinnedmessages_t));
Q_strncpyz(newp->setby, from, sizeof(newp->setby));
Q_strncpyz(newp->message, msg, sizeof(newp->message));
@ -884,101 +872,72 @@ void SV_GenerateBasicUserInfo(client_t *cl)
===================
SV_FullClientUpdate
Writes all update values to a sizebuf
Writes all update values to client. use to=NULL to broadcast.
===================
*/
void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext)
void SV_FullClientUpdate (client_t *client, client_t *to)
{
int i;
char info[MAX_INFO_STRING];
i = client - svs.clients;
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
if (!to)
{
MSG_WriteByte (buf, svc_updatefrags);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, sv.recordedplayer[i].frags);
MSG_WriteByte (buf, svc_updateping);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, sv.recordedplayer[i].ping);
MSG_WriteByte (buf, svc_updatepl);
MSG_WriteByte (buf, i);
MSG_WriteByte (buf, sv.recordedplayer[i].pl);
MSG_WriteByte (buf, svc_updateentertime);
MSG_WriteByte (buf, i);
MSG_WriteFloat (buf, 0);
Q_strncpyz (info, sv.recordedplayer[i].userinfo, sizeof(info));
Info_RemoveKey(info, "password"); //main password key
Info_RemoveKey(info, "*ip"); //don't broadcast this in playback
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
MSG_WriteByte (buf, svc_updateuserinfo);
MSG_WriteByte (buf, i);
MSG_WriteLong (buf, sv.recordedplayer[i].userid);
MSG_WriteString (buf, info);
for (i = 0; i < sv.allocated_client_slots; i++)
{
SV_FullClientUpdate(client, &svs.clients[i]);
}
return;
}
#endif
i = client - svs.clients;
//Sys_Printf("SV_FullClientUpdate: Updated frags for client %d\n", i);
MSG_WriteByte (buf, svc_updatefrags);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, client->old_frags);
if (ISQWCLIENT(to))
{
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Short(to, client->old_frags);
MSG_WriteByte (buf, svc_updateping);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, SV_CalcPing (client, false));
ClientReliableWrite_Begin (to, svc_updateping, 4);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Short (to, SV_CalcPing (client, false));
MSG_WriteByte (buf, svc_updatepl);
MSG_WriteByte (buf, i);
MSG_WriteByte (buf, client->lossage);
ClientReliableWrite_Begin (to, svc_updatepl, 3);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Byte (to, client->lossage);
MSG_WriteByte (buf, svc_updateentertime);
MSG_WriteByte (buf, i);
MSG_WriteFloat (buf, realtime - client->connection_started);
ClientReliableWrite_Begin (to, svc_updateentertime, 6);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Float (to, realtime - client->connection_started);
#ifdef warningmsg
#pragma warningmsg("this is a bug: it can be broadcast to all qw clients")
#endif
if (ftepext & PEXT_BIGUSERINFOS)
if ((to->fteprotocolextensions) & PEXT_BIGUSERINFOS)
Q_strncpyz (info, client->userinfo, sizeof(info));
else
Q_strncpyz (info, client->userinfobasic, sizeof(info));
Info_RemoveKey(info, "password"); //main password key
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
MSG_WriteByte (buf, svc_updateuserinfo);
MSG_WriteByte (buf, i);
MSG_WriteLong (buf, client->userid);
MSG_WriteString (buf, info);
}
#ifdef NQPROT
void SVNQ_FullClientUpdate (client_t *client, sizebuf_t *buf)
{
int playercolor, top, bottom;
int i;
i = client - svs.clients;
ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info));
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Long (to, client->userid);
ClientReliableWrite_String(to, info);
}
else if (ISNQCLIENT(to))
{
int top, bottom, playercolor;
char *nam = Info_ValueForKey(client->userinfo, "name");
if (i >= 16)
return;
return; //NQ clients will crash if they see a player index above 16.
//Sys_Printf("SV_FullClientUpdate: Updated frags for client %d\n", i);
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Short(to, client->old_frags);
MSG_WriteByte (buf, svc_updatefrags);
MSG_WriteByte (buf, i);
MSG_WriteShort (buf, client->old_frags);
MSG_WriteByte (buf, svc_updatename);
MSG_WriteByte (buf, i);
MSG_WriteString (buf, Info_ValueForKey(client->userinfo, "name"));
ClientReliableWrite_Begin(to, svc_updatename, 3 + strlen(nam));
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_String(to, nam);
top = atoi(Info_ValueForKey(client->userinfo, "topcolor"));
bottom = atoi(Info_ValueForKey(client->userinfo, "bottomcolor"));
@ -989,51 +948,13 @@ void SVNQ_FullClientUpdate (client_t *client, sizebuf_t *buf)
if (bottom > 13)
bottom = 13;
playercolor = top*16 + bottom;
MSG_WriteByte (buf, svc_updatecolors);
MSG_WriteByte (buf, i);
MSG_WriteByte (buf, playercolor);
}
#endif
/*
===================
SV_FullClientUpdateToClient
Writes all update values to a client's reliable stream
===================
*/
void SV_FullClientUpdateToClient (client_t *client, client_t *cl)
{
#ifdef NQPROT
if (!ISQWCLIENT(cl))
{
ClientReliableCheckBlock(cl, 24 + strlen(client->userinfo));
if (cl->num_backbuf) {
SVNQ_FullClientUpdate (client, &cl->backbuf);
ClientReliable_FinishWrite(cl);
} else
SVNQ_FullClientUpdate (client, &cl->netchan.message);
}
else
#endif
{
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
{
int i = client - svs.clients;
ClientReliableCheckBlock(cl, 24 + strlen(sv.recordedplayer[i].userinfo));
}
else
#endif
ClientReliableCheckBlock(cl, 24 + strlen(client->userinfo));
if (cl->num_backbuf) {
SV_FullClientUpdate (client, &cl->backbuf, cl->fteprotocolextensions);
ClientReliable_FinishWrite(cl);
} else
SV_FullClientUpdate (client, &cl->netchan.message, cl->fteprotocolextensions);
ClientReliableWrite_Begin (to, svc_updatecolors, 3);
ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Byte (to, playercolor);
}
}
/*
==============================================================================
@ -3101,7 +3022,7 @@ qboolean SV_ConnectionlessPacket (void)
}
#ifdef NQPROT
void SVNQ_ConnectionlessPacket(void)
qboolean SVNQ_ConnectionlessPacket(void)
{
sizebuf_t sb;
int header;
@ -3113,15 +3034,16 @@ void SVNQ_ConnectionlessPacket(void)
char buffer[256], buffer2[256];
netadr_t localaddr;
if (net_from.type == NA_LOOPBACK)
return;
return false;
if (!sv_listen_nq.value)
return;
return false;
MSG_BeginReading(svs.netprim);
header = LongSwap(MSG_ReadLong());
if (!(header & NETFLAG_CTL))
{
//this nasty chunk of code is to try to handle challenges with nq's challengeless protocol, by using stringcmds. woo. evil hacks.
if (sv_listen_nq.ival == 2)
if ((header & (NETFLAG_DATA|NETFLAG_EOM)) == (NETFLAG_DATA|NETFLAG_EOM))
{
@ -3154,7 +3076,7 @@ void SVNQ_ConnectionlessPacket(void)
newcl->netchan.incoming_reliable_sequence = sequence;
/*if there is anything else in the packet, we don't actually care. its reliable, so they'll resend*/
return;
return true;
}
else
MSG_ReadString();
@ -3193,15 +3115,17 @@ void SVNQ_ConnectionlessPacket(void)
*(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
return true;
}
}
}
return; //no idea what it is.
return false; //no idea what it is.
}
length = header & NETFLAG_LENGTH_MASK;
if (length != net_message.cursize)
return; //corrupt or not ours
return false; //corrupt or not ours
switch(MSG_ReadByte())
{
@ -3216,7 +3140,7 @@ void SVNQ_ConnectionlessPacket(void)
MSG_WriteString(&sb, "Incorrect game\n");
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
return; //not our game.
return false; //not our game.
}
if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
{
@ -3226,7 +3150,7 @@ void SVNQ_ConnectionlessPacket(void)
MSG_WriteString(&sb, "Incorrect version\n");
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
return; //not our version...
return false; //not our version...
}
mod = MSG_ReadByte();
modver = MSG_ReadByte();
@ -3272,10 +3196,10 @@ void SVNQ_ConnectionlessPacket(void)
SVC_DirectConnect();
}
}
break;
return true;
case CCREQ_SERVER_INFO:
if (Q_strcmp (MSG_ReadString(), NET_GAMENAME_NQ) != 0)
break;
return false;
sb.maxsize = sizeof(buffer);
sb.data = buffer;
@ -3298,7 +3222,7 @@ void SVNQ_ConnectionlessPacket(void)
MSG_WriteByte (&sb, NET_PROTOCOL_VERSION);
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
break;
return true;
case CCREQ_PLAYER_INFO:
/*one request per player, ouch ouch ouch, what will it make of 32 players, I wonder*/
sb.maxsize = sizeof(buffer);
@ -3326,7 +3250,7 @@ void SVNQ_ConnectionlessPacket(void)
}
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
break;
return true;
case CCREQ_RULE_INFO:
/*lol, nq is evil*/
sb.maxsize = sizeof(buffer);
@ -3366,8 +3290,9 @@ void SVNQ_ConnectionlessPacket(void)
}
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
break;
return true;
}
return false;
}
#endif
@ -3476,7 +3401,6 @@ SV_ReadPackets
//FIMXE: move to header
qboolean SV_GetPacket (void);
#endif
qboolean SV_ReadPackets (float *delay)
{
int i;
@ -3518,7 +3442,7 @@ qboolean SV_ReadPackets (float *delay)
if (ISNQCLIENT(cl))
{
if (cl->state != cs_zombie)
if (cl->state > cs_zombie)
{
if (NQNetChan_Process(&cl->netchan))
{
@ -3695,9 +3619,13 @@ dominping:
#endif
#ifdef NQPROT
SVNQ_ConnectionlessPacket();
if (SVNQ_ConnectionlessPacket())
continue;
#endif
if (NET_WasSpecialPacket())
continue;
// packet is not from a known client
// Con_Printf ("%s:sequenced packet without connection\n"
// ,NET_AdrToString(net_from));
@ -4297,26 +4225,7 @@ void SV_InitLocal (void)
Cvar_Register (&sv_listen_q3, cvargroup_servercontrol);
sv_listen_qw.restriction = RESTRICT_MAX;
#ifdef TCPCONNECT
Cvar_Register (&sv_port_tcp, cvargroup_servercontrol);
sv_port_tcp.restriction = RESTRICT_MAX;
#ifdef IPPROTO_IPV6
Cvar_Register (&sv_port_tcp6, cvargroup_servercontrol);
sv_port_tcp6.restriction = RESTRICT_MAX;
#endif
#endif
#ifdef IPPROTO_IPV6
Cvar_Register (&sv_port_ipv6, cvargroup_servercontrol);
sv_port_ipv6.restriction = RESTRICT_MAX;
#endif
#ifdef USEIPX
Cvar_Register (&sv_port_ipx, cvargroup_servercontrol);
sv_port_ipx.restriction = RESTRICT_MAX;
#endif
#ifdef HAVE_IPV4
Cvar_Register (&sv_port_ipv4, cvargroup_servercontrol);
sv_port_ipv4.restriction = RESTRICT_MAX;
#endif
SVNET_RegisterCvars();
Cvar_Register (&sv_reportheartbeats, cvargroup_servercontrol);
@ -4397,32 +4306,7 @@ void SV_InitLocal (void)
svs.log[1].cursize = 0;
svs.log[1].allowoverflow = true;
svs.free_lagged_packet = NULL;
// parse params for cvars
p = COM_CheckParm ("-port");
if (!p)
p = COM_CheckParm ("-svport");
if (p && p < com_argc)
{
int port = atoi(com_argv[p+1]);
if (!port)
port = PORT_QWSERVER;
#ifdef HAVE_IPV4
if (*sv_port_ipv4.string)
Cvar_SetValue(&sv_port_ipv4, port);
#endif
#ifdef IPPROTO_IPV6
if (*sv_port_ipv6.string)
Cvar_SetValue(&sv_port_ipv6, port);
#endif
#ifdef USEIPX
if (*sv_port_ipx.string)
Cvar_SetValue(&sv_port_ipx, port);
#endif
}
}

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifdef SV_MASTER

View file

@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
#include "winquake.h"
@ -683,7 +683,7 @@ typedef struct
#define SORT_NO 0
#define SORT_BY_DATE 1
int Sys_listdirFound(const char *fname, int fsize, void *uptr)
int Sys_listdirFound(const char *fname, int fsize, void *uptr, struct searchpath_s *spath)
{
file_t *f;
dir_t *dir = uptr;

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_nchan.c, user reliable data stream writes
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
// check to see if client block will fit, if not, rotate buffers

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_phys.c
#include "qwsvdef.h"
#include "quakedef.h"
#if !defined(CLIENTONLY) || defined(CSQC_DAT)
#include "pr_common.h"

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_main.c -- server main program
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
@ -2147,7 +2147,7 @@ void SV_UpdateToReliableMessages (void)
if (host_client->sendinfo)
{
host_client->sendinfo = false;
SV_FullClientUpdate (host_client, &sv.reliable_datagram, host_client->fteprotocolextensions);
SV_FullClientUpdate (host_client, NULL);
}
if (host_client->old_frags != curfrags)
{

View file

@ -131,27 +131,30 @@ queryresult_t *SQL_PullResult(sqlserver_t *server)
return qres;
}
//called by main thread
void SQL_PushRequest(sqlserver_t *server, queryrequest_t *qreq)
{
qreq->state = SR_PENDING;
Sys_LockConditional(server->requestcondv);
qreq->next = NULL;
qreq->nextqueue = NULL;
if (!server->requestslast)
server->requests = server->requestslast = qreq;
server->requestqueue = server->requestslast = qreq;
else
server->requestslast = server->requestslast->next = qreq;
server->requestslast = server->requestslast->nextqueue = qreq;
Sys_UnlockConditional(server->requestcondv);
}
//called by sql worker thread
queryrequest_t *SQL_PullRequest(sqlserver_t *server, qboolean lock)
{
queryrequest_t *qreq;
if (lock)
Sys_LockConditional(server->requestcondv);
qreq = server->requests;
qreq = server->requestqueue;
if (qreq)
{
server->requests = qreq->next;
if (!server->requests)
server->requestqueue = qreq->nextqueue;
if (!server->requestqueue)
server->requestslast = NULL;
}
Sys_UnlockConditional(server->requestcondv);
@ -249,7 +252,7 @@ int sql_serverworker(void *sref)
while (allokay)
{
Sys_LockConditional(server->requestcondv);
if (!server->requests) // this is needed for thread startup and to catch any "lost" changes
if (!server->requestqueue) // this is needed for thread startup and to catch any "lost" changes
Sys_ConditionWait(server->requestcondv);
needlock = false; // so we don't try to relock first round
@ -313,7 +316,6 @@ int sql_serverworker(void *sref)
qres->columns = columns;
qres->request = qreq;
qres->eof = true; // store result has no more rows to read afterwards
qreq->next = NULL;
SQL_PushResult(server, qres);
}
@ -363,7 +365,7 @@ int sql_serverworker(void *sref)
qres->request = qreq;
qres->firstrow = totalrows;
qres->eof = false;
qreq->next = NULL;
qreq->nextqueue = NULL;
//headers technically take a row.
for (i = 0; i < columns; i++)
@ -428,7 +430,7 @@ int sql_serverworker(void *sref)
qres->firstrow = totalrows;
qres->request = qreq;
qres->eof = true;
qreq->next = NULL;
qreq->nextqueue = NULL;
SQL_PushResult(server, qres);
}
@ -495,16 +497,26 @@ sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives)
return sqlservers[serveridx];
}
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx)
queryrequest_t *SQL_GetQueryRequest (sqlserver_t *server, int queryidx)
{
queryrequest_t *qreq;
for (qreq = server->requests; qreq; qreq = qreq->nextreq)
{
if (qreq->num == queryidx)
return qreq;
}
return NULL;
}
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx, int row)
{
queryresult_t *qres;
queryrequest_t *qreq;
qres = server->currentresult;
if (qres && qres->request && qres->request->num == queryidx)
return qres;
for (qres = server->persistresults; qres; qres = qres->next)
if (qres->request && qres->request->num == queryidx)
qreq = SQL_GetQueryRequest(server, queryidx);
for (qres = qreq->results; qres; qres = qres->next)
if (qres->request && qres->request->num == queryidx && row >= qres->firstrow && row < qres->firstrow + qres->rows)
return qres;
return NULL;
@ -533,20 +545,18 @@ static void SQL_DeallocResult(sqlserver_t *server, queryresult_t *qres)
break;
#endif
}
if (qres->request)
Z_Free(qres->request);
Z_Free(qres);
}
void SQL_ClosePersistantResult(sqlserver_t *server, queryresult_t *qres)
static void SQL_CloseRequestResult(sqlserver_t *server, queryresult_t *qres)
{
queryresult_t *prev, *cur;
prev = server->persistresults;
prev = qres->request->results;
if (prev == qres)
{
server->persistresults = prev->next;
qres->request->results = prev->next;
SQL_DeallocResult(server, prev);
return;
}
@ -562,25 +572,62 @@ void SQL_ClosePersistantResult(sqlserver_t *server, queryresult_t *qres)
}
}
//MT only. flush a result without discarding the request. will result in gaps.
void SQL_CloseResult(sqlserver_t *server, queryresult_t *qres)
{
if (!qres)
return;
if (qres == server->currentresult)
/* if (qres == server->currentresult)
{
SQL_DeallocResult(server, server->currentresult);
server->currentresult = NULL;
return;
}
*/
// else we have a persistant query
SQL_ClosePersistantResult(server, qres);
SQL_CloseRequestResult(server, qres);
}
void SQL_CloseAllResults(sqlserver_t *server)
//MT only. releases the request.
void SQL_CloseRequest(sqlserver_t *server, queryrequest_t *qreq, qboolean force)
{
while(qreq->results)
{
SQL_CloseResult(server, qreq->results);
}
//if the worker thread is still active with it for whatever reason, flag it as aborted but keep it otherwise valid. actually close it later on when we get the results back.
if (qreq->state != SR_FINISHED && qreq->state != SR_NEW)
qreq->state = SR_ABORTED;
else
{
queryrequest_t *prev, *cur;
//unlink and free it now that its complete.
prev = server->requests;
if (prev == qreq)
server->requests = prev->nextreq;
else
{
for (cur = prev->nextreq; cur; prev = cur, cur = prev->nextreq)
{
if (cur == qreq)
{
prev->nextreq = cur->nextreq;
break;
}
}
}
Z_Free(qreq);
}
}
void SQL_CloseAllRequests(sqlserver_t *server)
{
queryresult_t *oldqres, *qres;
// close orphaned results (we assume the lock is active or non-existant at this point)
//we assume lock is either held or the thread has already died. this function isn't (worker)thread safe.
// close pending results
qres = server->results;
while (qres)
{
@ -588,21 +635,13 @@ void SQL_CloseAllResults(sqlserver_t *server)
qres = qres->next;
SQL_DeallocResult(server, oldqres);
}
// close current
if (server->currentresult)
//now terminate all the requests
while(server->requests)
{
SQL_DeallocResult(server, server->currentresult);
server->currentresult = NULL;
SQL_CloseRequest(server, server->requests, true);
}
// close persistant results
qres = server->persistresults;
while (qres)
{
oldqres = qres;
qres = qres->next;
SQL_DeallocResult(server, oldqres);
}
server->persistresults = NULL;
// close server result
if (server->serverresult)
{
@ -613,10 +652,11 @@ void SQL_CloseAllResults(sqlserver_t *server)
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields)
{
if (!qres->result) // TODO: partial resultset logic not implemented yet
if (!qres->result)
return NULL;
else
{ // store_result query
row -= qres->firstrow;
if (qres->rows < row || qres->columns < col || col < 0)
return NULL;
@ -705,15 +745,15 @@ void SQL_CleanupServer(sqlserver_t *server)
Sys_DestroyMutex(server->resultlock);
// close orphaned requests
qreq = server->requests;
qreq = server->requestqueue;
while (qreq)
{
oldqreq = qreq;
qreq = qreq->next;
qreq = qreq->nextqueue;
Z_Free(oldqreq);
}
SQL_CloseAllResults(server);
SQL_CloseAllRequests(server);
for (i = SQL_CONNECT_STRUCTPARAMS; i < SQL_CONNECT_PARAMS; i++)
Z_Free(server->connectparams[i]);
@ -833,7 +873,7 @@ int SQL_NewServer(char *driver, char **paramstr)
return serverref;
}
int SQL_NewQuery(sqlserver_t *server, int callfunc, int type, int self, float selfid, int other, float otherid, char *str)
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), char *str, queryrequest_t **reqout)
{
int qsize = Q_strlen(str);
queryrequest_t *qreq;
@ -842,27 +882,32 @@ int SQL_NewQuery(sqlserver_t *server, int callfunc, int type, int self, float se
qreq = (queryrequest_t *)ZF_Malloc(sizeof(queryrequest_t) + qsize);
if (qreq)
{
qreq->persistant = (type == 1);
qreq->callback = callfunc;
qreq->selfent = self;
qreq->selfid = selfid;
qreq->otherent = other;
qreq->otherid = otherid;
qreq->state = SR_NEW;
querynum = qreq->num = server->querynum;
// prevent the reference num from getting too big to prevent FP problems
if (++server->querynum > 1000000)
while(1)
{
if (++server->querynum > (1<<21))
server->querynum = 1;
if (!SQL_GetQueryRequest(server, server->querynum))
break;
}
qreq->callback = callback;
Q_strncpy(qreq->query, str, qsize);
qreq->nextreq = server->requests;
server->requests = qreq;
SQL_PushRequest(server, qreq);
Sys_ConditionSignal(server->requestcondv);
*reqout = qreq;
return querynum;
}
*reqout = NULL;
return -1;
}
@ -945,6 +990,7 @@ qboolean SQL_Available(void)
void SQL_Status_f(void)
{
int i;
char *stat;
if (!SQL_Available())
Con_Printf("No SQL library available.\n");
@ -964,7 +1010,7 @@ void SQL_Status_f(void)
Sys_LockMutex(server->resultlock);
Sys_LockConditional(server->requestcondv);
for (qreq = server->requests; qreq; qreq = qreq->next)
for (qreq = server->requests; qreq; qreq = qreq->nextreq)
reqnum++;
for (qres = server->results; qres; qres = qres->next)
resnum++;
@ -988,11 +1034,21 @@ void SQL_Status_f(void)
if (reqnum)
{
Con_Printf ("- %i requests\n");
for (qreq = server->requests; qreq; qreq = qreq->next)
Con_Printf ("- %i requests\n", reqnum);
for (qreq = server->requests; qreq; qreq = qreq->nextqueue)
{
Con_Printf (" query #%i: %s\n",
switch (qreq->state)
{
case SR_NEW: stat = "new"; break;
case SR_PENDING: stat = "pending"; break;
case SR_PARTIAL: stat = "partial"; break;
case SR_FINISHED: stat = "finished"; break;
case SR_ABORTED: stat = "aborted"; break;
default: stat = "???"; break;
}
Con_Printf (" query #%i (%s): %s\n",
qreq->num,
stat,
qreq->query);
// TODO: function lookup?
}
@ -1000,7 +1056,7 @@ void SQL_Status_f(void)
if (resnum)
{
Con_Printf ("- %i results\n");
Con_Printf ("- %i pending results\n", resnum);
for (qres = server->results; qres; qres = qres->next)
{
Con_Printf (" * %i rows, %i columns",
@ -1047,7 +1103,7 @@ void SQL_Killall_f (void)
SQL_KillServers();
}
void SQL_ServerCycle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
void SQL_ServerCycle (void)
{
int i;
@ -1055,69 +1111,61 @@ void SQL_ServerCycle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server = sqlservers[i];
queryresult_t *qres;
queryrequest_t *qreq;
if (!server)
continue;
while (qres = SQL_PullResult(server))
{
qreq = qres->request;
qres->next = NULL;
if (qreq && qreq->callback)
{
qboolean persist;
//save it for later.
qres->next = qreq->results;
qreq->results = qres;
if (qreq->state == SR_ABORTED)
{
persist = false;
if (qres->eof)
SQL_CloseRequest(server, qreq, true);
}
else
{
if (qreq->state == SR_FINISHED)
Sys_Error("SQL: Results after finished!\n");
if (qreq->state == SR_PENDING)
qreq->state = SR_PARTIAL;
if (qres->eof)
qreq->state = SR_FINISHED;
persist = qreq->callback(qreq, qres->firstrow, qres->rows, qres->columns, qres->eof);
}
if (!persist)
{
SQL_CloseResult(server, qres);
if (qreq->state == SR_FINISHED)
SQL_CloseRequest(server, qreq, false);
}
}
else // error or server-only result
{
if (server->serverresult)
SQL_CloseResult(server, server->serverresult);
server->serverresult = qres;
}
}
if (server->terminated)
{
sqlservers[i] = NULL;
SQL_CleanupServer(server);
continue;
}
while (qres = SQL_PullResult(server))
{
qres->next = NULL;
if (qres->request && qres->request->callback)
{
if (server->active)
{ // only process results to callback if server is active
edict_t *ent;
server->currentresult = qres;
G_FLOAT(OFS_PARM0) = i;
G_FLOAT(OFS_PARM1) = qres->request->num;
G_FLOAT(OFS_PARM2) = qres->rows;
G_FLOAT(OFS_PARM3) = qres->columns;
G_FLOAT(OFS_PARM4) = qres->eof;
G_FLOAT(OFS_PARM5) = qres->firstrow;
// recall self and other references
ent = PROG_TO_EDICT(prinst, qres->request->selfent);
if (ent->isfree || ent->xv->uniquespawnid != qres->request->selfid)
pr_global_struct->self = pr_global_struct->world;
else
pr_global_struct->self = qres->request->selfent;
ent = PROG_TO_EDICT(prinst, qres->request->otherent);
if (ent->isfree || ent->xv->uniquespawnid != qres->request->otherid)
pr_global_struct->other = pr_global_struct->world;
else
pr_global_struct->other = qres->request->otherent;
PR_ExecuteProgram(prinst, qres->request->callback);
if (server->currentresult)
{
if (server->currentresult->request && server->currentresult->request->persistant)
{
// move into persistant list
server->currentresult->next = server->persistresults;
server->persistresults = server->currentresult;
}
else // just close the query
SQL_CloseResult(server, server->currentresult);
}
}
}
else // error or server-only result
{
if (server->serverresult)
Z_Free(server->serverresult);
server->serverresult = qres;
}
}
server->currentresult = NULL;
}
}

View file

@ -20,14 +20,30 @@ typedef enum
typedef struct queryrequest_s
{
int srvid;
int num; /* query number reference */
struct queryrequest_s *nextqueue; /* next request in queue */
struct queryrequest_s *nextreq; /* next request in queue */
struct queryresult_s *results; /* chain of received results */
enum
{
SR_NEW,
SR_PENDING,
SR_PARTIAL, //
SR_FINISHED, //waiting for close
SR_ABORTED //don't notify. destroy on finish.
} state; //maintained by main thread. worker *may* check for aborted state as a way to quickly generate an error.
qboolean (*callback)(struct queryrequest_s *req, int firstrow, int numrows, int numcols, qboolean eof); /* called on main thread once complete */
struct
{
qboolean persistant; /* persistant query */
struct queryrequest_s *next; /* next request in queue */
int callback; /* callback function reference */
int qccallback; /* callback function reference */
int selfent; /* self entity on call */
float selfid; /* self entity id on call */
int otherent; /* other entity on call */
float otherid; /* other entity id on call */
void *thread;
} user; /* sql code does not write anything in this struct */
char query[1]; /* query to run */
} queryrequest_t;
@ -61,13 +77,12 @@ typedef struct sqlserver_s
void *requestcondv; /* lock and conditional variable for queue read/write */
void *resultlock; /* mutex for queue read/write */
int querynum; /* next reference number for queries */
queryrequest_t *requests; /* query requests queue */
queryrequest_t *requests; /* list of pending and persistant requests */
queryrequest_t *requestqueue; /* query requests queue */
queryrequest_t *requestslast; /* query requests queue last link */
queryresult_t *results; /* query results queue */
queryresult_t *resultslast; /* query results queue last link */
queryresult_t *currentresult; /* current called result */
queryresult_t *persistresults; /* list of persistant results */
queryresult_t *serverresult; /* server error results */
queryresult_t *serverresult; /* most recent (orphaned) server error result */
char **connectparams; /* connect parameters (0 = host, 1 = user, 2 = pass, 3 = defaultdb) */
} sqlserver_t;
@ -77,19 +92,21 @@ void SQL_KillServers(void);
void SQL_DeInit(void);
sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives);
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx);
queryrequest_t *SQL_GetQueryRequest (sqlserver_t *server, int queryidx);
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx, int row);
//void SQL_DeallocResult(sqlserver_t *server, queryresult_t *qres);
void SQL_ClosePersistantResult(sqlserver_t *server, queryresult_t *qres);
void SQL_CloseResult(sqlserver_t *server, queryresult_t *qres);
void SQL_CloseRequest(sqlserver_t *server, queryrequest_t *qres, qboolean force);
void SQL_CloseAllResults(sqlserver_t *server);
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields);
int SQL_NewServer(char *driver, char **paramstr);
int SQL_NewQuery(sqlserver_t *server, int callfunc, int type, int self, float selfid, int other, float otherid, char *str);
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), char *str, queryrequest_t **reqout); //callback will be called on the main thread once the result is back
void SQL_Disconnect(sqlserver_t *server);
void SQL_Escape(sqlserver_t *server, char *src, char *dst, int dstlen);
const char *SQL_Info(sqlserver_t *server);
qboolean SQL_Available(void);
void SQL_ServerCycle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void SQL_ServerCycle (void);
extern cvar_t sql_driver;
extern cvar_t sql_host;

View file

@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#include "quakedef.h"
#include <sys/types.h>
#include <sys/timeb.h>
@ -425,7 +425,7 @@ qboolean Sys_Rename (char *oldfname, char *newfname)
return !rename(oldfname, newfname);
}
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath)
{
HANDLE r;
WIN32_FIND_DATA fd;
@ -457,13 +457,13 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
if (*fd.cFileName != '.')
{
Q_snprintfz(file, sizeof(file), "%s%s/", apath, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
else
{
Q_snprintfz(file, sizeof(file), "%s%s", apath, fd.cFileName);
go = func(file, fd.nFileSizeLow, parm);
go = func(file, fd.nFileSizeLow, parm, spath);
}
}
while(FindNextFile(r, &fd) && go);
@ -731,11 +731,15 @@ void ApplyColour(unsigned int chr)
void Sys_PrintColouredChar(unsigned int chr)
{
DWORD dummy;
wchar_t wc;
if (chr & CON_HIDDEN)
return;
ApplyColour(chr);
printf("%c", chr & CON_CHARMASK);
wc = chr & CON_CHARMASK;
WriteConsoleW(hconsoleout, &wc, 1, &dummy, NULL);
}
/*
@ -1003,6 +1007,9 @@ void Sys_Init (void)
Cmd_AddCommand("hide", Sys_HideConsole);
hconsoleout = GetStdHandle(STD_OUTPUT_HANDLE);
// SetConsoleCP(CP_UTF8);
// SetConsoleOutputCP(CP_UTF8);
}
void Sys_Shutdown (void)
@ -1336,4 +1343,28 @@ void Sys_Sleep (double seconds)
{
Sleep(seconds * 1000);
}
/*
================
Sys_RandomBytes
================
*/
#include <wincrypt.h>
qboolean Sys_RandomBytes(qbyte *string, int len)
{
HCRYPTPROV prov;
if(!CryptAcquireContext( &prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
return false;
}
if(!CryptGenRandom(prov, len, (BYTE *)string))
{
CryptReleaseContext( prov, 0);
return false;
}
CryptReleaseContext(prov, 0);
return true;
}
#endif

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_user.c -- server code for moving users
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY
#include "pr_common.h"
@ -1458,7 +1458,7 @@ void SVQW_Spawn_f (void)
// normally this could overflow, but no need to check due to backbuf
for (i=0, client = svs.clients ; i<MAX_CLIENTS ; i++, client++)
SV_FullClientUpdateToClient (client, host_client);
SV_FullClientUpdate(client, host_client);
SV_MVD_FullClientUpdate(NULL, host_client);
// send all current light styles
@ -2797,6 +2797,7 @@ void SV_BeginDownload_f(void)
if (result == -5)
{
//package download
result = 0;
host_client->download = FS_OpenVFS(name+8, "rb", FS_ROOT);
}
@ -2805,6 +2806,15 @@ void SV_BeginDownload_f(void)
//redirection protocol-specific code goes here.
if (result == -4)
{
#ifdef PEXT_CHUNKEDDOWNLOADS
if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS)
{
//redirect the client (before the message saying download failed)
char *s = va("dlsize \"%s\" r \"%s\"\n", name, redirection);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s));
ClientReliableWrite_String (host_client, s);
}
#endif
}
if (result == 0)
@ -2830,18 +2840,11 @@ void SV_BeginDownload_f(void)
break;
case -4:
result = -1;
error = "";
error = "Package contents not available individually\n";
break;
}
if (ISNQCLIENT(host_client))
{
SV_PrintToClient(host_client, PRINT_HIGH, error);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+12);
ClientReliableWrite_String (host_client, "\nstopdownload\n");
}
#ifdef PEXT_CHUNKEDDOWNLOADS
else if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS)
if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS)
{
ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(name));
ClientReliableWrite_Long (host_client, -1);
@ -2850,6 +2853,14 @@ void SV_BeginDownload_f(void)
}
else
#endif
if (ISNQCLIENT(host_client))
{
SV_PrintToClient(host_client, PRINT_HIGH, error);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+12);
ClientReliableWrite_String (host_client, "\nstopdownload\n");
}
else
{
SV_PrintToClient(host_client, PRINT_HIGH, error);
@ -2857,15 +2868,6 @@ void SV_BeginDownload_f(void)
ClientReliableWrite_Short (host_client, -1);
ClientReliableWrite_Byte (host_client, 0);
}
//it errored because it was a redirection.
//ask the client to grab the alternate file instead.
if (redirection)
{
//tell the client to download the new one.
ClientReliableWrite_Begin (host_client, ISQ2CLIENT(host_client)?svcq2_stufftext:svc_stufftext, 2+strlen(redirection));
ClientReliableWrite_String (host_client, va("\ndownload \"%s\"\n", redirection));
}
return;
}
@ -4418,7 +4420,7 @@ void SVNQ_Spawn_f (void)
// normally this could overflow, but no need to check due to backbuf
for (i=0, client = svs.clients; i<sv.allocated_client_slots ; i++, client++)
SV_FullClientUpdateToClient (client, host_client);
SV_FullClientUpdate(client, host_client);
SV_MVD_FullClientUpdate(NULL, host_client);
// send all current light styles

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
/*
I think globals.maxentities is the hard cap, rather than current max like in q1.

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_phys.c
#include "qwsvdef.h"
#include "quakedef.h"
#ifdef HLSERVER

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// world.c -- world query functions
#include "qwsvdef.h"
#include "quakedef.h"
#ifdef HLSERVER
#include "svhl_gcapi.h"

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// models.c -- model loading and caching
#include "qwsvdef.h"
#include "quakedef.h"
#ifdef SERVERONLY
model_t *loadmodel;

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#ifndef CLIENTONLY

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
#define Q2NUM_FOR_EDICT(ent) (((char *)ent - (char *)ge->edicts) / ge->edict_size)

View file

@ -1,4 +1,4 @@
#include "qwsvdef.h"
#include "quakedef.h"
//An implementation of a Q3 server...
//requires qvm implementation and existing q3 client stuff (or at least the overlapping stuff in q3common.c).

View file

@ -229,6 +229,7 @@ void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, void *data, net
}
}
#if 0
int Netchan_IsLocal (netadr_t adr)
{
struct sockaddr_in *sadr = (struct sockaddr_in *)&adr;
@ -267,7 +268,7 @@ int Netchan_IsLocal (netadr_t adr)
return false;
}
}
#endif

View file

@ -862,7 +862,7 @@ void PM_PlayerMove (pmove_t *pmove);
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qboolean isclient);
void Netchan_OutOfBandPrint (cluster_t *cluster, netadr_t adr, char *format, ...) PRINTFWARNING(3);
int Netchan_IsLocal (netadr_t adr);
//int Netchan_IsLocal (netadr_t adr);
void NET_InitUDPSocket(cluster_t *cluster, int port, qboolean ipv6);
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, void *data, netadr_t adr);
SOCKET NET_ChooseSocket(SOCKET sock[], netadr_t *adr);

View file

@ -2770,13 +2770,13 @@ I've removed the following from this function as it covered the menu (~Moodles):
tuiadmin:
if (!*cluster->adminpassword)
{
if (Netchan_IsLocal(v->netchan.remote_address))
/*if (Netchan_IsLocal(v->netchan.remote_address))
{
Sys_Printf(cluster, "Local player %s logs in as admin\n", v->name);
QW_SetMenu(v, MENU_ADMIN);
v->isadmin = true;
}
else
else*/
QW_PrintfToViewer(v, "There is no admin password set\nYou may not log in.\n");
}
else if (v->isadmin)

View file

@ -1,16 +1,22 @@
//Released under the terms of the gpl as this file uses a bit of quake derived code. All sections of the like are marked as such
#include "../plugin.h"
#include <time.h>
#define Q_strncpyz(o, i, l) do {strncpy(o, i, l-1);o[l-1]='\0';}while(0)
#define JCL_BUILD "1"
#define JCL_BUILD "2"
#define ARGNAMES ,sock
BUILTINR(int, Net_SetTLSClient, (qhandle_t sock));
#define ARGNAMES ,sock,certhostname
BUILTINR(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname));
#undef ARGNAMES
void (*Con_TrySubPrint)(const char *conname, const char *message);
void Fallback_ConPrint(const char *conname, const char *message)
{
Con_Print(message);
}
void Con_SubPrintf(char *subname, char *format, ...)
{
@ -21,7 +27,7 @@ void Con_SubPrintf(char *subname, char *format, ...)
vsnprintf (string, sizeof(string), format,argptr);
va_end (argptr);
Con_SubPrint(subname, string);
Con_TrySubPrint(subname, string);
}
@ -123,7 +129,7 @@ void Con_SubPrintf(char *subname, char *format, ...)
void JCL_Command(void);
int JCL_ExecuteCommand(int *args)
qintptr_t JCL_ExecuteCommand(qintptr_t *args)
{
char cmd[256];
Cmd_Argv(0, cmd, sizeof(cmd));
@ -135,13 +141,11 @@ int JCL_ExecuteCommand(int *args)
return false;
}
int JCL_ConExecuteCommand(int *args);
qintptr_t JCL_ConExecuteCommand(qintptr_t *args);
int JCL_Frame(int *args);
qintptr_t JCL_Frame(qintptr_t *args);
int (*Con_TrySubPrint)(char *conname, char *message);
int Plug_Init(int *args)
qintptr_t Plug_Init(qintptr_t *args)
{
if ( Plug_Export("Tick", JCL_Frame) &&
Plug_Export("ExecuteCommand", JCL_ExecuteCommand))
@ -155,7 +159,7 @@ int Plug_Init(int *args)
if (!Plug_Export("ConExecuteCommand", JCL_ConExecuteCommand))
{
Con_Printf("Jabber client plugin in single-console mode\n");
Con_TrySubPrint = Con_Print;
Con_TrySubPrint = Fallback_ConPrint;
}
else
Con_TrySubPrint = Con_SubPrint;
@ -182,7 +186,7 @@ int Plug_Init(int *args)
//but never used cos it breaks strings
#define JCL_MAXMSGLEN 2048
#define JCL_MAXMSGLEN 10000
typedef struct {
@ -193,7 +197,9 @@ typedef struct {
qhandle_t inlog;
qhandle_t outlog;
char bufferedinmessage[JCL_MAXMSGLEN+1]; //there is a max size for protocol. (conveinient eh?) (and it's text format)
char bufferedinmessage[JCL_MAXMSGLEN+1]; //servers are required to be able to handle messages no shorter than a specific size.
//which means we need to be able to handle messages when they get to us.
//servers can still handle larger messages if they choose, so this might not be enough.
int bufferedinammount;
char defaultdest[256];
@ -207,12 +213,16 @@ typedef struct {
int openbracket;
int instreampos;
qboolean noplain;
qboolean issecure;
qboolean connected; //fully on server and authed and everything.
qboolean noplain; //block plain-text password exposure
qboolean issecure; //tls enabled
char curquakeserver[2048];
char defaultnamespace[2048]; //should be 'jabber:client' or blank (and spammy with all the extra xmlns attribs)
} jclient_t;
jclient_t *jclient;
int JCL_ConExecuteCommand(int *args)
qintptr_t JCL_ConExecuteCommand(qintptr_t *args)
{
if (!jclient)
{
@ -229,7 +239,7 @@ int JCL_ConExecuteCommand(int *args)
void JCL_AddClientMessage(jclient_t *jcl, char *msg, int datalen)
{
Net_Send(jcl->socket, msg, datalen); //FIXME: This needs rewriting to cope with errors.
Con_Printf(COLOURYELLOW "<< %s \n",msg);
Con_SubPrintf("xmppout", COLOURYELLOW "%s \n",msg);
}
void JCL_AddClientMessageString(jclient_t *jcl, char *msg)
{
@ -275,7 +285,7 @@ jclient_t *JCL_Connect(char *server, int defport, qboolean usesecure, char *acco
if (usesecure)
{
if (Net_SetTLSClient(jcl->socket)<0)
if (Net_SetTLSClient(jcl->socket, server)<0)
{
Net_Close(jcl->socket);
free(jcl);
@ -299,7 +309,7 @@ jclient_t *JCL_Connect(char *server, int defport, qboolean usesecure, char *acco
strlcpy(jcl->domain, at+1, sizeof(jcl->domain));
strlcpy(jcl->password, password, sizeof(jcl->password));
strcpy(jcl->resource, "Quake");
strlcpy(jcl->resource, "Quake", sizeof(jcl->password));
Con_Printf("Trying to connect\n");
JCL_AddClientMessageString(jcl,
@ -320,6 +330,8 @@ typedef struct xmlparams_s {
typedef struct subtree_s {
char name[64];
char xmlns[64]; //namespace of the element
char xmlns_dflt[64]; //default namespace of children
char body[2048];
xmlparams_t *params;
@ -329,7 +341,18 @@ typedef struct subtree_s {
} xmltree_t;
void XML_Destroy(xmltree_t *t);
xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly)
char *XML_ParameterOfTree(xmltree_t *t, char *paramname)
{
xmlparams_t *p;
for (p = t->params; p; p = p->next)
if (!strcmp(p->name, paramname))
return p->val;
return NULL;
}
//fixme: we should accept+parse the default namespace
xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly, char *defaultnamespace)
{
xmlparams_t *p;
xmltree_t *child;
@ -338,6 +361,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
int pos;
char *tagend;
char *tagstart;
char *ns;
pos = *startpos;
while (buffer[pos] >= '\0' && buffer[pos] <= ' ')
{
@ -346,6 +370,12 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
pos++;
}
if (pos == maxpos)
{
*startpos = pos;
return NULL; //nothing anyway.
}
//expect a <
if (buffer[pos] != '<')
@ -384,9 +414,23 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
ret = malloc(sizeof(xmltree_t));
memset(ret, 0, sizeof(*ret));
strlcpy(ret->name, com_token, sizeof(ret->name));
// FIXME:parse the parameters
ns = strchr(com_token, ':');
if (ns)
{
*ns = 0;
ns++;
memcpy(ret->xmlns, "xmlns:", 6);
strlcpy(ret->xmlns+6, com_token, sizeof(ret->xmlns)-6);
strlcpy(ret->name, ns, sizeof(ret->name));
}
else
{
strlcpy(ret->xmlns, "xmlns", sizeof(ret->xmlns));
strlcpy(ret->name, com_token, sizeof(ret->name));
}
while(*tagstart)
{
int nlen;
@ -463,6 +507,12 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
ret->params = p;
}
ns = XML_ParameterOfTree(ret, ret->xmlns);
strlcpy(ret->xmlns, ns?ns:"", sizeof(ret->xmlns));
ns = XML_ParameterOfTree(ret, "xmlns");
strlcpy(ret->xmlns_dflt, ns?ns:defaultnamespace, sizeof(ret->xmlns_dflt));
tagend[-1] = '>';
if (tagend[-2] == '/')
@ -516,7 +566,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
break;
}
child = XML_Parse(buffer, &pos, maxpos, false);
child = XML_Parse(buffer, &pos, maxpos, false, ret->xmlns_dflt);
if (!child)
{
Con_Printf("Child block is unparsable\n");
@ -527,7 +577,11 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
ret->child = child;
}
else
ret->body[bodypos++] = buffer[pos++];
{
char c = buffer[pos++];
if (bodypos < sizeof(ret->body)-1)
ret->body[bodypos++] = c;
}
}
ret->body[bodypos++] = '\0';
@ -536,15 +590,6 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
return ret;
}
char *XML_ParameterOfTree(xmltree_t *t, char *paramname)
{
xmlparams_t *p;
for (p = t->params; p; p = p->next)
if (!strcmp(p->name, paramname))
return p->val;
return NULL;
}
void XML_Destroy(xmltree_t *t)
{
xmlparams_t *p, *np;
@ -631,7 +676,7 @@ void Base64_Byte(unsigned int byt)
base64[base64_len++] = Base64_From64((base64_cur>>6)&63);
base64[base64_len++] = Base64_From64((base64_cur>>0)&63);
base64[base64_len] = '\0';
Con_Printf("base64: %s\n", base64+base64_len-4);
// Con_Printf("base64: %s\n", base64+base64_len-4);
base64_bits = 0;
base64_cur = 0;
}
@ -713,27 +758,24 @@ int JCL_ClientFrame(jclient_t *jcl)
ret = Net_Recv(jcl->socket, jcl->bufferedinmessage+jcl->bufferedinammount, sizeof(jcl->bufferedinmessage)-1 - jcl->bufferedinammount);
if (ret == 0)
{
Con_Printf("JCL: Remote host disconnected\n");
return JCL_KILL;
}
if (ret < 0)
{
if (ret == N_WOULDBLOCK)
{
if (!jcl->bufferedinammount) //if we are half way through a message, read any possible conjunctions.
return JCL_DONE; //remove
}
else
if (ret < 0)
{
Con_Printf("JCL: socket error\n");
return JCL_KILL;
}
}
if (ret>0)
{
jcl->bufferedinammount+=ret;
jcl->bufferedinmessage[jcl->bufferedinammount] = 0;
Con_TrySubPrint("xmppin", jcl->bufferedinmessage+jcl->bufferedinammount-ret);
}
olddepth = jcl->tagdepth;
//we never end parsing in the middle of a < >
@ -771,11 +813,11 @@ int JCL_ClientFrame(jclient_t *jcl)
{ //first bit of info
pos = 0;
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, true);
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, true, "");
while (tree && !strcmp(tree->name, "?xml"))
{
XML_Destroy(tree);
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, true);
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, true, "");
}
if (!tree)
@ -783,17 +825,19 @@ int JCL_ClientFrame(jclient_t *jcl)
Con_Printf("Not an xml stream\n");
return JCL_KILL;
}
if (strcmp(tree->name, "stream:stream"))
if (strcmp(tree->name, "stream") || strcmp(tree->xmlns, "http://etherx.jabber.org/streams"))
{
Con_Printf("Not an xmpp stream\n");
return JCL_KILL;
}
strlcpy(jcl->defaultnamespace, tree->xmlns_dflt, sizeof(jcl->defaultnamespace));
ot = tree;
tree = tree->child;
ot->child = NULL;
Con_Printf("Discard\n");
XML_ConPrintTree(ot, 0);
// Con_Printf("Discard\n");
// XML_ConPrintTree(ot, 0);
XML_Destroy(ot);
if (!tree)
@ -818,7 +862,7 @@ int JCL_ClientFrame(jclient_t *jcl)
}
pos = 0;
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, false);
tree = XML_Parse(jcl->bufferedinmessage, &pos, jcl->instreampos, false, jcl->defaultnamespace);
if (!tree)
{
@ -827,12 +871,12 @@ int JCL_ClientFrame(jclient_t *jcl)
}
}
Con_Printf("read\n");
XML_ConPrintTree(tree, 0);
// Con_Printf("read\n");
// XML_ConPrintTree(tree, 0);
unparsable = true;
if (!strcmp(tree->name, "stream:features"))
if (!strcmp(tree->name, "features"))
{
if ((ot=XML_ChildOfTree(tree, "bind", 0)))
{
@ -846,6 +890,9 @@ int JCL_ClientFrame(jclient_t *jcl)
unparsable = false;
JCL_AddClientMessageString(jcl, "<iq type='set' id='H_1'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>");
JCL_AddClientMessageString(jcl, "<presence/>");
jcl->connected = true;
JCL_AddClientMessageString(jcl, "<iq type='get' to='gmail.com' id='H_2'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>");
}
@ -853,6 +900,7 @@ int JCL_ClientFrame(jclient_t *jcl)
{
if ((!jclient->issecure) && BUILTINISVALID(Net_SetTLSClient) && XML_ChildOfTree(tree, "starttls", 0) != NULL)
{
Con_Printf("Attempting to switch to TLS\n");
JCL_AddClientMessageString(jcl, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' />");
unparsable = false;
}
@ -862,24 +910,28 @@ int JCL_ClientFrame(jclient_t *jcl)
{
if (!strcmp(ot->body, "PLAIN"))
{
char msg[2048];
if (jclient->noplain && !jclient->issecure) //probably don't send plain without tls.
{
//plain can still be read with man-in-the-middle attacks, of course, even with stl.
Con_Printf("Ignoring auth \'%s\'\n", ot->body);
continue;
}
Con_Printf("Authing with \'%s\'\n", ot->body);
JCL_AddClientMessageString(jcl, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>");
Base64_Add(jclient->username, strlen(jcl->username));
Base64_Add("@", 1);
Base64_Add(jclient->domain, strlen(jcl->domain));
Con_Printf("Authing with \'%s\'%s\n", ot->body, jclient->issecure?" over tls/ssl":"");
// Base64_Add(jclient->username, strlen(jcl->username));
// Base64_Add("@", 1);
// Base64_Add(jclient->domain, strlen(jcl->domain));
Base64_Add("", 1);
Base64_Add(jclient->username, strlen(jcl->username));
Base64_Add("", 1);
Base64_Add(jcl->password, strlen(jcl->password));
Base64_Finish();
JCL_AddClientMessageString(jcl, base64);
JCL_AddClientMessageString(jcl, "</auth>");
snprintf(msg, sizeof(msg), "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>%s</auth>", base64);
JCL_AddClientMessageString(jcl, msg);
// JCL_AddClientMessageString(jcl, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>");
// JCL_AddClientMessageString(jcl, base64);
// JCL_AddClientMessageString(jcl, "</auth>");
unparsable = false;
break;
}
@ -911,12 +963,14 @@ int JCL_ClientFrame(jclient_t *jcl)
if (!BUILTINISVALID(Net_SetTLSClient))
{
Con_Printf("JCL: proceed without TLS\n");
XML_Destroy(tree);
return JCL_KILL;
}
if (Net_SetTLSClient(jcl->socket)<0)
if (Net_SetTLSClient(jcl->socket, jcl->domain)<0)
{
Con_Printf("JCL: failed to switch to TLS\n");
XML_Destroy(tree);
return JCL_KILL;
}
jclient->issecure = true;
@ -927,6 +981,7 @@ int JCL_ClientFrame(jclient_t *jcl)
JCL_AddClientMessageString(jcl, jcl->domain);
JCL_AddClientMessageString(jcl, "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
XML_Destroy(tree);
return JCL_DONE;
}
else if (!strcmp(tree->name, "stream:error"))
@ -938,6 +993,7 @@ int JCL_ClientFrame(jclient_t *jcl)
Con_Printf("JCL: Failure: %s\n", tree->child->name);
else
Con_Printf("JCL: Unknown failure\n");
XML_Destroy(tree);
return JCL_KILL;
}
else if (!strcmp(tree->name, "success"))
@ -960,7 +1016,6 @@ int JCL_ClientFrame(jclient_t *jcl)
char *from;
char *to;
char *id;
unparsable = false;
id = XML_ParameterOfTree(tree, "id");
from = XML_ParameterOfTree(tree, "from");
@ -972,55 +1027,213 @@ int JCL_ClientFrame(jclient_t *jcl)
ot = XML_ChildOfTree(tree, "query", 0);
if (ot)
{
f = XML_ParameterOfTree(tree, "xmlns");
if (f && to && from && !strcmp(f, "jabber:iq:version"))
{ //client->client version request
JCL_AddClientMessageString(jcl, "<iq type='result' to='");
JCL_AddClientMessageString(jcl, from);
JCL_AddClientMessageString(jcl, "' from='");
JCL_AddClientMessageString(jcl, to);
JCL_AddClientMessageString(jcl, "' id='");
JCL_AddClientMessageString(jcl, id);
JCL_AddClientMessageString(jcl, "'>");
if (from && !strcmp(ot->xmlns, "http://jabber.org/protocol/disco#info"))
{ //http://xmpp.org/extensions/xep-0030.html
char msg[2048];
int idletime = 0;
unparsable = false;
JCL_AddClientMessageString(jcl, "<query xmlns='jabber:iq:version'>"
snprintf(msg, sizeof(msg),
"<iq type='result' to='%s' id='%s'>"
"<query xmlns='http://jabber.org/protocol/disco#info'>"
"<identity category='client' type='pc' name='FTEQW'/>"
"<feature var='jabber:iq:version'/>"
#ifndef Q3_VM
"<feature var='urn:xmpp:time'/>"
#endif
"</query>"
"</iq>", from, id, idletime);
JCL_AddClientMessageString(jcl, msg);
}
else if (from && !strcmp(ot->xmlns, "jabber:iq:version"))
{ //client->client version request
char msg[2048];
unparsable = false;
snprintf(msg, sizeof(msg),
"<iq type='result' to='%s' id='%s'>"
"<query xmlns='jabber:iq:version'>"
"<name>FTEQW Jabber Plugin</name>"
"<version>"JCL_BUILD"</version>"
"<version>V"JCL_BUILD"</version>"
#ifdef Q3_VM
"<os>QVM plugin</os>"
#endif
"</query>");
"</query>"
"</iq>", from, id);
JCL_AddClientMessageString(jcl, "</iq>");
JCL_AddClientMessageString(jcl, msg);
}
/* else if (from && !strcmp(ot->xmlns, "jabber:iq:last"))
{ //http://xmpp.org/extensions/xep-0012.html
char msg[2048];
int idletime = 0;
unparsable = false;
//last activity
snprintf(msg, sizeof(msg),
"<iq type='result' to='%s' id='%s'>"
"<query xmlns='jabber:iq:last' seconds='%i'/>"
"</iq>", from, id, idletime);
JCL_AddClientMessageString(jcl, msg);
}
*/
}
#ifndef Q3_VM
ot = XML_ChildOfTree(tree, "time", 0);
if (ot && !strcmp(ot->xmlns, "urn:xmpp:time"))
{ //http://xmpp.org/extensions/xep-0202.html
char msg[2048];
char tz[256];
char timestamp[256];
int idletime = 0;
struct tm * timeinfo;
int tzs;
time_t rawtime;
time (&rawtime);
timeinfo = gmtime (&rawtime);
tzs = _timezone;
tzs *= -1;
snprintf(tz, sizeof(tz), "%+i:%i", tzs/(60*60), abs(tzs/60) % 60);
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%SZ", timeinfo);
unparsable = false;
//strftime
snprintf(msg, sizeof(msg),
"<iq type='result' to='%s' id='%s'>"
"<time xmlns='urn:xmpp:time'>"
"<tzo>+00:00</tzo>"
"<utc>2006-12-19T17:58:35Z</utc>"
"</time>"
"</iq>", from, id, tz, timestamp);
JCL_AddClientMessageString(jcl, msg);
}
#endif
if (unparsable)
{ //unsupported stuff
char msg[2048];
unparsable = false;
Con_Print("Unsupported iq get\n");
XML_ConPrintTree(tree, 0);
//tell them OH NOES, instead of requiring some timeout.
snprintf(msg, sizeof(msg),
"<iq type='error' to='%s' id='%s'>"
"<error type='cancel'>"
"<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
"</error>"
"</iq>", from, id);
JCL_AddClientMessageString(jcl, msg);
}
}
else if (f && !strcmp(f, "result"))
{
xmltree_t *c, *v;
unparsable = false;
c = XML_ChildOfTree(tree, "bind", 0);
if (c)
{
v = XML_ChildOfTree(c, "jid", 0);
if (v)
Con_Printf("Bound to jid \"%s\"\n", v->body);
}
else
{
Con_Print("Unrecognised iq result\n");
XML_ConPrintTree(tree, 0);
}
}
if (unparsable)
{
unparsable = false;
Con_Print("Unrecognised iq type\n");
XML_ConPrintTree(tree, 0);
}
}
else if (!strcmp(tree->name, "message"))
{
unparsable = false;
ot = XML_ChildOfTree(tree, "body", 0);
if (ot)
{
f = XML_ParameterOfTree(tree, "from");
if (f)
{
strlcpy(jcl->defaultdest, f, sizeof(jcl->defaultdest));
RenameConsole(f);
Con_SubPrintf(f, "%s: %s\n", f, ot->body);
}
if (f)
{
ot = XML_ChildOfTree(tree, "composing", 0);
if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates"))
{
unparsable = false;
Con_SubPrintf(f, "%s is typing\r", f);
}
ot = XML_ChildOfTree(tree, "paused", 0);
if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates"))
{
unparsable = false;
Con_SubPrintf(f, "%s has stopped typing\r", f);
}
ot = XML_ChildOfTree(tree, "inactive", 0);
if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates"))
{
unparsable = false;
Con_SubPrintf(f, "%s has become inactive\r", f);
}
ot = XML_ChildOfTree(tree, "active", 0);
if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates"))
{
unparsable = false;
Con_SubPrintf(f, "\r", f);
}
ot = XML_ChildOfTree(tree, "gone", 0);
if (ot && !strcmp(ot->xmlns, "http://jabber.org/protocol/chatstates"))
{
unparsable = false;
Con_SubPrintf(f, "%s has gone away\r", f);
}
}
ot = XML_ChildOfTree(tree, "body", 0);
if (ot)
{
unparsable = false;
if (f)
Con_SubPrintf(f, "%s: %s\n", f, ot->body);
else
Con_Print(ot->body);
LocalSound("misc/talk.wav");
}
else
if (unparsable)
{
unparsable = false;
Con_Print("Received a message without a body\n");
XML_ConPrintTree(tree, 0);
}
}
else if (!strcmp(tree->name, "presence"))
{
char *from = XML_ParameterOfTree(tree, "from");
xmltree_t *show = XML_ChildOfTree(tree, "show", 0);
xmltree_t *status = XML_ChildOfTree(tree, "status", 0);
xmltree_t *quake = XML_ChildOfTree(tree, "quake", 0);
xmltree_t *serverip = NULL;
if (quake && !strcmp(quake->xmlns, "fteqw.com:game"))
serverip = XML_ChildOfTree(quake, "serverip", 0);
if (serverip && *serverip->body)
Con_Printf("%s is now playing quake! ^[JOIN THEM!\\join\\%s^]\n", from, serverip->body);
else if (status && *status->body)
Con_Printf("%s is now %s: %s\n", from, show?show->body:"present", status->body);
else
Con_Printf("%s is now %s\n", from, show?show->body:"present");
//we should keep a list of the people that we know of.
unparsable = false;
}
@ -1054,11 +1267,40 @@ void JCL_CloseConnection(jclient_t *jcl)
//functions above this line allow connections to multiple servers.
//it is just the control functions that only allow one server.
int JCL_Frame(int *args)
qintptr_t JCL_Frame(qintptr_t *args)
{
int stat = JCL_CONTINUE;
if (jclient)
{
if (jclient->connected)
{
int dummystat;
char serveraddr[1024*16];
//get the last server address
if (!Cvar_GetString("cl_serveraddress", serveraddr, sizeof(serveraddr)))
serveraddr[0] = 0;
//if we can't get any stats, its because we're not actually on the server.
if (!CL_GetStats(0, &dummystat, 1))
serveraddr[0] = 0;
if (strcmp(jclient->curquakeserver, serveraddr))
{
char msg[1024];
strlcpy(jclient->curquakeserver, serveraddr, sizeof(jclient->curquakeserver));
if (!*jclient->curquakeserver)
strlcpy(msg, "<presence/>", sizeof(msg));
else
snprintf(msg, sizeof(msg),
"<presence>"
"<quake xmlns='fteqw.com:game'>"
"<serverip>sha1-hash-of-image</serverip>"
"</quake>"
"</presence>"
);
JCL_AddClientMessageString(jclient, msg);
}
}
while(stat == JCL_CONTINUE)
stat = JCL_ClientFrame(jclient);
if (stat == JCL_KILL)
@ -1163,6 +1405,10 @@ void JCL_Command(void)
Con_SubPrintf(jclient->defaultdest, "%s: "COLOURYELLOW"%s\n", ">>", msg);
}
else if (!strcmp(arg[0]+1, "raw"))
{
JCL_AddClientMessageString(jclient, arg[1]);
}
else
Con_Printf("Unrecognised command: %s\n", arg[0]);
}

View file

@ -55,7 +55,7 @@ BUILTIN(void, Con_Print, (const char *text)); //on to main console.
#undef ARGNAMES
#define ARGNAMES ,conname,text
BUILTIN(void, Con_SubPrint, (char *conname, char *text)); //on to named sub console (creating it too).
BUILTIN(void, Con_SubPrint, (const char *conname, const char *text)); //on to named sub console (creating it too).
#undef ARGNAMES
#define ARGNAMES ,old,new
BUILTIN(void, Con_RenameSub, (char *old, char *new)); //rename a subconsole
@ -120,7 +120,7 @@ BUILTINR(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stri
#undef ARGNAMES
#define ARGNAMES ,pnum,stats,maxstats
BUILTIN(void, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
BUILTINR(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
#undef ARGNAMES
#define ARGNAMES ,pnum,info
BUILTINR(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info));

View file

@ -6,6 +6,9 @@
typedef int qintptr_t;
typedef unsigned int quintptr_t;
typedef unsigned int size_t;
typedef signed int ssize_t;
#define TESTBI 1
#ifdef TESTBI
# define EBUILTIN(t, n, args) extern t (*n) args
@ -139,7 +142,7 @@ EBUILTIN(qboolean, Plug_ExportNative, (const char *funcname, void *func)); //set
#endif
EBUILTIN(void, Con_Print, (const char *text)); //on to main console.
EBUILTIN(void, Con_SubPrint, (char *subname, char *text)); //on to sub console.
EBUILTIN(void, Con_SubPrint, (const char *subname, const char *text)); //on to sub console.
EBUILTIN(void, Con_RenameSub, (char *oldname, char *newname)); //rename a console.
EBUILTIN(int, Con_IsActive, (char *conname));
EBUILTIN(void, Con_SetActive, (char *conname));
@ -165,7 +168,7 @@ EBUILTIN(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stri
EBUILTIN(void, GetPluginName, (int plugnum, char *buffer, int bufsize));
EBUILTIN(void, LocalSound, (char *soundname));
EBUILTIN(void, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
EBUILTIN(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
EBUILTIN(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info));
EBUILTIN(int, LocalPlayerNumber, (void));

View file

@ -57,7 +57,7 @@ retry:
precision=precision*10+*format-'0';
goto retry;
case '%': /*emit a %*/
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *format;
break;
@ -69,7 +69,7 @@ retry:
{
while (*string && precision--)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -78,7 +78,7 @@ retry:
{
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -87,7 +87,7 @@ retry:
break;
case 'c':
_int = va_arg(vargs, int);
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = _int;
tokens++;
@ -96,7 +96,7 @@ retry:
_int = va_arg(vargs, int);
if (_int < 0)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = '-';
_int *= -1;
@ -134,7 +134,7 @@ retry:
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -178,7 +178,7 @@ Con_Printf("%i bytes left\n", maxlen);
*/
if (_int < 0)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = '-';
_int *= -1;
@ -211,7 +211,7 @@ Con_Printf("%i bytes left\n", maxlen);
*/
while(precision>0)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
if (use0s)
*buffer++ = '0';
@ -222,7 +222,7 @@ Con_Printf("%i bytes left\n", maxlen);
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -235,7 +235,7 @@ Con_Printf("%i bytes left\n", maxlen);
_int = (int)_float;
if (_int < 0)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = '-';
_int *= -1;
@ -257,7 +257,7 @@ Con_Printf("%i bytes left\n", maxlen);
string = tempbuffer+i+1;
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -287,7 +287,7 @@ Con_Printf("%i bytes left\n", maxlen);
string = tempbuffer;
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -298,7 +298,7 @@ Con_Printf("%i bytes left\n", maxlen);
string = "ERROR IN FORMAT";
while (*string)
{
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *string++;
}
@ -306,7 +306,7 @@ Con_Printf("%i bytes left\n", maxlen);
}
break;
default:
if (--maxlen < 0)
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = *format;
break;