Added 'dir' command to play a directory of demos.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4790 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
332945dbba
commit
6c74368870
3 changed files with 179 additions and 39 deletions
|
@ -558,6 +558,7 @@ typedef struct {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SRC_BAD,
|
SRC_BAD,
|
||||||
SRC_DEMO,
|
SRC_DEMO,
|
||||||
|
SRC_DEMODIR,
|
||||||
SRC_UDP,
|
SRC_UDP,
|
||||||
SRC_TCP
|
SRC_TCP
|
||||||
} sourcetype_t;
|
} sourcetype_t;
|
||||||
|
@ -630,6 +631,7 @@ struct sv_s { //details about a server connection (also known as stream)
|
||||||
FILE *sourcefile;
|
FILE *sourcefile;
|
||||||
unsigned int filelength;
|
unsigned int filelength;
|
||||||
SOCKET sourcesock;
|
SOCKET sourcesock;
|
||||||
|
int last_random_number; // for demo directories randomizing stuff
|
||||||
|
|
||||||
// SOCKET tcpsocket; //tcp + mvd protocol
|
// SOCKET tcpsocket; //tcp + mvd protocol
|
||||||
// int tcplistenportnum;
|
// int tcplistenportnum;
|
||||||
|
|
|
@ -467,6 +467,8 @@ void Cmd_GenericConnect(cmdctxt_t *ctx, char *method, enum autodisconnect_e auto
|
||||||
{
|
{
|
||||||
if (!strncmp(method, "file", 4))
|
if (!strncmp(method, "file", 4))
|
||||||
Cmd_Printf(ctx, "%s requires a demo name parameter\n", Cmd_Argv(ctx, 0));
|
Cmd_Printf(ctx, "%s requires a demo name parameter\n", Cmd_Argv(ctx, 0));
|
||||||
|
else if (!strncmp(method, "dir", 3))
|
||||||
|
Cmd_Printf(ctx, "%s requires a demo directory parameter\n", Cmd_Argv(ctx, 0));
|
||||||
else
|
else
|
||||||
Cmd_Printf(ctx, "%s requires an ip:port parameter\n", Cmd_Argv(ctx, 0));
|
Cmd_Printf(ctx, "%s requires an ip:port parameter\n", Cmd_Argv(ctx, 0));
|
||||||
return;
|
return;
|
||||||
|
@ -498,6 +500,10 @@ void Cmd_MVDConnect(cmdctxt_t *ctx)
|
||||||
{
|
{
|
||||||
Cmd_GenericConnect(ctx, "file:", AD_NO);
|
Cmd_GenericConnect(ctx, "file:", AD_NO);
|
||||||
}
|
}
|
||||||
|
void Cmd_DirMVDConnect(cmdctxt_t *ctx)
|
||||||
|
{
|
||||||
|
Cmd_GenericConnect(ctx, "dir:", AD_NO);
|
||||||
|
}
|
||||||
|
|
||||||
void Cmd_Exec(cmdctxt_t *ctx)
|
void Cmd_Exec(cmdctxt_t *ctx)
|
||||||
{
|
{
|
||||||
|
@ -1258,6 +1264,8 @@ const rconcommands_t rconcommands[] =
|
||||||
{"demos", 0, 1, Cmd_DemoList, "shows the list of demos available on this proxy"},
|
{"demos", 0, 1, Cmd_DemoList, "shows the list of demos available on this proxy"},
|
||||||
{"demo", 0, 1, Cmd_MVDConnect, "adds a demo as a new stream"},
|
{"demo", 0, 1, Cmd_MVDConnect, "adds a demo as a new stream"},
|
||||||
{"playdemo", 0, 1, Cmd_MVDConnect},
|
{"playdemo", 0, 1, Cmd_MVDConnect},
|
||||||
|
{"dir", 0, 1, Cmd_DirMVDConnect, "adds a directory of demos as a new stream"},
|
||||||
|
{"playdir", 0, 1, Cmd_DirMVDConnect},
|
||||||
{"choke", 0, 1, Cmd_Choke, "chokes packets to the data rate in the stream, disables proxy-side interpolation"},
|
{"choke", 0, 1, Cmd_Choke, "chokes packets to the data rate in the stream, disables proxy-side interpolation"},
|
||||||
{"late", 0, 1, Cmd_Late, "enforces a time delay on packets sent through this proxy"},
|
{"late", 0, 1, Cmd_Late, "enforces a time delay on packets sent through this proxy"},
|
||||||
{"talking", 0, 1, Cmd_Talking, "permits viewers to talk to each other"},
|
{"talking", 0, 1, Cmd_Talking, "permits viewers to talk to each other"},
|
||||||
|
|
208
fteqtv/source.c
208
fteqtv/source.c
|
@ -58,6 +58,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "bsd_string.h"
|
#include "bsd_string.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <dirent.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -573,15 +574,30 @@ qboolean Net_ConnectToUDPServer(sv_t *qtv, char *ip)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean DemoFilenameIsOkay(char *fname)
|
qboolean DemoFilenameIsOkay(sv_t* qtv, char *fname, char *dir)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
if (strchr(dir, '/'))
|
||||||
|
return false; //unix path seperator
|
||||||
|
if (strchr(dir, '\\'))
|
||||||
|
return false; //windows path seperator
|
||||||
|
if (strchr(dir, ':'))
|
||||||
|
return false; //mac path seperator
|
||||||
|
if (*(dir) == '.')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (strchr(fname, '/'))
|
if (strchr(fname, '/'))
|
||||||
return false; //unix path seperator
|
return false; //unix path seperator
|
||||||
if (strchr(fname, '\\'))
|
if (strchr(fname, '\\'))
|
||||||
return false; //windows path seperator
|
return false; //windows path seperator
|
||||||
if (strchr(fname, ':'))
|
if (strchr(fname, ':'))
|
||||||
return false; //mac path seperator
|
return false; //mac path seperator
|
||||||
|
if (*(fname) == '.')
|
||||||
|
return false;
|
||||||
|
|
||||||
//now make certain that the last four characters are '.mvd' and not something like '.cfg' perhaps
|
//now make certain that the last four characters are '.mvd' and not something like '.cfg' perhaps
|
||||||
len = strlen(fname);
|
len = strlen(fname);
|
||||||
|
@ -619,6 +635,144 @@ qboolean DemoFilenameIsOkay(char *fname)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qboolean Net_ConnectToDemoServer(sv_t* qtv, char* ip, char* dir)
|
||||||
|
{
|
||||||
|
char fullname[512];
|
||||||
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
if (DemoFilenameIsOkay(qtv, ip, dir))
|
||||||
|
{
|
||||||
|
if (!dir)
|
||||||
|
snprintf(fullname, sizeof(fullname), "%s%s", qtv->cluster->demodir, ip);
|
||||||
|
else
|
||||||
|
snprintf(fullname, sizeof(fullname), "%s%s/%s", qtv->cluster->demodir, dir, ip);
|
||||||
|
qtv->sourcefile = fopen(fullname, "rb");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qtv->sourcefile = NULL;
|
||||||
|
|
||||||
|
if (qtv->sourcefile)
|
||||||
|
{
|
||||||
|
char smallbuffer[17];
|
||||||
|
fseek(qtv->sourcefile, 0, SEEK_END);
|
||||||
|
qtv->filelength = ftell(qtv->sourcefile);
|
||||||
|
|
||||||
|
//attempt to detect the end of the file
|
||||||
|
fseek(qtv->sourcefile, 0-sizeof(smallbuffer), SEEK_CUR);
|
||||||
|
fread(smallbuffer, 1, 17, qtv->sourcefile);
|
||||||
|
//0 is the time
|
||||||
|
if (smallbuffer[1] == dem_all || smallbuffer[1] == dem_read) //mvdsv changed it to read...
|
||||||
|
{
|
||||||
|
//2,3,4,5 are the length
|
||||||
|
if (smallbuffer[6] == svc_disconnect)
|
||||||
|
{
|
||||||
|
if (!strcmp(smallbuffer+7, "EndOfDemo"))
|
||||||
|
{
|
||||||
|
qtv->filelength -= 17;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(qtv->sourcefile, 0, SEEK_SET);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dir)
|
||||||
|
Sys_Printf(qtv->cluster, "Stream %i: Unable to open file %s\n", qtv->streamid, ip);
|
||||||
|
else
|
||||||
|
Sys_Printf(qtv->cluster, "Stream %i: Unable to open file %s in directory %s\n", qtv->streamid, ip, dir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Net_ConnectToDemoDirServer(sv_t* qtv, char *ip)
|
||||||
|
{
|
||||||
|
char fullname[512];
|
||||||
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
snprintf(fullname, sizeof(fullname), "%s%s", qtv->cluster->demodir, ip);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO: code for Windows directories goes here
|
||||||
|
// TODO: possible to do this without copy-pasting the entire GNU/Linux code below?
|
||||||
|
// TODO: also, what about MAC OS X?
|
||||||
|
Sys_Printf(qtv->cluster, "Windows support coming soon!\n");
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent* ent;
|
||||||
|
|
||||||
|
dir = opendir(fullname);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
char demoname[512];
|
||||||
|
int current_demo = 0;
|
||||||
|
int file_count = 0;
|
||||||
|
int random_number;
|
||||||
|
|
||||||
|
// count the files, important for determining a random demo file
|
||||||
|
while ((ent = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
if (ent->d_type == DT_REG && *(ent->d_name) != '.')
|
||||||
|
file_count++; // only add non-hidden and regular files
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_count == 0)
|
||||||
|
{
|
||||||
|
// empty directory
|
||||||
|
Sys_Printf(qtv->cluster, "Stream %i: Error: Directory is empty.\n", qtv->streamid);
|
||||||
|
closedir(dir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
dir = opendir(fullname);
|
||||||
|
|
||||||
|
// FIXME: not sure if srand should only be called once somewhere?
|
||||||
|
// FIXME: this is not really shuffling the demos, but does introduce some variety
|
||||||
|
srand(time(NULL));
|
||||||
|
while ((random_number = rand()%file_count + 1) == qtv->last_random_number);
|
||||||
|
qtv->last_random_number = random_number;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ent = readdir(dir);
|
||||||
|
if (!ent)
|
||||||
|
{
|
||||||
|
// reached the end of the directory, shouldn't happen
|
||||||
|
Sys_Printf(qtv->cluster, "Stream %i: Error: Reached end of directory (%s%s)\n", qtv->streamid, qtv->cluster->demodir, ip);
|
||||||
|
closedir(dir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent->d_type != DT_REG || *(ent->d_name) == '.')
|
||||||
|
{
|
||||||
|
continue; // ignore hidden and non-regular files
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++current_demo != random_number)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(demoname, sizeof(demoname), "%s/%s", ip, ent->d_name);
|
||||||
|
qtv->sourcefile = demoname;
|
||||||
|
closedir(dir);
|
||||||
|
if (Net_ConnectToDemoServer(qtv, ent->d_name, ip) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Sys_Printf(qtv->cluster, "Stream %i: Unable to open directory %s\n", qtv->streamid, qtv->cluster->demodir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*figures out the ip to connect to, and decides the protocol for it*/
|
/*figures out the ip to connect to, and decides the protocol for it*/
|
||||||
char *Net_DiagnoseProtocol(sv_t *qtv)
|
char *Net_DiagnoseProtocol(sv_t *qtv)
|
||||||
{
|
{
|
||||||
|
@ -646,11 +800,16 @@ char *Net_DiagnoseProtocol(sv_t *qtv)
|
||||||
type = SRC_DEMO;
|
type = SRC_DEMO;
|
||||||
ip += 5;
|
ip += 5;
|
||||||
}
|
}
|
||||||
|
else if (!strncmp(ip, "dir:", 4))
|
||||||
|
{
|
||||||
|
type = SRC_DEMODIR;
|
||||||
|
ip += 4;
|
||||||
|
}
|
||||||
|
|
||||||
at = strchrrev(ip, '@');
|
at = strchrrev(ip, '@');
|
||||||
if (at && (type == SRC_DEMO || type == SRC_TCP))
|
if (at && (type == SRC_DEMO || type == SRC_DEMODIR || type == SRC_TCP))
|
||||||
{
|
{
|
||||||
if (type == SRC_DEMO)
|
if (type == SRC_DEMO || type == SRC_DEMODIR)
|
||||||
type = SRC_TCP;
|
type = SRC_TCP;
|
||||||
ip = at+1;
|
ip = at+1;
|
||||||
}
|
}
|
||||||
|
@ -666,50 +825,21 @@ qboolean Net_ConnectToServer(sv_t *qtv)
|
||||||
qtv->usequakeworldprotocols = false;
|
qtv->usequakeworldprotocols = false;
|
||||||
qtv->pext = 0;
|
qtv->pext = 0;
|
||||||
|
|
||||||
if (qtv->sourcetype == SRC_DEMO)
|
if (qtv->sourcetype == SRC_DEMO || qtv->sourcetype == SRC_DEMODIR)
|
||||||
|
{
|
||||||
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME_DEMO; //wait half a minuite before trying to reconnect
|
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME_DEMO; //wait half a minuite before trying to reconnect
|
||||||
|
}
|
||||||
else
|
else
|
||||||
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
|
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
|
||||||
|
|
||||||
switch( qtv->sourcetype)
|
switch( qtv->sourcetype)
|
||||||
{
|
{
|
||||||
case SRC_DEMO:
|
case SRC_DEMO:
|
||||||
qtv->sourcesock = INVALID_SOCKET;
|
return Net_ConnectToDemoServer(qtv, ip, NULL);
|
||||||
if (DemoFilenameIsOkay(ip))
|
|
||||||
{
|
|
||||||
char fullname[512];
|
|
||||||
snprintf(fullname, sizeof(fullname), "%s%s", qtv->cluster->demodir, ip);
|
|
||||||
qtv->sourcefile = fopen(fullname, "rb");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
qtv->sourcefile = NULL;
|
|
||||||
if (qtv->sourcefile)
|
|
||||||
{
|
|
||||||
char smallbuffer[17];
|
|
||||||
fseek(qtv->sourcefile, 0, SEEK_END);
|
|
||||||
qtv->filelength = ftell(qtv->sourcefile);
|
|
||||||
|
|
||||||
//attempt to detect the end of the file
|
|
||||||
fseek(qtv->sourcefile, 0-sizeof(smallbuffer), SEEK_CUR);
|
|
||||||
fread(smallbuffer, 1, 17, qtv->sourcefile);
|
|
||||||
//0 is the time
|
|
||||||
if (smallbuffer[1] == dem_all || smallbuffer[1] == dem_read) //mvdsv changed it to read...
|
|
||||||
{
|
|
||||||
//2,3,4,5 are the length
|
|
||||||
if (smallbuffer[6] == svc_disconnect)
|
|
||||||
{
|
|
||||||
if (!strcmp(smallbuffer+7, "EndOfDemo"))
|
|
||||||
{
|
|
||||||
qtv->filelength -= 17;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(qtv->sourcefile, 0, SEEK_SET);
|
case SRC_DEMODIR:
|
||||||
return true;
|
return Net_ConnectToDemoDirServer(qtv, ip);
|
||||||
}
|
|
||||||
Sys_Printf(qtv->cluster, "Stream %i: Unable to open file %s\n", qtv->streamid, ip);
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
case SRC_UDP:
|
case SRC_UDP:
|
||||||
|
@ -1885,7 +2015,7 @@ void QTV_Run(sv_t *qtv)
|
||||||
if (qtv->errored == ERR_DISABLED)
|
if (qtv->errored == ERR_DISABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (qtv->curtime >= qtv->nextconnectattempt || qtv->curtime < qtv->nextconnectattempt - RECONNECT_TIME*2)
|
if (qtv->sourcetype == SRC_DEMODIR || qtv->curtime >= qtv->nextconnectattempt || qtv->curtime < qtv->nextconnectattempt - RECONNECT_TIME*2)
|
||||||
{
|
{
|
||||||
if (qtv->autodisconnect == AD_REVERSECONNECT) //2 means a reverse connection
|
if (qtv->autodisconnect == AD_REVERSECONNECT) //2 means a reverse connection
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue