Add a maptimes log, to display best times (and whether a map has actually been completed).

update the qi plugin a little, and for maptimes.
Try to fix a bug with android.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5480 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-06-21 03:59:46 +00:00
parent 5fabdcd186
commit 9c7ba654b5
19 changed files with 349 additions and 76 deletions

View File

@ -1069,7 +1069,7 @@ void PM_EnumeratePlugins(void (*callback)(const char *name))
{
if (d->dtype == DEP_FILE)
{
if (!Q_strncasecmp(d->name, "fteplug_", 8))
if (!Q_strncasecmp(d->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
callback(d->name);
}
}
@ -1094,8 +1094,8 @@ static int QDECL PM_EnumeratedPlugin (const char *name, qofs_t size, time_t mtim
char vmname[MAX_QPATH];
int len, l, a;
char *dot;
if (!strncmp(name, "fteplug_", 8))
Q_strncpyz(vmname, name+8, sizeof(vmname));
if (!strncmp(name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
Q_strncpyz(vmname, name+strlen(PLUGINPREFIX), sizeof(vmname));
else
Q_strncpyz(vmname, name, sizeof(vmname));
len = strlen(vmname);
@ -1192,7 +1192,7 @@ static void PM_PreparePackageList(void)
char nat[MAX_OSPATH];
FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat));
Con_DPrintf("Loading plugins from \"%s\"\n", nat);
Sys_EnumerateFiles(nat, "fteplug_*" ARCH_DL_POSTFIX, PM_EnumeratedPlugin, &foundone, NULL);
Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_DL_POSTFIX, PM_EnumeratedPlugin, &foundone, NULL);
if (foundone && !pluginpromptshown)
{
pluginpromptshown = true;
@ -2076,7 +2076,7 @@ static void PM_PackageEnabled(package_t *p)
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3"))
FS_ReloadPackFiles();
#ifdef PLUGINS
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, "fteplug_", 8))
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
Cmd_ExecuteString(va("plug_load %s\n", dep->name), RESTRICT_LOCAL);
#endif
#ifdef MENU_DAT
@ -2173,7 +2173,7 @@ static void PM_Download_Got(struct dl_download *dl)
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3"))
FS_UnloadPackFiles(); //we reload them after
#ifdef PLUGINS
if ((!stricmp(ext, "dll") || !stricmp(ext, "so")) && !Q_strncmp(dep->name, "fteplug_", 8))
if ((!stricmp(ext, "dll") || !stricmp(ext, "so")) && !Q_strncmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
Cmd_ExecuteString(va("plug_close %s\n", dep->name), RESTRICT_LOCAL); //try to purge plugins so there's no files left open
#endif
@ -2509,7 +2509,7 @@ void PM_ApplyChanges(void)
reloadpacks = true;
#ifdef PLUGINS //when disabling/purging plugins, be sure to unload them first (unfortunately there might be some latency before this can actually happen).
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, "fteplug_", 8))
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
Cmd_ExecuteString(va("plug_close %s\n", dep->name), RESTRICT_LOCAL); //try to purge plugins so there's no files left open
#endif

View File

@ -1173,7 +1173,7 @@ static jboolean FTENativeActivity_startup(JNIEnv *jni, jobject this, jstring ext
static void FTENativeActivity_surfacechange(JNIEnv *env, jobject this, jboolean teardown, jboolean recreate, jobject surface)
{
if (this == sys_activity)
if (!(*env)->IsSameObject(env, this, sys_activity))
{
LOGI("FTENativeActivity_surfacechange: inactive %p, active %p\n", this, sys_activity);
return; //wasn't me...
@ -1200,7 +1200,7 @@ static void FTENativeActivity_surfacechange(JNIEnv *env, jobject this, jboolean
}
static void FTENativeActivity_shutdown(JNIEnv *env, jobject this)
{
if (this != sys_activity)
if (!(*env)->IsSameObject(env, this, sys_activity))
{
LOGI("FTENativeActivity_shutdown: inactive %p, active %p\n", this, sys_activity);
return; //wasn't me...

View File

@ -526,9 +526,10 @@ struct vfsfile_s;
//standard return value is 0 on failure, or depth on success.
int FS_FLocateFile(const char *filename, unsigned int flags, flocation_t *loc);
struct vfsfile_s *FS_OpenReadLocation(flocation_t *location);
char *FS_WhichPackForLocation(flocation_t *loc, qboolean makereferenced);
const char *FS_WhichPackForLocation(flocation_t *loc, qboolean makereferenced);
qboolean FS_GetLocMTime(flocation_t *location, time_t *modtime);
char *FS_GetPackageDownloadFilename(flocation_t *loc);
const char *FS_GetPackageDownloadFilename(flocation_t *loc); //returns only packages (or null)
const char *FS_GetRootPackagePath(flocation_t *loc); //favours packages, but falls back on gamedirs.
qboolean FS_GetPackageDownloadable(const char *package);
char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly);
@ -867,6 +868,11 @@ qboolean IPLog_Merge_File(const char *fname);
#endif
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize);
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
qboolean Log_CheckMapCompletion(const char *packagename, const char *mapname, float *besttime, float *fulltime, float *bestkills, float *bestsecrets);
void Log_MapNowCompleted(void);
#endif
/*used by and for botlib and q3 gamecode*/
#define MAX_TOKENLENGTH 1024

View File

@ -1387,10 +1387,38 @@ fail:
return depth+1;
}
//returns the location's root package (or gamedir).
//(aka: loc->search->purepath, but stripping contained nested packs)
const char *FS_GetRootPackagePath(flocation_t *loc)
{
searchpath_t *sp, *search;
for (sp = loc->search; ;)
{
for (search = com_searchpaths; search; search = search->next)
{
if (search != sp)
if (search->handle->GeneratePureCRC) //only consider files that have a pure hash. this excludes system paths
if (!strncmp(search->purepath, sp->purepath, strlen(search->purepath)))
if (sp->purepath[strlen(search->purepath)] == '/') //also ensures that the path gets shorter, avoiding infinite loops as it fights between base+home dirs.
break;
}
if (search)
sp = search;
else
break;
}
//
if (sp)
return sp->purepath;
return NULL;
}
//returns the package/'gamedir/foo.pk3' filename to tell the client to download
//unfortunately foo.pk3 may contain a 'bar.pk3' and downloading dir/foo.pk3/bar.pk3 won't work
//so if loc->search is dir/foo.pk3/bar.pk3 find dir/foo.pk3 instead
char *FS_GetPackageDownloadFilename(flocation_t *loc)
const char *FS_GetPackageDownloadFilename(flocation_t *loc)
{
searchpath_t *sp, *search;
@ -1414,7 +1442,7 @@ char *FS_GetPackageDownloadFilename(flocation_t *loc)
return sp->purepath;
return NULL;
}
char *FS_WhichPackForLocation(flocation_t *loc, qboolean makereferenced)
const char *FS_WhichPackForLocation(flocation_t *loc, qboolean makereferenced)
{
char *ret;
if (!loc->search)
@ -6199,6 +6227,12 @@ static void FS_ChangeMod_f(void)
arg = va("map \"%s\"\n", Cmd_Argv(i++));
fs_loadedcommand = Z_StrDup(arg);
}
else if (!strcmp(arg, "spmap"))
{
Z_Free(fs_loadedcommand);
arg = va("deathmatch 0;coop 0;spmap \"%s\"\n", Cmd_Argv(i++));
fs_loadedcommand = Z_StrDup(arg);
}
else if (!strcmp(arg, "restart"))
{
Z_Free(fs_loadedcommand);

View File

@ -795,8 +795,164 @@ qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize)
}
#endif
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
static struct maplog_entry
{
struct maplog_entry *next;
float bestkills;
float bestsecrets;
float besttime; //updated when besttime<newtime (note: doesn't respond to user changelevels from the console...)
float fulltime; //updated when bestkills>=newkills
char name[1];
} *maplog_enties;
static void Log_MapsRead(void)
{
struct maplog_entry *m, **link = &maplog_enties;
vfsfile_t *f;
static qboolean maplog_loaded;
char line[8192], *s;
if (maplog_loaded)
return;
maplog_loaded = true;
f = FS_OpenVFS("maptimes.txt", "rb", FS_ROOT);
if (!f)
return; //no info yet.
while (VFS_GETS(f, line, sizeof(line)))
{
s = line;
s = COM_Parse(s);
m = Z_Malloc(sizeof(*m) + strlen(com_token));
strcpy(m->name, com_token);
s = COM_Parse(s);
m->besttime = atof(com_token);
s = COM_Parse(s);
m->fulltime = atof(com_token);
s = COM_Parse(s);
m->bestkills = atof(com_token);
s = COM_Parse(s);
m->bestsecrets = atof(com_token);
*link = m;
link = &m->next;
}
VFS_CLOSE(f);
}
struct maplog_entry *Log_FindMap(const char *purepackage, const char *mapname)
{
const char *name = va("%s/%s", purepackage, mapname);
struct maplog_entry *m;
Log_MapsRead();
for (m = maplog_enties; m; m = m->next)
{
if (!strcmp(m->name, name))
break;
}
return m;
}
static void Log_MapsDump(void)
{
if (maplog_enties)
{
struct maplog_entry *m;
vfsfile_t *f = FS_OpenVFS("maptimes.txt", "wbp", FS_ROOT);
if (f)
{
for(m = maplog_enties; m; m = m->next)
{
VFS_PRINTF(f, "\"%s\" %.9g %.9g %.9g %.9g\n", m->name, m->besttime, m->fulltime, m->bestkills, m->bestsecrets);
}
VFS_CLOSE(f);
}
}
}
qboolean Log_CheckMapCompletion(const char *packagename, const char *mapname, float *besttime, float *fulltime, float *bestkills, float *bestsecrets)
{
struct maplog_entry *m;
if (!packagename)
{
flocation_t loc;
if (!FS_FLocateFile(mapname, FSLF_DONTREFERENCE|FSLF_IGNORELINKS, &loc))
return false; //no idea which package, don't guess.
packagename = FS_GetRootPackagePath(&loc);
if (!packagename)
return false;
}
m = Log_FindMap(packagename, mapname);
if (m)
{
*besttime = m->besttime;
*fulltime = m->fulltime;
*bestkills = m->bestkills;
*bestsecrets = m->bestsecrets;
return true;
}
return false;
}
void Log_MapNowCompleted(void)
{
struct maplog_entry *m;
flocation_t loc;
float kills, secrets, oldprogress, newprogress, maptime;
const char *packagename;
//don't log it if its deathmatch/coop/cheating.
extern int sv_allow_cheats;
if (deathmatch.ival || coop.ival || sv_allow_cheats == 1)
return;
if (!FS_FLocateFile(sv.world.worldmodel->name, FSLF_DONTREFERENCE|FSLF_IGNORELINKS, &loc))
{
Con_Printf("completion log: unable to determine logical path for map\n");
return; //don't know
}
packagename = FS_GetRootPackagePath(&loc);
if (!packagename)
{
Con_Printf("completion log: unable to determine logical path for map\n");
return;
}
m = Log_FindMap(packagename, sv.world.worldmodel->name);
if (!m)
{
m = Z_Malloc(sizeof(*m)+strlen(packagename)+strlen(sv.world.worldmodel->name)+2);
sprintf(m->name, "%s/%s", packagename, sv.world.worldmodel->name);
m->fulltime = m->besttime = INFINITY;
m->bestkills = m->bestsecrets = 0;
m->next = maplog_enties;
maplog_enties = m;
}
kills = pr_global_struct->killed_monsters;
secrets = pr_global_struct->found_secrets;
maptime = sv.world.physicstime;
newprogress = secrets*10+kills;
oldprogress = m->bestsecrets*10+m->bestkills;
//if they got a new time record, update.
if (maptime<m->besttime)
m->besttime = maptime;
//if they got a new kills record, update
if (newprogress > oldprogress || (newprogress==oldprogress && maptime<m->fulltime))
{
m->bestkills = kills;
m->bestsecrets = secrets;
m->fulltime = maptime;
}
}
#endif
void Log_ShutDown(void)
{
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
Log_MapsDump();
#endif
#ifdef IPLOG
if (iplog_autodump.ival)
IPLog_Dump("iplog.txt");

View File

@ -252,8 +252,8 @@ static char *Plug_CleanName(const char *file, char *out, size_t sizeof_out)
//"fteplug_ezhud_x86.REV.dll" gets converted into "ezhud"
//skip fteplug_
if (!Q_strncasecmp(file, "fteplug_", 8))
file += 8;
if (!Q_strncasecmp(file, PLUGINPREFIX, strlen(PLUGINPREFIX)))
file += strlen(PLUGINPREFIX);
//strip .REV.dll
COM_StripAllExtensions(file, out, sizeof_out);
@ -283,19 +283,21 @@ static plugin_t *Plug_Load(const char *file, int type)
newplug->name = (char*)(newplug+1);
strcpy(newplug->name, temp);
if (!newplug->vm && (type & PLUG_NATIVE) && !Q_strncasecmp(file, "fteplug_", 8) && !Q_strcasecmp(ARCH_DL_POSTFIX+1, COM_FileExtension(file, temp, sizeof(temp))))
if (!newplug->vm && (type & PLUG_NATIVE) && !Q_strncasecmp(file, PLUGINPREFIX, strlen(PLUGINPREFIX)) && !Q_strcasecmp(ARCH_DL_POSTFIX+1, COM_FileExtension(file, temp, sizeof(temp))))
{
COM_StripExtension(file, temp, sizeof(temp));
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
#ifndef ANDROID
if (!newplug->vm && (type & PLUG_NATIVE))
{
Q_snprintfz(temp, sizeof(temp), "fteplug_%s_", file);
Q_snprintfz(temp, sizeof(temp), PLUGINPREFIX"%s_", file);
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
#endif
if (!newplug->vm && (type & PLUG_NATIVE))
{
Q_snprintfz(temp, sizeof(temp), "fteplug_%s", file);
Q_snprintfz(temp, sizeof(temp), PLUGINPREFIX"%s", file);
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
if (!newplug->vm && (type & PLUG_QVM))
@ -355,7 +357,7 @@ static int QDECL Plug_EnumeratedRoot (const char *name, qofs_t size, time_t mtim
char vmname[MAX_QPATH];
int len;
char *dot;
if (!strncmp(name, "fteplug_", 8))
if (!strncmp(name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
name += 8;
Q_strncpyz(vmname, name, sizeof(vmname));
len = strlen(vmname);
@ -1530,6 +1532,28 @@ static qintptr_t VARGS Plug_UpdateInputBuffer(void *offset, quintptr_t mask, con
return bufferlen;
}
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
qboolean FS_PathURLCache(const char *url, char *path, size_t pathsize);
static qintptr_t VARGS Plug_MapLog_Query(void *offset, quintptr_t mask, const qintptr_t *arg)
{
const char *packagename = VM_POINTER(arg[0]);
const char *mapname = VM_POINTER(arg[1]);
float *vals = VM_POINTER(arg[2]);
if (VM_OOB(arg[2], sizeof(*vals)*4))
return false;
if (!strncmp(packagename, "http://", 7) || !strncmp(packagename, "https://", 8))
{
char temp[MAX_OSPATH];
if (!FS_PathURLCache(packagename, temp, sizeof(temp)))
return false;
if (Log_CheckMapCompletion(temp, mapname, &vals[0], &vals[1], &vals[2], &vals[3]))
return true;
return false;
}
return Log_CheckMapCompletion(packagename, mapname, &vals[0], &vals[1], &vals[2], &vals[3]);
}
#endif
#ifdef USERBE
#include "pr_common.h"
//functions useful for rigid body engines.
@ -1567,7 +1591,7 @@ static void Plug_Load_f(void)
Con_Printf("Loads a plugin\n");
Con_Printf("plug_load [pluginpath]\n");
Con_Printf("example pluginpath: blah\n");
Con_Printf("will load fteplug_blah"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX" or $gamedir/plugins/blah.qvm\n");
Con_Printf("will load "PLUGINPREFIX"blah"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX" or $gamedir/plugins/blah.qvm\n");
return;
}
if (!Plug_Load(plugin, PLUG_EITHER))
@ -1695,6 +1719,10 @@ void Plug_Initialise(qboolean fromgamedir)
#endif
Plug_RegisterBuiltin("PR_GetVMInstance", Plug_PR_GetVMInstance, PLUG_BIF_DLLONLY);
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
Plug_RegisterBuiltin("MapLog_Query", Plug_MapLog_Query, 0);
#endif
Plug_Client_Init();
}
@ -1707,7 +1735,7 @@ void Plug_Initialise(qboolean fromgamedir)
{
FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat));
Con_DPrintf("Loading plugins from \"%s\"\n", nat);
Sys_EnumerateFiles(nat, "fteplug_*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL);
Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL);
}
if (fromgamedir)
{
@ -2201,7 +2229,7 @@ int QDECL Plug_List_Print(const char *fname, qofs_t fsize, time_t modtime, void
if (!Q_strncasecmp(existing, parm, strlen(parm)) && !Q_strcasecmp(existing+strlen(parm), fname))
return true;
}
Con_Printf("^[%s%s\\type\\plug_load %s\\^]: not loaded\n", (const char*)parm, fname, plugname+((!Q_strncasecmp(plugname,"fteplug_", 8))?8:0));
Con_Printf("^[%s%s\\type\\plug_load %s\\^]: not loaded\n", (const char*)parm, fname, plugname+((!Q_strncasecmp(plugname,PLUGINPREFIX, strlen(PLUGINPREFIX)))?strlen(PLUGINPREFIX):0));
}
}
return true;
@ -2223,14 +2251,14 @@ void Plug_List_f(void)
{
while ((mssuck=strchr(binarypath, '\\')))
*mssuck = '/';
Sys_EnumerateFiles(binarypath, "fteplug_*" ARCH_DL_POSTFIX, Plug_List_Print, binarypath, NULL);
Sys_EnumerateFiles(binarypath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, binarypath, NULL);
}
if (FS_NativePath("", FS_ROOT, rootpath, sizeof(rootpath)))
{
while ((mssuck=strchr(rootpath, '\\')))
*mssuck = '/';
if (strcmp(binarypath, rootpath))
Sys_EnumerateFiles(rootpath, "fteplug_*" ARCH_DL_POSTFIX, Plug_List_Print, rootpath, NULL);
Sys_EnumerateFiles(rootpath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, rootpath, NULL);
}
for (u = 0; staticplugins[u].name; u++)

View File

@ -106,7 +106,10 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
if (binroot)
{
Con_DPrintf("Attempting to load native library: %s\n", name);
#ifdef ANDROID
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
#else
if (!hVM && FS_NativePath(dllname_archpri, FS_BINARYPATH, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname)))
@ -116,27 +119,32 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain
hVM = Sys_LoadLibrary(fname, funcs);
if (!hVM && FS_NativePath(dllname_anycpu, FS_ROOT, fname, sizeof(fname)))
hVM = Sys_LoadLibrary(fname, funcs);
#endif
// run through the search paths
iterator = NULL;
while (!hVM && COM_IteratePaths(&iterator, NULL, 0, gpath, sizeof(gpath)))
{
#ifndef ANDROID
if (!hVM && FS_NativePath(va("%s_%s_"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name, gpath), FS_BINARYPATH, fname, sizeof(fname)))
{
Con_DLPrintf(2, "Loading native: %s\n", fname);
hVM = Sys_LoadLibrary(fname, funcs);
}
#endif
if (!hVM && FS_NativePath(va("%s_%s"ARCH_DL_POSTFIX, name, gpath), FS_BINARYPATH, fname, sizeof(fname)))
{
Con_DLPrintf(2, "Loading native: %s\n", fname);
hVM = Sys_LoadLibrary(fname, funcs);
}
#ifndef ANDROID
if (!hVM && FS_NativePath(va("%s_%s_"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name, gpath), FS_ROOT, fname, sizeof(fname)))
{
Con_DLPrintf(2, "Loading native: %s\n", fname);
hVM = Sys_LoadLibrary(fname, funcs);
}
#endif
if (!hVM && FS_NativePath(va("%s_%s"ARCH_DL_POSTFIX, name, gpath), FS_ROOT, fname, sizeof(fname)))
{
Con_DLPrintf(2, "Loading native: %s\n", fname);

View File

@ -49,6 +49,12 @@ void Plug_SBar(playerview_t *pv);
qboolean Plug_ServerMessage(char *buffer, int messagelevel);
void Plug_Tick(void);
qboolean Plugin_ExecuteString(void);
#ifdef ANDROID
#define PLUGINPREFIX "libplug_" //android is kinda annoying and only extracts specific files.
#else
#define PLUGINPREFIX "fteplug_" //this string defines what consitutes a plugin, as opposed to some other dll
#endif
#endif

View File

@ -104,8 +104,6 @@ public class FTENativeActivity extends android.app.Activity implements android.v
// }
super.onCreate(savedInstanceState);
//Needed because the InputQueue stuff blocks dispatchKeyEvent
getWindow().takeInputQueue(null);
}
//random helpers
@ -134,7 +132,7 @@ public class FTENativeActivity extends android.app.Activity implements android.v
{
try
{
String secondary = (String) android.content.pm.ApplicationInfo.class.getField("nativeLibraryRootDir").get(context.getApplicationInfo());
String secondary = (String) android.content.pm.ApplicationInfo.class.getField("nativeLibraryDir").get(context.getApplicationInfo());
return secondary;
}
catch (Exception e)

View File

@ -7866,42 +7866,34 @@ void R_RemapShader(const char *sourcename, const char *destname, float timeoffse
{
shader_t *o;
shader_t *n;
int i;
//make sure all types of the shader are remapped properly.
//if there's a .shader file with it then it should 'just work'.
char cleansrcname[MAX_QPATH];
Q_strncpyz(cleansrcname, sourcename, sizeof(cleansrcname));
COM_CleanUpPath(cleansrcname);
o = R_LoadShader (sourcename, SUF_NONE, NULL, NULL);
n = R_LoadShader (destname, SUF_NONE, NULL, NULL);
if (o)
for (i = 0; i < r_numshaders; i++)
{
if (!n)
n = o;
o->remapto = n;
o->remaptime = timeoffset; //this just feels wrong.
}
o = R_LoadShader (sourcename, SUF_2D, NULL, NULL);
n = R_LoadShader (destname, SUF_2D, NULL, NULL);
if (o)
{
if (!n)
n = o;
o->remapto = n;
o->remaptime = timeoffset;
}
o = R_LoadShader (sourcename, SUF_LIGHTMAP, NULL, NULL);
n = R_LoadShader (destname, SUF_LIGHTMAP, NULL, NULL);
if (o)
{
if (!n)
o = r_shaders[i];
if (o && o->uses)
{
n = R_LoadShader (destname, SUF_2D, NULL, NULL);
if (!n)
n = o;
if (!strcmp(o->name, cleansrcname))
{
n = R_LoadShader (destname, o->usageflags, NULL, NULL);
if (!n)
{ //if it isn't actually available on disk then don't care about usageflags, just find ANY that's already loaded.
// check the hash first
char cleandstname[MAX_QPATH];
Q_strncpyz(cleandstname, destname, sizeof(cleandstname));
COM_CleanUpPath(cleandstname);
n = Hash_Get(&shader_active_hash, cleandstname);
if (!n || !n->uses)
n = o;
}
o->remapto = n;
o->remaptime = timeoffset; //this just feels wrong.
}
}
o->remapto = n;
o->remaptime = timeoffset;
}
}

View File

@ -66,7 +66,6 @@ SOCKET FTP_BeginListening(int aftype, int port)
{
struct sockaddr_qstorage address;
unsigned long _true = true;
unsigned long _false = false;
int i;
SOCKET sock;
@ -116,6 +115,7 @@ SOCKET FTP_BeginListening(int aftype, int port)
//2=ipv6 only
if (aftype == 0)
{
unsigned long _false = false;
if (0 > setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&_false, sizeof(_false)))
{
//abort and do ipv4 only if hybrid sockets don't work.

View File

@ -728,6 +728,10 @@ void NPP_NQFlush(void)
}
#endif
#if defined(HAVE_CLIENT)
Log_MapNowCompleted();
#endif
for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++)
{
if (cl->state == cs_spawned && ISQWCLIENT(cl))
@ -1758,6 +1762,9 @@ void NPP_QWFlush(void)
break;
//ignore these.
case svc_intermission:
#if defined(HAVE_CLIENT)
Log_MapNowCompleted();
#endif
// if (writedest == &sv.reliable_datagram)
{
client_t *cl;

View File

@ -5925,6 +5925,10 @@ void QCBUILTIN PF_changelevel (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
return;
sv.mapchangelocked = true;
#ifdef HAVE_CLIENT
Log_MapNowCompleted();
#endif
#ifdef HEXEN2
if (progstype == PROG_H2)
{

View File

@ -392,8 +392,24 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
};
size_t u;
char stripped[64];
char completed[256];
if (name[5] == 'b' && name[6] == '_') //skip box models
return true;
*completed = 0;
#ifdef HAVE_CLIENT
{
float besttime, fulltime, kills, secrets;
if (Log_CheckMapCompletion(NULL, name, &besttime, &fulltime, &kills, &secrets))
{
if (kills || secrets)
Q_snprintfz(completed, sizeof(completed), "^7 - ^2best: ^1%.1f^2, full: ^1%.1f^2 (^1%.0f^2 kills, ^1%.0f^2 secrets)", besttime, fulltime, kills, secrets);
else
Q_snprintfz(completed, sizeof(completed), "^7 - ^2best: ^1%.1f^2", besttime);
}
}
#endif
COM_StripExtension(name+5, stripped, sizeof(stripped));
for (u = 0; u < countof(levelshots); u++)
{
@ -401,11 +417,11 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
if (COM_FCheckExists(ls))
{
Con_Printf("^[\\map\\%s\\img\\%s\\w\\64\\h\\48^]", stripped, ls);
Con_Printf("^[[%s]\\map\\%s\\tipimg\\%s^]\n", stripped, stripped, ls);
Con_Printf("^[[%s]%s\\map\\%s\\tipimg\\%s^]\n", stripped, completed, stripped, ls);
return true;
}
}
Con_Printf("^[[%s]\\map\\%s^]\n", stripped, stripped);
Con_Printf("^[[%s]%s\\map\\%s^]\n", stripped, completed, stripped);
return true;
}
static int QDECL ShowMapListExt (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)

View File

@ -3220,7 +3220,7 @@ static int SV_LocateDownload(const char *name, flocation_t *loc, char **replacem
if (replacementname)
{
#if 1
char *pakname = FS_GetPackageDownloadFilename(loc);
const char *pakname = FS_GetPackageDownloadFilename(loc);
if (pakname && strchr(pakname, '/'))
{
extern cvar_t allow_download_packages,allow_download_copyrighted; //non authoritive, but should normally match.

View File

@ -68,7 +68,7 @@ ifeq ($(PLUG_NATIVE_EXT),)
endif
ifeq ($(FTE_TARGET),droid)
#plugins get written to the tmp build dir, to avoid conflicts
PLUG_PREFIX=$(OUT_DIR)/m_droid-$(DROID_ARCH)/fteplug_
PLUG_PREFIX=$(OUT_DIR)/m_droid-$(DROID_ARCH)/libplug_
#don't bother with cpu arch postfixes. they'll be in separate directories anyway.
PLUG_NATIVE_EXT=.so
#libresolv has no public api on android...

View File

@ -170,6 +170,10 @@ BUILTINR(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
BUILTINR(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
#undef ARGNAMES
#define ARGNAMES ,packagename,mapname,stats
BUILTINR(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats));
#undef ARGNAMES
#ifndef Q3_VM
#define ARGNAMES ,vmid
BUILTINR(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/));
@ -526,6 +530,8 @@ static void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Con_GetConsoleString);
CHECKBUILTIN(Con_SetConsoleString);
CHECKBUILTIN(Con_POpen);
CHECKBUILTIN(MapLog_Query);
}
#ifndef Q3_VM

View File

@ -261,6 +261,8 @@ EBUILTIN(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
#endif
EBUILTIN(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
EBUILTIN(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats));
#ifndef Q3_VM
struct pubprogfuncs_s;
EBUILTIN(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/));

View File

@ -25,10 +25,10 @@
</file>
*/
xmltree_t *thedatabase;
qhandle_t dlcontext = -1;
static xmltree_t *thedatabase;
static qhandle_t dlcontext = -1;
struct
static struct
{
char namefilter[256];
int minrating;
@ -215,6 +215,7 @@ static void QI_RefreshMapList(qboolean forcedisplay)
xmltree_t *file;
const char *console = WINDOWNAME;
char descbuf[1024];
float donestats[4];
if (!QI_SetupWindow(console, forcedisplay))
return;
@ -257,16 +258,19 @@ static void QI_RefreshMapList(qboolean forcedisplay)
switch(atoi(type))
{
case 1:
type = "map";
type = "map"; //'single map file(s)'
break;
case 2:
type = "mod";
type = "mod"; //'Partial conversion'
break;
case 4:
type = "spd"; //'speedmapping'
break;
case 5:
type = "otr";
type = "otr"; //'misc files'
break;
default:
type = "???";
type = "???"; //no idea
break;
}
@ -320,20 +324,26 @@ static void QI_RefreshMapList(qboolean forcedisplay)
year += 2000;
else if (year < 1900)
year += 1900;
Q_snprintf(descbuf, sizeof(descbuf), "Id: %s\nAuthor: %s\nDate: %04u-%02u-%02u\nRating: %s\n\n", id, author, year, month, day, ratingtext);
Q_snprintf(descbuf, sizeof(descbuf), "^aId:^a %s\n^aAuthor(s):^a %s\n^aDate:^a %04u-%02u-%02u\n^aRating:^a %s\n\n", id, author, year, month, day, ratingtext);
QI_DeHTML(desc, descbuf + strlen(descbuf), sizeof(descbuf) - strlen(descbuf));
desc = descbuf;
Con_SubPrintf(console, "%s %s ^[^4%s: ^1%s\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s^]", type, ratingtext, id, XML_GetChildBody(file, "title", "<NO TITLE>"), desc, id, id);
for (startmapnum = 0; ; startmapnum++)
{
char bspfile[MAX_QPATH];
startmap = XML_ChildOfTree(tech, "startmap", startmapnum);
if (!startmap)
break;
Con_SubPrintf(console, "%s ^[%s (%s)\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]\n", type, XML_GetChildBody(file, "title", "<NO TITLE>"), startmap->body, desc, id, id, startmap->body);
Q_snprintf(bspfile, sizeof(bspfile), "maps/%s.bsp", startmap->body);
if (BUILTINISVALID(MapLog_Query) && pMapLog_Query(va(FILEDOWNLOADURL, id), bspfile, donestats))
Con_SubPrintf(console, " ^[^2[%s, complete %.1f]\\tip\\^7^aBest Time:^a ^2%.9f^7\n^aCompletion Time:^a %.9f\n^aKills:^a %.9f\n^aSecrets:^a %.9f\n\n\n%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]", startmap->body, donestats[0], donestats[0], donestats[1], donestats[2], donestats[3], desc, id, id, startmap->body);
else
Con_SubPrintf(console, " ^[^4[%s]\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]", startmap->body, desc, id, id, startmap->body);
}
if (!startmapnum)
Con_SubPrintf(console, "%s ^[%s\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s^]\n", type, XML_GetChildBody(file, "title", "<NO TITLE>"), desc, id, id);
Con_SubPrintf(console, "\n");
}
Con_SubPrintf(console, "\nFilter:\n");
@ -489,7 +499,7 @@ static void QI_RunMap(xmltree_t *qifile, const char *map)
map = "";
pCmd_AddText("fs_changemod map \"", false);
pCmd_AddText("fs_changemod spmap \"", false);
pCmd_AddText(map, false);
pCmd_AddText("\"", false);
QI_AddPackages(qifile);