From c8c73792891d621580c33767e0f1c0dc6b89110c Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 4 Mar 2021 21:33:51 +1100 Subject: [PATCH] Webclient: In singleplayer, show confirmation dialog before closing page unless map was saved within last 5 seconds --- src/Game.c | 5 +++++ src/Game.h | 2 ++ src/Menus.c | 1 + src/Window.c | 7 +++++++ src/World.c | 3 ++- src/World.h | 2 ++ 6 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Game.c b/src/Game.c index cd29e02c8..c74bd155b 100644 --- a/src/Game.c +++ b/src/Game.c @@ -649,6 +649,11 @@ static void Game_RunLoop(void) { /* Now thats there's a main loop, Game_SetFpsLimit will actually do something */ Game_SetFpsLimit(Options_GetEnum(OPT_FPS_LIMIT, 0, FpsLimit_Names, FPS_LIMIT_COUNT)); } + +cc_bool Game_ShouldClose(void) { + /* Running in multiplayer or map was saved within last 5 seconds */ + return !Server.IsSinglePlayer || (World.LastSave + 5 >= Game.Time); +} #else static void Game_RunLoop(void) { cc_uint64 lastRender, render; diff --git a/src/Game.h b/src/Game.h index d0c31e03b..de69a8194 100644 --- a/src/Game.h +++ b/src/Game.h @@ -78,6 +78,8 @@ void Game_SetFpsLimit(int method); /* Runs the main game loop until the window is closed. */ void Game_Run(int width, int height, const cc_string* title); +/* Whether the game should be allowed to automatically close */ +cc_bool Game_ShouldClose(void); /* Represents a game component. */ struct IGameComponent; diff --git a/src/Menus.c b/src/Menus.c index 0ace8c052..a446e83cb 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -1398,6 +1398,7 @@ static void SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string* #else Chat_Add1("&eSaved map to: %s", path); #endif + World.LastSave = Game.Time; Gui_ShowPauseMenu(); } diff --git a/src/Window.c b/src/Window.c index 9007e1031..07c2f0936 100644 --- a/src/Window.c +++ b/src/Window.c @@ -2745,6 +2745,7 @@ void Window_FreeFramebuffer(struct Bitmap* bmp) { #include #include #include +#include "Game.h" static cc_bool keyboardOpen, needResize; static int RawDpiScale(int x) { return (int)(x * emscripten_get_device_pixel_ratio()); } @@ -2908,6 +2909,12 @@ static EM_BOOL OnFullscreenChange(int type, const EmscriptenFullscreenChangeEven } static const char* OnBeforeUnload(int type, const void* ev, void *data) { + if (!Game_ShouldClose()) { + /* Exit pointer lock, otherwise when you press Ctrl+W, the */ + /* cursor remains invisible in the confirmation dialog */ + emscripten_exit_pointerlock(); + return "You have unsaved changes. Are you sure you want to quit?"; + } Window_Close(); return NULL; } diff --git a/src/World.c b/src/World.c index 958fe6ddb..834e75105 100644 --- a/src/World.c +++ b/src/World.c @@ -46,7 +46,8 @@ void World_Reset(void) { World.Blocks = NULL; World_SetDimensions(0, 0, 0); - World.Loaded = false; + World.Loaded = false; + World.LastSave = -200; Env_Reset(); } diff --git a/src/World.h b/src/World.h index b2d23b2f5..35fe083e2 100644 --- a/src/World.h +++ b/src/World.h @@ -44,6 +44,8 @@ CC_VAR extern struct _WorldData { /* Whether the world has finished loading/generating. */ /* NOTE: Blocks may still be NULL. (e.g. error during loading) */ cc_bool Loaded; + /* Point in time the current world was last saved at */ + double LastSave; } World; /* Frees the blocks array, sets dimensions to 0, resets environment to default. */