diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index ba1d99bc1..0cce16c89 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -3682,13 +3682,15 @@ void Host_DoRunFile(hrf_t *f)
int len = VFS_GETLEN(f->srcfile);
char *fdata = BZ_Malloc(len+1);
VFS_READ(f->srcfile, fdata, len);
- VFS_CLOSE(f->srcfile);
fdata[len] = 0;
man = FS_Manifest_Parse(fdata);
if (!man->updateurl)
man->updateurl = Z_StrDup(f->fname);
BZ_Free(fdata);
FS_ChangeGame(man, true);
+
+ f->flags |= HRF_ABORT;
+ Host_DoRunFile(f);
return;
}
}
@@ -4385,11 +4387,10 @@ void CL_ExecInitialConfigs(char *resetcommand)
{
int qrc, hrc, def;
- Cbuf_AddText ("cl_warncmd 0\n", RESTRICT_LOCAL);
-
- Cmd_ExecuteString("unbindall", RESTRICT_LOCAL);
- Cmd_ExecuteString("cvarreset *", RESTRICT_LOCAL);
- Cmd_ExecuteString(resetcommand, RESTRICT_LOCAL);
+ Cbuf_AddText("cl_warncmd 0\n", RESTRICT_LOCAL);
+ Cbuf_AddText("unbindall", RESTRICT_LOCAL);
+ Cbuf_AddText("cvarreset *", RESTRICT_LOCAL);
+ Cbuf_AddText(resetcommand, RESTRICT_LOCAL);
//who should we imitate?
qrc = COM_FDepthFile("quake.rc", true); //q1
@@ -4418,6 +4419,12 @@ void CL_ExecInitialConfigs(char *resetcommand)
com_parseutf8.ival = com_parseutf8.value;
+ //if the renderer is already up and running, be prepared to reload content to match the new conback/font/etc
+ if (qrenderer != QR_NONE)
+ Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
+ if (key_dest == key_menu)
+ Cbuf_AddText ("closemenu\ntogglemenu\n", RESTRICT_LOCAL); //make sure the menu has the right content loaded.
+
Cbuf_Execute (); //if the server initialisation causes a problem, give it a place to abort to
diff --git a/engine/client/input.h b/engine/client/input.h
index b9f998377..72afaf154 100644
--- a/engine/client/input.h
+++ b/engine/client/input.h
@@ -36,10 +36,10 @@ extern cvar_t in_xflip;
extern float mousecursor_x, mousecursor_y;
extern float mousemove_x, mousemove_y;
-#ifdef _SDL
+//#ifdef _SDL
void IN_ActivateMouse(void);
void IN_DeactivateMouse(void);
-#endif
+//#endif
int CL_TargettedSplit(qboolean nowrap);
diff --git a/engine/client/renderer.c b/engine/client/renderer.c
index f6b39a08d..36906df64 100644
--- a/engine/client/renderer.c
+++ b/engine/client/renderer.c
@@ -524,6 +524,7 @@ void R_InitTextures (void)
void R_SetRenderer_f (void);
+void R_ReloadRenderer_f (void);
void Renderer_Init(void)
{
@@ -540,6 +541,7 @@ void Renderer_Init(void)
r_blockvidrestart = true;
Cmd_AddCommand("setrenderer", R_SetRenderer_f);
Cmd_AddCommand("vid_restart", R_RestartRenderer_f);
+ Cmd_AddCommand("vid_reload", R_ReloadRenderer_f);
#ifdef RTLIGHTS
Cmd_AddCommand ("r_editlights_reload", R_ReloadRTLights_f);
@@ -1326,35 +1328,9 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
#endif
}
- switch (qrenderer)
+ if (newr && qrenderer != QR_NONE)
{
- case QR_NONE:
- Con_Printf( "\n"
- "-----------------------------\n"
- "Dedicated console created\n");
- break;
- case QR_SOFTWARE:
- Con_Printf( "\n"
- "-----------------------------\n"
- "Software renderer initialized\n");
- break;
-
- case QR_OPENGL:
- Con_Printf( "\n"
- "-----------------------------\n"
- "OpenGL renderer initialized\n");
- break;
-
- case QR_DIRECT3D9:
- Con_Printf( "\n"
- "-----------------------------\n"
- "Direct3d9 renderer initialized\n");
- break;
- case QR_DIRECT3D11:
- Con_Printf( "\n"
- "-----------------------------\n"
- "Direct3d11 renderer initialized\n");
- break;
+ Con_Printf("%s renderer initialized\n", newr->renderer->description);
}
TRACE(("dbg: R_ApplyRenderer: S_Restart_f\n"));
@@ -1368,6 +1344,12 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
return true;
}
+void R_ReloadRenderer_f (void)
+{
+ //reloads textures without destroying video context.
+ R_ApplyRenderer_Load(NULL);
+}
+
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_BPP 32
diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c
index 70d98d31f..be390f0f2 100644
--- a/engine/client/snd_dma.c
+++ b/engine/client/snd_dma.c
@@ -666,7 +666,6 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
start += len;
break;
case VOIP_OPUS:
-#if 1
len = bytes;
if (decodesamps > 0)
{
@@ -686,25 +685,6 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
bytes -= len;
start += len;
-#else
- //FIXME: we shouldn't need this crap
- bytes--;
- len = *start++;
- if (bytes < len)
- break;
- r = qopus_decode(s_voip.decoder[sender], start, len, decodebuf + decodesamps, sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps, false);
- if (r > 0)
- {
- decodesamps += r;
- s_voip.decseq[sender]++;
- seq++;
- }
- else if (r < 0)
- Con_Printf("Opus decoding error %i\n", r);
-
- bytes -= len;
- start += len;
-#endif
break;
}
}
@@ -1085,7 +1065,6 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
samps+=len / 2; //number of samplepairs eaten in this packet. for stats.
break;
case VOIP_OPUS:
-#if 1
{
//opus rtp only supports/allows a single chunk in each packet.
int frames;
@@ -1128,26 +1107,6 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
}
}
break;
-#else
- level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
- len = qopus_encode(s_voip.encoder, start, s_voip.encframesize, outbuf+(outpos+1), max(255, sizeof(outbuf) - (outpos+1)));
- if (len == 1) //packet does not need to be transmitted if it returns 1, supposedly. crazyness.
- len = 0;
- else if (len > 0)
- {
- outbuf[outpos] = len;
- outpos += 1+len;
- }
- else
- {
- //error!
- Con_Printf("Opus encoding error: %i\n", len);
- }
- s_voip.encsequence++;
- samps+=s_voip.encframesize;
- encpos += s_voip.encframesize*2;
- break;
-#endif
default:
outbuf[outpos] = 0;
break;
diff --git a/engine/common/common.h b/engine/common/common.h
index adf802e3b..2582ac555 100644
--- a/engine/common/common.h
+++ b/engine/common/common.h
@@ -336,7 +336,6 @@ extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in
//extern char *com_basedir;
void COM_WriteFile (const char *filename, const void *data, int len);
-FTE_DEPRECATED FILE *COM_WriteFileOpen (char *filename);
typedef struct {
struct searchpath_s *search;
@@ -457,6 +456,7 @@ typedef struct
struct
{
char *path; //the 'pure' name
+ qboolean crcknown; //if the crc was specified
unsigned int crc; //the public crc
char *mirrors[8]; //a randomized (prioritized) list of http mirrors to use.
int mirrornum; //the index we last tried to download from, so we still work even if mirrors are down.
diff --git a/engine/common/fs.c b/engine/common/fs.c
index e50d52903..109987fce 100644
--- a/engine/common/fs.c
+++ b/engine/common/fs.c
@@ -261,7 +261,10 @@ void FS_Manifest_Print(ftemanifest_t *man)
{
if (man->package[i].path)
{
- Con_Printf("package \"%s\" 0x%x", man->package[i].path, man->package[i].crc);
+ if (man->package[i].crcknown)
+ Con_Printf("package \"%s\" 0x%x", man->package[i].path, man->package[i].crc);
+ else
+ Con_Printf("package \"%s\" -", man->package[i].path);
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
if (man->package[i].mirrors[j])
Con_Printf(" \"%s\"", man->package[i].mirrors[j]);
@@ -348,11 +351,13 @@ static void FS_Manifest_ParseTokens(ftemanifest_t *man)
}
else
{
+ qboolean crcknown;
int crc;
int i, j;
if (!stricmp(fname, "package"))
Cmd_ShiftArgs(1, false);
+ crcknown = (strcmp(Cmd_Argv(1), "-") && *Cmd_Argv(1));
crc = strtoul(Cmd_Argv(1), NULL, 0);
for (i = 0; i < sizeof(man->package) / sizeof(man->package[0]); i++)
@@ -360,6 +365,7 @@ static void FS_Manifest_ParseTokens(ftemanifest_t *man)
if (!man->package[i].path)
{
man->package[i].path = Z_StrDup(Cmd_Argv(0));
+ man->package[i].crcknown = crcknown;
man->package[i].crc = crc;
for (j = 0; j < Cmd_Argc()-2 && j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
{
@@ -393,6 +399,13 @@ ftemanifest_t *FS_Manifest_Parse(const char *data)
data = Cmd_TokenizeString((char*)data, false, false);
FS_Manifest_ParseTokens(man);
}
+ if (!man->installation)
+ { //every manifest should have an internal name specified, so we can use the correct basedir
+ //if we don't recognise it, then we'll typically prompt (or just use the working directory), but always assuming a default at least ensures things are sane.
+ //fixme: we should probably fill in the basegame here (and share that logic with the legacy manifest generation code)
+ data = Cmd_TokenizeString((char*)"game quake", false, false);
+ FS_Manifest_ParseTokens(man);
+ }
return man;
}
@@ -576,22 +589,6 @@ void COM_WriteFile (const char *filename, const void *data, int len)
com_fschanged=true;
}
-FILE *COM_WriteFileOpen (char *filename) //like fopen, but based around quake's paths.
-{
- FILE *f;
- char name[MAX_OSPATH];
-
- if (!FS_NativePath(filename, FS_GAMEONLY, name, sizeof(name)))
- return NULL;
-
- COM_CreatePath(name);
-
- f = fopen (name, "wb");
-
- return f;
-}
-
-
/*
============
COM_CreatePath
@@ -1690,10 +1687,13 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
searchpath_t *oldp;
char pname[MAX_OSPATH];
char lname[MAX_OSPATH];
- snprintf(lname, sizeof(lname), "%#x", fs_manifest->package[i].crc);
+ if (fs_manifest->package[i].crcknown)
+ snprintf(lname, sizeof(lname), "%#x", fs_manifest->package[i].crc);
+ else
+ snprintf(lname, sizeof(lname), "");
if (!FS_GenCachedPakName(fs_manifest->package[i].path, lname, pname, sizeof(pname)))
continue;
- snprintf (lname, sizeof(lname), "%s%s", logicalpath, pname+ptlen+1);
+ snprintf (lname, sizeof(lname), "%s%s", logicalpaths, pname+ptlen+1);
for (oldp = com_searchpaths; oldp; oldp = oldp->next)
{
@@ -1714,7 +1714,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
handle = OpenNew (vfs, lname);
}
}
- if (handle)
+ if (handle && fs_manifest->package[i].crcknown)
{
int truecrc = handle->GeneratePureCRC(handle, 0, false);
if (truecrc != fs_manifest->package[i].crc)
@@ -3317,6 +3317,7 @@ static void FS_PackageDownloaded(struct dl_download *dl)
}
static void FS_BeginNextPackageDownload(void)
{
+ char *crcstr;
int j;
ftemanifest_t *man = fs_manifest;
vfsfile_t *check;
@@ -3329,7 +3330,11 @@ static void FS_BeginNextPackageDownload(void)
if (!man->package[j].path)
continue;
- if (!FS_GenCachedPakName(man->package[j].path, va("%#x", man->package[j].crc), buffer, sizeof(buffer)))
+ if (man->package[j].crcknown)
+ crcstr = va("%#x", man->package[j].crc);
+ else
+ crcstr = "";
+ if (!FS_GenCachedPakName(man->package[j].path, crcstr, buffer, sizeof(buffer)))
continue;
check = FS_OpenVFS(buffer, "rb", FS_ROOT);
@@ -3339,7 +3344,7 @@ static void FS_BeginNextPackageDownload(void)
continue;
}
FS_NativePath(buffer, FS_ROOT, fspdl_finalpath, sizeof(fspdl_finalpath));
- if (!FS_GenCachedPakName(va("%s.tmp", man->package[j].path), va("%#x", man->package[j].crc), buffer, sizeof(buffer)))
+ if (!FS_GenCachedPakName(va("%s.tmp", man->package[j].path), crcstr, buffer, sizeof(buffer)))
continue;
FS_NativePath(buffer, FS_ROOT, fspdl_temppath, sizeof(fspdl_temppath));
diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c
index 589125dc8..18b0ee207 100644
--- a/engine/common/gl_q2bsp.c
+++ b/engine/common/gl_q2bsp.c
@@ -605,7 +605,7 @@ static void SnapVector( vec3_t normal )
normal[i] = 1;
break;
}
- if( fabs( normal[i] - -1 ) < PLANE_NORMAL_EPSILON )
+ if( fabs( normal[i] + 1 ) < PLANE_NORMAL_EPSILON )
{
VectorClear( normal );
normal[i] = -1;
diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj
index eba3a3c99..4682c1009 100644
--- a/engine/dotnet2005/ftequake.vcproj
+++ b/engine/dotnet2005/ftequake.vcproj
@@ -17406,6 +17406,170 @@
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c
index 8843de796..ebc5d1e88 100644
--- a/engine/gl/gl_draw.c
+++ b/engine/gl/gl_draw.c
@@ -453,10 +453,7 @@ void GLDraw_Init (void)
int maxtexsize;
if (gltextures)
- {
- Con_Printf("gl_draw didn't shut down cleanly\n");
gltextures = NULL;
- }
memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets));
Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets);
@@ -470,12 +467,16 @@ void GLDraw_Init (void)
maxtexsize = gl_max_size.value;
+ if (uploadmemorybuffer)
+ BZ_Free(uploadmemorybuffer);
+ if (uploadmemorybufferintermediate)
+ BZ_Free(uploadmemorybufferintermediate);
//required to hold the image after scaling has occured
- sizeofuploadmemorybuffer = 1;
- sizeofuploadmemorybufferintermediate = 1;
+ sizeofuploadmemorybuffer = 0;
+ sizeofuploadmemorybufferintermediate = 0;
TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n"));
- uploadmemorybuffer = BZ_Realloc(uploadmemorybuffer, sizeofuploadmemorybuffer);
- uploadmemorybufferintermediate = BZ_Realloc(uploadmemorybufferintermediate, sizeofuploadmemorybufferintermediate);
+ uploadmemorybuffer = NULL;
+ uploadmemorybufferintermediate = NULL;
R2D_Init();
diff --git a/engine/http/httpserver.c b/engine/http/httpserver.c
index 7da66840e..6691d3556 100644
--- a/engine/http/httpserver.c
+++ b/engine/http/httpserver.c
@@ -11,6 +11,115 @@
static qboolean httpserverinitied = false;
qboolean httpserverfailed = false;
static int httpserversocket;
+static int httpserverport;
+
+#ifdef WEBSVONLY
+static int natpmpsocket = INVALID_SOCKET;
+static int natpmptime;
+#include
+static void sendnatpmp(int port)
+{
+ struct sockaddr_in router;
+ struct
+ {
+ qbyte ver;
+ qbyte op;
+ short reserved1;
+ short privport; short pubport;
+ int mapping_expectancy;
+ } pmpreqmsg;
+
+ int curtime = timeGetTime();
+ if (natpmpsocket == INVALID_SOCKET)
+ {
+ unsigned long _true = true;
+ natpmpsocket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (natpmpsocket == INVALID_SOCKET)
+ return;
+ ioctlsocket (natpmpsocket, FIONBIO, &_true);
+ }
+ else if (curtime - natpmptime < 0)
+ return;
+ natpmptime = curtime+60*1000;
+
+ memset(&router, 0, sizeof(router));
+ router.sin_family = AF_INET;
+ router.sin_port = htons(5351);
+ router.sin_addr.S_un.S_un_b.s_b1 = 192;
+ router.sin_addr.S_un.S_un_b.s_b2 = 168;
+ router.sin_addr.S_un.S_un_b.s_b3 = 0;
+ router.sin_addr.S_un.S_un_b.s_b4 = 1;
+
+ pmpreqmsg.ver = 0;
+ pmpreqmsg.op = 0;
+ pmpreqmsg.reserved1 = htons(0);
+ pmpreqmsg.privport = htons(port);
+ pmpreqmsg.pubport = htons(port);
+ pmpreqmsg.mapping_expectancy = htons(60*5);
+
+ sendto(natpmpsocket, (void*)&pmpreqmsg, 2, 0, (struct sockaddr*)&router, sizeof(router));
+
+ pmpreqmsg.op = 2;
+ sendto(natpmpsocket, (void*)&pmpreqmsg, sizeof(pmpreqmsg), 0, (struct sockaddr*)&router, sizeof(router));
+}
+void checknatpmp(int port)
+{
+ struct
+ {
+ qbyte ver; qbyte op; short resultcode;
+ int age;
+ union
+ {
+ struct
+ {
+ short privport; short pubport;
+ int mapping_expectancy;
+ };
+ qbyte ipv4[4];
+ };
+ } pmpreqrep;
+ struct sockaddr_in from;
+ int fromlen = sizeof(from);
+ int len;
+ static int oldip=-1;
+ static short oldport;
+ memset(&pmpreqrep, 0, sizeof(pmpreqrep));
+ sendnatpmp(port);
+ if (natpmpsocket == INVALID_SOCKET)
+ len = -1;
+ else
+ len = recvfrom(natpmpsocket, (void*)&pmpreqrep, sizeof(pmpreqrep), 0, (struct sockaddr*)&from, &fromlen);
+ if (len == 12 && pmpreqrep.op == 128)
+ {
+ if (oldip != *(int*)pmpreqrep.ipv4)
+ {
+ oldip = *(int*)pmpreqrep.ipv4;
+ oldport = 0;
+ IWebPrintf("Public ip is %i.%i.%i.%i\n", pmpreqrep.ipv4[0], pmpreqrep.ipv4[1], pmpreqrep.ipv4[2], pmpreqrep.ipv4[3]);
+ }
+ }
+ else if (len == 16 && pmpreqrep.op == 129)
+ {
+ if (oldport != pmpreqrep.pubport)
+ {
+ oldport = pmpreqrep.pubport;
+ IWebPrintf("Public udp port %i (local %i)\n", ntohs(pmpreqrep.pubport), ntohs(pmpreqrep.privport));
+ }
+ }
+ else if (len == 16 && pmpreqrep.op == 130)
+ {
+ if (oldport != pmpreqrep.pubport)
+ {
+ oldport = pmpreqrep.pubport;
+ IWebPrintf("Public tcp port %i (local %i)\n", ntohs(pmpreqrep.pubport), ntohs(pmpreqrep.privport));
+ }
+ }
+}
+#else
+void checknatpmp(int port)
+{
+}
+#endif
typedef enum {HTTP_WAITINGFORREQUEST,HTTP_SENDING} http_mode_t;
@@ -64,6 +173,7 @@ qboolean HTTP_ServerInit(int port)
httpserverinitied = true;
httpserverfailed = false;
+ httpserverport = port;
IWebPrintf("HTTP server is running\n");
return true;
@@ -554,6 +664,8 @@ qboolean HTTP_ServerPoll(qboolean httpserverwanted, int portnum) //loop while tr
HTTP_active_connections_t *cl;
+ if (httpserverport != portnum && httpserverinitied)
+ HTTP_ServerShutdown();
if (!httpserverinitied)
{
if (httpserverwanted)
@@ -566,6 +678,8 @@ qboolean HTTP_ServerPoll(qboolean httpserverwanted, int portnum) //loop while tr
return false;
}
+ checknatpmp(httpserverport);
+
if (httpconnectioncount>32)
return false;
diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c
index 6977877e6..06bc98632 100644
--- a/engine/qclib/initlib.c
+++ b/engine/qclib/initlib.c
@@ -1102,7 +1102,10 @@ pubprogfuncs_t deffuncs = {
PR_UglyValueString,
ED_ParseEval
};
-#undef printf
+static int PDECL qclib_null_printf(const char *s, ...)
+{
+ return 0;
+}
//defs incase following structure is not passed.
struct edict_s *safesv_edicts;
@@ -1115,7 +1118,7 @@ progexterns_t defexterns = {
NULL, //char *(*ReadFile) (char *fname, void *buffer, int len);
NULL, //int (*FileSize) (char *fname); //-1 if file does not exist
NULL, //bool (*WriteFile) (char *name, void *data, int len);
- printf, //void (*printf) (char *, ...);
+ qclib_null_printf, //void (*printf) (char *, ...);
(void*)exit, //void (*Sys_Error) (char *, ...);
NULL, //void (*Abort) (char *, ...);
sizeof(edictrun_t), //int edictsize; //size of edict_t