From 20882990e011f149ae77db117f52526f1cdc9f9a Mon Sep 17 00:00:00 2001 From: WasabiRaptor Date: Tue, 28 May 2024 10:44:34 -0400 Subject: [PATCH 1/4] error handling for missing techs --- source/game/StarPlayerTech.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/game/StarPlayerTech.cpp b/source/game/StarPlayerTech.cpp index 133f5f7..3f2db05 100644 --- a/source/game/StarPlayerTech.cpp +++ b/source/game/StarPlayerTech.cpp @@ -9,9 +9,13 @@ PlayerTech::PlayerTech() {} PlayerTech::PlayerTech(Json const& json) { m_availableTechs = jsonToStringSet(json.get("availableTechs")); m_enabledTechs = jsonToStringSet(json.get("enabledTechs")); - m_equippedTechs = jsonToMapKV>(json.get("equippedTechs"), [](Json t) { - return TechTypeNames.getLeft(t.toString()); - }, mem_fn(&Json::toString)); + auto techDatabase = Root::singleton().techDatabase(); + for (auto p : json.get("equippedTechs", JsonObject()).iterateObject()) { + if (techDatabase->contains(p.second.toString())) + m_equippedTechs.set(TechTypeNames.getLeft(p.first), p.second.toString()); + else + Logger::warn("Missing tech '%s' in slot '%s'", p.second.toString(), p.first); + } } Json PlayerTech::toJson() const { From 3cdc8316d63259484293de462a3275e8d4fde05f Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 29 May 2024 11:10:35 +1000 Subject: [PATCH 2/4] fix vertically offcenter graphicsmenu header text [skip ci] --- .../opensb/interface/windowconfig/graphicsmenu.config.patch.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/opensb/interface/windowconfig/graphicsmenu.config.patch.lua b/assets/opensb/interface/windowconfig/graphicsmenu.config.patch.lua index c808db7..02d305c 100644 --- a/assets/opensb/interface/windowconfig/graphicsmenu.config.patch.lua +++ b/assets/opensb/interface/windowconfig/graphicsmenu.config.patch.lua @@ -42,7 +42,7 @@ function patch(config) shift(clone(layout, "multiTextureLabel", "hardwareCursorLabel"), 98, -11).value = "HARDWARE CURSOR" shift(clone(layout, "multiTextureCheckbox", "hardwareCursorCheckbox"), 99, -11) - shift(layout.title, 0, 28) + shift(layout.title, 0, 24) shift(layout.resLabel, 0, 28) shift(layout.resSlider, 0, 28) shift(layout.resValueLabel, 0, 28) From 465f07a9b774d147bc7a55d600bdfd1cd9a7c4d4 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 29 May 2024 11:31:54 +1000 Subject: [PATCH 3/4] fix unknown tech logging --- source/game/StarPlayerTech.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/game/StarPlayerTech.cpp b/source/game/StarPlayerTech.cpp index 3f2db05..bf8053f 100644 --- a/source/game/StarPlayerTech.cpp +++ b/source/game/StarPlayerTech.cpp @@ -10,11 +10,12 @@ PlayerTech::PlayerTech(Json const& json) { m_availableTechs = jsonToStringSet(json.get("availableTechs")); m_enabledTechs = jsonToStringSet(json.get("enabledTechs")); auto techDatabase = Root::singleton().techDatabase(); - for (auto p : json.get("equippedTechs", JsonObject()).iterateObject()) { - if (techDatabase->contains(p.second.toString())) - m_equippedTechs.set(TechTypeNames.getLeft(p.first), p.second.toString()); + for (auto& p : json.getObject("equippedTechs")) { + String techName = p.second.toString(); + if (techDatabase->contains(techName)) + m_equippedTechs.set(TechTypeNames.getLeft(p.first), techName); else - Logger::warn("Missing tech '%s' in slot '%s'", p.second.toString(), p.first); + Logger::warn("Unequipping unknown tech '{}' from slot '{}'", techName, p.first); } } From a88b1e4ce07ad7aceb01babc232c43630fea85d2 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 29 May 2024 12:42:14 +1000 Subject: [PATCH 4/4] sequence parsing and parseArguments fixes --- source/core/StarJsonParser.hpp | 73 ++++++++++++-------- source/frontend/StarInterfaceLuaBindings.cpp | 4 +- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/source/core/StarJsonParser.hpp b/source/core/StarJsonParser.hpp index 0bf7443..5736f7f 100644 --- a/source/core/StarJsonParser.hpp +++ b/source/core/StarJsonParser.hpp @@ -39,7 +39,7 @@ template class JsonParser { public: JsonParser(JsonStream& stream) - : m_line(0), m_column(0), m_stream(stream) {} + : m_line(0), m_column(0), m_stream(stream), m_error(nullptr) {} virtual ~JsonParser() {} // Does not throw. On error, returned iterator will not be equal to end, and @@ -65,10 +65,7 @@ public: // Human readable parsing error, does not include line or column info. char const* error() const { - if (m_error.empty()) - return nullptr; - else - return m_error.c_str(); + return m_error; } size_t line() const { @@ -216,31 +213,42 @@ private: break; else { auto begin = m_current; + auto b_char = m_char; if (m_char >= '0' && m_char <= '9') { - number(); - if (m_error.empty()) { + try { + number(true); + } + catch (ParsingException const&) { + m_current = begin; + m_char = b_char; + } + if (m_error == nullptr) { next(); continue; } } - m_error.clear(); - m_current = begin; + m_error = nullptr; if (m_char == 't' || m_char == 'f' || m_char == 'n') { - word(); - if (m_error.empty()) { + try { + word(true); + } + catch (ParsingException const&) { + m_current = begin; + m_char = b_char; + } + if (m_error == nullptr) { next(); continue; } } - m_error.clear(); - m_current = begin; + m_error = nullptr; // well, shit. do a simple string parse until we hit whitespace // no fancy things like \n, do a proper string if you want that CharArray str; do { str += m_char; next(); - } while (m_char && !isSpace(m_char)); + } while (m_char != 0 && !isSpace(m_char)); m_stream.putString(str.c_str(), str.length()); } next(); @@ -253,7 +261,7 @@ private: m_stream.putString(s.c_str(), s.length()); } - void number() { + void number(bool seq = false) { std::basic_string buffer; bool isDouble = false; @@ -297,30 +305,35 @@ private: next(); } } + + if (seq && m_char != 0 && !isSpace(m_char)) + error("unexpected character after number"); if (isDouble) { try { m_stream.putDouble(buffer.c_str(), buffer.length()); } catch (std::exception const& e) { - error(std::string("Bad double: ") + e.what()); + error("bad double"); } } else { try { m_stream.putInteger(buffer.c_str(), buffer.length()); } catch (std::exception const& e) { - error(std::string("Bad integer: ") + e.what()); + error("bad integer"); } } } // true, false, or null - void word() { + void word(bool seq = false) { switch (m_char) { case 't': next(); check('r'); check('u'); check('e'); + if (seq && m_char != 0 && !isSpace(m_char)) + error("unexpected character after word"); m_stream.putBoolean(true); break; case 'f': @@ -329,6 +342,8 @@ private: check('l'); check('s'); check('e'); + if (seq && m_char != 0 && !isSpace(m_char)) + error("unexpected character after word"); m_stream.putBoolean(false); break; case 'n': @@ -336,6 +351,8 @@ private: check('u'); check('l'); check('l'); + if (seq && m_char != 0 && !isSpace(m_char)) + error("unexpected character after word"); m_stream.putNull(); break; default: @@ -502,34 +519,32 @@ private: } } else { // The only allowed characters following / in whitespace are / and * - error("/ character in whitespace is not follwed by '/' or '*', invalid comment"); + error("/ character in whitespace is not followed by '/' or '*', invalid comment"); return; } } else if (isSpace(m_char)) { buffer += m_char; next(); } else { - if (buffer.size() != 0) - m_stream.putWhitespace(buffer.c_str(), buffer.length()); - return; + break; } } if (buffer.size() != 0) m_stream.putWhitespace(buffer.c_str(), buffer.length()); } - void error(std::string msg) { - m_error = std::move(msg); + void error(const char* msg) { + m_error = msg; throw ParsingException(); } bool isSpace(char32_t c) { // Only whitespace allowed by JSON return c == 0x20 || // space - c == 0x09 || // horizontal tab - c == 0x0a || // newline - c == 0x0d || // carriage return - c == 0xfeff; // BOM or ZWNBSP + c == 0x09 || // horizontal tab + c == 0x0a || // newline + c == 0x0d || // carriage return + c == 0xfeff; // BOM or ZWNBSP } char32_t m_char; @@ -537,7 +552,7 @@ private: InputIterator m_end; size_t m_line; size_t m_column; - std::string m_error; + const char* m_error; JsonStream& m_stream; }; diff --git a/source/frontend/StarInterfaceLuaBindings.cpp b/source/frontend/StarInterfaceLuaBindings.cpp index 9523036..cbacb59 100644 --- a/source/frontend/StarInterfaceLuaBindings.cpp +++ b/source/frontend/StarInterfaceLuaBindings.cpp @@ -61,8 +61,8 @@ LuaCallbacks LuaBindings::makeChatCallbacks(MainInterface* mainInterface, Univer }); // just for SE compat - this shoulda been a utility callback :moyai: - callbacks.registerCallback("parseArguments", [](String const& args) { - return Json::parseSequence(args); + callbacks.registerCallback("parseArguments", [](String const& args) -> LuaVariadic { + return Json::parseSequence(args).toArray(); }); callbacks.registerCallback("command", [mainInterface](String const& command) -> StringList {