LeviLamina
Loading...
Searching...
No Matches
Overload.h
1#pragma once
2
3#include <cstddef>
4#include <stdexcept>
5#include <string>
6#include <string_view>
7#include <type_traits>
8
9#include "ll/api/command/Command.h"
10#include "ll/api/command/OverloadData.h"
11#include "ll/api/command/ParamTraits.h"
12
13namespace ll::command {
14
15template <reflection::Reflectable Params>
16class Overload : private OverloadData {
17 friend CommandHandle;
18
19 struct TestOffset : private ::Command {
20 uint64 placeholder{};
21 Params params;
22 };
23 static constexpr auto paramOffset = offsetof(Overload<Params>::TestOffset, params);
24 static constexpr auto placeholderOffset = offsetof(Overload<Params>::TestOffset, placeholder);
25
26 template <size_t I, bool Opt>
27 constexpr void addParam(std::string_view name) {
28 using OriginalType = std::remove_cvref_t<typename reflection::member_t<I, Params>>;
29 using RemoveOptionalType = remove_optional_t<OriginalType>;
30 int offset = (int)(paramOffset + reflection::member_offset_v<I, Params>);
31 int flagOffset = -1;
32 if constexpr (traits::is_specialization_of_v<OriginalType, Optional>) {
33 flagOffset = offset + OptionalOffsetGetter<RemoveOptionalType>::value;
34 }
36 Traits::transformData(
37 addParamImpl(
38 Traits::typeId(),
39 Traits::parseFn(),
40 name,
41 Traits::dataType(),
42 Traits::enumNameOrPostfix(),
43 Traits::subChain(),
44 offset,
45 flagOffset,
46 Opt,
47 Traits::options()
48 ),
49 getRegistrar()
50 );
51 }
52 explicit Overload(CommandHandle& handle, std::weak_ptr<mod::Mod> mod) : OverloadData(handle, std::move(mod)) {}
53
54 class ParamName {
55 std::string_view str;
56 int idx;
57
58 constexpr int indexSearcher(std::string_view s) {
59 int i{};
60 for (auto& member : reflection::member_name_array_v<Params>) {
61 if (member == s) return i;
62 i++;
63 }
64#ifndef __INTELLISENSE__
65 throw std::invalid_argument("invalid param " + std::string(str));
66#else
67 return -1;
68#endif
69 }
70
71 public:
72 template <class S>
73 requires(std::is_constructible_v<std::string_view, S const&>)
74 consteval ParamName(S const& s) : str(s),
75 idx(indexSearcher(s)) {}
76 constexpr std::string_view get() const { return str; }
77 constexpr int index() const { return idx; }
78 };
79
80public:
81 [[nodiscard]] constexpr Overload& optional(ParamName const name) {
82 meta::visitIndex<reflection::member_count_v<Params>>(name.index(), [&]<size_t I>() {
83 addParam<I, true>(name.get());
84 });
85 return *this;
86 }
87 [[nodiscard]] constexpr Overload& required(ParamName const name) {
88 meta::visitIndex<reflection::member_count_v<Params>>(name.index(), [&]<size_t I>() {
89 addParam<I, false>(name.get());
90 });
91 return *this;
92 }
93 [[nodiscard]] constexpr Overload& text(std::string_view text) {
94 addTextImpl(text, (int)placeholderOffset);
95 return *this;
96 }
97 template <class Fn>
98 [[nodiscard]] constexpr Overload& modify(Fn&& fn) {
99 std::invoke(std::forward<Fn>(fn), back());
100 return *this;
101 }
102
103 [[nodiscard]] constexpr Overload& postfix(std::string_view postfix) {
104 return modify([&](auto&& val) {
105 val.mEnumNameOrPostfix = storeStr(postfix);
106 val.mParamType = CommandParameterDataType::Postfix;
107 });
108 }
109 [[nodiscard]] constexpr Overload& option(CommandParameterOption option) {
110 return modify([&](auto&& val) { val.addOptions(option); });
111 }
112 [[nodiscard]] constexpr Overload& deoption(CommandParameterOption option) {
113 return modify([&](auto&& val) {
114 val.mOptions = (CommandParameterOption)((uchar)(val.mOptions) & (!(uchar)option));
115 });
116 return *this;
117 }
118
119 template <class Fn>
120 void constexpr execute(Fn&& fn) {
121 using E = std::remove_cvref_t<Fn>;
122 setFactory([fn = std::forward<Fn>(fn)]() -> std::unique_ptr<::Command> {
123 return std::unique_ptr<Command<Params, E>>(new Command<Params, E>{fn});
124 });
125 }
126};
127} // namespace ll::command
Definition Command.h:20
Definition ParamTraits.h:33