diff --git a/Ballance/BMapInspector/Rule.cpp b/Ballance/BMapInspector/Rule.cpp index 6e7f36e..5917a6f 100644 --- a/Ballance/BMapInspector/Rule.cpp +++ b/Ballance/BMapInspector/Rule.cpp @@ -23,10 +23,9 @@ namespace BMapInspector::Rule { Ruleset::Ruleset() : rules() { // Add rule into list. - //rules.emplace_back(new GpRule1()); + rules.emplace_back(new GpRule1()); rules.emplace_back(new GpRule2()); - //rules.emplace_back(new Gp3Rule()); - //rules.emplace_back(new Chirs1Rule()); + rules.emplace_back(new ChirsRule1()); rules.emplace_back(new YYCRule1()); rules.emplace_back(new YYCRule2()); rules.emplace_back(new BBugRule1()); diff --git a/Ballance/BMapInspector/Rule/ChirsRules.cpp b/Ballance/BMapInspector/Rule/ChirsRules.cpp index d3ca089..f694f09 100644 --- a/Ballance/BMapInspector/Rule/ChirsRules.cpp +++ b/Ballance/BMapInspector/Rule/ChirsRules.cpp @@ -1,18 +1,73 @@ #include "ChirsRules.hpp" +#include "Shared.hpp" + +namespace L = LibCmo; +namespace C = LibCmo::CK2; +namespace O = LibCmo::CK2::ObjImpls; namespace BMapInspector::Rule { - Chirs1Rule::Chirs1Rule() : IRule() {} - Chirs1Rule::~Chirs1Rule() {} - std::u8string_view Chirs1Rule::GetRuleName() const { - return u8"CHIRS1"; - } - void Chirs1Rule::Check(Reporter::Reporter& reporter, Map::Level& level) const { - // Report error if there is some material named Laterne_Verlauf - // but its texture is not pointed to Laterne_Verlauf texture. - // Report error if some materials' texture is Laterne_Verlauf, + // Reference: https://tieba.baidu.com/p/5913556704 + +#pragma region Chirs Rule 1 + + constexpr char8_t CHIRS1[] = u8"CHIRS1"; + + ChirsRule1::ChirsRule1() : IRule() {} + + ChirsRule1::~ChirsRule1() {} + + std::u8string_view ChirsRule1::GetRuleName() const { + return CHIRS1; + } + void ChirsRule1::Check(Reporter::Reporter& reporter, Map::Level& level) const { + constexpr char8_t MTL_NAME[] = u8"Laterne_Verlauf"; + auto* ctx = level.GetCKContext(); + + // Fetch Laterne_Verlauf first + auto* latern = Shared::FetchMaterial(ctx, MTL_NAME); + if (latern == nullptr) return; + + // Report warning if this material's texture is not Laterne_Verlauf.tga + auto* latern_tex = latern->GetTexture(); + if (latern_tex == nullptr) { + reporter.WriteWarning(CHIRS1, + u8R"(Find a material named "Laterne_Verlauf" but it doesn't have associated texture. )" + u8R"(It occupies the magic material "Laterne_Verlauf" which affect the ray of latern in game. Please confirm this is your intention.)"); + } else { + if (!Shared::CheckTextureFileName(latern_tex, Shared::TextureNames::LATERNE_VERLAUF)) { + reporter.WriteWarning(CHIRS1, + u8R"(Find a material named "Laterne_Verlauf" but its texture is not "Laterne_Verlauf.tga". )" + u8R"(It occupies the magic material "Laterne_Verlauf" which affect the ray of latern in game. Please confirm this is your intention.)"); + } + } + + // Report warning if there is multiple Laterne_Verlauf material. + auto next_latern = ctx->GetObjectByNameAndClass(MTL_NAME, C::CK_CLASSID::CKCID_MATERIAL, latern); + if (next_latern != nullptr) { + reporter.WriteWarning( + CHIRS1, + u8R"(There are multiple materials named "Laterne_Verlauf". This will cause the disappearance of some latern's rays.)"); + } + + // Report warning if some materials' texture is Laterne_Verlauf, // but its name is not Laterne_Verlauf. + for (auto* other_mtl : level.GetMaterials()) { + if (C::CKStrEqual(other_mtl->GetName(), MTL_NAME)) continue; - // Report error if there is multiple Laterne_Verlauf material. + auto other_mtl_tex = other_mtl->GetTexture(); + if (other_mtl_tex == nullptr) continue; + + if (Shared::CheckTextureFileName(other_mtl_tex, Shared::TextureNames::LATERNE_VERLAUF)) { + reporter.FormatWarning( + CHIRS1, + u8R"(Find material %s referring texture "Laterne_Verlauf.tga", but its name is not "Laterne_Verlauf". )" + u8R"(Please confirm the usage of this material. If it is used as "Laterne_Verlauf", please rename it into "Laterne_Verlauf" to have correct latern ray.)", + Shared::QuoteObjectName(other_mtl).c_str()); + } + } } + +#pragma endregion + } // namespace BMapInspector::Rule diff --git a/Ballance/BMapInspector/Rule/ChirsRules.hpp b/Ballance/BMapInspector/Rule/ChirsRules.hpp index 009e536..b20094c 100644 --- a/Ballance/BMapInspector/Rule/ChirsRules.hpp +++ b/Ballance/BMapInspector/Rule/ChirsRules.hpp @@ -3,19 +3,17 @@ namespace BMapInspector::Rule { - // Reference: https://tieba.baidu.com/p/5913556704 - /** - * @brief Chirs241097 Rule 1 + * @brief chirs241097 Rule 1 * @details * This rule will make sure that there is only 1 texture named Laterne_Verlauf in map, * which represent the ray of latern. */ - class Chirs1Rule : public IRule { + class ChirsRule1 : public IRule { public: - Chirs1Rule(); - virtual ~Chirs1Rule(); - YYCC_DELETE_COPY_MOVE(Chirs1Rule) + ChirsRule1(); + virtual ~ChirsRule1(); + YYCC_DELETE_COPY_MOVE(ChirsRule1) public: std::u8string_view GetRuleName() const override; diff --git a/Ballance/BMapInspector/Rule/GpRules.cpp b/Ballance/BMapInspector/Rule/GpRules.cpp index da19e47..3b851f5 100644 --- a/Ballance/BMapInspector/Rule/GpRules.cpp +++ b/Ballance/BMapInspector/Rule/GpRules.cpp @@ -8,17 +8,25 @@ namespace O = LibCmo::CK2::ObjImpls; namespace BMapInspector::Rule { + // Reference: https://tieba.baidu.com/p/3182981807 + #pragma region GP1 Rule + constexpr char8_t GP1[] = u8"GP1"; + GpRule1::GpRule1() : IRule() {} GpRule1::~GpRule1() {} std::u8string_view GpRule1::GetRuleName() const { - return u8"GP1"; + return GP1; } - void GpRule1::Check(Reporter::Reporter& reporter, Map::Level& level) const {} + void GpRule1::Check(Reporter::Reporter& reporter, Map::Level& level) const { + // TODO: + // Finish this rule. + // It is so complex that I don't want to implement it now. + } #pragma endregion @@ -98,7 +106,8 @@ namespace BMapInspector::Rule { auto sector_names = builder.get_sector9_names(); if (group_names.contains(sector_names.intuitive_name)) { reporter.WriteWarning( - GP2, u8R"(You are using intuitive sector name, "Sector_09", for sector 9. This is only accepted by new 999 sector loader.)"); + GP2, + u8R"(You are using intuitive sector name, "Sector_09", for sector 9. This is only accepted by new 999 sector loader.)"); } } @@ -128,20 +137,4 @@ namespace BMapInspector::Rule { #pragma endregion -#pragma region GP3 Rule - // - // Gp3Rule::Gp3Rule() : IRule() {} - // - // Gp3Rule::~Gp3Rule() {} - // - // std::u8string_view Gp3Rule::GetRuleName() const { - // return u8"GP3"; - // } - // - // void Gp3Rule::Check(Reporter::Reporter& reporter, Map::Level& level) const { - // // TODO: Mesh hash is not implemented. - // } - // - //#pragma endregion - } // namespace BMapInspector::Rule diff --git a/Ballance/BMapInspector/Rule/GpRules.hpp b/Ballance/BMapInspector/Rule/GpRules.hpp index e6ce3b1..4a223b0 100644 --- a/Ballance/BMapInspector/Rule/GpRules.hpp +++ b/Ballance/BMapInspector/Rule/GpRules.hpp @@ -3,8 +3,6 @@ namespace BMapInspector::Rule { - // Reference: https://tieba.baidu.com/p/3182981807 - /** * @brief Gamepiaynmo Rule 1 * @details @@ -43,43 +41,4 @@ namespace BMapInspector::Rule { void Check(Reporter::Reporter& reporter, Map::Level& level) const override; }; - ///** - // * @brief Gamepiaynmo Rule 2 - // * @details - // * Every Ballance group should not have any groups with same name. - // */ - //class GpRule2 : public IRule { - //public: - // GpRule2(); - // virtual ~GpRule2(); - // YYCC_DELETE_COPY_MOVE(GpRule2) - - //public: - // std::u8string_view GetRuleName() const override; - // void Check(Reporter::Reporter& reporter, Map::Level& level) const override; - //}; - - ///** - // * @brief Gamepiaynmo Rule 2 - // * @details - // * This rule make sure that one Ballance element must be grouped into only one sector group. - // * Multiple grouping and none grouping will throw error. - // */ - ///** - // * @brief Gamepiaynmo Rule 3 - // * @details - // * This rule make sure that all Ballance element is grouped into correct element group. - // * This rule will check the mesh of PH and guess which element it is. - // */ - //class Gp3Rule : public IRule { - //public: - // Gp3Rule(); - // virtual ~Gp3Rule(); - // YYCC_DELETE_COPY_MOVE(Gp3Rule) - - //public: - // std::u8string_view GetRuleName() const override; - // void Check(Reporter::Reporter& reporter, Map::Level& level) const override; - //}; - } diff --git a/Ballance/BMapInspector/Rule/Shared.cpp b/Ballance/BMapInspector/Rule/Shared.cpp index 2e59436..eb9b4b9 100644 --- a/Ballance/BMapInspector/Rule/Shared.cpp +++ b/Ballance/BMapInspector/Rule/Shared.cpp @@ -58,6 +58,10 @@ namespace BMapInspector::Rule::Shared { } } + O::CKMaterial* FetchMaterial(C::CKContext* ctx, L::CKSTRING name) { + return static_cast(ctx->GetObjectByNameAndClass(name, C::CK_CLASSID::CKCID_MATERIAL, nullptr)); + } + std::vector FetchPhysicalized3dObjects(C::CKContext* ctx) { std::vector rv; diff --git a/Ballance/BMapInspector/Rule/Shared.hpp b/Ballance/BMapInspector/Rule/Shared.hpp index 99dc965..b515754 100644 --- a/Ballance/BMapInspector/Rule/Shared.hpp +++ b/Ballance/BMapInspector/Rule/Shared.hpp @@ -56,6 +56,7 @@ namespace BMapInspector::Rule::Shared { namespace TextureNames { // clang-format off constexpr char8_t RAIL_ENVIRONMENT[] = u8"Rail_Environment.bmp"; + constexpr char8_t LATERNE_VERLAUF[] = u8"Laterne_Verlauf.tga"; // clang-format on } // namespace TextureNames @@ -117,6 +118,13 @@ namespace BMapInspector::Rule::Shared { * @return Found pointer to CKGroup, otherwise nullptr. */ O::CKGroup* FetchGroup(C::CKContext* ctx, L::CKSTRING name); + /** + * @brief + * @param[in] ctx Can not be nullptr. + * @param[in] name Can not be nullptr. + * @return Found pointer to CKMaterial, otherwise nullptr. + */ + O::CKMaterial* FetchMaterial(C::CKContext* ctx, L::CKSTRING name); std::vector FetchPhysicalized3dObjects(C::CKContext* ctx); /** * @brief Check whether given CKTexture has the given file name (case-insensitive).