mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-06 20:03:51 +00:00
194 lines
6.6 KiB
C++
194 lines
6.6 KiB
C++
#include "CommandAPI.h"
|
|
#include "APIHelp.h"
|
|
#include "McAPI.h"
|
|
#include "PlayerAPI.h"
|
|
#include <Tools/Utils.h>
|
|
#include <Engine/GlobalShareData.h>
|
|
#include <Engine/LocalShareData.h>
|
|
#include <Engine/EngineOwnData.h>
|
|
#include <Utils/STLHelper.h>
|
|
#include <RegCommandAPI.h>
|
|
#include <Global.hpp>
|
|
#include <filesystem>
|
|
#include <Configs.h>
|
|
#include <vector>
|
|
#include <string>
|
|
using namespace std;
|
|
|
|
//////////////////// Helper ////////////////////
|
|
|
|
bool RegisterCmd(const string& cmd, const string& describe, int cmdLevel) {
|
|
::Global<CommandRegistry>->registerCommand(cmd, describe.c_str(), (CommandPermissionLevel)cmdLevel, {(CommandFlagValue)0},
|
|
{(CommandFlagValue)0x80});
|
|
return true;
|
|
}
|
|
|
|
// Helper
|
|
void LLSERegisterNewCmd(bool isPlayerCmd, string cmd, const string& describe, int level, Local<Function> func) {
|
|
if (cmd[0] == '/')
|
|
cmd = cmd.erase(0, 1);
|
|
|
|
if (isPlayerCmd) {
|
|
localShareData->playerCmdCallbacks[cmd] = {EngineScope::currentEngine(), level, script::Global<Function>(func)};
|
|
globalShareData->playerRegisteredCmd[cmd] = LLSE_BACKEND_TYPE;
|
|
} else {
|
|
localShareData->consoleCmdCallbacks[cmd] = {EngineScope::currentEngine(), level, script::Global<Function>(func)};
|
|
globalShareData->consoleRegisteredCmd[cmd] = LLSE_BACKEND_TYPE;
|
|
}
|
|
|
|
//延迟注册
|
|
if (isCmdRegisterEnabled)
|
|
RegisterCmd(cmd, describe, level);
|
|
else
|
|
toRegCmdQueue.push_back({cmd, describe, level});
|
|
}
|
|
|
|
bool LLSERemoveCmdRegister(ScriptEngine* engine) {
|
|
erase_if(localShareData->playerCmdCallbacks, [&engine](auto& data) {
|
|
return data.second.fromEngine == engine;
|
|
});
|
|
erase_if(localShareData->consoleCmdCallbacks, [&engine](auto& data) {
|
|
return data.second.fromEngine == engine;
|
|
});
|
|
return true;
|
|
}
|
|
// Helper
|
|
|
|
Local<Value> McClass::regPlayerCmd(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 3);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kFunction);
|
|
if (args.size() >= 4)
|
|
CHECK_ARG_TYPE(args[3], ValueKind::kNumber);
|
|
|
|
try {
|
|
string cmd = args[0].asString().toString();
|
|
string describe = args[1].asString().toString();
|
|
int level = 0;
|
|
|
|
if (args.size() >= 4) {
|
|
int newLevel = args[3].asNumber().toInt32();
|
|
if (newLevel >= 0 && newLevel <= 3)
|
|
level = newLevel;
|
|
}
|
|
|
|
LLSERegisterNewCmd(true, cmd, describe, level, args[2].asFunction());
|
|
return Boolean::newBoolean(true);
|
|
}
|
|
CATCH("Fail in RegisterPlayerCmd!");
|
|
}
|
|
|
|
Local<Value> McClass::regConsoleCmd(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 3);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[1], ValueKind::kString);
|
|
CHECK_ARG_TYPE(args[2], ValueKind::kFunction);
|
|
|
|
try {
|
|
string cmd = args[0].asString().toString();
|
|
string describe = args[1].asString().toString();
|
|
|
|
LLSERegisterNewCmd(false, cmd, describe, 4, args[2].asFunction());
|
|
return Boolean::newBoolean(true);
|
|
}
|
|
CATCH("Fail in RegisterConsoleCmd!");
|
|
}
|
|
|
|
// Helper
|
|
bool SendCmdOutput(const std::string& output) {
|
|
string finalOutput(output);
|
|
finalOutput += "\r\n";
|
|
|
|
SymCall("??$_Insert_string@DU?$char_traits@D@std@@_K@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@QEBD_K@Z",
|
|
ostream&, ostream&, const char*, unsigned)(cout, finalOutput.c_str(), finalOutput.size());
|
|
return true;
|
|
}
|
|
// Helper
|
|
|
|
Local<Value> McClass::sendCmdOutput(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kString);
|
|
|
|
try {
|
|
return Boolean::newBoolean(SendCmdOutput(args[0].toStr()));
|
|
}
|
|
CATCH("Fail in SendCmdOutput!");
|
|
}
|
|
|
|
void ProcessRegCmdQueue() {
|
|
for (auto& cmdData : toRegCmdQueue) {
|
|
RegisterCmd(cmdData.cmd, cmdData.describe, cmdData.level);
|
|
}
|
|
toRegCmdQueue.clear();
|
|
}
|
|
|
|
string LLSEFindCmdReg(bool isPlayerCmd, const string& cmd, vector<string>& receiveParas, bool* fromOtherEngine) {
|
|
std::unordered_map<std::string, std::string>& registeredMap =
|
|
isPlayerCmd ? globalShareData->playerRegisteredCmd : globalShareData->consoleRegisteredCmd;
|
|
for (auto& [prefix, fromEngine] : registeredMap) {
|
|
if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' '))
|
|
//如果命令与注册前缀全匹配,或者目标前缀后面为空格
|
|
{
|
|
// Matched
|
|
if (fromEngine != LLSE_BACKEND_TYPE) {
|
|
*fromOtherEngine = true;
|
|
return string();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::map<std::string, CmdCallbackData, CmdCallbackMapCmp>& cmdMap =
|
|
isPlayerCmd ? localShareData->playerCmdCallbacks : localShareData->consoleCmdCallbacks;
|
|
|
|
for (auto& cmdData : cmdMap) {
|
|
string prefix = cmdData.first;
|
|
if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' '))
|
|
//如果命令与注册前缀全匹配,或者目标前缀后面为空格
|
|
{
|
|
// Matched
|
|
if (cmd.size() > prefix.size()) {
|
|
//除了注册前缀之外还有额外参数
|
|
receiveParas = SplitCmdLine(cmd.substr(prefix.size() + 1));
|
|
} else
|
|
receiveParas = vector<string>();
|
|
|
|
return prefix;
|
|
}
|
|
}
|
|
return string();
|
|
}
|
|
|
|
bool CallPlayerCmdCallback(Player* player, const string& cmdPrefix, const vector<string>& paras) {
|
|
EngineScope enter(localShareData->playerCmdCallbacks[cmdPrefix].fromEngine);
|
|
auto cmdData = localShareData->playerCmdCallbacks[cmdPrefix];
|
|
Local<Value> res{};
|
|
try {
|
|
Local<Array> args = Array::newArray();
|
|
for (auto& para : paras)
|
|
args.add(String::newString(para));
|
|
res = cmdData.func.get().call({}, PlayerClass::newPlayer(player), args);
|
|
}
|
|
CATCH_IN_CALLBACK("PlayerCmd");
|
|
if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CallServerCmdCallback(const string& cmdPrefix, const vector<string>& paras) {
|
|
EngineScope enter(localShareData->consoleCmdCallbacks[cmdPrefix].fromEngine);
|
|
auto cmdData = localShareData->consoleCmdCallbacks[cmdPrefix];
|
|
Local<Value> res{};
|
|
try {
|
|
Local<Array> args = Array::newArray();
|
|
for (auto& para : paras)
|
|
args.add(String::newString(para));
|
|
res = cmdData.func.get().call({}, args);
|
|
}
|
|
CATCH_IN_CALLBACK("ServerCmd");
|
|
if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false))
|
|
return false;
|
|
|
|
return true;
|
|
} |