Skip to content

Commit

Permalink
feat: add param traits to custom command param
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Oct 5, 2024
1 parent d81fc04 commit 387069b
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 55 deletions.
8 changes: 5 additions & 3 deletions src/ll/api/command/EnumName.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ struct unprefix_name_for_c {
static constexpr auto stored_name =
FixedString<ll::reflection::type_unprefix_name_v<T>.size()>{ll::reflection::type_unprefix_name_v<T>};
};

template <class T>
struct enum_name {
static constexpr char const* value = std::is_enum_v<T> ? (char const*)unprefix_name_for_c<T>::stored_name : nullptr;
struct enum_name;

template <concepts::Require<std::is_enum> T>
struct enum_name<T> {
static constexpr char const* value = unprefix_name_for_c<T>::stored_name;
};
template <class T>
struct enum_name<SoftEnum<T>> {
Expand Down
81 changes: 32 additions & 49 deletions src/ll/api/command/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,9 @@
#include <string_view>
#include <type_traits>

#include "ll/api/base/StdInt.h"
#include "ll/api/command/Command.h"
#include "ll/api/command/CommandRegistrar.h"
#include "ll/api/command/EnumName.h"
#include "ll/api/command/Optional.h"
#include "ll/api/command/OverloadData.h"
#include "ll/api/command/SoftEnum.h"

#include "mc/deps/core/common/bedrock/typeid_t.h"
#include "mc/server/commands/CommandParameterDataType.h"
#include "mc/server/commands/CommandParameterOption.h"
#include "mc/server/commands/CommandRegistry.h"
#include "mc/world/level/Command.h"
#include "ll/api/command/ParamTraits.h"

namespace ll::command {

Expand All @@ -33,43 +23,28 @@ class Overload : private OverloadData {
static constexpr auto paramOffset = offsetof(Overload<Params>::TestOffset, params);
static constexpr auto placeholderOffset = offsetof(Overload<Params>::TestOffset, placeholder);

constexpr Overload& addParam(std::string_view name, int index) {
meta::visitIndex<reflection::member_count_v<Params>>(index, [&, this]<size_t I>() {
using OriginalType = typename reflection::member_t<I, Params>;
using RemoveOptionalType = remove_optional_t<OriginalType>;
using ParamType = std::conditional_t<
traits::is_specialization_of_v<RemoveOptionalType, SoftEnum>,
std::string,
RemoveOptionalType>;
int offset = (int)(paramOffset + reflection::member_offset_v<I, Params>);
int flagOffset = -1;
if constexpr (traits::is_specialization_of_v<OriginalType, Optional>) {
flagOffset = offset + OptionalOffsetGetter<ParamType>::value;
}

CommandParameterDataType paramType = CommandParameterDataType::Basic;
if constexpr (std::is_enum_v<ParamType>) {
paramType = CommandParameterDataType::Enum;
CommandRegistrar::getInstance().template tryRegisterEnum<ParamType>();
} else if constexpr (traits::is_specialization_of_v<RemoveOptionalType, SoftEnum>) {
paramType = CommandParameterDataType::SoftEnum;
CommandRegistrar::getInstance().template tryRegisterSoftEnum<RemoveOptionalType>();
}

addParamImpl(
Bedrock::type_id<CommandRegistry, ParamType>(),
&CommandRegistry::parse<ParamType>,
name,
paramType,
enum_name_v<RemoveOptionalType>,
offset,
flagOffset,
true
);
});
return *this;
template <size_t I, bool Opt>
constexpr void addParam(std::string_view name) {
using OriginalType = std::remove_cvref_t<typename reflection::member_t<I, Params>>;
using RemoveOptionalType = remove_optional_t<OriginalType>;
int offset = (int)(paramOffset + reflection::member_offset_v<I, Params>);
int flagOffset = -1;
if constexpr (traits::is_specialization_of_v<OriginalType, Optional>) {
flagOffset = offset + OptionalOffsetGetter<RemoveOptionalType>::value;
}
using Traits = ParamTraits<RemoveOptionalType>;
Traits::transformData(addParamImpl(
Traits::typeId(),
Traits::parser(),
name,
Traits::dataType(),
Traits::enumNameOrPostfix(),
Traits::subChain(),
offset,
flagOffset,
Opt
));
}

explicit Overload(CommandHandle& handle, std::weak_ptr<mod::Mod> mod) : OverloadData(handle, std::move(mod)) {}

class ParamName : public std::string_view {
Expand All @@ -82,7 +57,11 @@ class Overload : private OverloadData {
if (member == s) return i;
i++;
}
#ifndef __INTELLISENSE__
throw std::invalid_argument("invalid param " + std::string(str));
#else
return -1;
#endif
}

public:
Expand All @@ -96,11 +75,15 @@ class Overload : private OverloadData {

public:
[[nodiscard]] constexpr Overload& optional(ParamName const name) {
addParam(name.get(), name.index()).back().mIsOptional = true;
meta::visitIndex<reflection::member_count_v<Params>>(name.index(), [&]<size_t I>() {
addParam<I, true>(name.get());
});
return *this;
}
[[nodiscard]] constexpr Overload& required(ParamName const name) {
addParam(name.get(), name.index()).back().mIsOptional = false;
meta::visitIndex<reflection::member_count_v<Params>>(name.index(), [&]<size_t I>() {
addParam<I, false>(name.get());
});
return *this;
}
[[nodiscard]] constexpr Overload& text(std::string_view text) {
Expand Down
31 changes: 29 additions & 2 deletions src/ll/api/command/OverloadData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,40 @@ CommandParameterData& OverloadData::addParamImpl(
int offset,
int flagOffset,
bool optional
) {
//TODO: remove in release
return addParamImpl(id, parser, name, type, enumNameOrPostfix, nullptr, offset, flagOffset, optional);
}

CommandParameterData& OverloadData::addParamImpl(
Bedrock::typeid_t<CommandRegistry> id,
CommandRegistry::ParseFn parser,
std::string_view name,
CommandParameterDataType type,
char const* enumNameOrPostfix,
char const* subChain,
int offset,
int flagOffset,
bool optional
) {
std::lock_guard lock{impl->mutex};
if (enumNameOrPostfix) {
enumNameOrPostfix = storeStr(enumNameOrPostfix);
}
auto& param =
impl->params.emplace_back(id, parser, std::string{name}, type, enumNameOrPostfix, offset, optional, flagOffset);
if (subChain) {
subChain = storeStr(subChain);
}
auto& param = impl->params.emplace_back(
id,
parser,
std::string{name},
type,
enumNameOrPostfix,
subChain,
offset,
optional,
flagOffset
);
if (id == Bedrock::type_id<CommandRegistry, CommandBlockName>()
|| id == Bedrock::type_id<CommandRegistry, CommandItem>()) {
param.addOptions(CommandParameterOption::HasSemanticConstraint);
Expand Down
12 changes: 12 additions & 0 deletions src/ll/api/command/OverloadData.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ class OverloadData {
bool optional
);

LLAPI CommandParameterData& addParamImpl(
Bedrock::typeid_t<CommandRegistry> id,
CommandRegistry::ParseFn parser,
std::string_view name,
CommandParameterDataType type,
char const* enumNameOrPostfix,
char const* subChain,
int offset,
int flagOffset,
bool optional
);

LLAPI CommandParameterData& addTextImpl(std::string_view text, int offset);

LLAPI void setFactory(std::function<std::unique_ptr<::Command>()>&& fn);
Expand Down
51 changes: 51 additions & 0 deletions src/ll/api/command/ParamTraits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <cstddef>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>

#include "ll/api/base/StdInt.h"
#include "ll/api/command/CommandRegistrar.h"
#include "ll/api/command/EnumName.h"
#include "ll/api/command/Optional.h"
#include "ll/api/command/SoftEnum.h"

#include "mc/deps/core/common/bedrock/typeid_t.h"
#include "mc/server/commands/CommandParameterData.h"
#include "mc/server/commands/CommandParameterDataType.h"
#include "mc/server/commands/CommandParameterOption.h"
#include "mc/server/commands/CommandRegistry.h"

namespace ll::command {
template <class T>
struct ParamTraits {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::Basic; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<T>; }
static constexpr char const* enumNameOrPostfix() { return nullptr; }
static constexpr char const* subChain() { return nullptr; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, T>(); }
static constexpr void transformData(CommandParameterData&) {}
};
template <concepts::Require<std::is_enum> T>
struct ParamTraits<T> {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::Enum; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<T>; }
static constexpr char const* enumNameOrPostfix() { return enum_name_v<T>; }
static constexpr char const* subChain() { return nullptr; }
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> {
static constexpr CommandParameterDataType dataType() { return CommandParameterDataType::SoftEnum; }
static inline CommandRegistry::ParseFn parser() { return &CommandRegistry::parse<std::string>; }
static constexpr char const* enumNameOrPostfix() { return enum_name_v<T>; }
static constexpr char const* subChain() { return nullptr; }
static Bedrock::typeid_t<CommandRegistry> typeId() { return Bedrock::type_id<CommandRegistry, std::string>(); }
static void transformData(CommandParameterData&) {
CommandRegistrar::getInstance().template tryRegisterSoftEnum<T>();
}
};
} // namespace ll::command
1 change: 1 addition & 0 deletions src/ll/api/command/runtime/RuntimeOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void RuntimeOverload::addParam(std::string_view name, ParamKindType kind, Comman
name,
type,
nullptr,
nullptr,
offset,
offset + OptionalOffsetGetter<ParamStorageType::value_type>::value,
true
Expand Down
3 changes: 2 additions & 1 deletion src/mc/server/commands/CommandParameterData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CommandParameterData::CommandParameterData(
std::string name,
::CommandParameterDataType type,
char const* enumNameOrPostfix,
char const* subChain,
int offset,
bool optional,
int flagOffset
Expand All @@ -14,7 +15,7 @@ CommandParameterData::CommandParameterData(
mParse(parser),
mName(std::move(name)),
mEnumNameOrPostfix(enumNameOrPostfix),
mSubChain(nullptr),
mSubChain(subChain),
mParamType(type),
mOffset(offset),
mSettedOffset(flagOffset),
Expand Down
1 change: 1 addition & 0 deletions src/mc/server/commands/CommandParameterData.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class CommandParameterData {
std::string name,
::CommandParameterDataType type,
char const* enumNameOrPostfix,
char const* subChain,
int offset,
bool optional,
int flagOffset
Expand Down

0 comments on commit 387069b

Please sign in to comment.