misc tweaks to support:
opening (qtv) urls with android browser. mvds should stream using the same mechanism, if they have the right mime type. arbitrary unicode basedirs in windows should work, and commandlines. not sure what else still doesn't work. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4539 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
c5f51a6801
commit
ad8d634916
16 changed files with 555 additions and 215 deletions
|
@ -30,6 +30,16 @@ WHOAMI:=$(shell whoami)
|
|||
#linux->nacl (FTE_TARGET=nacl NARCH=x86_64)
|
||||
#if you are cross compiling, you'll need to use FTE_TARGET=mytarget
|
||||
|
||||
#cygwin's make's paths confuses non-cygwin things
|
||||
RELEASE_DIR=$(BASE_DIR)/release
|
||||
DEBUG_DIR=$(BASE_DIR)/debug
|
||||
PROFILE_DIR=$(BASE_DIR)/profile
|
||||
ifneq ($(shell uname -o 2>&1 | grep Cygwin),)
|
||||
NATIVE_RELEASE_DIR=$(shell cygpath -m $(RELEASE_DIR))
|
||||
NATIVE_DEBUG_DIR=$(shell cygpath -m $(DEBUG_DIR))
|
||||
endif
|
||||
|
||||
|
||||
#correct the gcc build when cross compiling
|
||||
ifeq ($(FTE_TARGET),win32)
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep mingw),)
|
||||
|
@ -95,6 +105,8 @@ ifeq ($(FTE_TARGET),droid)
|
|||
#set up for linux
|
||||
TOOLCHAIN:=$(ANDROID_NDK_ROOT)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/bin/arm-linux-androideabi-
|
||||
else
|
||||
#FIXME: support mingw too...
|
||||
|
||||
#we're running upon windows
|
||||
ifeq ($(DROID_ARCH),x86)
|
||||
TOOLCHAIN:=$(ANDROID_NDK_ROOT)/toolchains/x86-4.7/prebuilt/windows-x86_64/bin/i686-linux-android-
|
||||
|
@ -275,9 +287,8 @@ PROGS_DIR=$(BASE_DIR)/qclib
|
|||
NACL_DIR=$(BASE_DIR)/nacl
|
||||
BOTLIB_DIR=$(BASE_DIR)/botlib
|
||||
|
||||
RELEASE_DIR=$(BASE_DIR)/release
|
||||
DEBUG_DIR=$(BASE_DIR)/debug
|
||||
PROFILE_DIR=$(BASE_DIR)/profile
|
||||
#NATIVE_RELEASE_DIR?=$(RELEASE_DIR)
|
||||
#NATIVE_DEBUG_DIR?=$(DEBUG_DIR)
|
||||
|
||||
ALL_CFLAGS=$(HAVECONFIG) $(VISIBILITY_FLAGS) $(CFLAGS) $(BASE_CFLAGS) $(WCFLAGS)
|
||||
|
||||
|
@ -1593,7 +1604,7 @@ endif
|
|||
@echo
|
||||
@$(JAVATOOL)jarsigner $(JARSIGNARGS) -digestalg SHA1 -sigalg MD5withRSA -keystore droid/ftekeystore droid/bin/FTEDroid-release-unsigned.apk autogen
|
||||
-rm -f $(RELEASE_DIR)/FTEDroid.apk
|
||||
$(ANDROID_HOME)/tools/zipalign 4 droid/bin/FTEDroid-release-unsigned.apk $(RELEASE_DIR)/FTEDroid.apk
|
||||
$(ANDROID_HOME)/tools/zipalign 4 droid/bin/FTEDroid-release-unsigned.apk $(NATIVE_RELEASE_DIR)/FTEDroid.apk
|
||||
|
||||
droid-opt:
|
||||
$(MAKE) FTE_TARGET=droid droid/build.xml droid/ftekeystore
|
||||
|
|
|
@ -74,6 +74,10 @@ void CL_StopPlayback (void)
|
|||
cls.demoplayback = DPB_NONE;
|
||||
cls.demoseeking = false; //just in case
|
||||
|
||||
if (cls.demoindownload)
|
||||
cls.demoindownload->status = DL_FAILED;
|
||||
cls.demoindownload = NULL;
|
||||
|
||||
if (cls.timedemo)
|
||||
CL_FinishTimeDemo ();
|
||||
}
|
||||
|
@ -1550,15 +1554,53 @@ void CL_PlayDemo_f (void)
|
|||
CL_PlayDemo(demoname);
|
||||
}
|
||||
|
||||
void CL_PlayDemo(char *demoname)
|
||||
void CL_DemoStreamFullyDownloaded(struct dl_download *dl)
|
||||
{
|
||||
char name[256];
|
||||
int ft, neg = false;
|
||||
int len;
|
||||
char type;
|
||||
char chr;
|
||||
int protocol;
|
||||
int start;
|
||||
//let the file get closed by the demo playback code.
|
||||
dl->file = NULL;
|
||||
//kill the reference now that its done.
|
||||
if (cls.demoindownload == dl)
|
||||
cls.demoindownload = NULL;
|
||||
}
|
||||
//dl is provided so that we can receive files via chunked/gziped http downloads and on systems that don't provide sockets etc. its tracked so we can cancel the download if the client aborts playback early.
|
||||
void CL_PlayDemoStream(vfsfile_t *file, struct dl_download *dl, char *filename, int demotype, float bufferdelay)
|
||||
{
|
||||
int protocol = CP_UNKNOWN;
|
||||
|
||||
if (demotype == DPB_NONE)
|
||||
{
|
||||
//peek etc?
|
||||
}
|
||||
|
||||
switch(demotype)
|
||||
{
|
||||
case DPB_EZTV:
|
||||
case DPB_MVD:
|
||||
case DPB_QUAKEWORLD:
|
||||
protocol = CP_QUAKEWORLD;
|
||||
break;
|
||||
#ifdef Q2CLIENT
|
||||
case DPB_QUAKE2:
|
||||
protocol = CP_QUAKE2;
|
||||
break;
|
||||
#endif
|
||||
#ifdef NQPROT
|
||||
case DPB_NETQUAKE:
|
||||
protocol = CP_NETQUAKE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (protocol == CP_UNKNOWN)
|
||||
{
|
||||
Con_Printf ("ERROR: demo format not supported: \"%s\".\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dl)
|
||||
dl->notifycomplete = CL_DemoStreamFullyDownloaded;
|
||||
|
||||
//
|
||||
// disconnect from server
|
||||
|
@ -1568,32 +1610,78 @@ void CL_PlayDemo(char *demoname)
|
|||
demo_flushcache();
|
||||
//
|
||||
// open the demo file
|
||||
//
|
||||
cls.demoindownload = dl;
|
||||
cls.demoinfile = file;
|
||||
if (!cls.demoinfile)
|
||||
{
|
||||
Con_Printf ("ERROR: couldn't open \"%s\".\n", filename);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
return;
|
||||
}
|
||||
if (filename)
|
||||
{
|
||||
Q_strncpyz (lastdemoname, filename, sizeof(lastdemoname));
|
||||
Con_Printf ("Playing demo from %s.\n", filename);
|
||||
}
|
||||
|
||||
cls.findtrack = (demotype == DPB_MVD || demotype == DPB_EZTV);
|
||||
|
||||
cls.demoplayback = demotype;
|
||||
cls.protocol = protocol;
|
||||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0);
|
||||
|
||||
demtime = -bufferdelay;
|
||||
cl.gametime = -bufferdelay;
|
||||
cl.gametimemark = demtime;
|
||||
if (demtime < -0.5)
|
||||
Con_Printf("Buffering for %g seconds\n", bufferdelay);
|
||||
cls.netchan.last_received=demtime;
|
||||
|
||||
TP_ExecTrigger ("f_demostart");
|
||||
}
|
||||
|
||||
void CL_PlayDemo(char *demoname)
|
||||
{
|
||||
char name[256];
|
||||
int ft, neg = false;
|
||||
int len;
|
||||
char type;
|
||||
char chr;
|
||||
int protocol;
|
||||
int start;
|
||||
vfsfile_t *f;
|
||||
|
||||
//
|
||||
// open the demo file
|
||||
//
|
||||
Q_strncpyz (name, demoname, sizeof(name));
|
||||
COM_DefaultExtension (name, ".qwd", sizeof(name));
|
||||
if (*name == '#')
|
||||
cls.demoinfile = VFSOS_Open(name+1, "rb");
|
||||
f = VFSOS_Open(name+1, "rb");
|
||||
else
|
||||
cls.demoinfile = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
if (!cls.demoinfile)
|
||||
f = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
if (!f)
|
||||
{
|
||||
Q_strncpyz (name, demoname, sizeof(name));
|
||||
COM_DefaultExtension (name, ".dem", sizeof(name));
|
||||
if (*name == '#')
|
||||
cls.demoinfile = VFSOS_Open(name+1, "rb");
|
||||
f = VFSOS_Open(name+1, "rb");
|
||||
else
|
||||
cls.demoinfile = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
f = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
}
|
||||
if (!cls.demoinfile)
|
||||
if (!f)
|
||||
{
|
||||
Q_strncpyz (name, demoname, sizeof(name));
|
||||
COM_DefaultExtension (name, ".mvd", sizeof(name));
|
||||
if (*name == '#')
|
||||
cls.demoinfile = VFSOS_Open(name+1, "rb");
|
||||
f = VFSOS_Open(name+1, "rb");
|
||||
else
|
||||
cls.demoinfile = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
f = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
}
|
||||
if (!cls.demoinfile)
|
||||
if (!f)
|
||||
{
|
||||
Con_Printf ("ERROR: couldn't open \"%s\".\n", demoname);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
|
@ -1602,115 +1690,56 @@ void CL_PlayDemo(char *demoname)
|
|||
Q_strncpyz (lastdemoname, demoname, sizeof(lastdemoname));
|
||||
Con_Printf ("Playing demo from %s.\n", name);
|
||||
|
||||
if (!VFS_GETLEN (cls.demoinfile))
|
||||
if (!VFS_GETLEN (f))
|
||||
{
|
||||
VFS_CLOSE(cls.demoinfile);
|
||||
cls.demoinfile = NULL;
|
||||
VFS_CLOSE(f);
|
||||
Con_Printf ("demo \"%s\" is empty.\n", demoname);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Q_strcasecmp(name + strlen(name) - 3, "mvd") ||
|
||||
!Q_strcasecmp(name + strlen(name) - 6, "mvd.gz"))
|
||||
{
|
||||
cls.demoplayback = DPB_MVD;
|
||||
cls.findtrack = true;
|
||||
}
|
||||
else
|
||||
cls.demoplayback = DPB_QUAKEWORLD;
|
||||
//figure out where we started
|
||||
start = VFS_TELL(f);
|
||||
|
||||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0);
|
||||
demtime = 0;
|
||||
cl.gametime = 0;
|
||||
cl.gametimemark = demtime;
|
||||
|
||||
cls.netchan.last_received=demtime;
|
||||
|
||||
|
||||
start = VFS_TELL(cls.demoinfile);
|
||||
VFS_READ(cls.demoinfile, &len, sizeof(len));
|
||||
VFS_READ(cls.demoinfile, &type, sizeof(type));
|
||||
VFS_READ(cls.demoinfile, &protocol, sizeof(protocol));
|
||||
VFS_SEEK(cls.demoinfile, start);
|
||||
//check if its a quake2 demo.
|
||||
VFS_READ(f, &len, sizeof(len));
|
||||
VFS_READ(f, &type, sizeof(type));
|
||||
VFS_READ(f, &protocol, sizeof(protocol));
|
||||
VFS_SEEK(f, start);
|
||||
if (len > 5 && type == svcq2_serverdata && protocol == PROTOCOL_VERSION_Q2)
|
||||
{
|
||||
#ifdef Q2CLIENT
|
||||
cls.demoplayback = DPB_QUAKE2;
|
||||
cls.protocol = CP_QUAKE2;
|
||||
#else
|
||||
Con_Printf ("ERROR: cannot play Quake2 demos.\n");
|
||||
CL_StopPlayback();
|
||||
CL_PlayDemoStream(f, NULL, name, DPB_QUAKE2, 0);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
//not quake2, check if its NQ
|
||||
ft = 0; //work out if the first line is a int for the track number.
|
||||
while ((VFS_READ(f, &chr, 1)==1) && (chr != '\n'))
|
||||
{
|
||||
ft = 0; //work out if the first line is a int for the track number.
|
||||
while ((VFS_READ(cls.demoinfile, &chr, 1)==1) && (chr != '\n'))
|
||||
{
|
||||
if (chr == '-')
|
||||
neg = true;
|
||||
else if (chr < '0' || chr > '9')
|
||||
break;
|
||||
else
|
||||
ft = ft * 10 + ((int)chr - '0');
|
||||
}
|
||||
if (neg)
|
||||
ft *= -1;
|
||||
if (chr == '\n')
|
||||
{
|
||||
#ifndef NQPROT
|
||||
Con_Printf ("ERROR: cannot play NQ demos.\n");
|
||||
CL_StopPlayback();
|
||||
return;
|
||||
#else
|
||||
//fixme: play that cdtrack.
|
||||
cls.protocol = CP_NETQUAKE;
|
||||
cls.demoplayback = DPB_NETQUAKE; //nq demos. :o)
|
||||
#endif
|
||||
}
|
||||
if (chr == '-')
|
||||
neg = true;
|
||||
else if (chr < '0' || chr > '9')
|
||||
break;
|
||||
else
|
||||
{
|
||||
cls.protocol = CP_QUAKEWORLD;
|
||||
|
||||
VFS_SEEK(cls.demoinfile, start); //quakeworld demo, so go back to start.
|
||||
}
|
||||
ft = ft * 10 + ((int)chr - '0');
|
||||
}
|
||||
if (neg)
|
||||
ft *= -1;
|
||||
if (chr == '\n')
|
||||
{
|
||||
CL_PlayDemoStream(f, NULL, name, DPB_NETQUAKE, 0);
|
||||
return;
|
||||
}
|
||||
VFS_SEEK(f, start);
|
||||
|
||||
TP_ExecTrigger ("f_demostart");
|
||||
}
|
||||
//its not NQ then. must be QuakeWorld, either .qwd or .mvd
|
||||
//could also be .qwz or .dmz or whatever that nq extension is. we don't support either.
|
||||
|
||||
void CL_QTVPlay (vfsfile_t *newf, qboolean iseztv)
|
||||
{
|
||||
CL_Disconnect_f ();
|
||||
|
||||
cls.demoinfile = newf;
|
||||
|
||||
demo_flushcache(); //just in case
|
||||
|
||||
if (iseztv)
|
||||
cls.demoplayback = DPB_EZTV;
|
||||
//mvd and qwd have no identifying markers, other than the extension.
|
||||
if (!Q_strcasecmp(name + strlen(name) - 3, "mvd") ||
|
||||
!Q_strcasecmp(name + strlen(name) - 6, "mvd.gz"))
|
||||
CL_PlayDemoStream(f, NULL, name, DPB_MVD, 0);
|
||||
else
|
||||
cls.demoplayback = DPB_MVD;
|
||||
|
||||
cls.findtrack = true;
|
||||
|
||||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0);
|
||||
demtime = -BUFFERTIME;
|
||||
cl.gametime = -BUFFERTIME;
|
||||
cl.gametimemark = demtime;
|
||||
if (demtime < -0.5)
|
||||
Con_Printf("Buffering for %i seconds\n", (int)-demtime);
|
||||
|
||||
cls.netchan.last_received=realtime;
|
||||
|
||||
cls.protocol = CP_QUAKEWORLD;
|
||||
TP_ExecTrigger ("f_demostart");
|
||||
CL_PlayDemoStream(f, NULL, name, DPB_NETQUAKE, 0);
|
||||
}
|
||||
|
||||
/*used with qtv*/
|
||||
|
@ -1779,7 +1808,8 @@ void CL_QTVPoll (void)
|
|||
|
||||
if (qtvrequestsize >= sizeof(qtvrequestbuffer) - 1)
|
||||
{
|
||||
Con_Printf("%i of %i...\n", qtvrequestsize, (int)sizeof(qtvrequestbuffer));
|
||||
//flag it as an error if the response is larger than we can handle.
|
||||
//this error gets ignored if the header is okay (any actual errors will get reported again by the demo code anyway), and only counts if the end of the reply header was not found.
|
||||
len = -1;
|
||||
}
|
||||
if (!qtvrequestsize && len == 0)
|
||||
|
@ -1934,7 +1964,7 @@ void CL_QTVPoll (void)
|
|||
|
||||
if (streamavailable)
|
||||
{
|
||||
CL_QTVPlay(qtvrequest, iseztv);
|
||||
CL_PlayDemoStream(qtvrequest, NULL, NULL, iseztv?DPB_EZTV:DPB_MVD, BUFFERTIME);
|
||||
qtvrequest = NULL;
|
||||
demo_resetcache(qtvrequestsize - (tail-qtvrequestbuffer), tail);
|
||||
return;
|
||||
|
@ -2219,7 +2249,7 @@ void CL_QTVPlay_f (void)
|
|||
if (raw)
|
||||
{
|
||||
VFS_WRITE(newf, msg, msglen);
|
||||
CL_QTVPlay(newf, false);
|
||||
CL_PlayDemoStream(qtvrequest, NULL, qtvhostname, DPB_MVD, BUFFERTIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -3586,13 +3586,20 @@ void Host_RunFileNotify(struct dl_download *dl)
|
|||
#define HRF_NOOVERWRITE (1<<1)
|
||||
#define HRF_ABORT (1<<3)
|
||||
#define HRF_OPENED (1<<4)
|
||||
#define HRF_DEMO (1<<8)
|
||||
#define HRF_QTVINFO (1<<9)
|
||||
#define HRF_MANIFEST (1<<10)
|
||||
#define HRF_BSP (1<<11)
|
||||
#define HRF_PACKAGE (1<<12)
|
||||
|
||||
#define HRF_DEMO_MVD (1<<8)
|
||||
#define HRF_DEMO_QWD (1<<9)
|
||||
#define HRF_DEMO_DM2 (1<<10)
|
||||
#define HRF_DEMO_DEM (1<<11)
|
||||
|
||||
#define HRF_QTVINFO (1<<12)
|
||||
#define HRF_MANIFEST (1<<13)
|
||||
#define HRF_BSP (1<<14)
|
||||
#define HRF_PACKAGE (1<<15)
|
||||
|
||||
#define HRF_ACTION (HRF_OVERWRITE|HRF_NOOVERWRITE|HRF_ABORT)
|
||||
#define HRF_DEMO (HRF_DEMO_MVD|HRF_DEMO_QWD|HRF_DEMO_DM2|HRF_DEMO_DEM)
|
||||
#define HRF_FILETYPES (HRF_DEMO|HRF_QTVINFO|HRF_MANIFEST|HRF_BSP|HRF_PACKAGE)
|
||||
typedef struct {
|
||||
unsigned int flags;
|
||||
vfsfile_t *srcfile;
|
||||
|
@ -3600,8 +3607,10 @@ typedef struct {
|
|||
char fname[1]; //system path or url.
|
||||
} hrf_t;
|
||||
|
||||
int waitingformanifest;
|
||||
void Host_DoRunFile(hrf_t *f);
|
||||
|
||||
void CL_PlayDemoStream(vfsfile_t *file, struct dl_download *, char *filename, int demotype, float bufferdelay);
|
||||
void CL_ParseQTVDescriptor(vfsfile_t *f, const char *name);
|
||||
|
||||
void Host_RunFileDownloaded(struct dl_download *dl)
|
||||
{
|
||||
|
@ -3612,6 +3621,75 @@ void Host_RunFileDownloaded(struct dl_download *dl)
|
|||
|
||||
Host_DoRunFile(f);
|
||||
}
|
||||
void Host_BeginFileDownload(struct dl_download *dl, char *mimetype)
|
||||
{
|
||||
//at this point the file is still downloading, so don't copy it out just yet.
|
||||
hrf_t *f = dl->user_ctx;
|
||||
|
||||
if (mimetype && !(f->flags & HRF_FILETYPES))
|
||||
{
|
||||
if (!strcmp(mimetype, "application/x-qtv")) //what uses this?
|
||||
f->flags |= HRF_QTVINFO;
|
||||
else if (!strcmp(mimetype, "text/x-quaketvident"))
|
||||
f->flags |= HRF_QTVINFO;
|
||||
else if (!strcmp(mimetype, "application/x-ftemanifest"))
|
||||
f->flags |= HRF_MANIFEST;
|
||||
else if (!strcmp(mimetype, "application/x-multiviewdemo"))
|
||||
f->flags |= HRF_MVD;
|
||||
// else if (!strcmp(mimetype, "application/x-ftebsp"))
|
||||
// f->flags |= HRF_BSP;
|
||||
// else if (!strcmp(mimetype, "application/x-ftepackage"))
|
||||
// f->flags |= HRF_PACKAGE;
|
||||
}
|
||||
|
||||
//FIXME: HRF_DEMO should be able to stream. create a vfs pipe for the download code to write to?
|
||||
|
||||
if (!(f->flags & HRF_FILETYPES))
|
||||
{
|
||||
char *ext = COM_FileExtension(f->fname);
|
||||
if (!strcmp(ext, "qwd"))
|
||||
f->flags |= HRF_DEMO_QWD;
|
||||
else if (!strcmp(ext, "mvd"))
|
||||
f->flags |= HRF_DEMO_MVD;
|
||||
else if (!strcmp(ext, "dm2"))
|
||||
f->flags |= HRF_DEMO_DM2;
|
||||
else if (!strcmp(ext, "dem"))
|
||||
f->flags |= HRF_DEMO_DEM;
|
||||
else if (!strcmp(ext, "qtv"))
|
||||
f->flags |= HRF_QTVINFO;
|
||||
else if (!strcmp(ext, "fmf"))
|
||||
f->flags |= HRF_MANIFEST;
|
||||
else if (!strcmp(ext, "bsp"))
|
||||
f->flags |= HRF_BSP;
|
||||
else if (!strcmp(ext, "pak") || !strcmp(ext, "pk3"))
|
||||
f->flags |= HRF_PACKAGE;
|
||||
else
|
||||
{
|
||||
//file type not guessable from extension.
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_MANIFEST)
|
||||
waitingformanifest++;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_DEMO_QWD)
|
||||
CL_PlayDemoStream((dl->file = VFSPIPE_Open()), dl, f->fname, DPB_QUAKEWORLD, 0);
|
||||
else if (f->flags & HRF_DEMO_MVD)
|
||||
CL_PlayDemoStream((dl->file = VFSPIPE_Open()), dl, f->fname, DPB_MVD, 0);
|
||||
else if (f->flags & HRF_DEMO_DM2)
|
||||
CL_PlayDemoStream((dl->file = VFSPIPE_Open()), dl, f->fname, DPB_QUAKE2, 0);
|
||||
else if (f->flags & HRF_DEMO_DEM)
|
||||
CL_PlayDemoStream((dl->file = VFSPIPE_Open()), dl, f->fname, DPB_NETQUAKE, 0);
|
||||
else
|
||||
return;
|
||||
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
void Host_RunFilePrompted(void *ctx, int button)
|
||||
{
|
||||
hrf_t *f = ctx;
|
||||
|
@ -3630,7 +3708,6 @@ void Host_RunFilePrompted(void *ctx, int button)
|
|||
Host_DoRunFile(f);
|
||||
}
|
||||
|
||||
qboolean waitingformanifest;
|
||||
void Host_DoRunFile(hrf_t *f)
|
||||
{
|
||||
char qname[MAX_QPATH];
|
||||
|
@ -3652,6 +3729,50 @@ void Host_DoRunFile(hrf_t *f)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(f->flags & HRF_FILETYPES))
|
||||
{
|
||||
char *ext;
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
if (!strncmp(f->fname, "http://", 7) && !f->srcfile)
|
||||
{
|
||||
if (!(f->flags & HRF_OPENED))
|
||||
{
|
||||
struct dl_download *dl;
|
||||
f->flags |= HRF_OPENED;
|
||||
dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded);
|
||||
dl->notifystarted = Host_BeginFileDownload;
|
||||
dl->user_ctx = f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//if we get here, we have no mime type to give us any clues.
|
||||
ext = COM_FileExtension(f->fname);
|
||||
if (!strcmp(ext, "qwd") || !strcmp(ext, "dem") || !strcmp(ext, "dm2") || !strcmp(ext, "mvd"))
|
||||
f->flags |= HRF_DEMO;
|
||||
if (!strcmp(ext, "qtv"))
|
||||
f->flags |= HRF_QTVINFO;
|
||||
if (!strcmp(ext, "fmf"))
|
||||
f->flags |= HRF_MANIFEST;
|
||||
if (!strcmp(ext, "bsp"))
|
||||
f->flags |= HRF_BSP;
|
||||
if (!strcmp(ext, "pak") || !strcmp(ext, "pk3"))
|
||||
f->flags |= HRF_PACKAGE;
|
||||
|
||||
//if we still don't know what it is, give up.
|
||||
if (!(f->flags & HRF_FILETYPES))
|
||||
{
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_MANIFEST)
|
||||
waitingformanifest++;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_DEMO)
|
||||
{
|
||||
//play directly via system path, no prompts needed
|
||||
|
@ -3661,15 +3782,6 @@ void Host_DoRunFile(hrf_t *f)
|
|||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
else if (f->flags & HRF_QTVINFO)
|
||||
{
|
||||
//play directly via url/system path, no prompts needed
|
||||
Cbuf_AddText(va("qtvplay \"#%s\"\n", f->fname), RESTRICT_LOCAL);
|
||||
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
else if (f->flags & HRF_BSP)
|
||||
{
|
||||
char shortname[MAX_QPATH];
|
||||
|
@ -3709,13 +3821,14 @@ void Host_DoRunFile(hrf_t *f)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!(f->flags & HRF_QTVINFO))
|
||||
{
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
|
||||
//at this point we need the file to have been opened.
|
||||
if (!(f->flags & HRF_OPENED))
|
||||
{
|
||||
f->flags |= HRF_OPENED;
|
||||
|
@ -3725,6 +3838,7 @@ void Host_DoRunFile(hrf_t *f)
|
|||
if (!strncmp(f->fname, "http://", 7))
|
||||
{
|
||||
struct dl_download *dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded);
|
||||
dl->notifystarted = Host_BeginFileDownload;
|
||||
dl->user_ctx = f;
|
||||
return;
|
||||
}
|
||||
|
@ -3746,6 +3860,17 @@ void Host_DoRunFile(hrf_t *f)
|
|||
return;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_QTVINFO)
|
||||
{
|
||||
//pass the file object to the qtv code instead of trying to install it.
|
||||
CL_ParseQTVDescriptor(f->srcfile, f->fname);
|
||||
f->srcfile = NULL;
|
||||
|
||||
f->flags |= HRF_ABORT;
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
|
||||
VFS_SEEK(f->srcfile, 0);
|
||||
|
||||
f->dstfile = FS_OpenVFS(qname, "rb", FS_GAME);
|
||||
|
@ -3818,25 +3943,10 @@ void Host_DoRunFile(hrf_t *f)
|
|||
//if file is specified, takes full ownership of said file, including destruction.
|
||||
qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file)
|
||||
{
|
||||
char *ext = COM_FileExtension(fname);
|
||||
hrf_t *f = Z_Malloc(sizeof(*f) + nlen);
|
||||
memcpy(f->fname, fname, nlen);
|
||||
f->fname[nlen] = 0;
|
||||
|
||||
if (!strcmp(ext, "qwd") || !strcmp(ext, "dem") || !strcmp(ext, "mvd"))
|
||||
f->flags |= HRF_DEMO;
|
||||
if (!strcmp(ext, "qtv"))
|
||||
f->flags |= HRF_QTVINFO;
|
||||
if (!strcmp(ext, "fmf"))
|
||||
f->flags |= HRF_MANIFEST;
|
||||
if (!strcmp(ext, "bsp"))
|
||||
f->flags |= HRF_BSP;
|
||||
if (!strcmp(ext, "pak") || !strcmp(ext, "pk3"))
|
||||
f->flags |= HRF_PACKAGE;
|
||||
|
||||
if (f->flags & HRF_MANIFEST)
|
||||
waitingformanifest++;
|
||||
|
||||
Host_DoRunFile(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -3894,7 +4004,6 @@ double Host_Frame (double time)
|
|||
|
||||
if (r_blockvidrestart)
|
||||
{
|
||||
extern qboolean waitingformanifest;
|
||||
if (waitingformanifest)
|
||||
return 0.1;
|
||||
Host_FinishLoading();
|
||||
|
@ -4284,10 +4393,10 @@ void CL_ExecInitialConfigs(char *resetcommand)
|
|||
{
|
||||
int qrc, hrc, def;
|
||||
|
||||
Cbuf_AddText("cl_warncmd 0\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("unbindall\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("cvar_purgedefaults\n", RESTRICT_LOCAL); //reset cvar defaults to their engine-specified values. the tail end of 'exec default.cfg' will update non-cheat defaults to mod-specified values.
|
||||
Cbuf_AddText("cvarreset *\n", RESTRICT_LOCAL); //reset all cvars to their current (engine) defaults
|
||||
Cbuf_AddText("cl_warncmd 0\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText(resetcommand, RESTRICT_LOCAL);
|
||||
Cbuf_AddText("\n", RESTRICT_LOCAL);
|
||||
|
||||
|
|
|
@ -1413,7 +1413,7 @@ void CL_RequestNextDownload (void)
|
|||
|
||||
int stage;
|
||||
/*already downloading*/
|
||||
if (cls.downloadmethod)
|
||||
if (cls.downloadmethod && !cls.demoplayback)
|
||||
return;
|
||||
|
||||
/*request downloads only if we're at the point where we've received a complete list of them*/
|
||||
|
@ -1442,7 +1442,7 @@ void CL_RequestNextDownload (void)
|
|||
fl = dl->flags;
|
||||
|
||||
/*if we don't require downloads don't queue requests until we're actually on the server, slightly more deterministic*/
|
||||
if (cls.state == ca_active || requiredownloads.value || (fl & DLLF_REQUIRED))
|
||||
if (cls.state == ca_active || (requiredownloads.value && !cls.demoplayback) || (fl & DLLF_REQUIRED))
|
||||
{
|
||||
if ((fl & DLLF_OVERWRITE) || !CL_CheckFile (dl->localname))
|
||||
{
|
||||
|
|
|
@ -415,6 +415,7 @@ typedef struct
|
|||
float demoseektime;
|
||||
qboolean timedemo;
|
||||
vfsfile_t *demoinfile;
|
||||
struct dl_download *demoindownload;
|
||||
float td_lastframe; // to meter out one message a frame
|
||||
int td_startframe; // host_framecount at start
|
||||
float td_starttime; // realtime at second frame of timedemo
|
||||
|
|
|
@ -432,6 +432,7 @@ skipwhite:
|
|||
return (char*)data;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct
|
||||
{
|
||||
vfsfile_t funcs;
|
||||
|
@ -513,7 +514,7 @@ vfsfile_t *VFSPIPE_Open(void)
|
|||
|
||||
return &newf->funcs;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1733,7 +1733,6 @@ WinMain
|
|||
HINSTANCE global_hInstance;
|
||||
int global_nCmdShow;
|
||||
char *argv[MAX_NUM_ARGVS];
|
||||
static char exename[MAX_PATH];
|
||||
HWND hwnd_dialog;
|
||||
|
||||
|
||||
|
@ -2548,6 +2547,58 @@ void VARGS Signal_Error_Handler(int i)
|
|||
|
||||
extern char sys_language[64];
|
||||
|
||||
static int Sys_ProcessCommandline(char **argv, int maxargc, char *argv0)
|
||||
{
|
||||
int argc = 0, i;
|
||||
wchar_t *wc = GetCommandLineW();
|
||||
unsigned char utf8cmdline[4096], *cl = utf8cmdline;
|
||||
narrowen(utf8cmdline, sizeof(utf8cmdline), wc);
|
||||
|
||||
// argv[argc] = argv0;
|
||||
// argc++;
|
||||
|
||||
while (*cl && (argc < maxargc))
|
||||
{
|
||||
while (*cl && *cl <= 32)
|
||||
cl++;
|
||||
|
||||
if (*cl)
|
||||
{
|
||||
if (*cl == '\"')
|
||||
{
|
||||
cl++;
|
||||
|
||||
argv[argc] = cl;
|
||||
argc++;
|
||||
|
||||
while (*cl && *cl != '\"')
|
||||
cl++;
|
||||
}
|
||||
else
|
||||
{
|
||||
argv[argc] = cl;
|
||||
argc++;
|
||||
|
||||
|
||||
while (*cl && *cl > 32)
|
||||
cl++;
|
||||
}
|
||||
|
||||
if (*cl)
|
||||
{
|
||||
*cl = 0;
|
||||
cl++;
|
||||
}
|
||||
}
|
||||
}
|
||||
argv[argc] = argv0;
|
||||
if (argc < 1)
|
||||
argc = 1;
|
||||
for (i = 0; i < argc; i++)
|
||||
argv[i] = strdup(argv[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
// MSG msg;
|
||||
|
@ -2562,6 +2613,15 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
|||
/* previous instances do not exist in Win32 */
|
||||
if (hPrevInstance)
|
||||
return 0;
|
||||
|
||||
/* determine if we're on nt early, so we don't do the wrong thing when checking commandlines */
|
||||
{
|
||||
OSVERSIONINFOA vinfo;
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
if (GetVersionExA (&vinfo))
|
||||
WinNT = vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) && defined(MULTITHREAD)
|
||||
Sys_SetThreadName(-1, "main thread");
|
||||
#endif
|
||||
|
@ -2626,44 +2686,6 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
|||
global_hInstance = hInstance;
|
||||
global_nCmdShow = nCmdShow;
|
||||
|
||||
parms.argc = 1;
|
||||
argv[0] = exename;
|
||||
|
||||
while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
|
||||
{
|
||||
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
|
||||
lpCmdLine++;
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
if (*lpCmdLine == '\"')
|
||||
{
|
||||
lpCmdLine++;
|
||||
|
||||
argv[parms.argc] = lpCmdLine;
|
||||
parms.argc++;
|
||||
|
||||
while (*lpCmdLine && *lpCmdLine != '\"')
|
||||
lpCmdLine++;
|
||||
}
|
||||
else
|
||||
{
|
||||
argv[parms.argc] = lpCmdLine;
|
||||
parms.argc++;
|
||||
|
||||
|
||||
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
|
||||
lpCmdLine++;
|
||||
}
|
||||
|
||||
if (*lpCmdLine)
|
||||
{
|
||||
*lpCmdLine = 0;
|
||||
lpCmdLine++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RESTARTTEST
|
||||
setjmp (restart_jmpbuf);
|
||||
#endif
|
||||
|
@ -2676,7 +2698,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
|||
}
|
||||
else
|
||||
GetModuleFileNameA(NULL, bindir, sizeof(bindir)-1);
|
||||
Q_strncpyz(exename, bindir, sizeof(exename));
|
||||
parms.argc = Sys_ProcessCommandline(argv, MAX_NUM_ARGVS, bindir);
|
||||
*COM_SkipPath(bindir) = 0;
|
||||
parms.argv = (const char **)argv;
|
||||
|
||||
|
@ -2724,8 +2746,18 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
|||
if (COM_CheckParm("-outputdebugstring"))
|
||||
debugout = true;
|
||||
|
||||
if (!GetCurrentDirectory (sizeof(cwd), cwd))
|
||||
Sys_Error ("Couldn't determine current directory");
|
||||
if (WinNT)
|
||||
{
|
||||
wchar_t wcwd[MAX_OSPATH];
|
||||
if (!GetCurrentDirectoryW (sizeof(wcwd)/sizeof(wchar_t), wcwd))
|
||||
Sys_Error ("Couldn't determine current directory");
|
||||
narrowen(cwd, sizeof(cwd), wcwd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetCurrentDirectoryA (sizeof(cwd), cwd))
|
||||
Sys_Error ("Couldn't determine current directory");
|
||||
}
|
||||
if (parms.argc >= 2)
|
||||
{
|
||||
if (*parms.argv[1] != '-' && *parms.argv[1] != '+')
|
||||
|
|
|
@ -2112,7 +2112,7 @@ int FTENET_GetLocalAddress(netadr_t *out, int port, int count, qboolean ipx, qbo
|
|||
return idx;
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
#elif defined(__linux__) && !defined(ANDROID)
|
||||
//in linux, looking up our own hostname to retrieve a list of local interface addresses will give no indication that other systems are able to do the same thing and is thus not supported.
|
||||
//there's some special api instead
|
||||
//glibc 2.3.
|
||||
|
@ -5043,7 +5043,28 @@ void NET_GetLocalAddress (int socket, netadr_t *out)
|
|||
if (out->type == NA_IP)
|
||||
{
|
||||
if (!*(int*)out->address.ip) //socket was set to auto
|
||||
*(int *)out->address.ip = *(int *)adr.address.ip; //change it to what the machine says it is, rather than the socket.
|
||||
{
|
||||
if (adr.type == NA_IP)
|
||||
*(int *)out->address.ip = *(int *)adr.address.ip; //change it to what the machine says it is, rather than the socket.
|
||||
}
|
||||
}
|
||||
if (out->type == NA_IPV6)
|
||||
{
|
||||
if (!((int*)out->address.ip6)[0] &&
|
||||
!((int*)out->address.ip6)[1] &&
|
||||
!((short*)out->address.ip6)[4] &&
|
||||
(!((short*)out->address.ip6)[5] || ((unsigned short*)out->address.ip6)[5]==0xffffu)
|
||||
&& !((int*)out->address.ip6)[3]) //ipv6 any or ipv4-mapped any.
|
||||
{
|
||||
if (adr.type == NA_IP)
|
||||
{
|
||||
memset(out->address.ip6, 0, sizeof(out->address.ip6));
|
||||
((short *)out->address.ip6)[5] = 0xffff;
|
||||
((int *)out->address.ip6)[3] = *(int *)adr.address.ip;
|
||||
}
|
||||
else if (adr.type == NA_IPV6)
|
||||
memcpy(out->address.ip6, adr.address.ip6, sizeof(out->address.ip6));
|
||||
}
|
||||
}
|
||||
|
||||
if (!notvalid)
|
||||
|
|
|
@ -522,7 +522,7 @@ static qboolean resetd3dbackbuffer(int width, int height)
|
|||
|
||||
static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func, IDXGIAdapter *adapt)
|
||||
{
|
||||
int flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
int flags = 0;//= D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
D3D_DRIVER_TYPE drivertype;
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
D3D_FEATURE_LEVEL flevel, flevels[] =
|
||||
|
|
|
@ -29660,6 +29660,14 @@
|
|||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="D3DRelease|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\net_ssl_winsspi.c"
|
||||
|
|
|
@ -13,16 +13,38 @@
|
|||
<activity android:name=".FTEDroidActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboardHidden|orientation">
|
||||
|
||||
<!-- launcher icon -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- mime types with unspecified schemes (please don't explode). one for each mime type. because I'm paranoid. -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:mimeType="application/x-qtv" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:mimeType="text/x-quaketvident" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:mimeType="application/x-ftemanifest" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- various file extensions for when people forgot the mime type or simply don't know it -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="http" android:host="*" android:pathPattern=".*\\.qtv" />
|
||||
<data android:scheme="content" android:host="*" android:pathPattern=".*\\.qtv" />
|
||||
<data android:scheme="file" android:host="*" android:pathPattern=".*\\.qtv" />
|
||||
|
|
|
@ -725,12 +725,16 @@ public class FTEDroidActivity extends Activity
|
|||
if (data.getScheme().equals("content"))
|
||||
{ //wtf.
|
||||
Cursor cursor = this.getContentResolver().query(data, null, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
myloc = cursor.getString(0);
|
||||
cursor.close();
|
||||
cursor.moveToFirst();
|
||||
myloc = cursor.getString(0);
|
||||
cursor.close();
|
||||
android.util.Log.i("FTEDroid", "intent content: " + myloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
myloc = data.toString();
|
||||
android.util.Log.i("FTEDroid", "intent url: " + myloc);
|
||||
}
|
||||
FTEDroidEngine.openfile(myloc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,6 +325,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
|
|||
struct http_dl_ctx_s *con = dl->ctx;
|
||||
char buffer[256];
|
||||
char Location[256];
|
||||
char mimetype[256];
|
||||
char *nl;
|
||||
char *msg;
|
||||
int ammount;
|
||||
|
@ -368,6 +369,10 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
|
|||
|
||||
msg = con->buffer;
|
||||
con->chunking = false;
|
||||
con->contentlength = 0;
|
||||
con->gzip = false;
|
||||
*mimetype = 0;
|
||||
*Location = 0;
|
||||
if (strnicmp(msg, "HTTP/", 5))
|
||||
{ //pre version 1. (lame servers.
|
||||
con->state = HC_GETTING;
|
||||
|
@ -404,6 +409,12 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
|
|||
break;//not complete, don't bother trying to parse it.
|
||||
if (!strnicmp(msg, "Content-Length: ", 16))
|
||||
con->contentlength = atoi(msg+16);
|
||||
else if (!strnicmp(msg, "Content-Type:", 13))
|
||||
{
|
||||
*nl = '\0';
|
||||
Q_strncpyz(mimetype, COM_TrimString(msg+13), sizeof(mimetype));
|
||||
*nl = '\n';
|
||||
}
|
||||
else if (!strnicmp(msg, "Location: ", 10))
|
||||
{
|
||||
*nl = '\0';
|
||||
|
@ -496,6 +507,9 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
|
|||
memmove(con->buffer, con->buffer+ammount, con->bufferused);
|
||||
}
|
||||
|
||||
if (dl->notifystarted)
|
||||
dl->notifystarted(dl, *mimetype?mimetype:NULL);
|
||||
|
||||
if (!dl->file)
|
||||
{
|
||||
#ifndef NPFTE
|
||||
|
@ -521,6 +535,8 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
|
|||
con->file = FS_OpenTemp();
|
||||
#else
|
||||
Con_Printf("HTTP: no support for gzipped files \"%s\"\n", dl->localname);
|
||||
dl->status = DL_FAILED;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -803,8 +819,8 @@ static int DL_Thread_Work(void *arg)
|
|||
{
|
||||
#ifdef NPFTE
|
||||
//the plugin doesn't have a download loop
|
||||
if (dl->notify)
|
||||
dl->notify(dl);
|
||||
if (dl->notifycomplete)
|
||||
dl->notifycomplete(dl);
|
||||
if (dl->file)
|
||||
VFS_CLOSE(dl->file);
|
||||
#else
|
||||
|
@ -830,7 +846,7 @@ qboolean DL_CreateThread(struct dl_download *dl, vfsfile_t *file, void (*NotifyF
|
|||
if (file)
|
||||
dl->file = file;
|
||||
if (NotifyFunction)
|
||||
dl->notify = NotifyFunction;
|
||||
dl->notifycomplete = NotifyFunction;
|
||||
|
||||
dl->threadctx = Sys_CreateThread("download", DL_Thread_Work, dl, THREADP_NORMAL, 0);
|
||||
if (!dl->threadctx)
|
||||
|
@ -896,14 +912,14 @@ void DL_Close(struct dl_download *dl)
|
|||
|
||||
static struct dl_download *activedownloads;
|
||||
unsigned int shownbytestart;
|
||||
/*create a download context and add it to the list, for lazy people*/
|
||||
/*create a download context and add it to the list, for lazy people. not threaded*/
|
||||
struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl))
|
||||
{
|
||||
struct dl_download *newdl = DL_Create(url);
|
||||
if (!newdl)
|
||||
return newdl;
|
||||
|
||||
newdl->notify = NotifyFunction;
|
||||
newdl->notifycomplete = NotifyFunction;
|
||||
if (localfile)
|
||||
Q_strncpyz(newdl->localname, localfile, sizeof(newdl->localname));
|
||||
|
||||
|
@ -951,10 +967,10 @@ void HTTP_CL_Think(void)
|
|||
if (!dl->poll(dl))
|
||||
{
|
||||
*link = dl->next;
|
||||
if (dl->file)
|
||||
if (dl->file && dl->file->Seek)
|
||||
VFS_SEEK(dl->file, 0);
|
||||
if (dl->notify)
|
||||
dl->notify(dl);
|
||||
if (dl->notifycomplete)
|
||||
dl->notifycomplete(dl);
|
||||
DL_Close(dl);
|
||||
continue;
|
||||
}
|
||||
|
@ -992,3 +1008,86 @@ void HTTP_CL_Think(void)
|
|||
}
|
||||
#endif
|
||||
#endif /*WEBCLIENT*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vfsfile_t funcs;
|
||||
|
||||
char *data;
|
||||
int maxlen;
|
||||
int writepos;
|
||||
int readpos;
|
||||
} vfspipe_t;
|
||||
|
||||
void QDECL VFSPIPE_Close(vfsfile_t *f)
|
||||
{
|
||||
vfspipe_t *p = (vfspipe_t*)f;
|
||||
free(p->data);
|
||||
free(p);
|
||||
}
|
||||
unsigned long QDECL VFSPIPE_GetLen(vfsfile_t *f)
|
||||
{
|
||||
vfspipe_t *p = (vfspipe_t*)f;
|
||||
return p->writepos - p->readpos;
|
||||
}
|
||||
//unsigned long QDECL VFSPIPE_Tell(vfsfile_t *f)
|
||||
//{
|
||||
// return 0;
|
||||
//}
|
||||
//qboolean QDECL VFSPIPE_Seek(vfsfile_t *f, unsigned long offset)
|
||||
//{
|
||||
// Con_Printf("Seeking is a bad plan, mmkay?\n");
|
||||
// return false;
|
||||
//}
|
||||
int QDECL VFSPIPE_ReadBytes(vfsfile_t *f, void *buffer, int len)
|
||||
{
|
||||
vfspipe_t *p = (vfspipe_t*)f;
|
||||
if (len > p->writepos - p->readpos)
|
||||
len = p->writepos - p->readpos;
|
||||
memcpy(buffer, p->data+p->readpos, len);
|
||||
p->readpos += len;
|
||||
|
||||
if (p->readpos > 8192)
|
||||
{
|
||||
//shift the memory down periodically
|
||||
//fixme: use cyclic buffer? max size, etc?
|
||||
memmove(p->data, p->data+p->readpos, p->writepos-p->readpos);
|
||||
|
||||
p->writepos -= p->readpos;
|
||||
p->readpos = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
int QDECL VFSPIPE_WriteBytes(vfsfile_t *f, const void *buffer, int len)
|
||||
{
|
||||
vfspipe_t *p = (vfspipe_t*)f;
|
||||
if (p->writepos + len > p->maxlen)
|
||||
{
|
||||
p->maxlen = p->writepos + len;
|
||||
p->data = realloc(p->data, p->maxlen);
|
||||
}
|
||||
memcpy(p->data+p->writepos, buffer, len);
|
||||
p->writepos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
vfsfile_t *VFSPIPE_Open(void)
|
||||
{
|
||||
vfspipe_t *newf;
|
||||
newf = malloc(sizeof(*newf));
|
||||
newf->data = NULL;
|
||||
newf->maxlen = 0;
|
||||
newf->readpos = 0;
|
||||
newf->writepos = 0;
|
||||
newf->funcs.Close = VFSPIPE_Close;
|
||||
newf->funcs.Flush = NULL;
|
||||
newf->funcs.GetLen = VFSPIPE_GetLen;
|
||||
newf->funcs.ReadBytes = VFSPIPE_ReadBytes;
|
||||
newf->funcs.Seek = NULL;//VFSPIPE_Seek;
|
||||
newf->funcs.Tell = NULL;//VFSPIPE_Tell;
|
||||
newf->funcs.WriteBytes = VFSPIPE_WriteBytes;
|
||||
newf->funcs.seekingisabadplan = true;
|
||||
|
||||
return &newf->funcs;
|
||||
}
|
||||
|
|
|
@ -142,9 +142,11 @@ struct dl_download
|
|||
|
||||
/*not used internally by the backend, but used by HTTP_CL_Get/thread wrapper*/
|
||||
struct dl_download *next;
|
||||
void (*notify) (struct dl_download *dl);
|
||||
void (*notifystarted) (struct dl_download *dl, char *mimetype); //mime can be null for some protocols, read dl->totalsize for size.
|
||||
void (*notifycomplete) (struct dl_download *dl);
|
||||
};
|
||||
|
||||
vfsfile_t *VFSPIPE_Open(void);
|
||||
void HTTP_CL_Think(void);
|
||||
struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl));
|
||||
struct dl_download *HTTP_CL_Put(const char *url, const char *mime, const char *data, size_t datalen, void (*NotifyFunction)(struct dl_download *dl));
|
||||
|
|
|
@ -154,7 +154,7 @@ 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");
|
||||
cvar_t pausable = CVAR("pausable", "1");
|
||||
cvar_t sv_banproxies = CVARD("banproxies", "0", "If enabled, anyone connecting via known proxy software will be refused entry. This should aid with blocking aimbots, but is only reliable for certain public proxies.");
|
||||
cvar_t sv_banproxies = CVARD("sv_banproxies", "0", "If enabled, anyone connecting via known proxy software will be refused entry. This should aid with blocking aimbots, but is only reliable for certain public proxies.");
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -79,7 +79,7 @@ cvar_t voteminimum = SCVAR("voteminimum", "4");
|
|||
cvar_t votepercent = SCVAR("votepercent", "-1");
|
||||
cvar_t votetime = SCVAR("votetime", "10");
|
||||
|
||||
cvar_t pr_allowbutton1 = SCVARF("pr_allowbutton1", "1", CVAR_LATCH);
|
||||
cvar_t pr_allowbutton1 = CVARFD("pr_allowbutton1", "1", CVAR_LATCH, "The button1 field is believed to have been intended to work with the +use command, but it was never hooked up. In NetQuake, this field was often repurposed for other things as it was not otherwise used (and cannot be removed without breaking the crc), while third-party QuakeWorld engines did decide to implement it as believed was intended. As a result, this cvar only applies to QuakeWorld mods and a value of 1 is only likely to cause issues with NQ mods that were ported to QW.");
|
||||
extern cvar_t sv_minping;
|
||||
|
||||
|
||||
|
@ -5692,7 +5692,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
|
||||
sv_player->v->button0 = ucmd->buttons & 1;
|
||||
sv_player->v->button2 = (ucmd->buttons >> 1) & 1;
|
||||
if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
|
||||
if (pr_allowbutton1.ival && progstype == PROG_QW) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
|
||||
sv_player->v->button1 = ((ucmd->buttons >> 2) & 1);
|
||||
// DP_INPUTBUTTONS
|
||||
sv_player->xv->button3 = ((ucmd->buttons >> 2) & 1);
|
||||
|
@ -6813,7 +6813,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
|
|||
|
||||
host_client->edict->v->button0 = bits & 1;
|
||||
host_client->edict->v->button2 = (bits >> 1) & 1;
|
||||
if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
|
||||
if (pr_allowbutton1.ival && progstype == PROG_QW) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
|
||||
host_client->edict->v->button1 = ((bits >> 2) & 1);
|
||||
// DP_INPUTBUTTONS
|
||||
host_client->edict->xv->button3 = ((bits >> 2) & 1);
|
||||
|
|
Loading…
Reference in a new issue