Tweaks for the flatpak builds.

This commit is contained in:
Shpoike 2023-04-21 12:36:13 +01:00
parent 3adec5d0a5
commit 0509f7c83c
22 changed files with 1281 additions and 576 deletions

View File

@ -61,8 +61,30 @@ IF (EXISTS ${CMAKE_SOURCE_DIR}/.git)
OUTPUT_VARIABLE FTE_BRANCH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
MESSAGE(STATUS "FTE GIT ${FTE_BRANCH} Revision git-${FTE_REVISON_GIT}, ${FTE_DATE}")
SET(SVNREVISION git-${FTE_REVISON_GIT})
EXECUTE_PROCESS(COMMAND
git rev-parse --is-shallow-repository
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE FTE_GIT_IS_SHALLOW
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
IF(FTE_GIT_IS_SHALLOW STREQUAL true)
MESSAGE(STATUS "shallow clone prevents calculation of revision number.")
SET(SVNREVISION "git-${FTE_REVISON_GIT}") #if its a shallow clone then we can't count commits properly so don't know what revision we actually are.
ELSE()
EXECUTE_PROCESS(COMMAND
git rev-list HEAD --count
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE SVNREVISION
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
MATH(EXPR SVNREVISION "${SVNREVISION} + 29") #not all svn commits managed to appear im the git repo, so we have a small bias to keep things consistent.
IF (FTE_BRANCH STREQUAL "master")
SET(SVNREVISION "${SVNREVISION}-git-${FTE_REVISON_GIT}")
ELSE()
SET(SVNREVISION "${FTE_BRANCH}-${SVNREVISION}-git-${FTE_REVISON_GIT}") #weird branches get a different form of revision, to reduce confusion.
ENDIF()
ENDIF()
MESSAGE(STATUS "FTE GIT ${FTE_BRANCH} Revision ${SVNREVISION}, ${FTE_DATE}")
SET(FTE_REVISON SVNREVISION=${SVNREVISION} SVNDATE=${FTE_DATE} FTE_BRANCH=${FTE_BRANCH})
ENDIF()
@ -225,7 +247,7 @@ IF(CMAKE_BUILD_TYPE MATCHES "Debug")
ENDIF()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFTE_LIBRARY_PATH=${CMAKE_INSTALL_FULL_LIBDIR}/${FTE_INSTALL_LIBDIR}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFTE_LIBRARY_PATH=${CMAKE_INSTALL_FULL_LIBDIR}/${FTE_INSTALL_LIBDIR} -DFTE_DATA_DIR=${CMAKE_INSTALL_FULL_DATAROOTDIR}")
FUNCTION(EMBED_PLUGIN_META PLUGNAME PLUGTITLE PLUGDESC)
SET_TARGET_PROPERTIES(plug_${PLUGNAME} PROPERTIES OUTPUT_NAME "${PLUGNAME}")
@ -235,10 +257,10 @@ FUNCTION(EMBED_PLUGIN_META PLUGNAME PLUGTITLE PLUGDESC)
#sadly we need to use a temp zip file, because otherwise zip insists on using zip64 extensions which breaks zip -A (as well as any attempts to read any files).
ADD_CUSTOM_COMMAND(
TARGET plug_${PLUGNAME} POST_BUILD
COMMAND echo "{\\n package fteplug_${PLUGNAME}\\n ver \"${SVNREVISION}\"\\n category Plugins\\n title \"${PLUGTITLE}\"\\n gamedir \"\"\\n desc \"${PLUGDESC}\"\\n}" | zip -q -9 -fz- $<TARGET_FILE:plug_${PLUGNAME}>.zip -
COMMAND cat $<TARGET_FILE:plug_${PLUGNAME}>.zip >> "$<TARGET_FILE:plug_${PLUGNAME}>"
COMMAND /bin/echo -e "{\\n package fteplug_${PLUGNAME}\\n ver \"${SVNREVISION}\"\\n category Plugins\\n title \"${PLUGTITLE}\"\\n gamedir \"\"\\n desc \"${PLUGDESC}\"\\n}" | zip -q -9 -fz- $<TARGET_FILE:plug_${PLUGNAME}>.zip -
COMMAND cmake -E cat $<TARGET_FILE:plug_${PLUGNAME}>.zip >> "$<TARGET_FILE:plug_${PLUGNAME}>"
COMMAND zip -A "$<TARGET_FILE:plug_${PLUGNAME}>"
COMMAND rm $<TARGET_FILE:plug_${PLUGNAME}>.zip
COMMAND cmake -E rm $<TARGET_FILE:plug_${PLUGNAME}>.zip
VERBATIM)
ENDFUNCTION()
@ -1585,6 +1607,14 @@ IF(FTE_MENU_SYS)
quakec/menusys/menu/options_video.qc
quakec/menusys/menu/quit.qc
)
ADD_CUSTOM_COMMAND(
TARGET menusys POST_BUILD
COMMAND /bin/echo -e "{\\n package fte_menusys\\n ver \"${SVNREVISION}\"\\n category Plugins\\n title \"Replacement Menus\"\\n gamedir \"id1\"\\n desc \"Modern menus to replace the ancient quake ones\"\\n}" | zip -q -9 -fz- menusys.pk3 - menu.dat
VERBATIM)
INSTALL(FILES
menusys.pk3
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/games/quake/id1/")
ENDIF()
SET(FTE_CSADDON true CACHE BOOL "CS Addon.")
@ -1616,4 +1646,12 @@ IF(FTE_CSADDON)
quakec/csaddon/src/cam.qc
quakec/csaddon/src/csaddon.qc
)
ADD_CUSTOM_COMMAND(
TARGET csaddon POST_BUILD
COMMAND /bin/echo -e "{\\n package fte_csaddon\\n ver \"${SVNREVISION}\"\\n category Plugins\\n title \"${PLUGTITLE}\"\\n gamedir \"id1\"\\n desc \"${PLUGDESC}\"\\n}" | zip -q -9 -fz- csaddon.pk3 - csaddon.dat
VERBATIM)
INSTALL(FILES
csaddon.pk3
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/games/quake/id1/")
ENDIF()

View File

@ -7006,7 +7006,7 @@ void CL_ArgumentOverrides(void)
}
//note that this does NOT include commandline.
void CL_ExecInitialConfigs(char *resetcommand)
void CL_ExecInitialConfigs(char *resetcommand, qboolean fullvidrestart)
{
#ifndef QUAKETC
int qrc, hrc;
@ -7085,7 +7085,9 @@ 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)
if (fullvidrestart)
Cbuf_AddText ("vid_restart\n", RESTRICT_LOCAL);
else if (qrenderer != QR_NONE)
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
// if (Key_Dest_Has(kdm_menu))
// Cbuf_AddText ("closemenu\ntogglemenu\n", RESTRICT_LOCAL); //make sure the menu has the right content loaded.
@ -7175,7 +7177,7 @@ void Host_FinishLoading(void)
#endif
}
if (PM_IsApplying(true))
if (PM_IsApplying() == 1)
{
#ifdef MULTITHREAD
Sys_Sleep(0.1);

View File

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#include "shader.h"
#include "gl_draw.h"
#include "fs.h"
//name of the current backdrop for the loading screen
char levelshotname[MAX_QPATH];
@ -2462,7 +2463,7 @@ void SCR_SetUpToDrawConsole (void)
{
if (CL_TryingToConnect()) //if we're trying to connect, make sure there's a loading/connecting screen showing instead of forcing the menu visible
SCR_SetLoadingStage(LS_CONNECTION);
else if (!Key_Dest_Has(kdm_menu) && !startuppending) //don't force anything until the startup stuff has been done
else if (!Key_Dest_Has(kdm_menu) && !Key_Dest_Has(kdm_prompt) && !PM_IsApplying() && !startuppending) //don't force anything until the startup stuff has been done
M_ToggleMenu_f();
}
}

View File

@ -1149,7 +1149,7 @@ void CL_SetInfoBlob (int pnum, const char *key, const char *value, size_t values
char *CL_TryingToConnect(void);
void CL_ExecInitialConfigs(char *defaultexec);
void CL_ExecInitialConfigs(char *defaultexec, qboolean fullvidrestart);
extern int cl_framecount; //number of times the entity lists have been cleared+reset.
extern int cl_numvisedicts;

File diff suppressed because it is too large Load Diff

View File

@ -2426,6 +2426,16 @@ void M_Menu_Main_f (void)
*/
SCR_EndLoadingPlaque(); //just in case...
if (!FS_GameIsInitialised())
{ //if you canceled the mods menu, quit instead.
if (!Key_Dest_Has(kdm_prompt) && !Key_Dest_Has(kdm_menu))
{
M_Menu_Mods_f(); //bring back the mods menu... THERE'S NO ESCAPE!!! (no basedir, so options etc is ponitless)
M_Menu_Quit_f(); //and a quit prompt, cos they probably hit escape or something.
}
return;
}
/*
if (0)
{

View File

@ -599,6 +599,9 @@ typedef struct {
demoloc_t *fs;
int pathlen;
//for the basedir picker...
ftemanifest_t *man;
char *command[64]; //these let the menu be used for nearly any sort of file browser.
char *ext[64];
int numext;
@ -646,41 +649,48 @@ static void M_DemoDraw(int x, int y, menucustom_t *control, emenu_t *menu)
if (!item)
info->firstitem = info->items;
if (!info->dragscroll && (keydown[K_MOUSE1] || keydown[K_TOUCH]))
if (keydown[K_MOUSE1] || keydown[K_TOUCHSLIDE])
{
info->dragscroll = 1;
info->mousedownpos = mousecursor_y;
}
if (info->dragscroll && (keydown[K_MOUSE1] || keydown[K_TOUCH]))
{
if (info->mousedownpos >= mousecursor_y+8)
if (!info->dragscroll)
{
info->dragscroll = 2;
info->mousedownpos -= 8;
if (info->firstitem->next)
{
if (info->firstitem == info->selected)
info->selected = info->firstitem->next;
info->firstitem = info->firstitem->next;
}
info->dragscroll = 1;
info->mousedownpos = mousecursor_y-y;
}
if (info->mousedownpos+8 <= mousecursor_y)
if (info->dragscroll)
{
info->dragscroll = 2;
info->mousedownpos += 8;
if (info->firstitem->prev)
if (info->mousedownpos >= mousecursor_y-y+8)
{
if (ty <= 24)
info->selected = info->selected->prev;
info->firstitem = info->firstitem->prev;
info->dragscroll = 2;
info->mousedownpos -= 8;
if (info->firstitem->next)
{
if (info->firstitem == info->selected)
info->selected = info->firstitem->next;
info->firstitem = info->firstitem->next;
}
}
if (info->mousedownpos+8 <= mousecursor_y-y)
{
info->dragscroll = 2;
info->mousedownpos += 8;
if (info->firstitem->prev)
{
if (ty <= 24)
info->selected = info->selected->prev;
info->firstitem = info->firstitem->prev;
}
}
}
}
else
info->dragscroll = 0;
control->common.height = vid.height-y;
item = info->firstitem;
while(item)
{
if (y >= vid.height)
if (y >= y+control->common.height)
return;
if (!item->isdir)
text = va("%-32.32s%6iKB", item->name+info->pathlen, item->size/1024);
@ -739,13 +749,10 @@ static qboolean M_DemoKey(menucustom_t *control, emenu_t *menu, int key, unsigne
info->selected = info->selected->next;
}
break;
case K_TOUCHTAP:
case K_MOUSE1:
case K_MOUSE1: //this is on release
if (info->dragscroll == 2)
{
info->dragscroll = 0;
break;
}
case K_TOUCHTAP:
it = info->firstitem;
i = (mousecursor_y - control->common.posy) / 8;
while(i > 0 && it && it->next)
@ -767,7 +774,7 @@ static qboolean M_DemoKey(menucustom_t *control, emenu_t *menu, int key, unsigne
{
if (info->selected->isdir)
ShowDemoMenu(menu, info->selected->name);
else
else if (info->numext)
{
extern int shift_down;
int extnum;
@ -945,6 +952,34 @@ static void M_Demo_Remove (emenu_t *menu)
{
demomenu_t *info = menu->data;
M_Demo_Flush(info);
FS_Manifest_Free(info->man);
info->man = NULL;
}
static void FS_GameDirPrompted(void *ctx, promptbutton_t btn)
{
emenu_t *menu = ctx;
if (Menu_IsLinked(&menu->menu))
{
demomenu_t *info = menu->data;
ftemanifest_t *man = info->man;
if (!man || info->fs->fsroot != FS_SYSTEM)
return; //erk? no exploits!
switch(btn)
{
case PROMPT_CANCEL:
return;
case PROMPT_YES:
info->man = NULL;
Menu_Unlink(&menu->menu, true); //try to kill the dialog menu.
FS_ChangeGame(man, true, true); //switch to that new gamedir
break;
case PROMPT_NO:
return;
}
}
}
static void ShowDemoMenu (emenu_t *menu, const char *path)
@ -1042,6 +1077,15 @@ static void ShowDemoMenu (emenu_t *menu, const char *path)
// COM_EnumerateFiles(match, DemoAddItem, info);
}
M_Demo_Flatten(info);
if (info->man && FS_DirHasAPackage(info->fs->path, info->man))
{
if (promptmenu)
return //wut? don't confuse basedirs here...
Z_Free(info->man->basedir);
info->man->basedir = Z_StrDup(info->fs->path);
Menu_Prompt(FS_GameDirPrompted, &menu->menu, va("Use this directory?%s", info->fs->path), "Yes!", NULL, "No", true);
}
}
void M_Demo_Reselect(demomenu_t *info, const char *name)
{
@ -1206,4 +1250,55 @@ void M_Menu_MediaFiles_f (void)
M_Demo_Reselect(info, info->fs->selname);
}
#endif
#include <stdlib.h>
void M_Menu_BasedirPrompt(ftemanifest_t *man)
{
demomenu_t *info;
emenu_t *menu;
char *start = getenv("HOME");
size_t l;
Key_Dest_Remove(kdm_console);
menu = M_CreateMenu(sizeof(demomenu_t) + sizeof(demoloc_t));
menu->remove = M_Demo_Remove;
info = menu->data;
info->man = man;
info->fs = (demoloc_t*)(info+1);
info->fs->fsroot = FS_SYSTEM;
if (!start || !*start || (l = strlen(info->fs->path))>=sizeof(info->fs->path))
strcpy(info->fs->path, "/");
else
strcpy(info->fs->path, start);
//make sure it has a trailing slash.
l = strlen(info->fs->path);
#ifdef _WIN32
if (info->fs->path[l-1] == '\\')
info->fs->path[l-1] = '/';
#endif
if (info->fs->path[l-1] != '/')
{
info->fs->path[l] = '/';
info->fs->path[l+1] = 0;
}
info->numext = 0;
MC_AddWhiteText(menu, 24, 170, 8, va("Where is %s installed?", man->formalname), false);
MC_AddWhiteText(menu, 16, 170, 24, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f", false);
info->list = MC_AddCustom(menu, 0, 32, NULL, 0, NULL);
info->list->common.width = 320;
info->list->draw = M_DemoDraw;
info->list->key = M_DemoKey;
menu->selecteditem = (menuoption_t*)info->list;
ShowDemoMenu(menu, info->fs->path);
M_Demo_Reselect(info, info->fs->selname);
}
#endif

View File

@ -428,6 +428,8 @@ void M_Complex_Key(emenu_t *currentmenu, int key, int unicode);
void M_Script_Init(void);
void M_Serverlist_Init(void);
void M_Menu_BasedirPrompt(ftemanifest_t *man);
const char *M_ChooseAutoSave(void);
void M_Menu_Main_f (void);
void M_Menu_SinglePlayer_f (void);

View File

@ -1195,20 +1195,24 @@ static int Crypto_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *sig
}
static void DoSign(const char *fname, int signtype)
{
qbyte digest[1024];
qbyte digest[1024], digest2[1024];
qbyte signature[2048];
qbyte base64[2048*4];
int sigsize;
vfsfile_t *f;
const char *auth = "Unknown";
const char *prefix = "";
int i = COM_CheckParm("-certhost");
if (i)
auth = com_argv[i+1];
i = COM_CheckParm("-prefix");
if (i)
prefix = com_argv[i+1];
f = FS_OpenVFS(fname, "rb", FS_SYSTEM);
if (f && signtype == -1)
{ //just report the qhash
searchpathfuncs_t *search = FS_OpenPackByExtension(f, NULL, fname, fname);
searchpathfuncs_t *search = FS_OpenPackByExtension(f, NULL, fname, fname, prefix);
if (search)
{
printf("%#08x", search->GeneratePureCRC(search, 0, 0));
@ -1232,27 +1236,53 @@ static void DoSign(const char *fname, int signtype)
h->terminate(digest, ctx);
VFS_CLOSE(f);
if (signtype == 0)
//prefix it by the prefix
if (*prefix)
{
h->init(ctx);
h->process(ctx, prefix, strlen(prefix));
h->process(ctx, "\0", 1);
h->process(ctx, digest, h->digestsize);
h->terminate(digest2, ctx);
}
else
memcpy(digest2, digest, h->digestsize);
if (signtype == 3)
{ //the stupid package crap in fmf files which is different just to be an absolute pain
printf(" prefix \"%s\"", prefix);
printf(" filesize %zu", ts);
base64[Base16_EncodeBlock(digest, h->digestsize, base64+2048, sizeof(base64)-2048-1)] = 0;
printf(" sha512 \"%s\"", base64+2048);
sigsize = Crypto_GenerateSignature(digest2, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf(" signature \"%s:%s\"\n", auth, base64);
}
else if (signtype == 0)
{ //old junk
if (*prefix)
printf(" \\\"prefix=%s\\\"", prefix);
printf(" \\\"dlsize=%zu\\\"", ts);
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
base64[Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64)-1)] = 0;
printf(" \\\"sha512=%s\\\"", base64);
sigsize = Crypto_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
sigsize = Crypto_GenerateSignature(digest2, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
}
else if (signtype == 2)
{ //spits out the raw signature.
sigsize = Crypto_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
sigsize = Crypto_GenerateSignature(digest2, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf("%s", base64);
}
else
{ //just spits out the hash
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
base64[Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64))] = 0;
printf("%s", base64);
}
}
@ -1461,7 +1491,7 @@ int main (int c, const char **v)
nostdout = 1;
//begin meta generation helpers
//fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3
//fteqw -privkey privcert.key -pubkey pubcert.key -certhost Spike -prefix foo -sign binaryfile.pk3
{
static struct
{
@ -1471,6 +1501,8 @@ int main (int c, const char **v)
{
{"-sign", 0},
{"-sign2", 2},
{"-signraw", 2},
{"-signfmfpkg", 3},
{"-qhash", -1},
{"-sha1", 1},
{"-sha256", 256},

View File

@ -689,7 +689,7 @@ static const char *replacementq1binds =
"bind LSHIFT +speed\n"
"bind RSHIFT +speed\n"
"bind + sizeup\n"
"bind = sizeup\n"
"bind - sizedown\n"
"bind 1 impulse 1\n"

View File

@ -5548,8 +5548,8 @@ static void COM_Version_f (void)
#ifdef FTE_BRANCH
Con_Printf("Branch: "STRINGIFY(FTE_BRANCH)"\n");
#endif
#if defined(SVNREVISION) && defined(SVNDATE)
Con_Printf("Revision: %s - %s\n",STRINGIFY(SVNREVISION), STRINGIFY(SVNDATE));
#elif defined(SVNREVISION) && defined(SVNDATE)
if (!strncmp(STRINGIFY(SVNREVISION), "git-", 4))
Con_Printf("GIT Revision: %s - %s\n",STRINGIFY(SVNREVISION), STRINGIFY(SVNDATE));
else
@ -8511,10 +8511,15 @@ char *version_string(void)
#ifdef OFFICIAL_RELEASE
Q_snprintfz(s, sizeof(s), "%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
#elif defined(SVNREVISION) && defined(SVNDATE)
#ifdef FTE_BRANCH
//something like 'FTE master 6410M-HASH'
Q_snprintfz(s, sizeof(s), "%s %s %s", DISTRIBUTION, STRINGIFY(FTE_BRANCH), STRINGIFY(SVNREVISION));
#else
if (!strncmp(STRINGIFY(SVNREVISION), "git-", 4))
Q_snprintfz(s, sizeof(s), "%s %s", DISTRIBUTION, STRINGIFY(SVNREVISION)); //if both are defined then its a known unmodified svn revision.
else
Q_snprintfz(s, sizeof(s), "%s SVN %s", DISTRIBUTION, STRINGIFY(SVNREVISION)); //if both are defined then its a known unmodified svn revision.
#endif
#else
#if defined(SVNREVISION)
if (!strncmp(STRINGIFY(SVNREVISION), "git-", 4))
@ -8569,9 +8574,17 @@ int parse_revision_number(const char *s, qboolean strict)
}
else
{
//[lower-]upper[M]
//svn: [lower-]upper[M]
//git: revision-git-hash[-dirty]
//git: branch-revision-git-hash[-dirty]
rev = strtoul(s, &e, 10);
if (*e && strict)
if (!strncmp(e, "-git", 4))
{ //if there's a -dirty in there then its bad.
//we can't validate that the commit id matches the same branch as this build. we'll just have to live with it.
if (strict && strstr(s, "-dirty"))
return false;
}
else if (*e && strict)
return false; //something odd.
}
return rev;

View File

@ -739,7 +739,7 @@ typedef struct
{
MANIFEST_SECURITY_NOT, //don't trust it, don't even allow downloadsurl.
MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages+force sources
MANIFEST_SECURITY_INSTALLER //built-in fmf files can force packages+sources
MANIFEST_SECURITY_INSTALLER //built-in fmf files can 'force' packages+sources
} security; //manifest was embedded in the engine. don't assume its already installed, but ask to install it (also, enable some extra permissions for writing dlls)
enum
@ -763,6 +763,7 @@ typedef struct
#ifdef PACKAGEMANAGER
char *downloadsurl; //optional installable files (menu)
char *installupd; //which download/updated package to install.
qboolean installable; //(expected) available packages give a playable experience, even if just a basic/demo version.
#endif
char *protocolname; //the name used for purposes of dpmaster
char *defaultexec; //execed after cvars are reset, to give game-specific engine-defaults.
@ -814,6 +815,7 @@ qboolean PM_CanInstall(const char *packagename);
void COM_InitFilesystem (void); //does not set up any gamedirs.
qboolean FS_DownloadingPackage(void);
void FS_CreateBasedir(const char *path);
qboolean FS_DirHasAPackage(char *basedir, ftemanifest_t *man);
qboolean FS_ChangeGame(ftemanifest_t *newgame, qboolean allowreloadconfigs, qboolean allowbasedirchange);
qboolean FS_GameIsInitialised(void);
void FS_Shutdown(void);
@ -844,7 +846,8 @@ void FS_CloseMapPackFile (searchpathfuncs_t *archive);
void COM_FlushTempoaryPacks(void);
void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm);
searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname);
void COM_EnumerateFilesReverse (const char *match, int (QDECL *func)(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath), void *parm);
searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname, const char *pakpathprefix);
extern qboolean com_installer; //says that the engine is running in an 'installer' mode, and that the correct basedir is not yet known.
extern struct cvar_s registered;

File diff suppressed because it is too large Load Diff

View File

@ -73,16 +73,16 @@ void FS_UnRegisterFileSystemModule(void *module);
void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, const char *pakpath, const char *qhash, const char *pakprefix, unsigned int packageflags);
void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, int minpri, int maxpri);
void PM_ManifestChanged(ftemanifest_t *man);
void *PM_GeneratePackageFromMeta(vfsfile_t *file, char *fname, size_t fnamesize, enum fs_relative *fsroot);
void PM_FileInstalled(const char *filename, enum fs_relative fsroot, void *metainfo, qboolean enable); //we finished installing a file via some other mechanism (drag+drop or from server. insert it into the updates menu.
void PM_EnumeratePlugins(void (*callback)(const char *name, qboolean blocked));
struct xcommandargcompletioncb_s;
void PM_EnumerateMaps(const char *partial, struct xcommandargcompletioncb_s *ctx);
void PM_LoadMap(const char *package, const char *map);
int PM_IsApplying(qboolean listsonly);
unsigned int PM_IsApplying(void);
unsigned int PM_MarkUpdates (void); //mark new/updated packages as needing install.
void PM_ApplyChanges(void); //for -install/-doinstall args
void PM_ManifestPackage(const char *name, int security);
qboolean PM_AreSourcesNew(qboolean doprompt);
qboolean PM_FindUpdatedEngine(char *syspath, size_t syspathsize); //names the engine we should be running
void PM_AddManifestPackages(ftemanifest_t *man);

View File

@ -2066,13 +2066,13 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
nlen += cl;
}
f->name[nlen] = 0;
}
ofs += entry.cesize;
if (prefix && *prefix)
{
if (!strcmp(prefix, ".."))
{
{ //strip leading directories blindly
char *c;
for (c = f->name; *c; )
{
@ -2081,8 +2081,20 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
}
memmove(f->name, c, strlen(c)+1);
}
else if (*prefix == '/')
{ //move any files with the specified prefix to the root
size_t prelen = strlen(prefix+1);
if (!strncmp(prefix+1, f->name, prelen))
{
if (f->name[prelen] == '/')
prelen++;
memmove(f->name, f->name+prelen, strlen(f->name+prelen)+1);
}
else
continue;
}
else
{
{ //add the specified text to the start of each file name (handy for 'maps')
size_t prelen = strlen(prefix);
size_t oldlen = strlen(f->name);
if (prelen+1+oldlen+1 > sizeof(f->name))
@ -2102,7 +2114,6 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
f->flags = entry.flags;
f->mtime = entry.mtime;
ofs += entry.cesize;
f++;
}
@ -2113,6 +2124,7 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
zip->files = NULL;
zip->numfiles = 0;
}
zip->numfiles = f - zip->files;
}
}

View File

@ -4010,6 +4010,7 @@ static Window X_CreateWindow(rendererstate_t *info, qboolean override, XVisualIn
XSizeHints szhints;
unsigned int mask;
Atom prots[2];
extern cvar_t vid_minsize;
/* window attributes */
attr.background_pixel = 0;
@ -4029,8 +4030,8 @@ static Window X_CreateWindow(rendererstate_t *info, qboolean override, XVisualIn
memset(&szhints, 0, sizeof(szhints));
szhints.flags = PMinSize|PPosition|PSize;
szhints.min_width = 320;
szhints.min_height = 200;
szhints.min_width = max(vid_minsize.vec4[0], 320);
szhints.min_height = max(vid_minsize.vec4[1], 200);
if (!fullscreen)
{

View File

@ -689,6 +689,8 @@ void SVNQ_New_f (void)
#ifdef OFFICIAL_RELEASE
Q_snprintfz(build, sizeof(build), "v%i.%02i", FTE_VER_MAJOR, FTE_VER_MINOR);
#elif defined(FTE_BRANCH)
Q_snprintfz(build, sizeof(build), "Rev %s", STRINGIFY(SVNREVISION));
#elif defined(SVNREVISION)
Q_snprintfz(build, sizeof(build), "SVN %s", STRINGIFY(SVNREVISION));
#else

View File

@ -1,7 +1,7 @@
{
"//":"To build:",
"//":" flatpak-builder --user --install --from-git=~/quake/fteqw-code-git build-dir flatpak.json",
"//":" (swap the git url for a web-based one if you're not gonna make any local changes first - note that it'll only take committed changes)",
"//":" flatpak-builder --user --install --from-git=https://github.com/fte-team/fteqw.git build-dir flatpak.json",
"//":" (drop the git arg if you're making local changes to this file - note that it'll only take committed changes, annoyingly there's no way to have the git sources pick up the proper url)",
"//":"To then run:",
"//":" cd ~/quake && flatpak run info.triptohell.fteqw",
@ -23,8 +23,10 @@
"//":"dri needed for gl",
"//":"ipc supposedly recommended for x11's shm stuff",
"//":"flatpak doesn't seem to support alsa. anyone not using pipewire is thus fucked, nothing I can do about that",
"//":"flatpak doesn't seem to support gamepads, at least not on the steamdeck.",
"//":"filesystem /usr/share/quake seems b0rked, we can't find standard gamedata there. still using 'host' because steam might have your game library on some other partition/device other than home.",
"//":"--device=all fixes gamepad so we have usable inputs on steamdeck (apparently there's no proper way around that)",
"//":"we request network... cos we ARE a game...",
"//":"--filesystem=host",
"finish-args": [
"--share=network",
@ -35,12 +37,6 @@
"--socket=wayland",
"--filesystem=host",
"--filesystem=/run/udev:ro",
"--device=all",
"--device=snd",
"--socket=pulseaudio"
],
"modules": [
@ -48,7 +44,7 @@
"name": "fteqw",
"buildsystem": "cmake",
"//":"Using sdl to ensure game controller support eg for steamdeck etc. This may result in some clipboard issues as flatpak's sdl is a little too old (and sdl sucked in delaying proper support).",
"//":"Using sdl to provide game controller support eg for steamdeck etc (FIXME: see above complaint about gamepads being unusable in flatpak...). This may result in some clipboard issues as flatpak's sdl is a little too old (and sdl sucked in delaying proper support).",
"//":"Server stuff disabled, flatpak is not a good match. commandline tools also disabled for the most part, no .desktop files for those",
"//":"install to /app/bin instead of /app/games, flatpak just prefers it that way and the distinction isn't useful.",
"config-opts": ["-DCMAKE_BUILD_TYPE=Release",
@ -72,7 +68,19 @@
"path": "/home/spike/quake/fteqw-code-git",
"//url": "https://github.com/fte-team/fteqw.git"
}
]
],
"//":"Add in our manifest files for TCs.",
"post-install": [
"install -d /app/etc/xdg/fte/",
"install games/*.fmf /app/etc/xdg/fte/",
"install -D games/quake-demo.fmf /app/share/games/quake/default.fmf",
"install -D games/hexen2-demo.fmf /app/share/games/hexen2-demo/default.fmf"
],
"build-options" : {
"no-debuginfo": true
}
}
]
}

17
games/fortressone.fmf Normal file
View File

@ -0,0 +1,17 @@
FTEMANIFEST 1
game quake
name "FortressOne"
basegame id1
gamedir fortress
protocolname FortressOne
//mixing fortressone and other fortress mods in the same gamedir gets messy (especially when protocolnames are being overriden inside configs)
mainconfig "fo.cfg"
//homedir usage is used only where required (or previously created). things like flatpak require its use.
//see quake-demo.fmf
archivedpackage id1/pak0.pak 0x4f069cac id1/pak0.pak https://updates.triptohell.info/moodles/live/QUAKE_SW.zip
//this is made complicated because we can't just use the pk3 as-is etc.
package fortress/fortressone.pk3 mirror "https://github.com/FortressOne/fte-config/releases/download/1.1.1-beta.1/fortressone-fte-linux-1.1.1-beta.1-portable.zip" crc 0x7d74337f prefix "/FortressOne/fortress" filesize 197849205 sha512 "42a0deaa571f30c56dac08603d94d968a603a6c2d64db29473cb25f7e1db29fe63260cc8cda2e41dbbb3decd5e1c5440aa6bbceeae45c3225dad359fe0559021" signature "Spike:OrVRb1AuVmPGSmPlMS37DmEs1UIOeAZpSFj8s9jweUDbSqbkBnY6+5tBI43MxqDtIRMhK1+zDoaRxyvR2HErks2hf1wVoDnwpVACi893tvhSKQ0yfKUfkdpqm8aQM7AU/22ZGj5zav6RtxoX+np/7rzfET0fHzCSaQS1d6/TeJaQ5rMPX13Bgu0CenuOD1rvVNXXPMD5d887Kd+y/kz4OVUH0/xkjua5LHsWwDroC5AwzQI/EsWbcJx+xppihKNdMboAr51dALDuWLeSYzswPoJZWppv9D0WbjLohiZU04gmys7JdLn1cclz5MvIinLNFK//adQHrISqDFJqBygni8k90A0BNwSjdVzf9f4bYtzwS5qFRNgYtONyb380cpFZtMMKLdLRne1K8Y4FljzaJztcbm5qBQCLjAaK+C405tUDddDToCyyGsO6Zxf7yzhlSXNTWv/qRgKx91w5pJNyACgYnspxr+xOX+6ewchZZi07uPOPwVrxoAkuIrkiJtUe"

7
games/hexen2-demo.fmf Normal file
View File

@ -0,0 +1,7 @@
//Note - the hexen2 demo is an unmaintained variation of an earlier build, incompatible with the later game. Any basedirs must be entirely separate.
game hexen2
name "Hexen2 Demo"
package "data/pak0.pak" crc 0x3bbcb56c mirror "unzip:H2Demo/Install/Hexen2/data1/pak0.pak,https://www.quaddicted.com/files/idgames2/idstuff/hexen2/H2Demo.exe"

11
games/quake-demo.fmf Normal file
View File

@ -0,0 +1,11 @@
//This can skip most of its details as the important stuff is baked into the engine and its best to avoid dupes.
//View some other file for a real example.
//Registered Quake is a strict superset of the shareware version, so we don't really need to care about whether its a demo or not.
FTEManifestVer 1
game quake
//the shareware license requires distribution in whole... so we'll just download the whole shareware zip and extract only what we need - assuming the user does not already have a copy.
archivedpackage id1/pak0.pak 0x4f069cac id1/pak0.pak https://fte.triptohell.info/moodles/live/QUAKE_SW.zip

235
games/xonotic_85.fmf Normal file
View File

@ -0,0 +1,235 @@
//-prefixed lines are effectively inserted before the default.cfg
//+prefixed lines are inserted AFTER default.cfg and will thus conflict/override the mod's own settings
game xonotic
name "FTE Xonotic (0.8.5)"
protocolname "Xonotic"
basegame data
basegame *ftedata //so stuff gets written here instead.
//xonotic 0.8.5 packages.
package "data/font-unifont-20220627.pk3" crc 0xa39ce3ad mirror "unzip:Xonotic/data/font-unifont-20220627.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
package "data/font-xolonium-20220627.pk3" crc 0x9553d8a4 mirror "unzip:Xonotic/data/font-xolonium-20220627.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
package "data/xonotic-20220627-data.pk3" crc 0x57a1ba9c mirror "unzip:Xonotic/data/xonotic-20220627-data.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
package "data/xonotic-20220627-maps.pk3" crc 0x1d3d7cf1 mirror "unzip:Xonotic/data/xonotic-20220627-maps.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
package "data/xonotic-20220627-music.pk3" crc 0x5d1dd373 mirror "unzip:Xonotic/data/xonotic-20220627-music.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
package "data/xonotic-20220627-nexcompat.pk3" crc 0x83f613b9 mirror "unzip:Xonotic/data/xonotic-20220627-nexcompat.pk3,https://github.com/garymoon/xonotic/releases/download/xonotic-v0.8.5/xonotic-0.8.5.zip"
//This sucks. overrides the *.dat files to work around gmqcc bugs (also smaller dat files at runtime, but still stupid and annoying and means compat hits the fan when using the standard csprogs on dp servers)
package "data/xonotic-fixups-0.8.5.zip" crc 0xe27b8ad3 mirror "xonotic-fixups-0.8.5.pk3"
//-set pr_fixbrokenqccarrays 2 //this can be used instead, but can cause its own problems.
-set dpcompat_set 1 //gah
-set dpcompat_console 1 //DP's $ stuff works differently from quakeworld. definitely more annoying, but xonotic's configs expect dp behaviour
-set dpcompat_smallerfonts 1 //in case its needed.
-set dpcompat_strcat_limit 16383 //work around xonotic network compatibility issue.
-set v_gammainverted 1
-set con_stayhidden 0
-set allow_download_pakcontents 1
-set allow_download_refpackages 0
-set sv_bigcoords ""
-set map_autoopenportals 1
-set sv_port 26000
-set cl_defaultport 26000
-set r_particlesdesc effectinfo
-if ($dedicated < 1) then set qport 654 //xonotic expects this cvar to exist only in clients (and uses it to detect client vs dedicated server). this entirely ignores 'setrenderer sv' of course. good luck with that one.
-set gl_info_extensions "GL_EXT_texture_compression_s3tc GL_ARB_texture_compression" //fte doesn't have a cvar that contains opengl extensions, in part because they don't apply to other renderers, thus making it kinda useless. and xonotic likes spamming warning messages, even though they're invalid half the time, and impossible for a user to work around the rest of the time.
-set cl_movement 1 //xonotic's physics are inconsistent with itself, but it judders even without prediction so we might as well enable it
-set cl_movement_replay "" //just to silence spam. actual value doesn't change anything in fte, and xonotic keeps changing it randomly anyway.
-set sv_nqplayerphysics 0 //xonotic runs async player physics. we've no need to force anything.
-set pr_enable_uriget 0 //enabling this causes xonotic's menu to get pissy about updates, which probably won't work very well with fte, so best to block all that crap. sadly this also breaks the stats stuff.
-set cl_lerp_smooth 0 //don't run in the past. DP has nothing like that the whole servertime/serverprevtime stuff will just get confused like hell.
-set r_shadow_realtime_nonworld_lightmaps 2 //DP's q3bsp lighting is doubled relative to q3, for some reason.
-set con_chatsize 8 //doesn't exist in FTE, resulting in qc division by 0 if not set.
-set con_textsize 12 //keep the console sized at a fixed 12pt point, regardless of actual res.
//con_stayhidden 1 //don't pop up the console randomly.
-set dpcompat_makeshitup 2 //ignore most of what the shaders are saying and just make shit up, adding deluxe+specular+fullbrights+reflectcube etc.
-set dpcompat_findradiusarealinks 1 //matches dp. should help performance.
-set sv_gameplayfix_spawnbeforethinks 1 //some nq mods actually break without this glitch. DP forces a fix, so match that behaviour because xonotic needs it.
//I copied this list out of the dp sourcecode. I don't know if xonotic needs them, but it normally has them anyway.
//fte doesn't even implement them all either, so that's fun. still, if it ever does then they'll at least get their expected values.
-set sv_gameplayfix_blowupfallenzombies 1
-set sv_gameplayfix_findradiusdistancetobox 1
-set sv_gameplayfix_grenadebouncedownslopes 1
-set sv_gameplayfix_slidemoveprojectiles 1
-set sv_gameplayfix_upwardvelocityclearsongroundflag 1
-set sv_gameplayfix_setmodelrealbox 1
-set sv_gameplayfix_droptofloorstartsolid 1
-set sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 1
-set sv_gameplayfix_noairborncorpse 1
-set sv_gameplayfix_noairborncorpse_allowsuspendeditems 1
-set sv_gameplayfix_easierwaterjump 1
-set sv_gameplayfix_delayprojectiles 1
-set sv_gameplayfix_multiplethinksperframe 1
-set sv_gameplayfix_fixedcheckwatertransition 1
-set sv_gameplayfix_q1bsptracelinereportstexture 1
-set sv_gameplayfix_swiminbmodels 1
-set sv_gameplayfix_downtracesupportsongroundflag 1
-set sv_gameplayfix_q2airaccelerate 0
//most of these cvars are not defined by FTE, but xonotic expects them anyway. so make sure they're there for the pmove code.
-set sv_jumpvelocity 270
-set sv_maxairspeed 30
-set sv_nostep 0
-set sv_jumpstep 1
-set sv_wateraccelerate -1
-set sv_waterfriction -1
-set sv_airaccel_sideways_friction 0
-set sv_airaccel_qw 1
-set sv_airaccel_qw_stretchfactor 0
-set sv_airstopaccelerate 0
-set sv_airstrafeaccelerate 0
-set sv_maxairstrafespeed 0
-set sv_airstrafeaccel_qw 0
-set sv_aircontrol 0
-set sv_aircontrol_penalty 0
-set sv_aircontrol_power 2
-set sv_aircontrol_backwards 0
-set sv_airspeedlimit_nonqw 0
-set sv_warsowbunny_turnaccel 0
-set sv_warsowbunny_accel 0.1585
-set sv_warsowbunny_topspeed 925
-set sv_warsowbunny_backtosideratio 0.8
-set sv_airaccelerate -1 //dp's default... to mean defer to sv_accelerate.
//all these cvars are implemented using a custom conback shader.
-set scr_conalphafactor 1
-set scr_conalpha2factor 0
-set scr_conalpha3factor 0
-set scr_conbrightness 1
-set scr_conscroll_x 0
-set scr_conscroll_y 0
-set scr_conscroll2_x 0
-set scr_conscroll2_y 0
-set scr_conscroll3_x 0
-set scr_conscroll3_y 0
-set r_textcontrast 1 //fixes colourpicker widget
-set com_parseutf8 1 //fte's name. interpret text as utf-8 when printing.
-set utf8_enable 1 //not fte's cvar name. have the qc builtins operate on codepoints rather than bytes (slower, still unaware of emoji, accents, etc).
-alias playermodel model //FTE uses userinfo stuff for this stuff
-alias playerskin skin //FTE uses userinfo stuff for this stuff
-set pr_csqc_memsize "64m" //xonotic is shit and inefficient. it really does need FAR too much memory.
-set pr_ssqc_memsize "96m" //xonotic is shit and inefficient. it really does need FAR too much memory.
-set r_deluxemapping 1 //load deluxemaps, cos they're a little prettier
-set dpcompat_nopremulpics 1 //0 has problems with dds files etc, which is frankly a shame.
//this won't force the menu to use a less laggy cursor, but should at least give the console a little more personality.
-set cl_cursor "gfx/menu/luma/cursor.jpg"
-set cl_cursor_scale 0.333
-set cl_cursor_bias_x 10
-set cl_cursor_bias_y 3.33
-set vid_gl20 1 //make sure various menu options are not greyed out
-set gl_specular 1 //DP's default, that makes things too shiny (because if you're going to make a texture then sadly most people want it to be seen)
-set dpcompat_corruptglobals 1 //stomp on random qc globals that were meant to be cachable from one frame to the next.
-set vid_pixelheight 1 //DP mods have a nasty tendancy to get confused when this cvar doesn't exist.
-set s_al_disable 1 //xonotic seems to clog ALL the openal audio buffers with useless sounds, so disable openal to prevent that from happening.
-set dpcompat_nopreparse 1 //No unicasts and stuff split over packets mean lengths of custom stuff cannot be determined, resulting in translation of other things failing to translate.
-set cl_loopbackprotocol dpp7 //needs to be some sort of nq protocol due to nopreparse. might as well match dp and network player velocity entirely separately from its position...
-set sv_listen_dp 1 //listen for dp-protocol client connections
-set sv_listen_qw 0 //ignore standard QW clients (they'll just get dp responses which they'll ignore)
-set sv_listen_nq 0 //nq-protocol clients will just be ignored.
-set sv_bigcoords 1 //kinda required for dpp7 to function correctly.
-set r_particlesdesc effectinfo
-set sv_mintic 0.0333 //should match dp's rate.
-set sv_maxtic 0 //fixed tick rates
-set cl_nolerp 0
-set sv_cullentities_trace 0 //still needs work. fte still has performance issues with tracing through patches
-set sv_curl_serverpackages "" //not in FTE, but xonotic warns when missing.
-set _cl_name "Stalking is illegal"
-set pr_autocreatecvars 0 //so we're more likely to notice unknown cvars.
//misc cvars that the gamecode checks for for unknowable reasons
//set r_texture_dds_load 1
//set vid_desktopfullscreen ${vid_fullscreen==2}
//set hud_panel_notify_print
//set con_chattime
//set con_chatsound
//set net_slist_pause
//set r_viewfbo ${r_hdr_framebuffer}
//set r_depthfirst
//set gl_vbo //removed from dp too
//set v_glslgamma
//set r_glsl_saturation
//set r_hdr_scenebrightness
//set sys_memsize_virtual
//set sys_memsize_physical
//set mod_q3bsp_nolightmaps
//set r_shadow_gloss ${gl_specular}
//set r_water ${r_portalrecursion>0}
//set r_water_resolutionmultiplier ${r_reflectrefract_scale}
//set cl_decals
//set cl_decals_models
//set r_drawdecals_drawdistance
//set cl_decals_fadetime
//set r_shadow_usenormalmap
//set r_coronas_occlusionquery
//set r_motionblur
//set cl_particles
//set r_drawparticles_drawdistance
//set snd_staticvolume
//set snd_channel0volume
//set snd_channel3volume
//set snd_channel6volume
//set snd_channel7volume
//set snd_channel4volume
//set snd_channel2volume
//set snd_channel1volume
//set snd_mutewhenidle ${snd_inactive==0}
//set snd_speed ${snd_khz}
//set snd_channels ${snd_numspeakers}
//set snd_swapstereo ${snd_leftisright}
//set snd_spatialization_control
//set m_accelerate
//set con_closeontoggleconsole
//set cl_movement_track_canjump
//set _cl_rate ${rate}
//set cl_curl_maxdownloads
//set cl_curl_maxspeed
//set shownetgraph ${r_netgraph}
//set cl_minfps
//set cl_maxidlefps ${cl_idlefps}
//set showtime
//set cl_capturevideo
//set g_campaignxonoticbeta_won
//set r_glsl_postprocess
//set joy_active
//set con_chatrect_x
//set con_chatrect_y
//set con_chatwidth
//set net_slist_favorites
//set cl_bobfall
//set cl_smoothviewheight
-maxplayers 16 //xonotic doesn't like empty to mean ((deathmatch||coop)?32:1), so be explicit.
-deathmatch 1 //normally gets set to 1 in dp when maxplayers is forced (coop be damned).
-pr_precachepic_slow 1 //xonotic sucks for this. its abuse of drawgetimagesize slows stuff down too.
-set mod_precache 2 //disabling this slashes ram usage. there might be some stutter from loading textures, but no outright stalls at least. the prediction misses are worse.
-set mod_precache 0 //FIXME: override sv_precacheplayermodels instead.
//FIXME: -set _q3bsp_bihtraces 1 //work around q3map2 being so defective and throwing 5000 brushes into a single leaf.
-set sv_gameplayfix_setmodelrealbox 0 //setting this to 0 prevents the server from stalling waiting for the thing to load.
+set sv_precacheplayermodels 0 //fte has loader threads, and the extra upfront load time is just annoying (override the mod's default).
-set s_precache 0 //mneh, sounds are overrated anyway.