]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
File upload support added.
authorLockl00p <97256723+Lockl00p@users.noreply.github.com>
Tue, 10 Oct 2023 17:31:25 +0000 (12:31 -0500)
committerLockl00p <97256723+Lockl00p@users.noreply.github.com>
Tue, 10 Oct 2023 17:31:25 +0000 (12:31 -0500)
cl_main.c
host.c
menu.c
quakedef.h

index 9418ee06f7dd5811921a3dd57a2c92b691cf767e..21033e8956f1c3a9feb005b5baf84ad1ac7b89c4 100644 (file)
--- 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 a92a43841086efc7a9fb26fa8f44f8f225705a37..f1ff60e2e788dd5652b892d9100b4a714e85f297 100644 (file)
--- 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 8b41f28919ce8c1e0f48d0170618b857f660d668..c8d0c81c94a1103afb183d999b0296d3b7204f65 100644 (file)
--- 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 <emscripten.h>
 
+#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;
index 0facdc5ab452aa89c8e423b1e51f2984626ceb0a..480fab3d3bb19340865056690c91999e9909b34a 100644 (file)
@@ -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