diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c18fe17..08384af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,13 +18,13 @@ jobs: - name: macOS os: macos-latest - - name: Android32 - os: ubuntu-latest - target: Android32 + # - name: Android32 + # os: ubuntu-latest + # target: Android32 - - name: Android64 - os: ubuntu-latest - target: Android64 + # - name: Android64 + # os: ubuntu-latest + # target: Android64 name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c11de..cfb85da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [3.0.0-beta.1] - 2024-11-28 + +### Changed + +- Target Windows and Mac only, until I find a fix for Android later +- Renamed GD List ID key to "gd-list-id" + +### Fixed + +- Integer input layer crash on android + ## [3.0.0] - 2024-11-24 ### Added diff --git a/mod.json b/mod.json index e08d816..b12708e 100644 --- a/mod.json +++ b/mod.json @@ -2,10 +2,9 @@ "geode": "4.0.1", "gd": { "win": "2.2074", - "android": "2.2074", "mac": "2.2074" }, - "version": "v3.0.0", + "version": "v3.0.0-beta.1", "id": "spaghettdev.gd-roulette", "name": "GD-Roulette", "developer": "SpaghettDev", diff --git a/src/custom_layers/RLIntegerInputLayer.cpp b/src/custom_layers/RLIntegerInputLayer.cpp index b87035e..c87549a 100644 --- a/src/custom_layers/RLIntegerInputLayer.cpp +++ b/src/custom_layers/RLIntegerInputLayer.cpp @@ -94,7 +94,7 @@ void RLIntegerInputLayer::onClose(CCObject*) { try { - m_integer = std::stoi(input_node->getString()); + m_integer = numFromString(input_node->getString()).unwrapOr(m_iili.fallback_value); } catch (...) { @@ -117,7 +117,7 @@ void RLIntegerInputLayer::onLeftButton(CCObject*) { try { - m_integer = std::stoi(input_node->getString()) - 1; + m_integer = numFromString(input_node->getString()).unwrapOr(m_iili.fallback_value) - 1; } catch (...) { @@ -135,7 +135,7 @@ void RLIntegerInputLayer::onRightButton(CCObject*) { try { - m_integer = std::stoi(input_node->getString()) + 1; + m_integer = numFromString(input_node->getString()).unwrapOr(m_iili.fallback_value) + 1; } catch (...) { diff --git a/src/roulette/manager/DataManager.hpp b/src/roulette/manager/DataManager.hpp index e37f49f..3a39732 100644 --- a/src/roulette/manager/DataManager.hpp +++ b/src/roulette/manager/DataManager.hpp @@ -36,7 +36,7 @@ namespace DataManager }; const std::unordered_map MISC_KEY_TO_NAME{ - { DMMiscKey::GD_LIST_ID, "gdListID" }, + { DMMiscKey::GD_LIST_ID, "gd-list-id" }, }; struct SavedArrayInfo @@ -56,6 +56,52 @@ namespace DataManager }; } + namespace + { + const auto saveDataPath = geode::Mod::get()->getSaveDir() / "save_data"; + + GameState readGameState() + { + GameState fromDisk; + std::ifstream saveDataFile(saveDataPath, std::ios::binary); + saveDataFile.read(reinterpret_cast(&fromDisk), sizeof(GameState)); + + // TODO: Add checksum and integrity check here or something + + return fromDisk; + } + + GameState writeGameStateSafe(bool force_clean = false) + { + std::ifstream saveDataFileIn(saveDataPath, std::ios::binary); + saveDataFileIn.seekg(0, std::ios::end); + + if (force_clean || saveDataFileIn.fail() || saveDataFileIn.tellg() != sizeof(GameState)) + { + GameState defaultValue; + + std::ofstream saveDataFileOut(saveDataPath, std::ios::binary); + saveDataFileOut.write(reinterpret_cast(&defaultValue), sizeof(GameState)); + + return defaultValue; + } + + GameState fromDisk; + saveDataFileIn.seekg(0); + saveDataFileIn.read(reinterpret_cast(&fromDisk), sizeof(GameState)); + + return fromDisk; + } + + void writeGameState(const GameState& value) + { + std::ofstream(saveDataPath, std::ios::binary).write( + reinterpret_cast(&value), + sizeof(GameState) + ); + } + } + namespace traits { template @@ -122,17 +168,6 @@ namespace DataManager template [[nodiscard]] traits::KeyTrait::type get() { - using value_t = typename traits::KeyTrait::type; - - if constexpr (key == DMMiscKey::SAVE_DATA) - { - value_t fromDisk; - std::ifstream saveDataFile(geode::Mod::get()->getSaveDir() / "save_data", std::ios::binary); - saveDataFile.read(reinterpret_cast(&fromDisk), sizeof(value_t)); - - return fromDisk; - } - return setDefaultSafe(); } @@ -173,17 +208,9 @@ namespace DataManager void set(const typename traits::KeyTrait::type& value) { if constexpr (key == DMMiscKey::SAVE_DATA) - { - std::ofstream saveDataFile(geode::Mod::get()->getSaveDir() / "save_data"); - saveDataFile.write( - reinterpret_cast(&value), - sizeof(typename traits::KeyTrait::type) - ); - } + writeGameState(value); else - { geode::Mod::get()->setSavedValue(values::MISC_KEY_TO_NAME.at(key), value); - } } @@ -223,26 +250,7 @@ namespace DataManager using save_container_t = std::conditional_t, uint64_t, value_t>; if constexpr (key == DMMiscKey::SAVE_DATA) - { - std::ifstream saveDataFileIn(geode::Mod::get()->getSaveDir() / "save_data", std::ios::binary); - saveDataFileIn.seekg(0, std::ios::end); - - if (saveDataFileIn.fail() || saveDataFileIn.tellg() != sizeof(value_t)) - { - value_t defaultValue; - - std::ofstream saveDataFileOut(geode::Mod::get()->getSaveDir() / "save_data", std::ios::binary); - saveDataFileOut.write(reinterpret_cast(&defaultValue), sizeof(value_t)); - - return defaultValue; - } - - value_t fromDisk; - saveDataFileIn.seekg(0); - saveDataFileIn.read(reinterpret_cast(&fromDisk), sizeof(value_t)); - - return fromDisk; - } + return writeGameStateSafe(); else { auto& container = geode::Mod::get()->getSaveContainer(); diff --git a/src/roulette/manager/GameState.hpp b/src/roulette/manager/GameState.hpp index 1befb73..92ac6cd 100644 --- a/src/roulette/manager/GameState.hpp +++ b/src/roulette/manager/GameState.hpp @@ -1,9 +1,11 @@ #pragma once +static_assert(true); // clangd bug fix + #pragma pack(push, 1) struct GameState { - int levelID = 0; + int levelID = 0; int skipsUsed = 0; int numLevels = 0; int levelPercentage = 0;