mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-21 19:41:14 +00:00
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:
parent
fed1fb62a7
commit
6a831e2f99
84 changed files with 2998 additions and 2482 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -965,13 +965,13 @@ void CLNQ_Connect_f (void)
|
|||
CL_BeginServerConnect(26000);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef IRCCONNECT
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] == '\\')
|
||||
|
|
|
@ -468,78 +468,78 @@ 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];
|
||||
char file[MAX_OSPATH];
|
||||
char truepath[MAX_OSPATH];
|
||||
char *s;
|
||||
struct dirent *ent;
|
||||
struct stat st;
|
||||
DIR *dir;
|
||||
char apath[MAX_OSPATH];
|
||||
char file[MAX_OSPATH];
|
||||
char truepath[MAX_OSPATH];
|
||||
char *s;
|
||||
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 = "";
|
||||
*apath = '\0';
|
||||
if (!gpath)
|
||||
gpath = "";
|
||||
*apath = '\0';
|
||||
|
||||
Q_strncpyz(apath, match, sizeof(apath));
|
||||
for (s = apath+strlen(apath)-1; s >= apath; s--)
|
||||
{
|
||||
if (*s == '/')
|
||||
{
|
||||
s[1] = '\0';
|
||||
match += s - apath+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s < apath) //didn't find a '/'
|
||||
*apath = '\0';
|
||||
|
||||
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);
|
||||
dir = opendir(truepath);
|
||||
if (!dir)
|
||||
{
|
||||
Con_DPrintf("Failed to open dir %s\n", truepath);
|
||||
return true;
|
||||
}
|
||||
do
|
||||
{
|
||||
ent = readdir(dir);
|
||||
if (!ent)
|
||||
break;
|
||||
if (*ent->d_name != '.')
|
||||
{
|
||||
if (wildcmp(match, ent->d_name))
|
||||
{
|
||||
Q_snprintfz(file, sizeof(file), "%s/%s", truepath, ent->d_name);
|
||||
|
||||
if (stat(file, &st) == 0)
|
||||
{
|
||||
Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":"");
|
||||
|
||||
if (!func(file, st.st_size, parm))
|
||||
{
|
||||
closedir(dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Stat failed for \"%s\"\n", file);
|
||||
}
|
||||
}
|
||||
} while(1);
|
||||
closedir(dir);
|
||||
|
||||
return true;
|
||||
Q_strncpyz(apath, match, sizeof(apath));
|
||||
for (s = apath+strlen(apath)-1; s >= apath; s--)
|
||||
{
|
||||
if (*s == '/')
|
||||
{
|
||||
s[1] = '\0';
|
||||
match += s - apath+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s < apath) //didn't find a '/'
|
||||
*apath = '\0';
|
||||
|
||||
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);
|
||||
dir = opendir(truepath);
|
||||
if (!dir)
|
||||
{
|
||||
Con_DPrintf("Failed to open dir %s\n", truepath);
|
||||
return true;
|
||||
}
|
||||
do
|
||||
{
|
||||
ent = readdir(dir);
|
||||
if (!ent)
|
||||
break;
|
||||
if (*ent->d_name != '.')
|
||||
{
|
||||
if (wildcmp(match, ent->d_name))
|
||||
{
|
||||
Q_snprintfz(file, sizeof(file), "%s/%s", truepath, ent->d_name);
|
||||
|
||||
if (stat(file, &st) == 0)
|
||||
{
|
||||
Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":"");
|
||||
|
||||
if (!func(file, st.st_size, parm, spath))
|
||||
{
|
||||
closedir(dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Stat failed for \"%s\"\n", file);
|
||||
}
|
||||
}
|
||||
} while(1);
|
||||
closedir(dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -568,7 +568,8 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception
|
|||
BOOL (WINAPI *pIsDebuggerPresent)(void);
|
||||
|
||||
#ifdef PRINTGLARRAYS
|
||||
DumpGLState();
|
||||
if (qrenderer == QR_OPENGL)
|
||||
DumpGLState();
|
||||
#endif
|
||||
|
||||
hKernel = LoadLibrary ("kernel32");
|
||||
|
@ -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)
|
||||
end = COM_ParseFunString(CON_WHITEMASK, text, msg, sizeof(msg), false);
|
||||
out = wide;
|
||||
in = msg;
|
||||
wlen = 0;
|
||||
for (in = msg; in < end; in++)
|
||||
{
|
||||
//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;
|
||||
for (in = msg; in < end; in++)
|
||||
if (!(*in & CON_HIDDEN))
|
||||
{
|
||||
if (!(*in & CON_HIDDEN))
|
||||
*out++ = dequake(*in & CON_CHARMASK);
|
||||
*out++ = dequake(*in & CON_CHARMASK);
|
||||
wlen++;
|
||||
}
|
||||
*out = 0;
|
||||
OutputDebugStringW(wide);
|
||||
}
|
||||
*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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,10 +82,12 @@ 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 UDP_CloseSocket (int socket);
|
||||
void NET_Shutdown (void);
|
||||
int NET_GetPacket (netsrc_t netsrc, int firstsock);
|
||||
void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to);
|
||||
|
@ -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);
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
624
engine/common/net_ssl_winsspi.c
Normal file
624
engine/common/net_ssl_winsspi.c
Normal 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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -146,140 +146,141 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
//
|
||||
// server to client
|
||||
//
|
||||
#define svc_bad 0
|
||||
#define svc_nop 1
|
||||
#define svc_disconnect 2
|
||||
#define svcqw_updatestatbyte 3 // [qbyte] [qbyte]
|
||||
#define svcnq_updatestatlong 3 // [qbyte] [long]
|
||||
#define svc_version 4 // [long] server version
|
||||
#define svc_setview 5 // [short] entity number
|
||||
#define svc_sound 6 // <see code>
|
||||
#define svc_time 7 // [float] server time
|
||||
#define svc_print 8 // [qbyte] id [string] null terminated string
|
||||
#define svc_stufftext 9 // [string] stuffed into client's console buffer
|
||||
// the string should be \n terminated
|
||||
#define svc_setangle 10 // [angle3] set the view angle to this absolute value
|
||||
#define svc_bad 0
|
||||
#define svc_nop 1
|
||||
#define svc_disconnect 2
|
||||
#define svcqw_updatestatbyte 3 // [qbyte] [qbyte]
|
||||
#define svcnq_updatestatlong 3 // [qbyte] [long]
|
||||
#define svc_version 4 // [long] server version
|
||||
#define svc_setview 5 // [short] entity number
|
||||
#define svc_sound 6 // <see code>
|
||||
#define svc_time 7 // [float] server time
|
||||
#define svc_print 8 // [qbyte] id [string] null terminated string
|
||||
#define svc_stufftext 9 // [string] stuffed into client's console buffer
|
||||
// the string should be \n terminated
|
||||
#define svc_setangle 10 // [angle3] set the view angle to this absolute value
|
||||
|
||||
#define svc_serverdata 11 // [long] protocol ...
|
||||
#define svc_lightstyle 12 // [qbyte] [string]
|
||||
#define svc_updatename 13 // [qbyte] [string]
|
||||
#define svc_updatefrags 14 // [qbyte] [short]
|
||||
#define svc_clientdata 15 // <shortbits + data>
|
||||
#define svc_stopsound 16 // <see code>
|
||||
#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
|
||||
#define svc_particle 18 // [vec3] <variable>
|
||||
#define svc_damage 19
|
||||
#define svc_serverdata 11 // [long] protocol ...
|
||||
#define svc_lightstyle 12 // [qbyte] [string]
|
||||
#define svc_updatename 13 // [qbyte] [string]
|
||||
#define svc_updatefrags 14 // [qbyte] [short]
|
||||
#define svc_clientdata 15 // <shortbits + data>
|
||||
#define svc_stopsound 16 // <see code>
|
||||
#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
|
||||
#define svc_particle 18 // [vec3] <variable>
|
||||
#define svc_damage 19
|
||||
|
||||
#define svc_spawnstatic 20
|
||||
#define svcfte_spawnstatic2 21
|
||||
#define svc_spawnbaseline 22
|
||||
#define svc_spawnstatic 20
|
||||
#define svcfte_spawnstatic2 21
|
||||
#define svc_spawnbaseline 22
|
||||
|
||||
#define svc_temp_entity 23 // variable
|
||||
#define svc_setpause 24 // [qbyte] on / off
|
||||
#define svc_signonnum 25 // [qbyte] used for the signon sequence
|
||||
#define svc_temp_entity 23 // variable
|
||||
#define svc_setpause 24 // [qbyte] on / off
|
||||
#define svc_signonnum 25 // [qbyte] used for the signon sequence
|
||||
|
||||
#define svc_centerprint 26 // [string] to put in center of the screen
|
||||
#define svc_centerprint 26 // [string] to put in center of the screen
|
||||
|
||||
#define svc_killedmonster 27
|
||||
#define svc_foundsecret 28
|
||||
#define svc_killedmonster 27
|
||||
#define svc_foundsecret 28
|
||||
|
||||
#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten
|
||||
#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten
|
||||
|
||||
#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle
|
||||
#define svc_finale 31 // [string] text
|
||||
#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle
|
||||
#define svc_finale 31 // [string] text
|
||||
|
||||
#define svc_cdtrack 32 // [qbyte] track
|
||||
#define svc_sellscreen 33
|
||||
#define svc_cdtrack 32 // [qbyte] track
|
||||
#define svc_sellscreen 33
|
||||
|
||||
#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt?
|
||||
#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt?
|
||||
|
||||
|
||||
|
||||
//QW svcs
|
||||
#define svc_smallkick 34 // set client punchangle to 2
|
||||
#define svc_bigkick 35 // set client punchangle to 4
|
||||
#define svc_smallkick 34 // set client punchangle to 2
|
||||
#define svc_bigkick 35 // set client punchangle to 4
|
||||
|
||||
#define svc_updateping 36 // [qbyte] [short]
|
||||
#define svc_updateentertime 37 // [qbyte] [float]
|
||||
#define svc_updateping 36 // [qbyte] [short]
|
||||
#define svc_updateentertime 37 // [qbyte] [float]
|
||||
|
||||
#define svcqw_updatestatlong 38 // [qbyte] [long]
|
||||
#define svcqw_updatestatlong 38 // [qbyte] [long]
|
||||
|
||||
#define svc_muzzleflash 39 // [short] entity
|
||||
#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
|
||||
#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8
|
||||
#define svc_chokecount 44 // [qbyte] packets choked
|
||||
#define svc_modellist 45 // [strings]
|
||||
#define svc_soundlist 46 // [strings]
|
||||
#define svc_packetentities 47 // [...]
|
||||
#define svc_deltapacketentities 48 // [...]
|
||||
#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||
#define svc_entgravity 50 // gravity change, for prediction
|
||||
#define svc_setinfo 51 // setinfo on a client
|
||||
#define svc_serverinfo 52 // serverinfo
|
||||
#define svc_updatepl 53 // [qbyte] [qbyte]
|
||||
#define svc_download 41 // [short] size [size bytes]
|
||||
#define svc_playerinfo 42 // variable
|
||||
#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8
|
||||
#define svc_chokecount 44 // [qbyte] packets choked
|
||||
#define svc_modellist 45 // [strings]
|
||||
#define svc_soundlist 46 // [strings]
|
||||
#define svc_packetentities 47 // [...]
|
||||
#define svc_deltapacketentities 48 // [...]
|
||||
#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||
#define svc_entgravity 50 // gravity change, for prediction
|
||||
#define svc_setinfo 51 // setinfo on a client
|
||||
#define svc_serverinfo 52 // serverinfo
|
||||
#define svc_updatepl 53 // [qbyte] [qbyte]
|
||||
|
||||
//mvdsv extended svcs (for mvd playback)
|
||||
#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8
|
||||
#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8
|
||||
|
||||
//FTE extended svcs
|
||||
#ifdef PEXT_SOUNDDBL
|
||||
#define svcfte_soundextended 55
|
||||
#define svcfte_soundlistshort 56
|
||||
#define svcfte_soundextended 55
|
||||
#define svcfte_soundlistshort 56
|
||||
#endif
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
#define svcfte_lightstylecol 57
|
||||
#define svcfte_lightstylecol 57
|
||||
#endif
|
||||
|
||||
//#define svcfte_svcremoved 58
|
||||
//#define svcfte_svcremoved 58
|
||||
|
||||
//#define svcfte_svcremoved 59
|
||||
|
||||
#ifdef PEXT_MODELDBL
|
||||
#define svcfte_modellistshort 60 // [strings]
|
||||
#define svcfte_modellistshort 60 // [strings]
|
||||
#endif
|
||||
|
||||
//#define svc_ftesetclientpersist 61 //ushort DATA
|
||||
|
||||
#define svc_setportalstate 62
|
||||
#define svc_setportalstate 62
|
||||
|
||||
#define svcfte_particle2 63
|
||||
#define svcfte_particle3 64
|
||||
#define svcfte_particle4 65
|
||||
#define svcfte_spawnbaseline2 66
|
||||
#define svcfte_particle2 63
|
||||
#define svcfte_particle3 64
|
||||
#define svcfte_particle4 65
|
||||
#define svcfte_spawnbaseline2 66
|
||||
|
||||
#define svcfte_customtempent 67
|
||||
#define svcfte_customtempent 67
|
||||
|
||||
#define svcfte_choosesplitclient 68
|
||||
#define svcfte_showpic 69
|
||||
#define svcfte_hidepic 70
|
||||
#define svcfte_movepic 71
|
||||
#define svcfte_updatepic 72
|
||||
#define svcfte_choosesplitclient 68
|
||||
#define svcfte_showpic 69
|
||||
#define svcfte_hidepic 70
|
||||
#define svcfte_movepic 71
|
||||
#define svcfte_updatepic 72
|
||||
|
||||
#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
|
||||
//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
|
||||
|
||||
#ifdef PEXT_CSQC
|
||||
#define svcfte_csqcentities 76 //entity lump for csqc
|
||||
#define svcfte_csqcentities 76 //entity lump for csqc
|
||||
#endif
|
||||
|
||||
#define svcfte_precache 77
|
||||
#define svcfte_precache 77
|
||||
|
||||
#define svcfte_updatestatstring 78
|
||||
#define svcfte_updatestatfloat 79
|
||||
#define svcfte_updatestatstring 78
|
||||
#define svcfte_updatestatfloat 79
|
||||
|
||||
#define svcfte_trailparticles 80 // [short] entnum [short] effectnum [vector] start [vector] end
|
||||
#define svcfte_pointparticles 81 // [short] effectnum [vector] start [vector] velocity [short] count
|
||||
#define svcfte_pointparticles1 82 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
|
||||
#define svcfte_trailparticles 80 // [short] entnum [short] effectnum [vector] start [vector] end
|
||||
#define svcfte_pointparticles 81 // [short] effectnum [vector] start [vector] velocity [short] count
|
||||
#define svcfte_pointparticles1 82 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
|
||||
|
||||
#define svcfte_cgamepacket 83
|
||||
#define svcfte_voicechat 84
|
||||
#define svcfte_cgamepacket 83
|
||||
#define svcfte_voicechat 84
|
||||
#define svcfte_setangledelta 85 // [angle3] add this to the current viewangles
|
||||
#define svcfte_updateentities 86
|
||||
#define svcfte_updateentities 86
|
||||
|
||||
|
||||
//fitz svcs
|
||||
|
@ -291,18 +292,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define svcfitz_spawnstaticsound2 44
|
||||
|
||||
//DP extended svcs
|
||||
#define svcdp_downloaddata 50
|
||||
#define svcdp_updatestatbyte 51
|
||||
#define svcnq_effect 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
|
||||
#define svcnq_effect2 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
|
||||
#define svcdp_precache 54 // [short] precacheindex [string] filename, precacheindex is + 0 for modelindex and +32768 for soundindex
|
||||
#define svcdp_spawnbaseline2 55
|
||||
#define svcdp_entities 57
|
||||
#define svcdp_csqcentities 58
|
||||
#define svcdp_spawnstaticsound2 59 // [coord3] [short] samp [byte] vol [byte] aten
|
||||
#define svcdp_trailparticles 60 // [short] entnum [short] effectnum [vector] start [vector] end
|
||||
#define svcdp_pointparticles 61 // [short] effectnum [vector] start [vector] velocity [short] count
|
||||
#define svcdp_pointparticles1 62 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
|
||||
#define svcdp_downloaddata 50
|
||||
#define svcdp_updatestatbyte 51
|
||||
#define svcnq_effect 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
|
||||
#define svcnq_effect2 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
|
||||
#define svcdp_precache 54 // [short] precacheindex [string] filename, precacheindex is + 0 for modelindex and +32768 for soundindex
|
||||
#define svcdp_spawnbaseline2 55
|
||||
#define svcdp_entities 57
|
||||
#define svcdp_csqcentities 58
|
||||
#define svcdp_spawnstaticsound2 59 // [coord3] [short] samp [byte] vol [byte] aten
|
||||
#define svcdp_trailparticles 60 // [short] entnum [short] effectnum [vector] start [vector] end
|
||||
#define svcdp_pointparticles 61 // [short] effectnum [vector] start [vector] velocity [short] count
|
||||
#define svcdp_pointparticles1 62 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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
|
@ -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,12 +648,9 @@ 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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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])
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
/*Testing this code should typically be done with the three following mods:
|
||||
|
|
|
@ -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,16 +5728,51 @@ 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 (qres)
|
||||
if (G_FLOAT(OFS_PARM2) < 0)
|
||||
{
|
||||
data = SQL_ReadField(server, qres, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), true);
|
||||
if (data)
|
||||
qreq = SQL_GetQueryRequest(server, G_FLOAT(OFS_PARM1));
|
||||
if (qreq->results)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = Q_atof(data);
|
||||
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)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = Q_atof(data);
|
||||
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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
/*
|
||||
NPC chat:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,156 +872,89 @@ 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];
|
||||
|
||||
if (!to)
|
||||
{
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
{
|
||||
SV_FullClientUpdate(client, &svs.clients[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
i = client - svs.clients;
|
||||
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
if (sv.demofile)
|
||||
//Sys_Printf("SV_FullClientUpdate: Updated frags for client %d\n", i);
|
||||
|
||||
if (ISQWCLIENT(to))
|
||||
{
|
||||
MSG_WriteByte (buf, svc_updatefrags);
|
||||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteShort (buf, sv.recordedplayer[i].frags);
|
||||
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.recordedplayer[i].ping);
|
||||
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, sv.recordedplayer[i].pl);
|
||||
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, 0);
|
||||
ClientReliableWrite_Begin (to, svc_updateentertime, 6);
|
||||
ClientReliableWrite_Byte (to, i);
|
||||
ClientReliableWrite_Float (to, realtime - client->connection_started);
|
||||
|
||||
Q_strncpyz (info, sv.recordedplayer[i].userinfo, sizeof(info));
|
||||
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_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);
|
||||
return;
|
||||
ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info));
|
||||
ClientReliableWrite_Byte (to, i);
|
||||
ClientReliableWrite_Long (to, client->userid);
|
||||
ClientReliableWrite_String(to, info);
|
||||
}
|
||||
#endif
|
||||
|
||||
//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);
|
||||
|
||||
MSG_WriteByte (buf, svc_updateping);
|
||||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteShort (buf, SV_CalcPing (client, false));
|
||||
|
||||
MSG_WriteByte (buf, svc_updatepl);
|
||||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteByte (buf, client->lossage);
|
||||
|
||||
MSG_WriteByte (buf, svc_updateentertime);
|
||||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteFloat (buf, 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)
|
||||
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;
|
||||
|
||||
if (i >= 16)
|
||||
return;
|
||||
|
||||
//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);
|
||||
|
||||
MSG_WriteByte (buf, svc_updatename);
|
||||
MSG_WriteByte (buf, i);
|
||||
MSG_WriteString (buf, Info_ValueForKey(client->userinfo, "name"));
|
||||
|
||||
top = atoi(Info_ValueForKey(client->userinfo, "topcolor"));
|
||||
bottom = atoi(Info_ValueForKey(client->userinfo, "bottomcolor"));
|
||||
top &= 15;
|
||||
if (top > 13)
|
||||
top = 13;
|
||||
bottom &= 15;
|
||||
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))
|
||||
else if (ISNQCLIENT(to))
|
||||
{
|
||||
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);
|
||||
int top, bottom, playercolor;
|
||||
char *nam = Info_ValueForKey(client->userinfo, "name");
|
||||
|
||||
if (i >= 16)
|
||||
return; //NQ clients will crash if they see a player index above 16.
|
||||
|
||||
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
|
||||
ClientReliableWrite_Byte (to, i);
|
||||
ClientReliableWrite_Short(to, client->old_frags);
|
||||
|
||||
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"));
|
||||
top &= 15;
|
||||
if (top > 13)
|
||||
top = 13;
|
||||
bottom &= 15;
|
||||
if (bottom > 13)
|
||||
bottom = 13;
|
||||
playercolor = top*16 + bottom;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifdef SV_MASTER
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
server->querynum = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,30 @@ typedef enum
|
|||
|
||||
typedef struct queryrequest_s
|
||||
{
|
||||
int num; /* query number reference */
|
||||
qboolean persistant; /* persistant query */
|
||||
struct queryrequest_s *next; /* next request in queue */
|
||||
int callback; /* 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 */
|
||||
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 */
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "qwsvdef.h"
|
||||
#include "quakedef.h"
|
||||
|
||||
#define Q2NUM_FOR_EDICT(ent) (((char *)ent - (char *)ge->edicts) / ge->edict_size)
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
@ -526,8 +576,12 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
|
|||
child->sibling = ret->child;
|
||||
ret->child = child;
|
||||
}
|
||||
else
|
||||
ret->body[bodypos++] = buffer[pos++];
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -714,26 +759,23 @@ 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 (!jcl->bufferedinammount) //if we are half way through a message, read any possible conjunctions.
|
||||
return JCL_DONE; //remove
|
||||
}
|
||||
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
|
||||
{
|
||||
Con_Printf("JCL: socket error\n");
|
||||
return JCL_KILL;
|
||||
}
|
||||
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'>"
|
||||
"<name>FTEQW Jabber Plugin</name>"
|
||||
"<version>"JCL_BUILD"</version>"
|
||||
#ifdef Q3_VM
|
||||
"<os>QVM plugin</os>"
|
||||
#endif
|
||||
"</query>");
|
||||
|
||||
JCL_AddClientMessageString(jcl, "</iq>");
|
||||
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>V"JCL_BUILD"</version>"
|
||||
#ifdef Q3_VM
|
||||
"<os>QVM plugin</os>"
|
||||
#endif
|
||||
"</query>"
|
||||
"</iq>", from, id);
|
||||
|
||||
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
|
||||
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;
|
||||
f = XML_ParameterOfTree(tree, "from");
|
||||
|
||||
if (f)
|
||||
{
|
||||
strlcpy(jcl->defaultdest, f, sizeof(jcl->defaultdest));
|
||||
RenameConsole(f);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
f = XML_ParameterOfTree(tree, "from");
|
||||
unparsable = false;
|
||||
if (f)
|
||||
{
|
||||
strlcpy(jcl->defaultdest, f, sizeof(jcl->defaultdest));
|
||||
RenameConsole(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]);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue