mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-03 16:25:35 +00:00
Add various debug functions
This commit is contained in:
parent
179b33a7ab
commit
fd12ee672d
2
deps/cpp-httplib
vendored
2
deps/cpp-httplib
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 301faa074c4a0fa1dbe470dfb4f77912caa1c57f
|
Subproject commit b324921c1aeff2976544128e4bb2a0979a4aa595
|
@ -21,6 +21,7 @@ private:
|
|||||||
void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false);
|
void RunAsCommand(const std::string& cmd, bool IgnoreNotACommand = false);
|
||||||
void ChangeToLuaConsole(const std::string& LuaStateId);
|
void ChangeToLuaConsole(const std::string& LuaStateId);
|
||||||
void ChangeToRegularConsole();
|
void ChangeToRegularConsole();
|
||||||
|
void HandleLuaInternalCommand(const std::string& cmd);
|
||||||
|
|
||||||
void Command_Lua(const std::string& cmd);
|
void Command_Lua(const std::string& cmd);
|
||||||
void Command_Help(const std::string& cmd);
|
void Command_Help(const std::string& cmd);
|
||||||
|
@ -32,8 +32,8 @@ static constexpr size_t TLuaArgTypes_Bool = 3;
|
|||||||
class TLuaPlugin;
|
class TLuaPlugin;
|
||||||
|
|
||||||
struct TLuaResult {
|
struct TLuaResult {
|
||||||
std::atomic_bool Ready;
|
bool Ready;
|
||||||
std::atomic_bool Error;
|
bool Error;
|
||||||
std::string ErrorMessage;
|
std::string ErrorMessage;
|
||||||
sol::object Result { sol::lua_nil };
|
sol::object Result { sol::lua_nil };
|
||||||
TLuaStateId StateId;
|
TLuaStateId StateId;
|
||||||
@ -89,6 +89,7 @@ public:
|
|||||||
std::unique_lock Lock(mResultsToCheckMutex);
|
std::unique_lock Lock(mResultsToCheckMutex);
|
||||||
return mResultsToCheck.size();
|
return mResultsToCheck.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLuaStateCount() {
|
size_t GetLuaStateCount() {
|
||||||
std::unique_lock Lock(mLuaStatesMutex);
|
std::unique_lock Lock(mLuaStatesMutex);
|
||||||
return mLuaStates.size();
|
return mLuaStates.size();
|
||||||
@ -152,6 +153,12 @@ public:
|
|||||||
|
|
||||||
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
|
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
|
||||||
|
|
||||||
|
// Debugging functions (slow)
|
||||||
|
std::unordered_map<std::string /*event name */, std::vector<std::string> /* handlers */> Debug_GetEventsForState(TLuaStateId StateId);
|
||||||
|
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueueForState(TLuaStateId StateId);
|
||||||
|
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Debug_GetStateFunctionQueueForState(TLuaStateId StateId);
|
||||||
|
std::vector<TLuaResult> Debug_GetResultsToCheckForState(TLuaStateId StateId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CollectAndInitPlugins();
|
void CollectAndInitPlugins();
|
||||||
void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config);
|
void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config);
|
||||||
@ -170,6 +177,10 @@ private:
|
|||||||
void operator()() override;
|
void operator()() override;
|
||||||
sol::state_view State() { return sol::state_view(mState); }
|
sol::state_view State() { return sol::state_view(mState); }
|
||||||
|
|
||||||
|
// Debug functions, slow
|
||||||
|
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueue();
|
||||||
|
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Debug_GetStateFunctionQueue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
||||||
sol::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
sol::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
||||||
|
@ -107,10 +107,10 @@ void TConsole::ChangeToLuaConsole(const std::string& LuaStateId) {
|
|||||||
mStateId = LuaStateId;
|
mStateId = LuaStateId;
|
||||||
mIsLuaConsole = true;
|
mIsLuaConsole = true;
|
||||||
if (mStateId != mDefaultStateId) {
|
if (mStateId != mDefaultStateId) {
|
||||||
Application::Console().WriteRaw("Entered Lua console for state '" + mStateId + "'. To exit, type `exit()`");
|
Application::Console().WriteRaw("Attached to Lua state '" + mStateId + "'. For help, type `:help`. To detach, type `:detach`");
|
||||||
mCommandline.set_prompt("lua @" + LuaStateId + "> ");
|
mCommandline.set_prompt("lua @" + LuaStateId + "> ");
|
||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Entered Lua console. To exit, type `exit()`");
|
Application::Console().WriteRaw("Attached to Lua. For help, type `:help`. To detach, type `:detach`");
|
||||||
mCommandline.set_prompt("lua> ");
|
mCommandline.set_prompt("lua> ");
|
||||||
}
|
}
|
||||||
mCachedRegularHistory = mCommandline.history();
|
mCachedRegularHistory = mCommandline.history();
|
||||||
@ -122,9 +122,9 @@ void TConsole::ChangeToRegularConsole() {
|
|||||||
if (mIsLuaConsole) {
|
if (mIsLuaConsole) {
|
||||||
mIsLuaConsole = false;
|
mIsLuaConsole = false;
|
||||||
if (mStateId != mDefaultStateId) {
|
if (mStateId != mDefaultStateId) {
|
||||||
Application::Console().WriteRaw("Left Lua console for state '" + mStateId + "'.");
|
Application::Console().WriteRaw("Detached from Lua state '" + mStateId + "'.");
|
||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Left Lua console.");
|
Application::Console().WriteRaw("Detached from Lua.");
|
||||||
}
|
}
|
||||||
mCachedLuaHistory = mCommandline.history();
|
mCachedLuaHistory = mCommandline.history();
|
||||||
mCommandline.set_history(mCachedRegularHistory);
|
mCommandline.set_history(mCachedRegularHistory);
|
||||||
@ -364,6 +364,58 @@ void TConsole::RunAsCommand(const std::string& cmd, bool IgnoreNotACommand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TConsole::HandleLuaInternalCommand(const std::string& cmd) {
|
||||||
|
if (cmd == "detach") {
|
||||||
|
ChangeToRegularConsole();
|
||||||
|
} else if (cmd == "queued") {
|
||||||
|
auto QueuedFunctions = LuaAPI::MP::Engine->Debug_GetStateFunctionQueueForState(mStateId);
|
||||||
|
Application::Console().WriteRaw("Pending functions in State '" + mStateId + "'");
|
||||||
|
std::unordered_map<std::string, size_t> FunctionsCount;
|
||||||
|
std::vector<std::string> FunctionsInOrder;
|
||||||
|
while (!QueuedFunctions.empty()) {
|
||||||
|
auto Tuple = QueuedFunctions.front();
|
||||||
|
QueuedFunctions.pop();
|
||||||
|
FunctionsInOrder.push_back(std::get<0>(Tuple));
|
||||||
|
FunctionsCount[std::get<0>(Tuple)] += 1;
|
||||||
|
}
|
||||||
|
std::set<std::string> Uniques;
|
||||||
|
for (const auto& Function : FunctionsInOrder) {
|
||||||
|
if (Uniques.count(Function) == 0) {
|
||||||
|
Uniques.insert(Function);
|
||||||
|
if (FunctionsCount.at(Function) > 1) {
|
||||||
|
Application::Console().WriteRaw(" " + Function + " (" + std::to_string(FunctionsCount.at(Function)) + "x)");
|
||||||
|
} else {
|
||||||
|
Application::Console().WriteRaw(" " + Function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Application::Console().WriteRaw("Executed functions waiting to be checked in State '" + mStateId + "'");
|
||||||
|
for (const auto& Function : LuaAPI::MP::Engine->Debug_GetResultsToCheckForState(mStateId)) {
|
||||||
|
Application::Console().WriteRaw(" '" + Function.Function + "' (Ready? " + (Function.Ready ? "Yes" : "No") + ", Error? " + (Function.Error ? "Yes: '" + Function.ErrorMessage + "'" : "No") + ")");
|
||||||
|
}
|
||||||
|
} else if (cmd == "events") {
|
||||||
|
auto Events = LuaAPI::MP::Engine->Debug_GetEventsForState(mStateId);
|
||||||
|
Application::Console().WriteRaw("Registered Events + Handlers for State '" + mStateId + "'");
|
||||||
|
for (const auto& EventHandlerPair : Events) {
|
||||||
|
Application::Console().WriteRaw(" Event '" + EventHandlerPair.first + "'");
|
||||||
|
for (const auto& Handler : EventHandlerPair.second) {
|
||||||
|
Application::Console().WriteRaw(" " + Handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (cmd == "help") {
|
||||||
|
Application::Console().WriteRaw(R"(BeamMP Lua Debugger
|
||||||
|
All commands must be prefixed with a `:`. Non-prefixed commands are interpreted as Lua.
|
||||||
|
|
||||||
|
Commands
|
||||||
|
:detach detaches (exits) from this Lua console
|
||||||
|
:help displays this help
|
||||||
|
:events shows a list of currently registered events
|
||||||
|
:queued shows a list of all pending and queued functions)");
|
||||||
|
} else {
|
||||||
|
beammp_error("internal command '" + cmd + "' is not known");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TConsole::TConsole() {
|
TConsole::TConsole() {
|
||||||
mCommandline.enable_history();
|
mCommandline.enable_history();
|
||||||
mCommandline.set_history_limit(20);
|
mCommandline.set_history_limit(20);
|
||||||
@ -381,8 +433,8 @@ TConsole::TConsole() {
|
|||||||
if (mIsLuaConsole) {
|
if (mIsLuaConsole) {
|
||||||
if (!mLuaEngine) {
|
if (!mLuaEngine) {
|
||||||
beammp_info("Lua not started yet, please try again in a second");
|
beammp_info("Lua not started yet, please try again in a second");
|
||||||
} else if (cmd == "exit()") {
|
} else if (!cmd.empty() && cmd.at(0) == ':') {
|
||||||
ChangeToRegularConsole();
|
HandleLuaInternalCommand(cmd.substr(1));
|
||||||
} else {
|
} else {
|
||||||
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
||||||
while (!Future->Ready) {
|
while (!Future->Ready) {
|
||||||
|
@ -149,6 +149,50 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string /*event name */, std::vector<std::string> /* handlers */> TLuaEngine::Debug_GetEventsForState(TLuaStateId StateId) {
|
||||||
|
std::unordered_map<std::string, std::vector<std::string>> Result;
|
||||||
|
std::unique_lock Lock(mLuaEventsMutex);
|
||||||
|
for (const auto& EventNameToEventMap : mLuaEvents) {
|
||||||
|
for (const auto& IdSetOfHandlersPair : EventNameToEventMap.second) {
|
||||||
|
if (IdSetOfHandlersPair.first == StateId) {
|
||||||
|
for (const auto& Handler : IdSetOfHandlersPair.second) {
|
||||||
|
Result[EventNameToEventMap.first].push_back(Handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> TLuaEngine::Debug_GetStateExecuteQueueForState(TLuaStateId StateId) {
|
||||||
|
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Result;
|
||||||
|
std::unique_lock Lock(mLuaStatesMutex);
|
||||||
|
Result = mLuaStates.at(StateId)->Debug_GetStateExecuteQueue();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> TLuaEngine::Debug_GetStateFunctionQueueForState(TLuaStateId StateId) {
|
||||||
|
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> Result;
|
||||||
|
std::unique_lock Lock(mLuaStatesMutex);
|
||||||
|
Result = mLuaStates.at(StateId)->Debug_GetStateFunctionQueue();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TLuaResult> TLuaEngine::Debug_GetResultsToCheckForState(TLuaStateId StateId) {
|
||||||
|
std::unique_lock Lock(mResultsToCheckMutex);
|
||||||
|
auto ResultsToCheckCopy = mResultsToCheck;
|
||||||
|
Lock.unlock();
|
||||||
|
std::vector<TLuaResult> Result;
|
||||||
|
while (!ResultsToCheckCopy.empty()) {
|
||||||
|
auto ResultToCheck = std::move(ResultsToCheckCopy.front());
|
||||||
|
ResultsToCheckCopy.pop();
|
||||||
|
if (ResultToCheck->StateId == StateId) {
|
||||||
|
Result.push_back(*ResultToCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
|
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
|
||||||
for (const auto& Result : Results) {
|
for (const auto& Result : Results) {
|
||||||
bool Cancelled = false;
|
bool Cancelled = false;
|
||||||
@ -671,6 +715,16 @@ void TLuaEngine::StateThreadData::operator()() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> TLuaEngine::StateThreadData::Debug_GetStateExecuteQueue() {
|
||||||
|
std::unique_lock Lock(mStateExecuteQueueMutex);
|
||||||
|
return mStateExecuteQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::vector<TLuaArgTypes>>> TLuaEngine::StateThreadData::Debug_GetStateFunctionQueue() {
|
||||||
|
std::unique_lock Lock(mStateFunctionQueueMutex);
|
||||||
|
return mStateFunctionQueue;
|
||||||
|
}
|
||||||
|
|
||||||
void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS) {
|
void TLuaEngine::CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS) {
|
||||||
std::unique_lock Lock(mTimedEventsMutex);
|
std::unique_lock Lock(mTimedEventsMutex);
|
||||||
TimedEvent Event {
|
TimedEvent Event {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user