diff --git a/common/bspfile.cc b/common/bspfile.cc index bc6e736f..062c2452 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -110,6 +110,8 @@ struct gamedef_generic_t : public gamedef_t std::string get_contents_display(const contentflags_t &) const override { throw std::bad_cast(); } + void contents_make_valid(contentflags_t &contents) const override { throw std::bad_cast(); } + const std::initializer_list &get_hull_sizes() const override { throw std::bad_cast(); } contentflags_t face_get_contents(const std::string &, const surfflags_t &, const contentflags_t &) const override { throw std::bad_cast(); } @@ -457,27 +459,36 @@ public: } if (contents_are_clip(contents)) { - base += "| CLIP"; + base += " | CLIP"; } if (contents_are_origin(contents)) { - base += "| ORIGIN"; + base += " | ORIGIN"; } switch (get_data(contents).detail) { case detail_type_t::DETAIL: - base += "| DETAIL"; + base += " | DETAIL"; break; case detail_type_t::ILLUSIONARY: - base += "| DETAIL[ILLUSIONARY]"; + base += " | DETAIL[ILLUSIONARY]"; break; case detail_type_t::FENCE: - base += "| DETAIL[FENCE]"; + base += " | DETAIL[FENCE]"; break; } return base; } + void contents_make_valid(contentflags_t &contents) const override + { + // todo: anything smarter we can do here? + // think this can't even happen in Q1 anyways + if (!contents_are_valid(contents, false)) { + contents = { CONTENTS_SOLID }; + } + } + const std::initializer_list &get_hull_sizes() const { static std::initializer_list hulls = { @@ -1007,6 +1018,26 @@ struct gamedef_q2_t : public gamedef_t return s; } + void contents_make_valid(contentflags_t &contents) const override + { + if (contents_are_valid(contents, false)) { + return; + } + + bool got = false; + + for (int32_t i = 0; i < 8; i++) { + if (!got) { + if (contents.native & nth_bit(i)) { + got = true; + continue; + } + } else { + contents.native &= ~nth_bit(i); + } + } + } + const std::initializer_list &get_hull_sizes() const { static constexpr std::initializer_list hulls = {}; @@ -1477,6 +1508,11 @@ bool contentflags_t::is_origin(const gamedef_t *game) const return game->contents_are_origin(*this); } +void contentflags_t::make_valid(const gamedef_t *game) +{ + game->contents_make_valid(*this); +} + std::string contentflags_t::to_string(const gamedef_t *game) const { std::string s = game->get_contents_display(*this); diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index 441da88a..79166b60 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -614,6 +614,8 @@ struct contentflags_t bool is_clip(const gamedef_t *game) const; bool is_origin(const gamedef_t *game) const; + void make_valid(const gamedef_t *game); + inline bool is_fence(const gamedef_t *game) const { return is_detail_fence(game) || is_detail_illusionary(game); } @@ -1825,6 +1827,7 @@ struct gamedef_t virtual contentflags_t contents_remap_for_export(const contentflags_t &contents) const = 0; virtual contentflags_t combine_contents(const contentflags_t &a, const contentflags_t &b) const = 0; virtual std::string get_contents_display(const contentflags_t &contents) const = 0; + virtual void contents_make_valid(contentflags_t &contents) const = 0; virtual const std::initializer_list &get_hull_sizes() const = 0; virtual contentflags_t face_get_contents( const std::string &texname, const surfflags_t &flags, const contentflags_t &contents) const = 0; diff --git a/qbsp/map.cc b/qbsp/map.cc index 0e4bcb0c..268fe11a 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1410,25 +1410,12 @@ static void ParseTextureDef(parser_t &parser, mapface_t &mapface, const mapbrush tx->flags = mapface.flags = {extinfo.info->flags}; tx->value = mapface.value = extinfo.info->value; - if (!contentflags_t{mapface.contents}.is_valid(options.target_game, false)) - { - logging::print("WARNING: line {}: face has invalid contents {} ({})\n", mapface.linenum, mapface.contents.to_string(options.target_game), mapface.contents.native); - - // TODO: move into game - if (options.target_game->id == GAME_QUAKE_II) { - bool got = false; + contentflags_t contents { mapface.contents }; - for (int i = 0; i < 8; i++) { - if (!got) { - if (mapface.contents.native & nth_bit(i)) { - got = true; - continue; - } - } else { - mapface.contents.native &= ~nth_bit(i); - } - } - } + if (!contents.is_valid(options.target_game, false)) { + auto old_contents = contents; + options.target_game->contents_make_valid(contents); + logging::print("WARNING: line {}: face has invalid contents {}, remapped to {}\n", mapface.linenum, old_contents.to_string(options.target_game), contents.to_string(options.target_game)); } switch (tx_type) {