From 497db80b9b689679dc6ad009a8efe14656064447 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Tue, 2 Jan 2024 05:54:43 -0600 Subject: [PATCH] Add in emscripten-specific branching menus and special load/save routines for online saving. --- Crawler/Crawler.cpp | 7 +- Crawler/Crawler.vcxproj | 4 ++ Crawler/Crawler.vcxproj.filters | 3 + Crawler/MainMenuWindow.cpp | 6 +- Crawler/Menu.cpp | 1 + Crawler/Menu.h | 2 + Crawler/MenuLabel.h | 6 +- Crawler/SaveFile.cpp | 90 ++++++++++++++----------- Crawler/UserIDMenu.cpp | 46 +++++++++++++ Crawler/Version.h | 2 +- Crawler/assets/config/configuration.txt | 6 +- Crawler/config.h | 2 + Crawler/emscripten_build.ps1 | 11 ++- Crawler/olcPixelGameEngine.h | 20 +++--- Crawler/olcUTIL_DataFile.h | 15 +++++ 15 files changed, 161 insertions(+), 60 deletions(-) create mode 100644 Crawler/UserIDMenu.cpp diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index a14d6257..5fd69fea 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -238,8 +238,6 @@ bool Crawler::OnUserCreate(){ #ifndef __EMSCRIPTEN__ SetupDiscord(); #endif - - SendRequest("index.html",""); return true; } @@ -2568,4 +2566,9 @@ void Crawler::ResetGame(){ void Crawler::OnRequestCompleted(const std::string_view receivedData)const{ std::cout<<"Received in engine: "< + + + + diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index 58a90e28..7da615e8 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -674,6 +674,9 @@ Source Files\Interface + + Source Files\Interface + diff --git a/Crawler/MainMenuWindow.cpp b/Crawler/MainMenuWindow.cpp index f6776e83..f37883a9 100644 --- a/Crawler/MainMenuWindow.cpp +++ b/Crawler/MainMenuWindow.cpp @@ -49,7 +49,11 @@ void Menu::InitializeMainMenuWindow(){ mainMenuWindow->ADD("New Game Button",MenuComponent)({{12,4},{72,24}},"New Game",[](MenuFuncData data){ game->TextEntryEnable(true); - Menu::OpenMenu(SAVE_FILE_NAME); + #ifdef __EMSCRIPTEN__ + Menu::OpenMenu(USER_ID); + #else + Menu::OpenMenu(SAVE_FILE_NAME); + #endif return true; })END; mainMenuWindow->ADD("Load Game Button",MenuComponent)({{12,36},{72,24}},"Load Game",[](MenuFuncData data){ diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 242e669f..6bb8a786 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -113,6 +113,7 @@ void Menu::InitializeMenus(){ InitializeConsumableCraftItemWindow(); InitializeSaveFileWindow(); InitializeLoadGameWindow(); + InitializeUserIDWindow(); for(MenuType type=MenuType(int(MenuType::ENUM_START)+1);typeGetWrappedTextSizeProp(label,rect.size.x,adjustedScale)): - vf2d(game->GetWrappedTextSize(label,rect.size.x,adjustedScale)); + vf2d(game->GetWrappedTextSizeProp(label,rect.size.x-8,adjustedScale)): + vf2d(game->GetWrappedTextSize(label,rect.size.x-8,adjustedScale)); if(fitToLabel){ labelTextSize= @@ -93,7 +93,7 @@ protected: } } - vf2d drawPos=rect.middle()-vf2d{labelTextSize}/2; //Assume centered. + vf2d drawPos=vf2d{-4.f,0.f}+rect.middle()-vf2d{labelTextSize}/2; //Assume centered. if(!centered){ drawPos=vf2d{rect.pos.x+2,rect.middle().y-labelTextSize.y/2}; //We should at least vertically align here. } diff --git a/Crawler/SaveFile.cpp b/Crawler/SaveFile.cpp index d7543092..f1fd6c07 100644 --- a/Crawler/SaveFile.cpp +++ b/Crawler/SaveFile.cpp @@ -114,55 +114,63 @@ const void SaveFile::SaveGame(){ utils::datafile::Write(metadata,"save_file_path"_S+"metadata.dat"); utils::datafile::INITIAL_SETUP_COMPLETE=true; + + #ifdef __EMSCRIPTEN__ + Server_SaveFile(); + #endif } const void SaveFile::LoadGame(){ - std::filesystem::create_directories("save_file_path"_S); - utils::datafile loadFile; - if(std::filesystem::exists("save_file_path"_S+std::format("save.{:04}",saveFileID))){ - utils::datafile::Read(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID)); - game->ResetGame(); - for(auto&[key,data]:loadFile["Items"].GetOrderedKeys()){ - std::weak_ptrnewItem=Inventory::AddItem(data["Item Name"].GetString(),data["Amt"].GetInt()); - newItem.lock()->enhancementLevel=data["Enhancement Level"].GetInt(); - if(loadFile.GetProperty(std::format("Items.{}",key)).HasProperty("Attributes")){ - for(auto&[attr,data]:loadFile.GetProperty(std::format("Items.{}.Attributes",key)).GetOrderedKeys()){ - newItem.lock()->randomizedStats.A(attr)=data.GetReal(); + #ifdef __EMSCRIPTEN__ + Server_GetFile(); + #else + std::filesystem::create_directories("save_file_path"_S); + utils::datafile loadFile; + if(std::filesystem::exists("save_file_path"_S+std::format("save.{:04}",saveFileID))){ + utils::datafile::Read(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID)); + game->ResetGame(); + for(auto&[key,data]:loadFile["Items"].GetOrderedKeys()){ + std::weak_ptrnewItem=Inventory::AddItem(data["Item Name"].GetString(),data["Amt"].GetInt()); + newItem.lock()->enhancementLevel=data["Enhancement Level"].GetInt(); + if(loadFile.GetProperty(std::format("Items.{}",key)).HasProperty("Attributes")){ + for(auto&[attr,data]:loadFile.GetProperty(std::format("Items.{}.Attributes",key)).GetOrderedKeys()){ + newItem.lock()->randomizedStats.A(attr)=data.GetReal(); + } } - } - if(data.HasProperty("LoadoutSlot")){ - uint8_t loadoutSlot=data["LoadoutSlot"].GetInt(); - if(loadoutSlot!=255){ - game->SetLoadoutItem(loadoutSlot,newItem.lock()->ActualName()); + if(data.HasProperty("LoadoutSlot")){ + uint8_t loadoutSlot=data["LoadoutSlot"].GetInt(); + if(loadoutSlot!=255){ + game->SetLoadoutItem(loadoutSlot,newItem.lock()->ActualName()); + } } - } - EquipSlot slot=EquipSlot(loadFile.GetProperty(std::format("Items.{}.Equip Slot",key)).GetInt()); - if(slot!=EquipSlot::NONE){ //This should be equipped somewhere! - Inventory::EquipItem(newItem,slot); + EquipSlot slot=EquipSlot(loadFile.GetProperty(std::format("Items.{}.Equip Slot",key)).GetInt()); + if(slot!=EquipSlot::NONE){ //This should be equipped somewhere! + Inventory::EquipItem(newItem,slot); + } } + game->ChangePlayerClass(classutils::StringToClass(loadFile["Player"]["Class"].GetString())); + game->GetPlayer()->level=loadFile["Player"]["Level"].GetInt(); + game->GetPlayer()->SetMoney(loadFile["Player"]["Money"].GetInt()); + game->GetPlayer()->currentLevelXP=loadFile["Player"]["Current EXP"].GetInt(); + game->GetPlayer()->totalXPEarned=loadFile["Player"]["Total EXP"].GetInt(); + for(auto&[key,data]:loadFile["Player"]["Base Stats"].GetOrderedKeys()){ + game->GetPlayer()->SetBaseStat(key,data.GetReal()); + } + for(const auto&[key,data]:loadFile["Unlocks"].GetOrderedKeys()){ + Unlock::UnlockArea(key); + } + State_OverworldMap::SetStageMarker(loadFile["Overworld Map Location"].GetString()); + game->SetChapter(loadFile["Chapter"].GetInt()); + SaveFile::SetSaveFileName(loadFile["Save Name"].GetString()); + game->SetRuntime(loadFile["Game Time"].GetReal()); + game->GetPlayer()->RecalculateEquipStats(); + + GameState::ChangeState(States::OVERWORLD_MAP,0.5f); + }else{ + std::cout<ChangePlayerClass(classutils::StringToClass(loadFile["Player"]["Class"].GetString())); - game->GetPlayer()->level=loadFile["Player"]["Level"].GetInt(); - game->GetPlayer()->SetMoney(loadFile["Player"]["Money"].GetInt()); - game->GetPlayer()->currentLevelXP=loadFile["Player"]["Current EXP"].GetInt(); - game->GetPlayer()->totalXPEarned=loadFile["Player"]["Total EXP"].GetInt(); - for(auto&[key,data]:loadFile["Player"]["Base Stats"].GetOrderedKeys()){ - game->GetPlayer()->SetBaseStat(key,data.GetReal()); - } - for(const auto&[key,data]:loadFile["Unlocks"].GetOrderedKeys()){ - Unlock::UnlockArea(key); - } - State_OverworldMap::SetStageMarker(loadFile["Overworld Map Location"].GetString()); - game->SetChapter(loadFile["Chapter"].GetInt()); - SaveFile::SetSaveFileName(loadFile["Save Name"].GetString()); - game->SetRuntime(loadFile["Game Time"].GetReal()); - game->GetPlayer()->RecalculateEquipStats(); - - GameState::ChangeState(States::OVERWORLD_MAP,0.5f); - }else{ - std::cout< + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions or derivations of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions or derivative works in binary form must reproduce the above +copyright notice. This list of conditions and the following disclaimer must be +reproduced in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +Portions of this software are copyright © 2023 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion + +#include "Menu.h" +#include "MenuLabel.h" + +void Menu::InitializeUserIDWindow(){ + Menu*userIDWindow=CreateMenu(USER_ID,CENTERED,vi2d{144,96}); + + userIDWindow->ADD("User ID Creation Explanation",MenuLabel)({{0,0},{144,96}},"user_id_message"_FS+"\n\n"+"user_id_message2"_FS,1.f,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END; +} \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index b01f7ba9..cafac076 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 5283 +#define VERSION_BUILD 5285 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/assets/config/configuration.txt b/Crawler/assets/config/configuration.txt index d2a3294b..0c9424e8 100644 --- a/Crawler/assets/config/configuration.txt +++ b/Crawler/assets/config/configuration.txt @@ -117,4 +117,8 @@ water_reflection_update_time = 0.5 water_reflection_time_step = 0.6 # the amount of scaling done to the water reflection. -water_reflection_scale_factor = 0.05 \ No newline at end of file +water_reflection_scale_factor = 0.05 + +# The message displayed to the user about ID creation. +user_id_message = You are playing the web build of this game. In order to save progress, we ask that you provide a unique username to identify your save data with. +user_id_message2 = Only game save data will be stored. \ No newline at end of file diff --git a/Crawler/config.h b/Crawler/config.h index be752d37..4665069a 100644 --- a/Crawler/config.h +++ b/Crawler/config.h @@ -51,6 +51,8 @@ utils::datafilefloatdata operator ""_f(const char*key,std::size_t len); utils::datafiledoubledata operator ""_d(const char*key,std::size_t len); //Read a string key from the config. std::string operator ""_S(const char*key,std::size_t len); +//Read a full string key from the config. +std::string operator ""_FS(const char*key,std::size_t len); //Read an integer key from the config. int operator ""_I(const char*key,std::size_t len); //Read a float key from the config. diff --git a/Crawler/emscripten_build.ps1 b/Crawler/emscripten_build.ps1 index 82d0964e..299cb300 100644 --- a/Crawler/emscripten_build.ps1 +++ b/Crawler/emscripten_build.ps1 @@ -1,3 +1,12 @@ cd .. ./emscripten_build.ps1 -./emscripten_run.ps1 \ No newline at end of file +if( -not $? ) +{ + $msg = $Error[0].Exception.Message + "$msg" + exit +} +else +{ + ./emscripten_run.ps1 +} \ No newline at end of file diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h index fa91d63f..df64b5b2 100644 --- a/Crawler/olcPixelGameEngine.h +++ b/Crawler/olcPixelGameEngine.h @@ -3718,13 +3718,13 @@ namespace olc skip--; continue; } - if(c==' '||c=='\t'){ + if(c==' '||c=='\t'||c=='\n'){ drawingMarker.x+=lettersWidth; lettersWidth=0; wrappingOccurred=false; } if(wrappingOccurred){ - if(c!=' '&&c!='\t'){ + if(c!=' '&&c!='\t'&&c!='\n'){ wrappingOccurred=false; maxWidth=std::max(maxWidth,drawingMarker.x); }else{ @@ -3835,7 +3835,7 @@ namespace olc skip--; continue; } - if(c==' '||c=='\t'){ + if(c==' '||c=='\t'||c=='\n'){ for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialSprite(vi2d(pos + drawingMarker), fontRenderable.Sprite(), vi2d(letter.sourcePos), vi2d(letter.sourceSize), scale, Sprite::Flip::NONE,letter.col); drawingMarker.x += 8.0f * scale; @@ -3844,7 +3844,7 @@ namespace olc wrappingOccurred=false; } if(wrappingOccurred){ - if(c!=' '&&c!='\t'){ + if(c!=' '&&c!='\t'&&c!='\n'){ wrappingOccurred=false; }else{ continue; @@ -3974,14 +3974,14 @@ namespace olc skip--; continue; } - if(c==' '||c=='\t'){ + if(c==' '||c=='\t'||c=='\n'){ drawingMarker.x+=lettersWidth; lettersWidth=0; wrappingOccurred=false; maxWidth=std::max(maxWidth,drawingMarker.x); } if(wrappingOccurred){ - if(c!=' '&&c!='\t'){ + if(c!=' '&&c!='\t'&&c!='\n'){ wrappingOccurred=false; }else{ continue; @@ -4065,7 +4065,7 @@ namespace olc skip--; continue; } - if(c==' '||c=='\t'){ + if(c==' '||c=='\t'||c=='\n'){ for(PixelGameEngine::StringDecalData&letter:letters){ DrawPartialSprite(vi2d(pos + drawingMarker), GetFontSprite(), vi2d(letter.sourcePos), vi2d(letter.sourceSize), scale,Sprite::Flip::NONE, letter.col); drawingMarker.x += float(vFontSpacing[letter.c - 32].y) * scale; @@ -4074,7 +4074,7 @@ namespace olc wrappingOccurred=false; } if(wrappingOccurred){ - if(c!=' '&&c!='\t'){ + if(c!=' '&&c!='\t'&&c!='\n'){ wrappingOccurred=false; }else{ continue; @@ -7106,7 +7106,8 @@ namespace olc EM_ASM({ - + + requestResp=""; // olc_ApsectRatio // // Used by olc_ResizeHandler to calculate the viewport from the @@ -7347,7 +7348,6 @@ namespace olc olc::Platform::ptrPGE->olc_CoreUpdate(); char*ptr=(char*)EM_ASM_PTR({ if(requestResp!==""){ - console.log("Request received: "+requestResp); var newPtr=stringToNewUTF8(requestResp); requestResp=""; return newPtr; diff --git a/Crawler/olcUTIL_DataFile.h b/Crawler/olcUTIL_DataFile.h index a07f4806..ffcd8df8 100644 --- a/Crawler/olcUTIL_DataFile.h +++ b/Crawler/olcUTIL_DataFile.h @@ -61,8 +61,11 @@ David Barr, aka javidx9, �OneLoneCoder 2019, 2020, 2021, 2022 #include #include #include +#include #include "Error.h" +using namespace std::literals; + int operator ""_I(const char*key,std::size_t len); namespace olc::utils @@ -96,6 +99,18 @@ namespace olc::utils } } + // Retrieves the String Value of a Property, to include all values that are normally separated by the list separator. + inline const std::string GetFullString() const + { + return std::accumulate(m_vContent.begin(),m_vContent.end(),""s,[](std::string str,const std::string&data){ + if(str.size()==0){ + return std::move(str)+data; + }else{ + return std::move(str)+","+data; + } + }); + } + // Retrieves the Real Value of a Property (for a given index) or 0.0 inline const double GetReal(const size_t nItem = 0) const {