diff --git a/CMakeLists.txt b/CMakeLists.txt index 71b572ec1..1390aca7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,10 @@ SET(FTE_BUILD_CONFIG ${CMAKE_HOME_DIRECTORY}/engine/common/config_fteqw.h CACHE SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};CONFIG_FILE_NAME=${FTE_BUILD_CONFIG}) SET(FTE_USE_SDL false CACHE BOOL "Force the use of SDL instead of using native builds.") +INCLUDE(GNUInstallDirs) +SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.") +SET(FTE_INSTALL_LIBDIR fteqw CACHE STRING "Binary dir to install to.") + IF(NOT WIN32) SET(SYS_LIBS ${SYS_LIBS} m) ELSE() @@ -221,11 +225,13 @@ 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}") + FUNCTION(EMBED_PLUGIN_META PLUGNAME PLUGTITLE PLUGDESC) SET_TARGET_PROPERTIES(plug_${PLUGNAME} PROPERTIES OUTPUT_NAME "${PLUGNAME}") SET_TARGET_PROPERTIES(plug_${PLUGNAME} PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(plug_${PLUGNAME} PROPERTIES LINK_FLAGS "-Wl,--no-undefined") - SET(INSTALLTARGS ${INSTALLTARGS} "plug_${PLUGNAME}") + SET(INSTALLTARGS ${INSTALLTARGS} "plug_${PLUGNAME}" PARENT_SCOPE) #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 @@ -1247,11 +1253,7 @@ IF(FTE_PLUG_NAMEMAKER) plugins/namemaker/namemaker.c ) SET_TARGET_PROPERTIES(plug_namemaker PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES}") - SET_TARGET_PROPERTIES(plug_namemaker PROPERTIES OUTPUT_NAME "namemaker") - SET_TARGET_PROPERTIES(plug_namemaker PROPERTIES PREFIX "fteplug_") - SET_TARGET_PROPERTIES(plug_namemaker PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(plug_namemaker ${SYS_LIBS}) - SET(INSTALLTARGS ${INSTALLTARGS} plug_namemaker) EMBED_PLUGIN_META(namemaker "Name Maker Plugin" "Provides a lame UI for selecting arbitrary non-ascii glyphs as part of your nickname.") ENDIF() @@ -1531,13 +1533,16 @@ IF(FTE_PLUG_XMPP) ENDIF() ENDIF() #android -INCLUDE(GNUInstallDirs) -SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.") INSTALL(TARGETS ${INSTALLTARGS} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/${FTE_INSTALL_BINDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/${FTE_INSTALL_LIBDIR}" ) +INSTALL(FILES + fteqw.desktop + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications/") + + SET(FTE_MENU_SYS true CACHE BOOL "Compile System Menu.") IF(FTE_MENU_SYS) ADD_CUSTOM_TARGET(menusys ALL diff --git a/engine/client/cl_ignore.c b/engine/client/cl_ignore.c index 46166c805..91d5600a8 100644 --- a/engine/client/cl_ignore.c +++ b/engine/client/cl_ignore.c @@ -460,10 +460,13 @@ static void Ignoreteam_f(void) } if (j == MAX_TEAMIGNORELIST) Con_Printf("You cannot ignore more than %d teams\n", MAX_TEAMIGNORELIST); - Q_strncpyz(ignoreteamlist[j], arg, sizeof(ignoreteamlist[j])); - if (j + 1 < MAX_TEAMIGNORELIST) - ignoreteamlist[j + 1][0] = 0; - Con_Printf("Added team %s to ignore list\n", arg); + else + { + Q_strncpyz(ignoreteamlist[j], arg, sizeof(ignoreteamlist[j])); + if (j + 1 < MAX_TEAMIGNORELIST) + ignoreteamlist[j + 1][0] = 0; + Con_Printf("Added team %s to ignore list\n", arg); + } return; } } diff --git a/engine/client/image.c b/engine/client/image.c index 14e9a3a81..f5e565ffe 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -4633,8 +4633,10 @@ static void *ReadEXRFile(qbyte *buf, size_t len, const char *fname, int *outwidt fd = mkstemp(tname); //bsd4.3/posix1-2001 if (fd >= 0) { - write(fd, buf, len); - ctx = exr.OpenInputFile(tname); + if (write(fd, buf, len) == len) + ctx = exr.OpenInputFile(tname); + else + ctx = NULL; close(fd); //we don't need the input file now. unlink(tname); #endif diff --git a/engine/client/m_download.c b/engine/client/m_download.c index ff0fb0b61..87becc57a 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -2075,9 +2075,16 @@ static void PM_PreparePackageList(void) #ifdef PLUGINS { char nat[MAX_OSPATH]; - FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat)); - Con_DPrintf("Loading plugins from \"%s\"\n", nat); - Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_DL_POSTFIX, PM_EnumeratedPlugin, &pluginsadded, NULL); + if (FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat))) + { + Con_DPrintf("Loading plugins from \"%s\"\n", nat); + Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_DL_POSTFIX, PM_EnumeratedPlugin, &pluginsadded, NULL); + } + if (FS_NativePath("", FS_LIBRARYPATH, nat, sizeof(nat))) + { + Con_DPrintf("Loading plugins from \"%s\"\n", nat); + Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_DL_POSTFIX, PM_EnumeratedPlugin, &pluginsadded, NULL); + } } #endif } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 6fb4e725a..2aff2df5e 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -4445,7 +4445,8 @@ void M_Menu_Mods_f (void) MC_AddFrameStart(menu, 32); for (i = 0; i<1 || Mods_GetMod(i); i++) { - c = MC_AddCustom(menu, 64, 32+i*8, menu->data, i, NULL); + struct modlist_s *mod = Mods_GetMod(i); + c = MC_AddCustom(menu, 64, 32+i*8, menu->data, i, (mod&&mod->manifest)?mod->manifest->basedir:NULL); // if (!menu->selecteditem) // menu->selecteditem = (menuoption_t*)c; c->common.height = 8; diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index 7ec6912a6..a5c8a3be3 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -729,7 +729,7 @@ static int Sys_EnumerateFiles2 (const char *truepath, int apathofs, const char * { Q_snprintfz(file, sizeof(file), "%s/%s", truepath, ent->d_name); - if (stat(file, &st) == 0) + if (stat(file, &st) == 0 || lstat(file, &st) == 0) { Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":""); @@ -740,8 +740,8 @@ static int Sys_EnumerateFiles2 (const char *truepath, int apathofs, const char * return false; } } - else - printf("Stat failed for \"%s\"\n", file); +// else +// printf("Stat failed for \"%s\"\n", file); } } } while(1); diff --git a/engine/common/cmd.c b/engine/common/cmd.c index e87ba7fd5..34e8b1acb 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -1190,9 +1190,8 @@ static void Cmd_Alias_f (void) // check for overlap with a command if (Cmd_Exists (s)) { //commands always take precedence over aliases (so mods can't clobber 'quit' etc), so creating an alias with one of these names is stupid. always try to rename them. - if (Cmd_IsInsecure()) + if (Cmd_IsInsecure() && snprintf(cmd, sizeof(cmd), "%s_a", s) < sizeof(cmd)) { - snprintf(cmd, sizeof(cmd), "%s_a", s); if (Cmd_Exists (cmd)) { Con_Printf (S_COLOR_RED"Can't register alias, %s is a command\n", s); @@ -1211,9 +1210,8 @@ static void Cmd_Alias_f (void) { //aliases take precedence over cvars (while cvars can be set via 'set'), so user's choice. if (Cvar_FindVar (s)) { - if (Cmd_IsInsecure()) + if (Cmd_IsInsecure() && snprintf(cmd, sizeof(cmd), "%s_a", s) < sizeof(cmd)) { - snprintf(cmd, sizeof(cmd), "%s_a", s); Con_Printf (S_COLOR_RED"alias %s: renamed to %s due to cvar conflict\n", s, cmd); s = cmd; } diff --git a/engine/common/fs.c b/engine/common/fs.c index 19efce592..0f89e75c7 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -471,11 +471,10 @@ static void FS_Manifest_Print(ftemanifest_t *man) { if (man->gamepath[i].path) { - size_t bufsize = strlen(man->gamepath[i].path) + 16; - char *str = Z_Malloc(bufsize); - if (man->gamepath[i].flags & GAMEDIR_PRIVATE) - Q_strncatz(str, "*", bufsize); - Q_strncatz(str, man->gamepath[i].path, bufsize); + char *str = va("%s%s%s", + (man->gamepath[i].flags & GAMEDIR_QSHACK)?"/":"", + (man->gamepath[i].flags & GAMEDIR_PRIVATE)?"*":"", + man->gamepath[i].path); if (man->gamepath[i].flags & GAMEDIR_BASEGAME) Con_Printf("basegame %s\n", COM_QuotedString(str, buffer, sizeof(buffer), false)); @@ -2304,6 +2303,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out char cleanname[MAX_QPATH]; char *last; qboolean wasbase; //to handle out-of-order base/game dirs. + int nlen; if (relativeto == FS_SYSTEM) { @@ -2322,7 +2322,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out { //this is sometimes used to query the actual path. //don't alow it for other stuff though. - if (relativeto != FS_ROOT && relativeto != FS_BINARYPATH && relativeto != FS_GAMEONLY) + if (relativeto != FS_ROOT && relativeto != FS_BINARYPATH && relativeto != FS_LIBRARYPATH && relativeto != FS_GAMEONLY) return false; } else @@ -2337,29 +2337,36 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out case FS_GAME: //this is really for diagnostic type stuff... if (FS_FLocateFile(fname, FSLF_IFFOUND, &loc)) { - snprintf(out, outlen, "%s/%s", loc.search->logicalpath, fname); + nlen = snprintf(out, outlen, "%s/%s", loc.search->logicalpath, fname); break; } //fallthrough case FS_GAMEONLY: if (com_homepathenabled) - snprintf(out, outlen, "%s%s/%s", com_homepath, gamedirfile, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_homepath, gamedirfile, fname); else - snprintf(out, outlen, "%s%s/%s", com_gamepath, gamedirfile, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_gamepath, gamedirfile, fname); break; + case FS_LIBRARYPATH: +#ifdef FTE_LIBRARY_PATH + nlen = snprintf(out, outlen, STRINGIFY(FTE_LIBRARY_PATH)"/%s", fname); + break; +#else + return false; +#endif case FS_BINARYPATH: if (host_parms.binarydir && *host_parms.binarydir) - snprintf(out, outlen, "%s%s", host_parms.binarydir, fname); + nlen = snprintf(out, outlen, "%s%s", host_parms.binarydir, fname); else - snprintf(out, outlen, "%s%s", host_parms.basedir, fname); + nlen = snprintf(out, outlen, "%s%s", host_parms.basedir, fname); break; case FS_ROOT: if (com_installer) return false; if (com_homepathenabled) - snprintf(out, outlen, "%s%s", com_homepath, fname); + nlen = snprintf(out, outlen, "%s%s", com_homepath, fname); else - snprintf(out, outlen, "%s%s", com_gamepath, fname); + nlen = snprintf(out, outlen, "%s%s", com_gamepath, fname); break; case FS_BASEGAMEONLY: // fte/ @@ -2376,9 +2383,9 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out if (!last) return false; //eep? if (com_homepathenabled) - snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); else - snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); break; case FS_PUBGAMEONLY: // $gamedir/ or qw/ but not fte/ last = NULL; @@ -2399,9 +2406,9 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out if (!last) return false; //eep? if (com_homepathenabled) - snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); else - snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); break; case FS_PUBBASEGAMEONLY: // qw/ (fixme: should be the last non-private basedir) last = NULL; @@ -2417,14 +2424,14 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out if (!last) return false; //eep? if (com_homepathenabled) - snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname); else - snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); + nlen = snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); break; default: Sys_Error("FS_NativePath case not handled\n"); } - return true; + return nlen < outlen; } //returns false to stop the enumeration. check the return value of the fs enumerator to see if it was canceled by this return value. @@ -3832,6 +3839,68 @@ qboolean FS_Restarted(unsigned int *since) return false; } +#ifdef __WIN32 //already assumed to be case insensitive. let the OS keep fixing up the paths itself. +static void FS_FixupFileCase(char *out, size_t outsize, const char *basedir, const char *entry) +{ + Q_snprintfz(out, outsize, "%s%s", basedir, entry); +} +#else +struct fixupcase_s +{ + char *out; + size_t outsize; + const char *match; + size_t matchlen; + qboolean isdir; //directory results have a trailing / +}; +static int FS_FixupFileCaseResult(const char *name, qofs_t sz, time_t modtime, void *vparm, searchpathfuncs_t *spath) +{ + struct fixupcase_s *parm = vparm; + if (strlen(name) != parm->matchlen+parm->isdir) + return true; + if (parm->isdir && name[parm->matchlen] != '/') + return true; + if (Q_strncasecmp(name, parm->match, parm->matchlen)) + return true; + memcpy(parm->out, name, parm->matchlen); + return !!Q_strncmp(name, parm->match, parm->matchlen); //stop if we find the exact path case. otherwise keep looking +} +//like snprintf("%s%s") but fixes up 'gamedir' case to a real file +static qboolean FS_FixupFileCase(char *out, size_t outsize, const char *basedir, const char *entry, qboolean isdir) +{ + char *s; + struct fixupcase_s parm = {out+strlen(basedir), outsize-strlen(basedir), entry, strlen(entry), isdir}; + if (Q_snprintfz(out, outsize, "%s%s", basedir, entry) >= outsize || outsize < strlen(basedir)+1 || parm.outsize < parm.matchlen+1) + return false; //over sized?... + if (strchr(entry, '/')) for(;;) + { + parm.match = entry; + s = strchr(entry, '/'); + if (s) + { + parm.isdir = true; + parm.matchlen = s-entry; + Sys_EnumerateFiles(basedir, "*", FS_FixupFileCaseResult, &parm, NULL); + parm.out += parm.matchlen+1; + parm.outsize -= parm.matchlen+1; + entry += (s-entry)+1; + } + else + { + parm.isdir = isdir; + parm.matchlen = strlen(entry); + parm.out[-1] = 0; + Sys_EnumerateFiles(out, "*", FS_FixupFileCaseResult, &parm, NULL); + parm.out[-1] = '/'; + break; + } + } + else + Sys_EnumerateFiles(basedir, "*", FS_FixupFileCaseResult, &parm, NULL); + return true; +} +#endif + /* ================ FS_AddGameDirectory @@ -3883,13 +3952,12 @@ static searchpath_t *FS_AddSingleGameDirectory (searchpath_t **oldpaths, const c static void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, unsigned int loadstuff, unsigned int flags) { char syspath[MAX_OSPATH]; - Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, puredir); - gameonly_gamedir = FS_AddSingleGameDirectory(oldpaths, puredir, syspath, loadstuff, flags&~(com_homepathenabled?SPF_WRITABLE:0u)); - if (com_homepathenabled) - { - Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, puredir); + if (FS_FixupFileCase(syspath, sizeof(syspath), com_gamepath, puredir, true)) + gameonly_gamedir = FS_AddSingleGameDirectory(oldpaths, puredir, syspath, loadstuff, flags&~(com_homepathenabled?SPF_WRITABLE:0u)); + else + gameonly_gamedir = NULL; + if (com_homepathenabled && FS_FixupFileCase(syspath, sizeof(syspath), com_homepath, puredir, true)) gameonly_homedir = FS_AddSingleGameDirectory(oldpaths, puredir, syspath, loadstuff, flags); - } else gameonly_homedir = NULL; } @@ -4165,7 +4233,7 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths) #define QCFG "//schemes quake qw\n" QUAKEOVERRIDES "set com_parseutf8 0\n" QRPCOMPAT #define KEXCFG "//schemes quake_r2\n" QUAKEOVERRIDES "set com_parseutf8 1\nset campaign 0\nset net_enable_dtls 1\nset sv_mintic 0.016666667\nset sv_maxtic $sv_mintic\nset cl_netfps 60\n" /*NetQuake reconfiguration, to make certain people feel more at home...*/ -#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\n" QCFG "cfg_save_auto 1\nset sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n" +#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\n" QCFG "cfg_save_auto 1\nset pm_bunnyfriction 1\nset sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n" #define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\ncl_sbar 2\nset gl_load24bit 1\n" #define FITZCFG NQCFG "fps_preset builtin_spasm\ncl_sbar 2\nset gl_load24bit 1\n" #define TENEBRAECFG NQCFG "fps_preset builtin_tenebrae\n" @@ -4256,7 +4324,7 @@ static const gamemode_info_t gamemode_info[] = { //because we can. 'fps_preset spasm' is hopefully close enough... {"-fitz", "nq", QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},FITZCFG,{"id1"}, "FauxFitz", UPDATEURL(Q1)}, //because we can - {"-tenebrae", NULL, QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},TENEBRAECFG,{"id1", "tenebrae"}, "FauxTenebrae", UPDATEURL(Q1)}, + {"-tenebrae", NULL, QUAKEPROT, {"tenebrae/Pak0.pak","id1/quake.rc"},TENEBRAECFG,{"id1", "tenebrae"}, "FauxTenebrae", UPDATEURL(Q1)}, //quake's mission packs should not be favoured over the base game nor autodetected //third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content. @@ -5573,6 +5641,8 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base return true; if (!strcmp(gamename, "quake") || !strcmp(gamename, "afterquake") || !strcmp(gamename, "netquake") || !strcmp(gamename, "spasm") || !strcmp(gamename, "fitz") || !strcmp(gamename, "tenebrae")) { + if (Sys_SteamHasFile(basepath, basepathlen, "Quake", "Id1/PAK0.PAK")) //dos legacies need to die. + return true; if (Sys_SteamHasFile(basepath, basepathlen, "Quake", "id1/PAK0.PAK")) //dos legacies need to die. return true; if (Sys_SteamHasFile(basepath, basepathlen, "Quake", "id1/pak0.pak")) //people may have tried to sanitise it already. @@ -5709,16 +5779,19 @@ static qboolean FS_DirHasAPackage(char *basedir, ftemanifest_t *man) return defaultret; } +#ifdef _WIN32 //false stops the search (and returns that value to FS_DirHasGame) static int QDECL FS_DirDoesHaveGame(const char *fname, qofs_t fsize, time_t modtime, void *ctx, searchpathfuncs_t *subdir) { return false; } +#endif //just check each possible file, see if one is there. static qboolean FS_DirHasGame(const char *basedir, int gameidx) { int j; + char realpath[MAX_OSPATH]; //none listed, just assume its correct. if (!gamemode_info[gameidx].auniquefile[0]) @@ -5728,8 +5801,13 @@ static qboolean FS_DirHasGame(const char *basedir, int gameidx) { if (!gamemode_info[gameidx].auniquefile[j]) continue; //no more +#ifdef _WIN32 if (!Sys_EnumerateFiles(basedir, gamemode_info[gameidx].auniquefile[j], FS_DirDoesHaveGame, NULL, NULL)) return true; //search was cancelled by the callback, so it actually got called. +#else + if (FS_FixupFileCase(realpath, sizeof(realpath), basedir, gamemode_info[gameidx].auniquefile[j], false) && access(realpath, R_OK) == 0) + return true; //something readable. +#endif } return false; } @@ -5784,7 +5862,7 @@ static int FS_IdentifyDefaultGame(char *newbase, int sizeof_newbase, qboolean fi if (gamenum != -1) Q_strncpyz(newbase, host_parms.binarydir, sizeof_newbase); } - if (gamenum == -1 && *com_homepath && !fixedbase) + if (gamenum == -1 && *com_homepath && com_homepathusable && !fixedbase) { gamenum = FS_IdentifyDefaultGameFromDir(com_homepath); if (gamenum != -1) @@ -6771,7 +6849,7 @@ int FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man), Q_strncpyz(basedir, com_gamepath, sizeof(basedir)); if (gamemode_info[i].manifestfile || ((gamemode_info[i].exename || (i>0&&gamemode_info[i].customexec&&gamemode_info[i-1].customexec&&strcmp(gamemode_info[i].customexec,gamemode_info[i-1].customexec))) && FS_DirHasGame(com_gamepath, i)) || - (e.anygamedir&&Sys_FindGameData(NULL, gamemode_info[i].argname+1, basedir, sizeof(basedir), true))) + (e.anygamedir&&Sys_FindGameData(NULL, gamemode_info[i].argname+1, basedir, sizeof(basedir), false))) { man = FS_GenerateLegacyManifest(i, basedir); if (e.callback(e.usr, man)) diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 625922e87..61eff720c 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -4234,7 +4234,7 @@ ftenet_generic_connection_t *FTENET_Datagram_EstablishConnection(ftenet_connecti } if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) - Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(neterrno())); + Sys_Error ("FTENET_Datagram_EstablishConnection: ioctl FIONBIO: %s", strerror(neterrno())); //ipv6 sockets need to add themselves to a multicast group, so that we can receive broadcasts on a lan #if defined(HAVE_IPV6) @@ -8935,7 +8935,7 @@ int TCP_OpenStream (netadr_t *remoteaddr, const char *remotename) setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&recvbufsize, sizeof(recvbufsize)); if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) - Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(neterrno())); + Sys_Error ("TCP_OpenStream: ioctl FIONBIO: %s", strerror(neterrno())); #ifdef UNIXSOCKETS if (remoteaddr->type == AF_UNIX) diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 94d9c85ed..543c4c659 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -173,6 +173,7 @@ static plugin_t *Plug_Load(const char *file) static enum fs_relative prefixes[] = { FS_BINARYPATH, + FS_LIBRARYPATH, #ifndef ANDROID FS_ROOT, #endif @@ -1259,9 +1260,16 @@ void Plug_Initialise(qboolean fromgamedir) { if (!fromgamedir) { - FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat)); - Con_DPrintf("Loading plugins from \"%s\"\n", nat); - Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); + if (FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat))) + { + Con_DPrintf("Loading plugins from \"%s\"\n", nat); + Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); + } + if (FS_NativePath("", FS_LIBRARYPATH, nat, sizeof(nat))) + { + Con_DPrintf("Loading plugins from \"%s\"\n", nat); + Sys_EnumerateFiles(nat, PLUGINPREFIX"*" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); + } } } if (plug_loaddefault.ival & 1) @@ -1753,6 +1761,7 @@ int QDECL Plug_List_Print(const char *fname, qofs_t fsize, time_t modtime, void void Plug_List_f(void) { char binarypath[MAX_OSPATH]; + char librarypath[MAX_OSPATH]; char rootpath[MAX_OSPATH]; unsigned int u; plugin_t *plug; @@ -1775,9 +1784,22 @@ void Plug_List_f(void) while ((mssuck=strchr(binarypath, '\\'))) *mssuck = '/'; #endif - Con_DPrintf("Scanning for plugins at %s:\n", binarypath); + Con_Printf("Scanning for plugins at %s:\n", binarypath); Sys_EnumerateFiles(binarypath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, binarypath, NULL); } + if (FS_NativePath("", FS_LIBRARYPATH, librarypath, sizeof(librarypath))) + { +#ifdef _WIN32 + char *mssuck; + while ((mssuck=strchr(librarypath, '\\'))) + *mssuck = '/'; +#endif + if (strcmp(librarypath, rootpath)) + { + Con_Printf("Scanning for plugins at %s:\n", librarypath); + Sys_EnumerateFiles(librarypath, PLUGINPREFIX"*" ARCH_DL_POSTFIX, Plug_List_Print, librarypath, NULL); + } + } if (FS_NativePath("", FS_ROOT, rootpath, sizeof(rootpath))) { #ifdef _WIN32 diff --git a/engine/gl/gl_vidsdl.c b/engine/gl/gl_vidsdl.c index 53148e817..9a6ce4004 100644 --- a/engine/gl/gl_vidsdl.c +++ b/engine/gl/gl_vidsdl.c @@ -806,10 +806,7 @@ static qboolean VKVID_Init (rendererstate_t *info, unsigned char *palette) vkGetInstanceProcAddr = SDL_Vulkan_GetVkGetInstanceProcAddr(); if (!VK_Init(info, extnames, VKSDL_CreateSurface, NULL)) - { - SDL_ShowSimpleMessageBox(0, "FTEQuake", extnames[1], sdlwindow); return false; - } return true; } rendererinfo_t vkrendererinfo = diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index e38a6ff5d..03167907b 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -4848,6 +4848,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre okay = vrsetup.createinstance(&vrsetup, NULL, NULL); if (!okay) { + Con_TPrintf(CON_ERROR"Unable to create vulkan instance\n"); if (info->vr) info->vr->Shutdown(); return false; diff --git a/flatpak.json b/flatpak.json new file mode 100644 index 000000000..028cbc42e --- /dev/null +++ b/flatpak.json @@ -0,0 +1,79 @@ +{ + "//":"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)", + "//":"To then run:", + "//":" cd ~/quake && flatpak run info.triptohell.fteqw", + + "//":"To then create a bundle:", + "//":" flatpak build-bundle ~/.local/share/flatpak/repo fteqw.flatpak info.triptohell.fteqw", + "//":"Which can then be distributed and hopefully double-clicked etc, or just 'flatpak install --user fteqw.flatpak'.", + + "//":"Note: If you're making a TC, add your data/fmf as an extra module somehow, and remove the filesystem=host access.", + + "app-id": "info.triptohell.fteqw", + "runtime": "org.freedesktop.Platform", + "runtime-version":"22.08", + "sdk": "org.freedesktop.Sdk", + "command": "fteqw", + + "rename-desktop-file":"fteqw.desktop", + "strip":"true", + + "//":"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", + "//":"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)", + "finish-args": [ + "--share=network", + + "--device=dri", + + "--share=ipc", + "--socket=x11", + + "--socket=wayland", + + "--filesystem=host", + "--filesystem=/run/udev:ro", + + "--device=all", + + "--device=snd", + "--socket=pulseaudio" + ], + "modules": [ + { + "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).", + "//":"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", + "-DFTE_USE_SDL=true", + + "-DFTE_ENGINE_SERVER_ONLY=false", + "-DFTE_TOOL_QTV=false", + "-DFTE_TOOL_MASTER=false", + "-DFTE_TOOL_HTTPSV=false", + "-DFTE_TOOL_QCC=true", + "-DFTE_TOOL_IQM=false", + "-DFTE_TOOL_IMAGE=false", + + "-DCMAKE_INSTALL_PREFIX=/app", + "-DCMAKE_INSTALL_FULL_LIBDIR=/app/lib", + "-DCMAKE_INSTALL_DATAROOTDIR=/app/share", + "-DFTE_INSTALL_BINDIR=bin"], + "sources": [ + { + "type": "git", + "path": "/home/spike/quake/fteqw-code-git", + "//url": "https://github.com/fte-team/fteqw.git" + } + ] + } + ] +} + diff --git a/fteqw.desktop b/fteqw.desktop new file mode 100644 index 000000000..25012a204 --- /dev/null +++ b/fteqw.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=FTEQW Game Engine +Comment=Awesome First Person Shooter +Exec=fteqw %u +Icon=info.triptohell.fteqw +Terminal=false +Categories=Game; +MimeType=application/x-quakeworlddemo;x-scheme-handler/quake;x-scheme-handler/qw; +Actions=quake;rerel;netquake;quake2;quake3;hexen2;hexen2mp + +[Desktop Action quake] +Name=Play Quake +Exec=fteqw %u -quake + +[Desktop Action rerel] +Name=Play Quake Rerelease +Exec=fteqw %u -quake_rerel + +[Desktop Action netquake] +Name=Play Classic Quake +Exec=fteqw %u -netquake + +[Desktop Action quake2] +Name=Play QuakeII +Exec=fteqw %u -quake2 + +[Desktop Action quake3] +Name=Play Quake III Arena +Exec=fteqw %u -quake + +[Desktop Action hexen2] +Name=Play Hexen2 +Exec=fteqw %u -hexen2 + +[Desktop Action hexen2mp] +Name=Play Hexen2 Mission Pack +Exec=fteqw %u -portals + diff --git a/plugins/avplug/avdecode.c b/plugins/avplug/avdecode.c index 25a7804b5..dc45fb980 100644 --- a/plugins/avplug/avdecode.c +++ b/plugins/avplug/avdecode.c @@ -4,7 +4,7 @@ static plugfsfuncs_t *filefuncs; static plugaudiofuncs_t *audiofuncs; -//#include "libavcodec/avcodec.h" +#include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" diff --git a/plugins/avplug/avencode.c b/plugins/avplug/avencode.c index 3de872a6c..5eca9a074 100644 --- a/plugins/avplug/avencode.c +++ b/plugins/avplug/avencode.c @@ -3,7 +3,7 @@ #include "libavformat/avformat.h" //#include "libavformat/avio.h" -//#include "libavcodec/avcodec.h" +#include "libavcodec/avcodec.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h"