From 3eb6cfcb17b1c0c256f3217b11a2d4bf36700f9d Mon Sep 17 00:00:00 2001 From: Hat Kid <6624576+Hat-Kid@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:20:32 +0100 Subject: [PATCH] custom levels: add support for `symbol`, `type`, and `string` lumps (#3337) --- custom_levels/jak1/test-zone/test-zone.jsonc | 5 ++- custom_levels/jak2/test-zone/test-zone.jsonc | 8 +++-- goalc/build_level/common/Entity.cpp | 33 ++++++++++++++++++++ goalc/build_level/common/ResLump.cpp | 25 +++++++++++++++ goalc/build_level/common/ResLump.h | 13 ++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/custom_levels/jak1/test-zone/test-zone.jsonc b/custom_levels/jak1/test-zone/test-zone.jsonc index b1ce3dd2b2..d89c1f730d 100644 --- a/custom_levels/jak1/test-zone/test-zone.jsonc +++ b/custom_levels/jak1/test-zone/test-zone.jsonc @@ -24,7 +24,7 @@ // integer types: int32, uint32, enum-int32, enum-uint32 // float types: float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°) // vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees) - // special types: eco-info, cell-info, buzzer-info, water-height + // special types: symbol, type, string, eco-info, cell-info, buzzer-info, water-height // // examples: // @@ -51,6 +51,9 @@ // // adds a buzzer-info tag: // "eco-info": ["buzzer-info", "(game-task training-buzzer)", 5] + // + // adds a 'symbol' tag (using the 'type' and 'string' lump types works the same way): + // "symbol-list": ["symbol", "sym-1", "sym-2"] // The base actor id for your custom level. If you have multiple levels this should be unique! "base_id": 100, diff --git a/custom_levels/jak2/test-zone/test-zone.jsonc b/custom_levels/jak2/test-zone/test-zone.jsonc index 92573d5267..ae2bddbb19 100644 --- a/custom_levels/jak2/test-zone/test-zone.jsonc +++ b/custom_levels/jak2/test-zone/test-zone.jsonc @@ -21,9 +21,10 @@ "double_sided_collide": false, // available res-lump tag types: - // value types: int32, uint32, enum-int32, enum-uint32, float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°) + // integer types: int32, uint32, enum-int32, enum-uint32 + // float types: float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°) // vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees) - // special types: eco-info, water-height + // special types: symbol, type, string, eco-info, cell-info, buzzer-info, water-height // // examples: // @@ -44,6 +45,9 @@ // // adds an eco-info tag: // "eco-info": ["eco-info", "(pickup-type health)", 2] + // + // adds a 'type' tag (using the "symbol" and "string" lump types works the same way): + // "spawn-types": ["type", "spyder", "juicer"] // The base actor id for your custom level. If you have multiple levels, this should be unique! "base_id": 100, diff --git a/goalc/build_level/common/Entity.cpp b/goalc/build_level/common/Entity.cpp index 34c81197ce..0659c82a27 100644 --- a/goalc/build_level/common/Entity.cpp +++ b/goalc/build_level/common/Entity.cpp @@ -202,6 +202,39 @@ static std::unordered_map(name, data, -1000000000.0000); }}, + {"symbol", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"type", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"string", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, // vectors {"vector", [](const std::string& name, diff --git a/goalc/build_level/common/ResLump.cpp b/goalc/build_level/common/ResLump.cpp index ec8cc8b699..757824a887 100644 --- a/goalc/build_level/common/ResLump.cpp +++ b/goalc/build_level/common/ResLump.cpp @@ -215,6 +215,31 @@ int ResSymbol::get_alignment() const { return 4; } +ResType::ResType(const std::string& name, const std::vector& str, float key_frame) + : Res(name, key_frame), m_str(str) {} + +ResType::ResType(const std::string& name, const std::string& str, float key_frame) + : Res(name, key_frame), m_str({str}) {} + +TagInfo ResType::get_tag_info() const { + TagInfo result; + result.elt_type = "type"; + result.elt_count = m_str.size(); + result.inlined = false; + result.data_size = 4 * m_str.size(); + return result; +} + +void ResType::write_data(DataObjectGenerator& gen) const { + for (auto& str : m_str) { + gen.add_type_tag(str); + } +} + +int ResType::get_alignment() const { + return 4; +} + void ResLump::add_res(std::unique_ptr res) { m_sorted = false; m_res.emplace_back(std::move(res)); diff --git a/goalc/build_level/common/ResLump.h b/goalc/build_level/common/ResLump.h index fc51dd846d..755e448190 100644 --- a/goalc/build_level/common/ResLump.h +++ b/goalc/build_level/common/ResLump.h @@ -125,6 +125,19 @@ class ResSymbol : public Res { std::vector m_str; }; +class ResType : public Res { + public: + ResType(const std::string& name, const std::vector& str, float key_frame); + ResType(const std::string& name, const std::string& str, float key_frame); + + TagInfo get_tag_info() const override; + void write_data(DataObjectGenerator& gen) const override; + int get_alignment() const override; + + private: + std::vector m_str; +}; + /* (deftype res-lump (basic) ((length int32 :offset-assert 4)