qbsp: strip _tb_ keys, convert __TB_empty to skip

This commit is contained in:
Eric Wasylishen 2023-01-30 00:28:31 -07:00
parent 9edad10b0f
commit 302d600f4c
5 changed files with 54 additions and 0 deletions

View File

@ -182,6 +182,11 @@ void entdict_t::parse(parser_base_t &parser)
} }
} }
bool entdict_t::operator==(const entdict_t& other) const
{
return this->keyvalues == other.keyvalues;
}
void EntData_ParseInto(parser_t &parser, std::vector<entdict_t> &vector) void EntData_ParseInto(parser_t &parser, std::vector<entdict_t> &vector)
{ {
/* go through all the entities */ /* go through all the entities */

View File

@ -68,6 +68,9 @@ public:
// the parser must be at a position where { is // the parser must be at a position where { is
// the next token parsed. // the next token parsed.
void parse(parser_base_t &parser); void parse(parser_base_t &parser);
// order-sensitive
bool operator==(const entdict_t& other) const;
}; };
void EntData_ParseInto(parser_t &parser, std::vector<entdict_t> &vector); void EntData_ParseInto(parser_t &parser, std::vector<entdict_t> &vector);

View File

@ -459,6 +459,8 @@ static bool IsSkipName(const char *name)
return true; return true;
if (!Q_strcasecmp(name, "null")) // zhlt compat if (!Q_strcasecmp(name, "null")) // zhlt compat
return true; return true;
if (!Q_strcasecmp(name, "__TB_empty"))
return true;
return false; return false;
} }
@ -3287,6 +3289,11 @@ void WriteEntitiesToString()
map.bsp.dentdata += "{\n"; map.bsp.dentdata += "{\n";
for (auto &ep : entity.epairs) { for (auto &ep : entity.epairs) {
if (ep.first.starts_with("_tb_")) {
// Remove TrenchBroom keys. _tb_textures tends to be long and can crash vanilla clients.
// generally, these are mapper metadata and unwanted in the .bsp.
continue;
}
if (ep.first.size() >= qbsp_options.target_game->max_entity_key - 1) { if (ep.first.size() >= qbsp_options.target_game->max_entity_key - 1) {
logging::print("WARNING: {} at {} has long key {} (length {} >= {})\n", entity.epairs.get("classname"), logging::print("WARNING: {} at {} has long key {} (length {} >= {})\n", entity.epairs.get("classname"),

View File

@ -0,0 +1,21 @@
// Game: Quake 2
// Format: Quake2
// entity 0
{
"classname" "worldspawn"
"_tb_textures" "textures/e1u1;textures/e1u2;textures/e1u3;textures/e1u4;textures/e2u1;textures/e2u2;textures/e2u3;textures/e3u1;textures/e3u2;textures/e3u3"
// brush 0
{
( -64 -64 -32 ) ( -64 -63 -32 ) ( -64 -64 -31 ) __TB_empty 0 0 0 1 1
( -64 -64 -32 ) ( -64 -64 -31 ) ( -63 -64 -32 ) __TB_empty 0 0 0 1 1
( -64 -64 -32 ) ( -63 -64 -32 ) ( -64 -63 -32 ) __TB_empty 0 0 0 1 1
( 64 64 0 ) ( 64 65 0 ) ( 65 64 0 ) __TB_empty 0 0 0 1 1
( 64 64 0 ) ( 65 64 0 ) ( 64 64 1 ) __TB_empty 0 0 0 1 1
( 64 64 0 ) ( 64 64 1 ) ( 64 65 0 ) __TB_empty 0 0 0 1 1
}
}
// entity 1
{
"classname" "info_player_start"
"origin" "-48 -16 24"
}

View File

@ -635,3 +635,21 @@ TEST_CASE("q2_hint_missing_faces" * doctest::test_suite("testmaps_q2") * doctest
CHECK(BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {36, 144, 30})); CHECK(BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {36, 144, 30}));
} }
TEST_CASE("q2_tb_cleanup" * doctest::test_suite("testmaps_q2"))
{
const auto [bsp, bspx, prt] = LoadTestmapQ2("q2_tb_cleanup.map");
{
INFO("check that __TB_empty was converted to skip");
CHECK(nullptr == BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}));
}
{
auto ents = EntData_Parse(bsp);
REQUIRE(ents.size() == 2);
INFO("check that _tb_textures was stripped out");
CHECK(entdict_t{{"classname", "worldspawn"}} == ents[0]);
}
}