diff --git a/code/client/citicore/console/Console.CommandHelpers.h b/code/client/citicore/console/Console.CommandHelpers.h index a166e85ef8..86e0194676 100644 --- a/code/client/citicore/console/Console.CommandHelpers.h +++ b/code/client/citicore/console/Console.CommandHelpers.h @@ -7,6 +7,7 @@ class ConsoleCommand { private: int m_token; + std::string m_resource = "internal"; ConsoleCommandManager* m_manager; public: @@ -30,7 +31,7 @@ class ConsoleCommand using ConsoleCommandFunction = internal::ConsoleCommandFunction; - m_token = m_manager->Register(name, [=](ConsoleExecutionContext& context) { + m_token = m_manager->Register(name, m_resource, [=](ConsoleExecutionContext& context) { return ConsoleCommandFunction::Call(functionRef, context); }, ConsoleCommandFunction::kNumArguments); } diff --git a/code/client/citicore/console/Console.Commands.cpp b/code/client/citicore/console/Console.Commands.cpp index 4b965a79c9..557e2da5b3 100644 --- a/code/client/citicore/console/Console.Commands.cpp +++ b/code/client/citicore/console/Console.Commands.cpp @@ -7,7 +7,7 @@ #include ConsoleCommandManager::ConsoleCommandManager(console::Context* parentContext) - : m_parentContext(parentContext), m_curToken(0) + : m_parentContext(parentContext), m_curToken(0) { } @@ -15,12 +15,12 @@ ConsoleCommandManager::~ConsoleCommandManager() { } -int ConsoleCommandManager::Register(const std::string& name, const THandler& handler, size_t arity) +int ConsoleCommandManager::Register(const std::string& name, std::string resource, const THandler& handler, size_t arity) { std::unique_lock lock(m_mutex); int token = m_curToken.fetch_add(1); - m_entries.insert({name, Entry{name, handler, token, arity}}); + m_entries.insert({ name, Entry{ name, handler, resource, token, arity } }); return token; } @@ -55,7 +55,7 @@ void ConsoleCommandManager::Invoke(const std::string& commandString, const std:: return; } - std::string command = arguments.Shift(); + std::string command = arguments.Shift(); m_rawCommand = commandString; @@ -98,7 +98,7 @@ void ConsoleCommandManager::InvokeDirect(const std::string& commandName, const P // Don't print to the console if a remote client tried to execute an unknown command. if (executionContext.empty()) { - console::Printf("cmd", "No such command %s.\n", commandName.c_str()); + console::Printf("cmd", "No such command %s.\n", commandName.c_str()); } return; } @@ -167,7 +167,7 @@ void ConsoleCommandManager::ForAllCommands2(const std::function +template struct ConsoleArgumentTraits { - using Less = std::less; + using Less = std::less; using Greater = std::greater; - using Equal = std::equal_to; + using Equal = std::equal_to; }; -template +template struct ConsoleArgumentName { inline static const char* Get() @@ -159,23 +171,23 @@ struct ConsoleArgumentName } }; -template +template struct ConsoleArgumentType { static std::string Unparse(const TArgument& argument) { - //static_assert(false, "Unknown ConsoleArgumentType unparse handler (try defining one?)"); + // static_assert(false, "Unknown ConsoleArgumentType unparse handler (try defining one?)"); TArgument::__fatal(); } static bool Parse(const std::string& input, TArgument* out) { - //static_assert(false, "Unknown ConsoleArgumentType parse handler (try defining one?)"); + // static_assert(false, "Unknown ConsoleArgumentType parse handler (try defining one?)"); TArgument::__fatal(); } }; -template <> +template<> struct ConsoleArgumentType { static std::string Unparse(const std::string& input) @@ -190,7 +202,7 @@ struct ConsoleArgumentType } }; -template <> +template<> struct ConsoleArgumentName { inline static const char* Get() @@ -199,7 +211,7 @@ struct ConsoleArgumentName } }; -template +template struct ConsoleArgumentType::value>::type> { static std::string Unparse(const TArgument& input) @@ -247,7 +259,7 @@ struct ConsoleArgumentType +template struct ConsoleArgumentType::value && !std::is_same::value>> { static std::string Unparse(const TArgument& input) @@ -271,7 +283,7 @@ struct ConsoleArgumentType +template struct ConsoleArgumentType::value>> { static std::string Unparse(const TArgument& input) @@ -301,7 +313,6 @@ class ExternalContext : public std::any ExternalContext(const std::any& any) : std::any(any) { - } }; #else @@ -316,13 +327,13 @@ class ExternalContext namespace internal { -template +template inline bool ParseArgument(const std::string& input, TArgument* out) { return ConsoleArgumentType::Parse(input, out); } -template +template inline bool ParseArgument(const ConsoleExecutionContext& context, int argInput, TArgument* out) { return ConsoleArgumentType::Parse(context.arguments[argInput], out); @@ -351,25 +362,25 @@ inline bool ParseArgument(const ConsoleExecutionContext& contex return true; } -template +template constexpr int AddOneArg = Iterator + 1; -template +template int AddOneArg = Iterator; -template +template std::string UnparseArgument(const TArgument& input) { return ConsoleArgumentType::Unparse(input); } -template +template struct ConsoleCommandFunction { constexpr static const size_t kNumArguments = -1; }; -template +template struct ConsoleCommandFunction> { using TFunc = std::function; @@ -409,9 +420,8 @@ struct ConsoleCommandFunction> } public: - // non-terminator iterator - template + template static std::enable_if_t<(Iterator < sizeof...(Args)), bool> CallInternal(TFunc func, ConsoleExecutionContext& context, TupleType tuple) { // the type of the current argument @@ -421,9 +431,9 @@ struct ConsoleCommandFunction> if (ParseArgument(context, ArgIterator, &argument)) { return CallInternal>( - func, - context, - std::tuple_cat(std::move(tuple), std::forward_as_tuple(std::forward(argument)))); + func, + context, + std::tuple_cat(std::move(tuple), std::forward_as_tuple(std::forward(argument)))); } context.errorBuffer << "Could not convert argument " << std::to_string(Iterator) << " (" << context.arguments[Iterator] << ") to " << typeid(ArgType).name() << std::endl; @@ -432,7 +442,7 @@ struct ConsoleCommandFunction> } // terminator - template + template static std::enable_if_t<(Iterator == sizeof...(Args)), bool> CallInternal(TFunc func, ConsoleExecutionContext& context, TupleType tuple) { apply(func, std::move(tuple)); diff --git a/code/components/citizen-scripting-core/src/ResourceScriptFunctions.cpp b/code/components/citizen-scripting-core/src/ResourceScriptFunctions.cpp index 68addf365c..526dd80eaf 100644 --- a/code/components/citizen-scripting-core/src/ResourceScriptFunctions.cpp +++ b/code/components/citizen-scripting-core/src/ResourceScriptFunctions.cpp @@ -26,15 +26,15 @@ struct CommandObject { std::string name; + std::string resource; int32_t arity; - CommandObject(const std::string& name, size_t arity) - : name(name), arity(arity) + CommandObject(const std::string& name, std::string resource, size_t arity) + : name(name), resource(resource), arity(arity) { - } - MSGPACK_DEFINE_MAP(name, arity); + MSGPACK_DEFINE_MAP(name, resource, arity); }; static InitFunction initFunction([] () @@ -125,6 +125,7 @@ static InitFunction initFunction([] () { auto resourceManager = resource->GetManager(); auto consoleCxt = resourceManager->GetComponent(); + std::string resourceName = resource->GetName(); outerRefs[commandName] = commandRef; @@ -139,7 +140,7 @@ static InitFunction initFunction([] () seGetCurrentContext()->AddAccessControlEntry(se::Principal{ "builtin.everyone" }, se::Object{ "command." + commandName }, se::AccessType::Allow); } - int commandToken = consoleCxt->GetCommandManager()->Register(commandName, [=](ConsoleExecutionContext& context) + int commandToken = consoleCxt->GetCommandManager()->Register(commandName, resourceName, [=](ConsoleExecutionContext& context) { try { @@ -159,7 +160,7 @@ static InitFunction initFunction([] () resource->OnStop.Connect([consoleCxt, commandToken]() { consoleCxt->GetCommandManager()->Unregister(commandToken); - }, INT32_MAX); + },INT32_MAX); } } }); @@ -181,7 +182,7 @@ static InitFunction initFunction([] () consoleCxt->GetCommandManager()->ForAllCommands2([&commandList](const console::CommandMetadata& command) { - commandList.emplace_back(command.GetName(), (command.GetArity() == -1) ? -1 : int32_t(command.GetArity())); + commandList.emplace_back(command.GetName(), command.GetResourceName(), (command.GetArity() == -1) ? -1 : int32_t(command.GetArity())); }); context.SetResult(fx::SerializeObject(commandList)); @@ -189,6 +190,30 @@ static InitFunction initFunction([] () } }); + fx::ScriptEngine::RegisterNativeHandler("GET_RESOURCE_COMMANDS", [](fx::ScriptContext& context) + { + std::string resourceName = context.CheckArgument(0); + std::vector commandList; + + // find the resource + fx::ResourceManager* resourceManager = fx::ResourceManager::GetCurrent(); + fwRefContainer resource = resourceManager->GetResource(resourceName); + auto consoleCxt = resourceManager->GetComponent(); + + if (resource.GetRef()) + { + consoleCxt->GetCommandManager()->ForAllCommands2([&commandList, &resourceName](const console::CommandMetadata& command) + { + if (command.MatchResourceName(resourceName)) + { + commandList.emplace_back(command.GetName(), command.GetResourceName(), (command.GetArity() == -1) ? -1 : int32_t(command.GetArity())); + } + }); + } + + context.SetResult(fx::SerializeObject(commandList)); + }); + fx::ScriptEngine::RegisterNativeHandler("GET_INSTANCE_ID", [](fx::ScriptContext& context) { fx::OMPtr runtime; diff --git a/ext/native-decls/GetRegisteredCommands.md b/ext/native-decls/GetRegisteredCommands.md index e210ba3fd1..7e1e5895a5 100644 --- a/ext/native-decls/GetRegisteredCommands.md +++ b/ext/native-decls/GetRegisteredCommands.md @@ -13,13 +13,32 @@ The data returned adheres to the following layout: ``` [ { -"name": "cmdlist" +"name": "cmdlist", +"resource": "resource", +"arity" = -1, }, { "name": "command1" +"resource": "resource_2", +"arity" = -1, } ] ``` ## Return value An object containing registered commands. + +## Example + +```lua +RegisterCommand("showCommands", function() + local commands = GetRegisteredCommands() + print(("There is currently ^5%s^7 commands registered"):format(#commands)) + + local commandList = "" + for i=1, #commands do + commandlist = commandList + ("%s: %s (arguments: %s)\n"):format(commands[i].resource, commands[i].name, commands[i].arity) + end + + print(commandList) +end) \ No newline at end of file diff --git a/ext/native-decls/GetResourceCommands.md b/ext/native-decls/GetResourceCommands.md new file mode 100644 index 0000000000..a06a9f55df --- /dev/null +++ b/ext/native-decls/GetResourceCommands.md @@ -0,0 +1,45 @@ +--- +ns: CFX +apiset: shared +--- +## GET_RESOURCE_COMMANDS + +```c +object GET_RESOURCE_COMMANDS(char* resource); +``` + +Returns all commands registered by the specified resource. +The data returned adheres to the following layout: +``` +[ +{ +"name": "cmdlist", +"resource": "example_resource", +"arity" = -1, +}, +{ +"name": "command1" +"resource": "example_resource2", +"arity" = -1, +} +] +``` + +## Return value +An object containing registered commands. + +## Example + +```lua +RegisterCommand("getCommands", function(_, args) + local commands = GetResourceCommands(args[1]) + print(("Resource ^5%s^7 Has ^5%s^7 Commands Registered"):format(args[1], #commands)) + + local commandList = "" + for i=1, #commands do + commandlist = commandList + ("%s, "):format(commands[i].name) + end + + print(commandList) +end) +```