From: Lockl00p <97256723+Lockl00p@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:31:25 +0000 (-0500) Subject: File upload support added. X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2f44cb8efee6d3cb6d49c8e1ce7013e175629036;p=xonotic%2Fdarkplaces.git File upload support added. --- diff --git a/cl_main.c b/cl_main.c index 9418ee06..21033e89 100644 --- a/cl_main.c +++ b/cl_main.c @@ -103,7 +103,11 @@ cvar_t cl_minfps_qualitymultiply = {CF_CLIENT | CF_ARCHIVE, "cl_minfps_qualitymu cvar_t cl_minfps_qualityhysteresis = {CF_CLIENT | CF_ARCHIVE, "cl_minfps_qualityhysteresis", "0.05", "reduce all quality increments by this to reduce flickering"}; cvar_t cl_minfps_qualitystepmax = {CF_CLIENT | CF_ARCHIVE, "cl_minfps_qualitystepmax", "0.1", "maximum quality change in a single frame"}; cvar_t cl_minfps_force = {CF_CLIENT, "cl_minfps_force", "0", "also apply quality reductions in timedemo/capturevideo"}; +#ifndef __EMSCRIPTEN__ cvar_t cl_maxfps = {CF_CLIENT | CF_ARCHIVE, "cl_maxfps", "0", "maximum fps cap, 0 = unlimited, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"}; +#else +cvar_t cl_maxfps = {CF_CLIENT | CF_ARCHIVE, "cl_maxfps", "60", "maximum fps cap, 0 = unlimited, if game is running faster than this it will wait before running another frame (useful to make cpu time available to other programs)"}; +#endif cvar_t cl_maxfps_alwayssleep = {CF_CLIENT | CF_ARCHIVE, "cl_maxfps_alwayssleep","1", "gives up some processing time to other applications each frame, value in milliseconds, disabled if cl_maxfps is 0"}; cvar_t cl_maxidlefps = {CF_CLIENT | CF_ARCHIVE, "cl_maxidlefps", "20", "maximum fps cap when the game is not the active window (makes cpu time available to other programs"}; diff --git a/host.c b/host.c index a92a4384..f1ff60e2 100644 --- a/host.c +++ b/host.c @@ -43,6 +43,148 @@ A client can NOT be started if the system started as a dedicated server. Memory is cleared / released when a server or client begins, not when they end. */ +#ifdef __EMSCRIPTEN__ + +EM_JS(bool,syncFS,(bool x),{ + FS.syncfs(x,function(e){ + if(e){ + alert("FileSystem Save Error: "+e); + return false; + } else{ + console.log("Filesystem Saved!"); + return true; + } + })}); + +EM_JS(void,emshutdown,(),{ + FS.syncfs(false,function(e){ + if(e){ + alert("FileSystem Save Error: "+e+" while shutting down."); + return false; + } else{ + console.log("Filesystem Saved!"); + return true; + } + }); + window.close(); +}) + +EM_JS(char*,rm,(char* x),{ + const mode = FS.lookupPath(UTF8ToString(x)).node.mode; + if(FS.isFile(mode)){ + FS.unlink(UTF8ToString(x)); + return stringToNewUTF8("File removed"); + } + else { + return stringToNewUTF8(x+" is not a File."); + } + }); + +EM_JS(char*,rmdir,(char* x),{ + const mode = FS.lookupPath(UTF8ToString(x)).node.mode; + if(FS.isDir(mode)){ + try{FS.rmdir(UTF8ToString(x));} catch (error) {return stringToNewUTF8("Unable to remove directory. Is it not empty?");} + + return stringToNewUTF8("Directory removed"); + } + else { + return stringToNewUTF8(x+" is not a directory."); + } + }); + +EM_JS(void,readyup,(),{ + if (isready() == 0) { + alert("No GameData Found. Please upload all GameData using the \"em_upload\" command, save with \"em_save\" and restart the game!"); + //straight off stackoverflow(well, slightly changed). Thanks, Riot! + FS.mkdir("/save/data"); + } +}); + +EM_JS(char*,upload,(char* todirectory),{ + if(UTF8ToString(todirectory).slice(-1) != "/"){ + currentname = UTF8ToString(todirectory) + "/"; + } + else{ + currentname = UTF8ToString(todirectory); + } + + file_selector.click(); + return stringToNewUTF8("Upload started"); + +}); + +EM_JS(char*, listfiles,(char* directory),{ if(UTF8ToString(directory) == ""){ + console.log("listing cwd"); + return stringToNewUTF8(FS.readdir(FS.cwd()).toString()) +} +try{ +return stringToNewUTF8(FS.readdir(UTF8ToString(directory)).toString()); +} catch(error){ + return stringToNewUTF8("directory not found"); +} +}); + +void listfiles_f(cmd_state_t *cmd){ + if(Cmd_Argc(cmd) != 2){ + + Con_Printf(listfiles("")); + Con_Printf("\n"); + } + else{ + Con_Printf(listfiles(Cmd_Argv(cmd,1)) ); + Con_Printf("\n"); + } +} +void savefs_f(cmd_state_t *cmd){ + Con_Printf("Saving Files\n"); + if(syncFS(false)){ + Con_Printf("Files Saved to Browser Storage\n"); + } else{ + Con_Printf("File Save failed.\n"); + } +} + +void upload_f(cmd_state_t *cmd){ + if(Cmd_Argc(cmd) != 2){ + Con_Printf(upload("/save/data")); + Con_Printf("\n"); + } + else{ + Con_Printf(upload(Cmd_Argv(cmd,1))); + Con_Printf("\n"); + } +} + +void rm_f(cmd_state_t *cmd){ + if(Cmd_Argc(cmd) != 2){ + Con_Printf("No file to remove"); + } + else{ + Con_Printf(rm(Cmd_Argv(cmd,1))); + Con_Printf("\n"); + } +} + +void rmdir_f(cmd_state_t *cmd){ + if(Cmd_Argc(cmd) != 2){ + Con_Printf("No directory to remove"); + } + else{ + Con_Printf(rmdir(Cmd_Argv(cmd,1))); + Con_Printf("\n"); + } +} +bool engineup = false; + +void fillcanvas(){ + EmscriptenFullscreenStrategy strat; + strat.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF; + strat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF; + strat.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; + emscripten_enter_soft_fullscreen("canvas",&strat); +} + +#endif host_static_t host; @@ -67,6 +209,8 @@ cvar_t locksession = {CF_CLIENT | CF_SERVER, "locksession", "0", "Lock the sessi cvar_t host_isclient = {CF_SHARED | CF_READONLY, "_host_isclient", "0", "If 1, clientside is active."}; + + /* ================ Host_AbortCurrentFrame @@ -214,7 +358,7 @@ void Host_SaveConfig(const char *file) FS_Close (f); } - EM_ASM(FS.syncfs()); + syncFS(false); } static void Host_SaveConfig_f(cmd_state_t *cmd) @@ -253,6 +397,9 @@ Resets key bindings and cvars to defaults and then reloads scripts */ static void Host_LoadConfig_f(cmd_state_t *cmd) { + #ifdef __EMSCRIPTEN__ + syncFS(true); + #endif // reset all cvars, commands and aliases to init values Cmd_RestoreInitState(); #ifdef CONFIG_MENU @@ -276,6 +423,13 @@ static void Host_InitLocal (void) Cmd_AddCommand(CF_SHARED, "saveconfig", Host_SaveConfig_f, "save settings to config.cfg (or a specified filename) immediately (also automatic when quitting)"); Cmd_AddCommand(CF_SHARED, "loadconfig", Host_LoadConfig_f, "reset everything and reload configs"); Cmd_AddCommand(CF_SHARED, "sendcvar", SendCvar_f, "sends the value of a cvar to the server as a sentcvar command, for use by QuakeC"); + #ifdef __EMSCRIPTEN__ + Cmd_AddCommand(CF_SHARED, "em_ls", listfiles_f, "Lists Files in specified directory defaulting to the current working directory (Emscripten Only)"); + Cmd_AddCommand(CF_SHARED, "em_upload", upload_f, "Upload file to specified directory defaulting to /save/data (Emscripten Only)"); + Cmd_AddCommand(CF_SHARED, "em_save", savefs_f, "Save file changes to browser (Emscripten Only)"); + Cmd_AddCommand(CF_SHARED, "em_rm", rm_f, "Remove a file from game Filesystem (Emscripten Only)"); + Cmd_AddCommand(CF_SHARED, "em_rmdir", rmdir_f, "Remove a directory from game Filesystem (Emscripten Only)"); + #endif Cvar_RegisterVariable (&host_framerate); Cvar_RegisterCallback (&host_framerate, Host_Framerate_c); Cvar_RegisterVariable (&host_speeds); @@ -371,6 +525,10 @@ Host_Init */ static void Host_Init (void) { + #ifdef __EMSCRIPTEN__ + readyup(); + fillcanvas(); + #endif int i; const char* os; char vabuf[1024]; @@ -452,7 +610,11 @@ static void Host_Init (void) FS_Init(); // construct a version string for the corner of the console - os = DP_OS_NAME; + #ifndef __EMSCRIPTEN__ + os = DP_OS_NAME; + #else + os = "Emscripten"; + #endif dpsnprintf (engineversion, sizeof (engineversion), "%s %s %s", gamename, os, buildstring); Con_Printf("%s\n", engineversion); @@ -562,7 +724,10 @@ static void Host_Init (void) } Con_DPrint("========Initialized=========\n"); - + + #ifdef __EMSCRIPTEN__ + engineup = true; + #endif if (cls.state != ca_dedicated) SV_StartThread(); } @@ -729,11 +894,15 @@ static inline double Host_UpdateTime (double newtime, double oldtime) return time; } -#ifdef __EMSCRIPTEN__ -EM_JS(void,emshutdown,(),{FS.syncfs(); window.close();}); -#endif + void Host_Loop(void){ // Something bad happened, or the server disconnected + #ifdef __EMSCRIPTEN__ + if(engineup == false){ + return; + } + #endif + if (setjmp(host.abortframe)) { host.state = host_active; // In case we were loading @@ -748,18 +917,19 @@ void Host_Loop(void){ sleeptime -= Sys_DirtyTime() - host.dirtytime; // execution time host.sleeptime = Host_Sleep(sleeptime); + #ifdef __EMSCRIPTEN__ - if(host.state == host_shutdown){ - emshutdown(); - } + if(host.state == host_shutdown){emshutdown(); engineup = false;} #endif + } + + void Host_Main(void) { - + Host_Init(); // Start! - host.realtime = 0; oldtime = Sys_DirtyTime(); diff --git a/menu.c b/menu.c index 8b41f289..c8d0c81c 100644 --- a/menu.c +++ b/menu.c @@ -21,9 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cdaudio.h" #include "image.h" #include "progsvm.h" - #include "mprogdefs.h" +#ifdef __EMSCRIPTEN__ + #include +#endif #define TYPE_DEMO 1 #define TYPE_GAME 2 #define TYPE_BOTH 3 @@ -358,7 +360,7 @@ static int m_main_cursor; static qbool m_missingdata = false; static int MAIN_ITEMS = 4; // Nehahra: Menu Disable - +static qbool emmenu = false; void M_Menu_Main_f(cmd_state_t *cmd) { @@ -412,10 +414,15 @@ void M_Menu_Main_f(cmd_state_t *cmd) MAIN_ITEMS = 5; // check if the game data is missing and use a different main menu if so + m_missingdata = !forceqmenu.integer && !Draw_IsPicLoaded(Draw_CachePic_Flags(s, CACHEPICFLAG_FAILONMISSING)); if (m_missingdata) MAIN_ITEMS = 2; + #ifdef __EMSCRIPTEN__ + MAIN_ITEMS=1; + emmenu = true; + #endif /* if (key_dest != key_menu) { @@ -435,7 +442,14 @@ static void M_Main_Draw (void) cachepic_t *p; char vabuf[1024]; - if (m_missingdata) + if(emmenu){ + M_Background(640, 480); //fall back is always to 640x480, this makes it most readable at that. + float y; + const char *s; + y = 480/3-16; + s = "Press Enter to Start Game";M_PrintRed ((640-strlen(s)*8)*0.5, (480/3)-16, s);y+=8; + } + else if (m_missingdata) { float y; const char *s; @@ -495,7 +509,11 @@ static void M_Main_Draw (void) M_DrawPic (54, 32 + m_main_cursor * 20, va(vabuf, sizeof(vabuf), "gfx/menudot%i", f+1)); } +void M_Menu_Restart_f(cmd_state_t *cmd){ + Cbuf_AddText(cmd, "loadconfig\nmenu_reset\n"); + Cbuf_Execute(cmd->cbuf); +} static void M_Main_Key(cmd_state_t *cmd, int key, int ascii) { @@ -523,7 +541,10 @@ static void M_Main_Key(cmd_state_t *cmd, int key, int ascii) case K_ENTER: m_entersound = true; - + if(emmenu){ + emmenu = false; + M_Menu_Restart_f(cmd); + } if (m_missingdata) { switch (m_main_cursor) @@ -2734,6 +2755,7 @@ static void M_Keys_Key(cmd_state_t *cmd, int k, int ascii) } } + void M_Menu_Reset_f(cmd_state_t *cmd) { key_dest = key_menu; diff --git a/quakedef.h b/quakedef.h index 0facdc5a..480fab3d 100644 --- a/quakedef.h +++ b/quakedef.h @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __EMSCRIPTEN__ #define CONFIGFILENAME "config.cfg" #else - #define CONFIGFILENAME "/config/config.cfg" + #define CONFIGFILENAME "/save/config.cfg" #endif // moveflags values