From d81fc045de891614f1139d00d9cf4d78b51cc06b Mon Sep 17 00:00:00 2001 From: OEOTYAN Date: Sat, 5 Oct 2024 22:56:44 +0800 Subject: [PATCH] feat: make command param checker into compile time --- src/ll/api/base/CompilerPredefine.h | 3 +- src/ll/api/command/Overload.h | 64 ++++++++++++++++----------- src/ll/api/memory/linux/Signature.cpp | 2 +- src/ll/api/mod/ModManagerRegistry.cpp | 2 +- src/ll/api/reflection/Reflection.h | 30 ++++++++++++- src/ll/api/utils/StringUtils_win.cpp | 2 +- src/ll/core/command/ModManage.cpp | 9 ++-- src/mc/deps/core/mce/Color.h | 4 +- src/mc/enums/BookEditAction.h | 2 +- src/mc/nbt/DoubleTag.h | 2 +- src/mc/world/ContainerIterator.h | 6 +-- src/mc/world/level/BlockSource.h | 7 ++- 12 files changed, 82 insertions(+), 51 deletions(-) diff --git a/src/ll/api/base/CompilerPredefine.h b/src/ll/api/base/CompilerPredefine.h index 693f2322a1..f051bb1ba3 100644 --- a/src/ll/api/base/CompilerPredefine.h +++ b/src/ll/api/base/CompilerPredefine.h @@ -196,6 +196,7 @@ extern "C" void* __cdecl __RTCastToVoid(void*); #pragma pack(pop, rttidata) // NOLINTEND #endif +struct _IMAGE_DOS_HEADER; // No one guarantees that the compiler's internal definitions are correct namespace ll::internal { @@ -220,7 +221,7 @@ using CatchableType = ::_CatchableType; using ThrowInfo = ::_ThrowInfo; #endif -extern "C" struct _IMAGE_DOS_HEADER __ImageBase; // NOLINT(bugprone-reserved-identifier) +extern "C" ::_IMAGE_DOS_HEADER __ImageBase; // NOLINT(bugprone-reserved-identifier) [[nodiscard]] LL_FORCEINLINE void* getCurrentModuleHandle() noexcept { return &__ImageBase; } diff --git a/src/ll/api/command/Overload.h b/src/ll/api/command/Overload.h index 1f0d5012b1..16e7bb1749 100644 --- a/src/ll/api/command/Overload.h +++ b/src/ll/api/command/Overload.h @@ -30,27 +30,18 @@ class Overload : private OverloadData { uint64 placeholder{}; Params params; }; - static inline auto ParamOffset = offsetof(Overload::TestOffset, params); - static inline auto PlaceholderOffset = offsetof(Overload::TestOffset, placeholder); - - constexpr Overload& addParam(std::string_view name) { - bool hasName{}; - reflection::forEachMember((*(Params*)ParamOffset), [&, this](std::string_view param, auto& val) { - if (name != param) { - return; - } - hasName = true; - - using OriginalType = std::remove_cvref_t; + static constexpr auto paramOffset = offsetof(Overload::TestOffset, params); + static constexpr auto placeholderOffset = offsetof(Overload::TestOffset, placeholder); + constexpr Overload& addParam(std::string_view name, int index) { + meta::visitIndex>(index, [&, this]() { + using OriginalType = typename reflection::member_t; using RemoveOptionalType = remove_optional_t; - - using ParamType = std::conditional_t< - traits::is_specialization_of_v, - std::string, - RemoveOptionalType>; - - int offset = (int)(size_t)std::addressof(val); + using ParamType = std::conditional_t< + traits::is_specialization_of_v, + std::string, + RemoveOptionalType>; + int offset = (int)(paramOffset + reflection::member_offset_v); int flagOffset = -1; if constexpr (traits::is_specialization_of_v) { flagOffset = offset + OptionalOffsetGetter::value; @@ -76,25 +67,44 @@ class Overload : private OverloadData { true ); }); - if (!hasName) { - throw std::invalid_argument("invalid param " + std::string(name)); - } return *this; } explicit Overload(CommandHandle& handle, std::weak_ptr mod) : OverloadData(handle, std::move(mod)) {} + class ParamName : public std::string_view { + std::string_view str; + int idx; + + constexpr int indexSearcher(std::string_view s) { + int i{}; + for (auto& member : reflection::member_name_array_v) { + if (member == s) return i; + i++; + } + throw std::invalid_argument("invalid param " + std::string(str)); + } + + public: + template + requires(std::is_constructible_v) + consteval ParamName(S const& s) : str(s), + idx(indexSearcher(s)) {} + constexpr std::string_view get() const { return str; } + constexpr int index() const { return idx; } + }; + public: - [[nodiscard]] constexpr Overload& optional(std::string_view name) { - addParam(name).back().mIsOptional = true; + [[nodiscard]] constexpr Overload& optional(ParamName const name) { + addParam(name.get(), name.index()).back().mIsOptional = true; return *this; } - [[nodiscard]] constexpr Overload& required(std::string_view name) { - addParam(name).back().mIsOptional = false; + [[nodiscard]] constexpr Overload& required(ParamName const name) { + addParam(name.get(), name.index()).back().mIsOptional = false; return *this; } [[nodiscard]] constexpr Overload& text(std::string_view text) { - addTextImpl(text, (int)PlaceholderOffset); + addTextImpl(text, (int)placeholderOffset); return *this; } template diff --git a/src/ll/api/memory/linux/Signature.cpp b/src/ll/api/memory/linux/Signature.cpp index 64cb22a809..009b82d18a 100644 --- a/src/ll/api/memory/linux/Signature.cpp +++ b/src/ll/api/memory/linux/Signature.cpp @@ -10,7 +10,7 @@ void* SignatureView::resolve(std::span range, bool disableErrorOutput const auto scanEnd = range.end() - elements.size() + 1; for (auto i = range.begin(); i != scanEnd; i++) { - i = std::find( i, scanEnd, firstByte); + i = std::find(i, scanEnd, firstByte); if (i == scanEnd) [[unlikely]] { break; } diff --git a/src/ll/api/mod/ModManagerRegistry.cpp b/src/ll/api/mod/ModManagerRegistry.cpp index 219f52a209..e0681bc91d 100644 --- a/src/ll/api/mod/ModManagerRegistry.cpp +++ b/src/ll/api/mod/ModManagerRegistry.cpp @@ -34,7 +34,7 @@ Expected<> ModManagerRegistry::loadMod(Manifest manifest) noexcept try { std::string name = manifest.name; std::string type = manifest.type; return getManager(type)->load(std::move(manifest)).transform([&, this] { - auto iter = impl->loadedMods.insert_or_assign(std::move(name), std::move(type)).first; + impl->loadedMods.insert_or_assign(std::move(name), std::move(type)).first; }); } else { return makeStringError("Unrecognized mod type: {0}"_tr(manifest.type)); diff --git a/src/ll/api/reflection/Reflection.h b/src/ll/api/reflection/Reflection.h index 583693cc67..032f570c76 100644 --- a/src/ll/api/reflection/Reflection.h +++ b/src/ll/api/reflection/Reflection.h @@ -27,12 +27,38 @@ template concept Reflectable = is_reflectable_v; template -constexpr auto const name_array_v = boost::pfr::names_as_array>(); +constexpr auto const member_name_array_v = boost::pfr::names_as_array>(); + +template +constexpr auto const member_count_v = boost::pfr::tuple_size_v; + +template +using member_t = typename boost::pfr::tuple_element_t; + +template +struct OffsetGetter { + template + struct AlignedStorage { + alignas(A) char storage[S]; + }; + template + using AlignedTuple = boost::pfr::detail::sequence_tuple::tuple...>; + + template + static ptrdiff_t offset(std::index_sequence) noexcept { + AlignedTuple...> layout{}; + return static_cast(&get(layout).storage[0]) + - static_cast(&get<0>(layout).storage[0]); + } +}; + +template +inline auto const member_offset_v = OffsetGetter::template offset(std::make_index_sequence>()); template constexpr void forEachMember(T&& value, F&& func) { boost::pfr::for_each_field(std::forward(value), [func = std::forward(func)](auto&& field, std::size_t idx) { - func(name_array_v[idx], std::forward(field)); + func(member_name_array_v[idx], std::forward(field)); }); } } // namespace ll::reflection diff --git a/src/ll/api/utils/StringUtils_win.cpp b/src/ll/api/utils/StringUtils_win.cpp index 896d35c0dc..0e599b5733 100644 --- a/src/ll/api/utils/StringUtils_win.cpp +++ b/src/ll/api/utils/StringUtils_win.cpp @@ -130,7 +130,7 @@ std::string getMcCodeFromTextStyle(fmt::text_style style) { if (fg.is_rgb) { auto color = mce::Color(fg.value.rgb_color); // clang-format off - constexpr const auto carr = std::array{ + constexpr const std::array carr{ std::pair{cf::BLACK , mce::Color(0x000000)}, std::pair{cf::DARK_BLUE , mce::Color(0x0000AA)}, std::pair{cf::DARK_GREEN , mce::Color(0x00AA00)}, std::pair{cf::DARK_AQUA , mce::Color(0x00AAAA)}, std::pair{cf::DARK_RED , mce::Color(0xAA0000)}, std::pair{cf::DARK_PURPLE , mce::Color(0xAA00AA)}, diff --git a/src/ll/core/command/ModManage.cpp b/src/ll/core/command/ModManage.cpp index 49c53d14bd..298a6a4755 100644 --- a/src/ll/core/command/ModManage.cpp +++ b/src/ll/core/command/ModManage.cpp @@ -55,12 +55,9 @@ void registerModManageCommand() { std::string{mod::modsEnumName}, mod::ModRegistrar::getInstance().getSortedModNames() ); - auto& cmd = CommandRegistrar::getInstance().getOrCreateCommand( - Util::toLower(selfModName), - "LeviLamina's main command"_tr(), - config.permission - ); - cmd.alias("ll"); + auto& cmd = CommandRegistrar::getInstance() + .getOrCreateCommand(Util::toLower(selfModName), "LeviLamina's main command"_tr(), config.permission) + .alias("ll"); cmd.overload().text("load").required("mod").execute( [](CommandOrigin const&, CommandOutput& output, LeviCommand3 const& param) { if (ll::mod::ModManagerRegistry::getInstance().hasMod(param.mod)) { diff --git a/src/mc/deps/core/mce/Color.h b/src/mc/deps/core/mce/Color.h index dffefea18d..e3e4f4a35d 100644 --- a/src/mc/deps/core/mce/Color.h +++ b/src/mc/deps/core/mce/Color.h @@ -14,8 +14,6 @@ class Color : public ll::math::floatN4 { public: [[nodiscard]] constexpr Color() noexcept = default; - [[nodiscard]] constexpr Color(uint hex) noexcept : Color((hex >> 16) & 0xFF, (hex >> 8) & 0xFF, hex & 0xFF) {} - template [[nodiscard]] constexpr Color(T0 const& ir, T1 const& ig, T2 const& ib, T3 const& ia = 255) noexcept : floatN4( @@ -33,6 +31,8 @@ class Color : public ll::math::floatN4 { requires(V::size() == 3) : floatN4(v.r, v.g, v.b, a) {} + [[nodiscard]] constexpr Color(uint hex) noexcept : Color((hex >> 16) & 0xFF, (hex >> 8) & 0xFF, hex & 0xFF) {} + [[nodiscard]] constexpr Color(std::string_view hex) noexcept : floatN4(0, 0, 0, 1) { // NOLINT if (hex[0] == '#') { hex = hex.substr(1); diff --git a/src/mc/enums/BookEditAction.h b/src/mc/enums/BookEditAction.h index ff39f26d17..649f2e9e79 100644 --- a/src/mc/enums/BookEditAction.h +++ b/src/mc/enums/BookEditAction.h @@ -8,4 +8,4 @@ enum class BookEditAction : uchar { Delete = 0x2, Swap = 0x3, Sign = 0x4, -}; \ No newline at end of file +}; diff --git a/src/mc/nbt/DoubleTag.h b/src/mc/nbt/DoubleTag.h index b00561e9d0..0cd1100bf6 100644 --- a/src/mc/nbt/DoubleTag.h +++ b/src/mc/nbt/DoubleTag.h @@ -10,7 +10,7 @@ class DoubleTag : public ::Tag { public: double data; - constexpr DoubleTag& operator=(double value) noexcept{ + constexpr DoubleTag& operator=(double value) noexcept { data = value; return *this; } diff --git a/src/mc/world/ContainerIterator.h b/src/mc/world/ContainerIterator.h index 6bd436606a..d2fda96b7c 100644 --- a/src/mc/world/ContainerIterator.h +++ b/src/mc/world/ContainerIterator.h @@ -13,9 +13,7 @@ class ContainerIterator { using reference = value_type&; using iterator_category = std::random_access_iterator_tag; - [[nodiscard]] constexpr ContainerIterator(T* container, int position) - : mContainer(container), - mSlot(position) {} + [[nodiscard]] constexpr ContainerIterator(T* container, int position) : mContainer(container), mSlot(position) {} [[nodiscard]] constexpr bool operator==(const ContainerIterator& other) const { return mSlot == other.mSlot && mContainer == other.mContainer; @@ -30,7 +28,7 @@ class ContainerIterator { return mContainer->getItemNonConst(mSlot); } } - [[nodiscard]] constexpr pointer operator->() const { + [[nodiscard]] constexpr pointer operator->() const { if constexpr (std::is_const_v) { return &mContainer->getItem(mSlot); } else { diff --git a/src/mc/world/level/BlockSource.h b/src/mc/world/level/BlockSource.h index d3a32d7ef8..2242c5ac58 100644 --- a/src/mc/world/level/BlockSource.h +++ b/src/mc/world/level/BlockSource.h @@ -120,8 +120,7 @@ class BlockSource : public IBlockSource, public std::enable_shared_from_this&, class AABB const& intersectTestBox, bool withUnloadedChunks) const; + MCVAPI void fetchAABBs(std::vector&, class AABB const& intersectTestBox, bool withUnloadedChunks) const; // vIndex: 21 MCVAPI void @@ -170,11 +169,11 @@ class BlockSource : public IBlockSource, public std::enable_shared_from_this> - fetchEntities(class Actor const* except, class AABB const& bb, bool useHitbox, bool); + fetchEntities(class Actor const* except, class AABB const& bb, bool useHitbox, bool); // vIndex: 32 MCVAPI gsl::span> - fetchEntities(::ActorType, class AABB const&, class Actor const*, std::function); + fetchEntities(::ActorType, class AABB const&, class Actor const*, std::function); // vIndex: 33 MCVAPI bool