From b06d63ba836407fd4d69a0a04372a08c30737a3a Mon Sep 17 00:00:00 2001 From: Hat Kid <6624576+Hat-Kid@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:29:30 +0100 Subject: [PATCH] custom levels: sort actors by aid and check for duplicates (#3315) When giving entities custom actor IDs in your level JSON, it is possible to break entity lookups by actor ID if the actors are not sorted by ID because `entity-by-aid` expects them to be in order. This sorts the actor list by ID before generating the level file and also checks for any duplicates. --- goalc/build_level/jak1/build_level.cpp | 6 ++++++ goalc/build_level/jak2/build_level.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/goalc/build_level/jak1/build_level.cpp b/goalc/build_level/jak1/build_level.cpp index 1c79972879..4a6b4d534c 100644 --- a/goalc/build_level/jak1/build_level.cpp +++ b/goalc/build_level/jak1/build_level.cpp @@ -48,6 +48,12 @@ bool run_build_level(const std::string& input_file, auto dts = decompiler::DecompilerTypeSystem(GameVersion::Jak1); dts.parse_enum_defs({"decompiler", "config", "jak1", "all-types.gc"}); add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234), dts); + std::sort(actors.begin(), actors.end(), [](auto& a, auto& b) { return a.aid < b.aid; }); + auto duplicates = std::adjacent_find(actors.begin(), actors.end(), + [](auto& a, auto& b) { return a.aid == b.aid; }); + ASSERT_MSG(duplicates == actors.end(), + fmt::format("Actor IDs must be unique. Found at least two actors with ID {}", + duplicates->aid)); file.actors = std::move(actors); // ambients std::vector ambients; diff --git a/goalc/build_level/jak2/build_level.cpp b/goalc/build_level/jak2/build_level.cpp index 44bb3e05d6..2e418e8bb7 100644 --- a/goalc/build_level/jak2/build_level.cpp +++ b/goalc/build_level/jak2/build_level.cpp @@ -47,6 +47,12 @@ bool run_build_level(const std::string& input_file, dts.parse_enum_defs({"decompiler", "config", "jak2", "all-types.gc"}); std::vector actors; add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234), dts); + std::sort(actors.begin(), actors.end(), [](auto& a, auto& b) { return a.aid < b.aid; }); + auto duplicates = std::adjacent_find(actors.begin(), actors.end(), + [](auto& a, auto& b) { return a.aid == b.aid; }); + ASSERT_MSG(duplicates == actors.end(), + fmt::format("Actor IDs must be unique. Found at least two actors with ID {}", + duplicates->aid)); file.actors = std::move(actors); // cameras // nodes