Open codehz opened 4 years ago
@codehz What about void teleport_to_player(CommandOriginHelper&/Helper class for access to BDS CommandOrigin/ origin,CustomCommandResult& res,ServerPlayer sp){ //origin.getPlayer returns ServerPlayer if(!origin.isPlayer()){ res.error(); res<<"error "<<123<<origin.getName(); //overloaded << operator } } BDLCMDRegistry::registerCommand("tpa",overload1/Infer arguments automatically /,overload2,if_no_overload_found_handler);
@codehz and could you please show how to register a command with enum? like /tpa {accept,deny},etc.
to register enum:
enum class MyEnum: int {A, B};
auto test = BDLCommandRegistry::newEnum<MyEnum>("test");
test.add("A", MyEnum::A);
test.add("B", MyEnum::B);
dynamic enum:
// in global scope
static auto test = BDLCommandRegistry::newDynamicEnum<decltype("test_dynamic"_dynenum)>(); // use gcc extension to generate type from string
// in some function
test.set({"A", "B"});
test.clear();
test.add("C");
and a better command register method:
auto command = BDLCommandRegistry::newCommand("command");
command.add(impl_01);
command.add(impl_02);
command.set_fallback(if_no_overload_found_handler); // I'm not sure if it can be implemented...
maybe we should use codegen insteads of just template meta programming... or the argument name cannot be inferred from function.. (and optional argument)
@codehz yeah,you're right.
I wonder whether
BTW, the command parsing is happened in server side.. so the malformed command expression would be able to detect in server side and rerouting to fallback handler.. seems pointless..
@codehz using mojang command overload api seems like a morr complex way to solve problem(need to generate class and vtable dynamically(or need a codegen),need to reverse-engineer more api). Use a simple lexer with overload support maybe a better choice? Maybe we can use tricks to make client show overloads,like multi-line command description.(hadnt tested)
@codehz I dont know if duplicated availableCommandsPacket with only one command works well.(it means sending overloads of a mod commands after server sent previous availableCommandsPacket to client ) Modifing availableCommandsPacket::write seems like a difficult job.
@codehz @CodeHz new idea:
void tpa_to_impl(...,ServerPlayer* sp,int xx){
}
CommandBase cmd("tpa");
cmd.overload("to <dest:player> <testval:int>",tpa_to_impl);//use template like overload(string_view,void(*)(...,T ,T2) to determine how many arguments need to be parsed(in base.h) and base.so just exports regCommand0(sview,void *function),regCommand1...,etc..
and lexer parses overload,and do some preparations(convert string to int,ServerPlayer*,etc)
and use (void(*)(...,void*,void*))callback(arg0,arg1,argx)
CONS : 1.assume that all arguments are 64bits long.(so passing string_view and const string(abi:cxx11) cant work?(because string_view uses two registers).And float cant work ad well(because it uses %xmm0 register) ) 2.use a lot of else if to make right calls(right counts of arguments)
alternative concept: for codegen
// header (.h)
struct Teleport : CustomCommandDescription {
static constexpr auto name = "teleport";
static constexpr auto permission = CommandPermission::OP;
// any name
void impl_01(ServerPlayer *target); // generate `teleport <target: player>`
// use std::optional for optional argument
void impl_02(Vec3 pos, std::optional<int> angle); // generate `teleport <pos: position> [angle: int]`
// use enum
void impl_03(MyEnum target); // generate `teleport <target: my_enum>`
};
extern "C" {
BDL_EXPORT int mod_register_command(CommandRegistry *); // codegen
}
// impl (.cpp)
void Teleport::impl_01(ServerPlayer *target) {}
....
Concept:
Note: the pattern of the command is
CustomCommandResult (*)(CommandOrigin &origin, T... t)