mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +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 ChangeToLuaConsole(const std::string& LuaStateId);
|
||||
void ChangeToRegularConsole();
|
||||
void HandleLuaInternalCommand(const std::string& cmd);
|
||||
|
||||
void Command_Lua(const std::string& cmd);
|
||||
void Command_Help(const std::string& cmd);
|
||||
|
@ -32,8 +32,8 @@ static constexpr size_t TLuaArgTypes_Bool = 3;
|
||||
class TLuaPlugin;
|
||||
|
||||
struct TLuaResult {
|
||||
std::atomic_bool Ready;
|
||||
std::atomic_bool Error;
|
||||
bool Ready;
|
||||
bool Error;
|
||||
std::string ErrorMessage;
|
||||
sol::object Result { sol::lua_nil };
|
||||
TLuaStateId StateId;
|
||||
@ -89,6 +89,7 @@ public:
|
||||
std::unique_lock Lock(mResultsToCheckMutex);
|
||||
return mResultsToCheck.size();
|
||||
}
|
||||
|
||||
size_t GetLuaStateCount() {
|
||||
std::unique_lock Lock(mLuaStatesMutex);
|
||||
return mLuaStates.size();
|
||||
@ -152,6 +153,12 @@ public:
|
||||
|
||||
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:
|
||||
void CollectAndInitPlugins();
|
||||
void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config);
|
||||
@ -170,6 +177,10 @@ private:
|
||||
void operator()() override;
|
||||
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:
|
||||
sol::table Lua_TriggerGlobalEvent(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;
|
||||
mIsLuaConsole = true;
|
||||
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 + "> ");
|
||||
} 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> ");
|
||||
}
|
||||
mCachedRegularHistory = mCommandline.history();
|
||||
@ -122,9 +122,9 @@ void TConsole::ChangeToRegularConsole() {
|
||||
if (mIsLuaConsole) {
|
||||
mIsLuaConsole = false;
|
||||
if (mStateId != mDefaultStateId) {
|
||||
Application::Console().WriteRaw("Left Lua console for state '" + mStateId + "'.");
|
||||
Application::Console().WriteRaw("Detached from Lua state '" + mStateId + "'.");
|
||||
} else {
|
||||
Application::Console().WriteRaw("Left Lua console.");
|
||||
Application::Console().WriteRaw("Detached from Lua.");
|
||||
}
|
||||
mCachedLuaHistory = mCommandline.history();
|
||||
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() {
|
||||
mCommandline.enable_history();
|
||||
mCommandline.set_history_limit(20);
|
||||
@ -381,8 +433,8 @@ TConsole::TConsole() {
|
||||
if (mIsLuaConsole) {
|
||||
if (!mLuaEngine) {
|
||||
beammp_info("Lua not started yet, please try again in a second");
|
||||
} else if (cmd == "exit()") {
|
||||
ChangeToRegularConsole();
|
||||
} else if (!cmd.empty() && cmd.at(0) == ':') {
|
||||
HandleLuaInternalCommand(cmd.substr(1));
|
||||
} else {
|
||||
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
||||
while (!Future->Ready) {
|
||||
|
@ -149,6 +149,50 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
|
||||
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) {
|
||||
for (const auto& Result : Results) {
|
||||
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) {
|
||||
std::unique_lock Lock(mTimedEventsMutex);
|
||||
TimedEvent Event {
|
||||
|
Loading…
x
Reference in New Issue
Block a user