Skip to content

Commit

Permalink
refactor: make param option and praser into traits
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Oct 6, 2024
1 parent 0a89e9f commit 0414add
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 83 deletions.
15 changes: 6 additions & 9 deletions src-test/server/testCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,12 @@ LL_AUTO_TYPE_INSTANCE_HOOK(

CommandRegistrar::getInstance().tryRegisterSoftEnum("hello", {"SoftEnum1", "af1451"});

CommandRegistrar::getInstance().tryRegisterEnum(
CommandRegistrar::getInstance().tryRegisterRuntimeEnum(
"testenum",
{
{"testenumhhhh", 124144},
{"hrshh54w4t4", 67584 }
},
Bedrock::type_id<CommandRegistry, std::pair<
std::string,
uint64>>(),
&CommandRegistry::parse<std::pair<
std::string,
uint64>>
}
);

cmd.runtimeOverload()
Expand All @@ -146,7 +140,10 @@ LL_AUTO_TYPE_INSTANCE_HOOK(
auto range = self["range"].get<ParamKind::IntegerRange>();
output.success("range : {} {}", range.mMinValue, range.mMaxValue);
output.success("SoftEnum : {}", self["se"].get<ParamKind::SoftEnum>());
output.success("Enum : {}", self["enummmmm"].get<ParamKind::Enum>());
output.success(
"Enum : {}",
reinterpret_cast<std::pair<std::string, uint64> const&>(self["enummmmm"].get<ParamKind::Enum>())
);
});

cmd.overload<ParamTest3>()
Expand Down
5 changes: 3 additions & 2 deletions src/ll/api/command/CommandRegistrar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "ll/api/base/StdInt.h"
#include "ll/api/command/CommandHandle.h"
#include "ll/api/command/OverloadData.h"
#include "ll/api/command/runtime/RuntimeEnum.h"
#include "ll/api/service/Bedrock.h"
#include "ll/api/service/GamingStatus.h"
#include "ll/api/utils/StringUtils.h"
Expand Down Expand Up @@ -122,13 +123,13 @@ bool CommandRegistrar::tryRegisterRuntimeEnum(
std::string const& name,
std::vector<std::pair<std::string, uint64>> values
) {
return tryRegisterEnum(name, std::move(values), Bedrock::type_id<CommandRegistry, std::pair<std::string, uint64>>(), &CommandRegistry::parse<std::pair<std::string, uint64>>);
return tryRegisterEnum(name, std::move(values), Bedrock::type_id<CommandRegistry, RuntimeEnum>(), &CommandRegistry::parse<RuntimeEnum>);
}
bool CommandRegistrar::addRuntimeEnumValues(
std::string const& name,
std::vector<std::pair<std::string, uint64>> values
) {
return addEnumValues(name, std::move(values), Bedrock::type_id<CommandRegistry, std::pair<std::string, uint64>>());
return addEnumValues(name, std::move(values), Bedrock::type_id<CommandRegistry, RuntimeEnum>());
}
bool CommandRegistrar::hasSoftEnum(std::string const& name) { return getRegistry().mSoftEnumLookup.contains(name); }

Expand Down
5 changes: 3 additions & 2 deletions src/ll/api/command/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ class Overload : private OverloadData {
using Traits = ParamTraits<RemoveOptionalType>;
Traits::transformData(addParamImpl(
Traits::typeId(),
Traits::parser(),
Traits::parseFn(),
name,
Traits::dataType(),
Traits::enumNameOrPostfix(),
Traits::subChain(),
offset,
flagOffset,
Opt
Opt,
Traits::options()
));
}
explicit Overload(CommandHandle& handle, std::weak_ptr<mod::Mod> mod) : OverloadData(handle, std::move(mod)) {}
Expand Down
27 changes: 14 additions & 13 deletions src/ll/api/command/OverloadData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ CommandParameterData& OverloadData::addParamImpl(
bool optional
) {
// TODO: remove in release
return addParamImpl(
auto& param = addParamImpl(
id,
parser,
name,
Expand All @@ -70,8 +70,15 @@ CommandParameterData& OverloadData::addParamImpl(
{},
offset,
flagOffset,
optional
optional,
type == CommandParameterDataType::Enum ? CommandParameterOption::EnumAutocompleteExpansion
: CommandParameterOption::None
);
if (id == Bedrock::type_id<CommandRegistry, CommandBlockName>()
|| id == Bedrock::type_id<CommandRegistry, CommandItem>()) {
param.addOptions(CommandParameterOption::HasSemanticConstraint);
}
return param;
}

CommandParameterData& OverloadData::addParamImpl(
Expand All @@ -83,10 +90,11 @@ CommandParameterData& OverloadData::addParamImpl(
std::string_view subChain,
int offset,
int flagOffset,
bool optional
bool optional,
CommandParameterOption options
) {
std::lock_guard lock{impl->mutex};
auto& param = impl->params.emplace_back(
return impl->params.emplace_back(
id,
parser,
std::string{name},
Expand All @@ -95,16 +103,9 @@ CommandParameterData& OverloadData::addParamImpl(
storeStr(subChain),
offset,
optional,
flagOffset
flagOffset,
options
);
if (id == Bedrock::type_id<CommandRegistry, CommandBlockName>()
|| id == Bedrock::type_id<CommandRegistry, CommandItem>()) {
param.addOptions(CommandParameterOption::HasSemanticConstraint);
}
if (type == CommandParameterDataType::Enum) {
param.addOptions(CommandParameterOption::EnumAutocompleteExpansion);
}
return param;
}
CommandParameterData& OverloadData::addTextImpl(std::string_view text, int offset) {
std::lock_guard lock{impl->mutex};
Expand Down
3 changes: 2 additions & 1 deletion src/ll/api/command/OverloadData.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class OverloadData {
std::string_view subChain,
int offset,
int flagOffset,
bool optional
bool optional,
CommandParameterOption options
);

LLAPI CommandParameterData& addTextImpl(std::string_view text, int offset);
Expand Down
79 changes: 70 additions & 9 deletions src/ll/api/command/ParamTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,93 @@

namespace ll::command {
template <class T>
struct ParamTraits {
struct ParamTraitsBase {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::Basic; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<T>; }
static constexpr CommandParameterOption options() { return CommandParameterOption::None; }
static inline CommandRegistry::ParseFn parseFn() { return &CommandRegistry::parse<T>; }
static constexpr std::string_view enumNameOrPostfix() { return {}; }
static constexpr std::string_view subChain() { return {}; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, T>(); }
static constexpr void transformData(CommandParameterData&) {}
};
template <class T>
struct ParamTraits : ParamTraitsBase<T> {};
template <class T>
struct EnumParser {
bool
operator()(CommandRegistry const& registry, void* storage, CommandRegistry::ParseToken const& token, CommandOrigin const&, int, std::string&, std::vector<std::string>&)
const {
*(T*)storage = (T)registry.getEnumData(token);
return true;
}
};
template <concepts::Require<std::is_enum> T>
struct ParamTraits<T> {
struct ParamTraits<T> : ParamTraitsBase<T> {
using Parser = EnumParser<T>;
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::Enum; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<T>; }
static constexpr CommandParameterOption options() { return CommandParameterOption::EnumAutocompleteExpansion; }
static constexpr std::string_view enumNameOrPostfix() { return enum_name_v<T>; }
static constexpr std::string_view subChain() { return {}; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, T>(); }
static void transformData(CommandParameterData&) { CommandRegistrar::getInstance().template tryRegisterEnum<T>(); }
};
template <concepts::Specializes<SoftEnum> T>
struct ParamTraits<T> {
struct ParamTraits<T> : ParamTraitsBase<T> {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::SoftEnum; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<std::string>; }
static constexpr CommandParameterOption options() { return CommandParameterOption::EnumAutocompleteExpansion; }
static inline CommandRegistry::ParseFn parseFn() { return &CommandRegistry::parse<std::string>; }
static constexpr std::string_view enumNameOrPostfix() { return enum_name_v<T>; }
static constexpr std::string_view subChain() { return {}; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, std::string>(); }
static void transformData(CommandParameterData&) {
CommandRegistrar::getInstance().template tryRegisterSoftEnum<T>();
}
};
struct EmptyParser {
bool
operator()(CommandRegistry const&, void*, CommandRegistry::ParseToken const&, CommandOrigin const&, int, std::string&, std::vector<std::string>&)
const {
return false;
}
};
template <>
struct ParamTraits<bool> : ParamTraitsBase<bool> {
using Parser = EmptyParser;
};
template <>
struct ParamTraits<DimensionType> : ParamTraitsBase<DimensionType> {
using Parser = EmptyParser;
};
template <>
struct ParamTraits<CommandItem> : ParamTraitsBase<CommandItem> {
using Parser = EmptyParser;
static constexpr CommandParameterOption options() { return CommandParameterOption::HasSemanticConstraint; }
};
template <>
struct ParamTraits<CommandBlockName> : ParamTraitsBase<CommandBlockName> {
using Parser = EmptyParser;
static constexpr CommandParameterOption options() { return CommandParameterOption::HasSemanticConstraint; }
};
template <>
struct ParamTraits<MobEffect const*> : ParamTraitsBase<MobEffect const*> {
using Parser = EmptyParser;
};
template <>
struct ParamTraits<ActorDefinitionIdentifier const*> : ParamTraitsBase<ActorDefinitionIdentifier const*> {
using Parser = EmptyParser;
};
} // namespace ll::command

template <class T>
inline bool CommandRegistry::parse(
void* storage,
CommandRegistry::ParseToken const& token,
CommandOrigin const& origin,
int version,
std::string& error,
std::vector<std::string>& errorParams
) const {
using Traits = ll::command::ParamTraits<T>;
if constexpr (requires { typename Traits::Parser; }) {
return (typename Traits::Parser{})(*this, storage, token, origin, version, error, errorParams);
} else {
static_assert(ll::traits::always_false<T>, "param traits missing parser type");
}
}
6 changes: 4 additions & 2 deletions src/ll/api/command/runtime/ParamKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "ll/api/base/Meta.h"
#include "ll/api/command/Optional.h"
#include "ll/api/command/ParamTraits.h"
#include "ll/api/command/Runtime/RuntimeEnum.h"

#include "mc/deps/core/common/bedrock/typeid_t.h"
#include "mc/server/commands/BlockStateCommandParam.h"
Expand Down Expand Up @@ -64,8 +66,8 @@ using ParamKindList = meta::TypeList<
float,
::DimensionType,
std::string,
std::pair<std::string, uint64>,
std::string,
RuntimeEnum,
RuntimeSoftEnum,
CommandSelector<Actor>,
CommandSelector<Player>,
CommandPosition,
Expand Down
36 changes: 36 additions & 0 deletions src/ll/api/command/runtime/RuntimeEnum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <string>

#include "ll/api/base/StdInt.h"
#include "ll/api/command/ParamTraits.h"

namespace ll::command {
struct RuntimeEnum {
std::string name;
uint64 index;
};
struct RuntimeSoftEnum : std::string {
using std::string::string;
};
template <>
struct ParamTraits<RuntimeEnum> : ParamTraitsBase<RuntimeEnum> {
struct Parser {
bool
operator()(CommandRegistry const& registry, void* storage, CommandRegistry::ParseToken const& token, CommandOrigin const&, int, std::string&, std::vector<std::string>&)
const {
*(RuntimeEnum*)storage = {token.toString(), registry.getEnumData(token)};
return true;
}
};
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::Enum; }
static constexpr CommandParameterOption options() { return CommandParameterOption::EnumAutocompleteExpansion; }
};
template <>
struct ParamTraits<RuntimeSoftEnum> : ParamTraitsBase<RuntimeSoftEnum> {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::SoftEnum; }
static constexpr CommandParameterOption options() { return CommandParameterOption::EnumAutocompleteExpansion; }
static inline CommandRegistry::ParseFn parseFn() { return &CommandRegistry::parse<std::string>; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, std::string>(); }
};
} // namespace ll::command
40 changes: 23 additions & 17 deletions src/ll/api/command/runtime/RuntimeOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,24 @@ RuntimeOverload::RuntimeOverload(CommandHandle& handle, std::weak_ptr<mod::Mod>
RuntimeOverload::RuntimeOverload(RuntimeOverload&&) = default;
RuntimeOverload::~RuntimeOverload() = default;

void RuntimeOverload::addParam(std::string_view name, ParamKindType kind, CommandParameterDataType type) {
void RuntimeOverload::addParam(std::string_view name, ParamKindType kind, bool optional) {
int offset = (int)(sizeof(RuntimeCommand) + impl->params.size() * sizeof(ParamStorageType));
meta::visitIndex<ParamKind::Count>(kind, [&]<size_t N> {
using ParamType = ParamKindList::get<N>;
addParamImpl(
Bedrock::type_id<CommandRegistry, ParamType>(),
&CommandRegistry::parse<ParamType>,

using Traits = ParamTraits<ParamType>;
Traits::transformData(addParamImpl(
Traits::typeId(),
Traits::parseFn(),
name,
type,
{},
{},
Traits::dataType(),
Traits::enumNameOrPostfix(),
Traits::subChain(),
offset,
offset + OptionalOffsetGetter<ParamStorageType::value_type>::value,
true
);
optional,
Traits::options()
));
});
impl->params.emplace_back(name, kind);
}
Expand All @@ -41,30 +44,33 @@ RuntimeOverload& RuntimeOverload::optional(std::string_view name, ParamKindType
if (kind == ParamKind::Enum || kind == ParamKind::SoftEnum) {
throw std::invalid_argument("enum kind need enum name");
}
addParam(name, kind, CommandParameterDataType::Basic);
addParam(name, kind, true);
return *this;
}
RuntimeOverload& RuntimeOverload::required(std::string_view name, ParamKindType kind) {
std::lock_guard l{lock()};
optional(name, kind).back().mIsOptional = false;
if (kind == ParamKind::Enum || kind == ParamKind::SoftEnum) {
throw std::invalid_argument("enum kind need enum name");
}
addParam(name, kind, false);
return *this;
}
RuntimeOverload& RuntimeOverload::optional(std::string_view name, ParamKindType enumKind, std::string_view enumName) {
std::lock_guard l{lock()};
if (enumKind != ParamKind::Enum && enumKind != ParamKind::SoftEnum) {
throw std::invalid_argument("invalid enum kind");
}
if (enumKind == ParamKind::Enum) {
addParam(name, enumKind, CommandParameterDataType::Enum);
} else {
addParam(name, enumKind, CommandParameterDataType::SoftEnum);
}
addParam(name, enumKind, true);
back().mEnumNameOrPostfix = storeStr(enumName);
return *this;
}
RuntimeOverload& RuntimeOverload::required(std::string_view name, ParamKindType enumKind, std::string_view enumName) {
std::lock_guard l{lock()};
optional(name, enumKind, enumName).back().mIsOptional = false;
if (enumKind != ParamKind::Enum && enumKind != ParamKind::SoftEnum) {
throw std::invalid_argument("invalid enum kind");
}
addParam(name, enumKind, false);
back().mEnumNameOrPostfix = storeStr(enumName);
return *this;
}
RuntimeOverload& RuntimeOverload::text(std::string_view text) {
Expand Down
2 changes: 1 addition & 1 deletion src/ll/api/command/runtime/RuntimeOverload.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RuntimeOverload : private OverloadData {

RuntimeOverload(CommandHandle&, std::weak_ptr<mod::Mod> mod);

void addParam(std::string_view name, ParamKindType kind, CommandParameterDataType type);
void addParam(std::string_view name, ParamKindType kind, bool optional);

public:
LLNDAPI RuntimeOverload& optional(std::string_view name, ParamKindType kind);
Expand Down
Loading

0 comments on commit 0414add

Please sign in to comment.