diff --git a/include/Cubed/tools/json_utils.hpp b/include/Cubed/tools/json_utils.hpp new file mode 100644 index 0000000..043742c --- /dev/null +++ b/include/Cubed/tools/json_utils.hpp @@ -0,0 +1,8 @@ + +#include +#include +#include +namespace Tools { +std::unordered_map +doc_to_map(const rapidjson::Document& doc); +} \ No newline at end of file diff --git a/include/Cubed/tools/sensitive_filter.hpp b/include/Cubed/tools/sensitive_filter.hpp index a980921..bf93e9f 100644 --- a/include/Cubed/tools/sensitive_filter.hpp +++ b/include/Cubed/tools/sensitive_filter.hpp @@ -1,11 +1,13 @@ #pragma once -#include +#include +#include +#include namespace Cubed { class SensitiveFilter { public: SensitiveFilter(); - void load(const nlohmann::json& j); + void load(const rapidjson::Document& doc); std::string filter(std::string_view text); private: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6427fe9..99ce13c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,4 +103,5 @@ target_sources(${PROJECT_NAME} gameplay/server_entity_manager.cpp gameplay/client_entity_manager.cpp gameplay/systems/wander_ai_system.cpp + tools/json_utils.cpp ) \ No newline at end of file diff --git a/src/gameplay/hitbox_manager.cpp b/src/gameplay/hitbox_manager.cpp index ba29357..e1d1514 100644 --- a/src/gameplay/hitbox_manager.cpp +++ b/src/gameplay/hitbox_manager.cpp @@ -5,9 +5,10 @@ #include "Cubed/tools/log.hpp" #include "Cubed/tools/name_space.hpp" -#include +#include +#include namespace fs = std::filesystem; -using nlohmann::json; +using namespace rapidjson; namespace Cubed { HitboxManager::HitboxManager() { @@ -84,21 +85,30 @@ HitboxManager::Handle HitboxManager::load(std::string_view name) { glm::vec3 center; glm::vec3 half; std::ifstream s{p}; - json j = json::parse(s); - if (j.contains("boxes")) { - const json* box = &j["boxes"]; - if (box->is_array() && !box->empty()) { - box = &(*box)[0]; - } - if (box->contains("center")) { - center.x = (*box)["center"].at(0).get(); - center.y = (*box)["center"].at(1).get(); - center.z = (*box)["center"].at(2).get(); - } - if (box->contains("half")) { - half.x = (*box)["half"].at(0).get(); - half.y = (*box)["half"].at(1).get(); - half.z = (*box)["half"].at(2).get(); + IStreamWrapper isw(s); + Document doc; + doc.ParseStream(isw); + if (doc.HasParseError()) { + auto code = doc.GetParseError(); + + throw std::runtime_error( + std::format("Parse {} failed, error code {}", p.string(), + static_cast(code))); + } + if (doc.HasMember("boxes")) { + const Value& box = doc["boxes"]; + if (box.IsArray()) { + const Value& b = box[0]; + if (b.HasMember("center")) { + center.x = b["center"][0].GetFloat(); + center.y = b["center"][1].GetFloat(); + center.z = b["center"][2].GetFloat(); + } + if (b.HasMember("half")) { + half.x = b["half"][0].GetFloat(); + half.y = b["half"][1].GetFloat(); + half.z = b["half"][2].GetFloat(); + } } } { diff --git a/src/gameplay/server_world.cpp b/src/gameplay/server_world.cpp index 5387d47..35addcf 100644 --- a/src/gameplay/server_world.cpp +++ b/src/gameplay/server_world.cpp @@ -8,14 +8,15 @@ #include "Cubed/tools/net_utils.hpp" #include "Cubed/tools/uuid.hpp" -#include #include +#include +#include #include using namespace std::chrono; using namespace std::chrono_literals; using namespace google::protobuf; +using namespace rapidjson; namespace fs = std::filesystem; -using nlohmann::json; namespace Cubed { ServerWorld::ServerWorld(Config& config) : m_config(config), m_entity_manager(*this) {} @@ -212,8 +213,13 @@ void ServerWorld::init_world() { try { fs::path path = std::format("{}SensitiveLexicon.json", ASSETS_PATH); std::ifstream s{path}; - json j = json::parse(s); - m_filter.load(j); + if (!s.is_open()) { + throw std::runtime_error("can't open SensitiveLexicon.json"); + } + IStreamWrapper isw(s); + Document doc; + doc.ParseStream(isw); + m_filter.load(doc); } catch (const std::exception& e) { Logger::error("Load SensitiveLexicon.json Fail"); m_enable_filter = false; diff --git a/src/localization.cpp b/src/localization.cpp index d4380b7..aae2077 100644 --- a/src/localization.cpp +++ b/src/localization.cpp @@ -1,12 +1,14 @@ #include "Cubed/localization.hpp" #include "Cubed/tools/cubed_assert.hpp" +#include "Cubed/tools/json_utils.hpp" #include "Cubed/tools/log.hpp" #include -#include -using json = nlohmann::json; +#include +#include namespace fs = std::filesystem; +using namespace rapidjson; namespace Cubed { Localization::Localization() {} Localization& Localization::instance() { @@ -25,10 +27,19 @@ void Localization::load_language(std::string_view language) { return; } try { - json j = json::parse(file); + IStreamWrapper isw(file); + Document doc; + doc.ParseStream(isw); + if (doc.HasParseError()) { + auto code = doc.GetParseError(); + + throw std::runtime_error( + std::format("Parse {} failed, error code {}", path, + static_cast(code))); + } m_translations.clear(); - j.get_to(m_translations); - } catch (const json::parse_error& e) { + m_translations = Tools::doc_to_map(doc); + } catch (const std::exception& e) { Logger::error("JSON syntax error: {}", e.what()); } } diff --git a/src/tools/json_utils.cpp b/src/tools/json_utils.cpp new file mode 100644 index 0000000..69b48d3 --- /dev/null +++ b/src/tools/json_utils.cpp @@ -0,0 +1,54 @@ +#include "Cubed/tools/json_utils.hpp" + +#include +#include +#include +#include +#include +namespace Tools { + +using rapidjson::Document; +using rapidjson::Value; + +namespace { +std::string serialize_value(const Value& v, rapidjson::StringBuffer& buf) { + rapidjson::Writer w(buf); + v.Accept(w); + return buf.GetString(); +} +} // namespace + +std::unordered_map doc_to_map(const Document& doc) { + std::unordered_map m; + if (!doc.IsObject()) + return m; + + for (auto it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) { + const std::string KEY(it->name.GetString(), it->name.GetStringLength()); + const Value& v = it->value; + std::string val; + if (v.IsString()) { + val.assign(v.GetString(), v.GetStringLength()); + } else if (v.IsInt()) { + val = std::to_string(v.GetInt()); + } else if (v.IsUint()) { + val = std::to_string(v.GetUint()); + } else if (v.IsInt64()) { + val = std::to_string(v.GetInt64()); + } else if (v.IsUint64()) { + val = std::to_string(v.GetUint64()); + } else if (v.IsDouble()) { + val = std::to_string(v.GetDouble()); + } else if (v.IsBool()) { + val = v.GetBool() ? "true" : "false"; + } else if (v.IsNull()) { + val = "null"; + } else { + rapidjson::StringBuffer buf; + val = serialize_value(v, buf); + } + m.emplace(KEY, val); + } + return m; +} +} // namespace Tools \ No newline at end of file diff --git a/src/tools/sensitive_filter.cpp b/src/tools/sensitive_filter.cpp index 9456ed9..cff4710 100644 --- a/src/tools/sensitive_filter.cpp +++ b/src/tools/sensitive_filter.cpp @@ -2,18 +2,25 @@ #include #include -using nlohmann::json; +using namespace rapidjson; namespace Cubed { SensitiveFilter::SensitiveFilter() { }; -void SensitiveFilter::load(const nlohmann::json& j) { +void SensitiveFilter::load(const Document& doc) { trie.clear(); trie.emplace_back(); - for (const auto& item : j["words"]) { - - auto str = item.get(); + if (!doc.HasMember("words")) { + return; + } + const Value& words = doc["words"]; + for (SizeType i = 0; i < words.Size(); ++i) { + const auto& w = words[i]; + if (!w.IsString()) { + continue; + } + std::string str(w.GetString(), w.GetStringLength()); std::u32string word; utf8::utf8to32(str.begin(), str.end(), std::back_inserter(word)); insert(word);