Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions include/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@

#include <doctest/doctest.h>
#include <filesystem>
#include <sol/sol.hpp>
namespace fs = std::filesystem;

#include "Settings.h"
#include "TConsole.h"

using LuaFunction = std::variant<std::shared_ptr<sol::main_protected_function>, std::string>;
struct Version {
uint8_t major;
uint8_t minor;
Expand Down Expand Up @@ -267,7 +268,7 @@ void LogChatMessage(const std::string& name, int id, const std::string& msg);

std::vector<uint8_t> Comp(std::span<const uint8_t> input);
std::vector<uint8_t> DeComp(std::span<const uint8_t> input);

std::string GetFunctionName(const LuaFunction& cb);
std::string GetPlatformAgnosticErrorString();
#define S_DSN SU_RAW

Expand Down
32 changes: 17 additions & 15 deletions include/TLuaEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <set>
#include <toml.hpp>
#include <unordered_map>
#include <utility>
#include <vector>

#define SOL_ALL_SAFETIES_ON 1
Expand Down Expand Up @@ -76,7 +77,7 @@ struct TLuaResult {
std::string ErrorMessage;
sol::object Result { sol::lua_nil };
TLuaStateId StateId;
std::string Function;
LuaFunction Function;
std::shared_ptr<std::mutex> ReadyMutex {
std::make_shared<std::mutex>()
};
Expand Down Expand Up @@ -112,7 +113,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
};

struct QueuedFunction {
std::string FunctionName;
LuaFunction FunctionObject;
std::shared_ptr<TLuaResult> Result;
std::vector<TLuaValue> Args;
std::string EventName; // optional, may be empty
Expand Down Expand Up @@ -167,9 +168,9 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
void ReportErrors(const std::vector<std::shared_ptr<TLuaResult>>& Results);
bool HasState(TLuaStateId StateId);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const TLuaChunk& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName, const std::vector<TLuaValue>& Args, const std::string& EventName);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const LuaFunction& FunctionObject, const std::vector<TLuaValue>& Args, const std::string& EventName);
void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false);
void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName);
void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const LuaFunction& FunctionObject);
/**
*
* @tparam ArgsT Template Arguments for the event (Metadata) todo: figure out what this means
Expand All @@ -182,7 +183,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName, TLuaStateId IgnoreId, ArgsT&&... Args) {
std::unique_lock Lock(mLuaEventsMutex);
beammp_event(EventName);
if (mLuaEvents.find(EventName) == mLuaEvents.end()) { // if no event handler is defined for 'EventName', return immediately
if (!mLuaEvents.contains(EventName)) { // if no event handler is defined for 'EventName', return immediately
return {};
}

Expand All @@ -202,7 +203,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerLocalEvent(const TLuaStateId& StateId, const std::string& EventName, ArgsT&&... Args) {
std::unique_lock Lock(mLuaEventsMutex);
beammp_event(EventName + " in '" + StateId + "'");
if (mLuaEvents.find(EventName) == mLuaEvents.end()) { // if no event handler is defined for 'EventName', return immediately
if (!mLuaEvents.contains(EventName)) { // if no event handler is defined for 'EventName', return immediately
return {};
}
std::vector<std::shared_ptr<TLuaResult>> Results;
Expand All @@ -213,11 +214,12 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
}
return Results;
}
std::set<std::string> GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId);
std::set<std::variant<std::shared_ptr<sol::basic_protected_function<sol::basic_reference<true>>>, std::string>> GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId);
void CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS, CallStrategy Strategy);
void CancelEventTimers(const std::string& EventName, TLuaStateId StateId);
sol::state_view GetStateForPlugin(const fs::path& PluginPath);
TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath);
void ClearEventsForState(const std::string& StateID);
void AddResultToCheck(const std::shared_ptr<TLuaResult>& Result);

static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
Expand All @@ -226,9 +228,9 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
std::vector<std::string> GetStateTableKeysForState(TLuaStateId StateId, std::vector<std::string> keys);

// Debugging functions (slow)
std::unordered_map<std::string /*event name */, std::vector<std::string> /* handlers */> Debug_GetEventsForState(TLuaStateId StateId);
std::unordered_map<std::string /*event name */, std::vector<LuaFunction> /* handlers */> Debug_GetEventsForState(TLuaStateId StateId);
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueueForState(TLuaStateId StateId);
std::vector<QueuedFunction> Debug_GetStateFunctionQueueForState(TLuaStateId StateId);
std::deque<QueuedFunction> Debug_GetStateFunctionQueueForState(TLuaStateId StateId);
std::vector<TLuaResult> Debug_GetResultsToCheckForState(TLuaStateId StateId);

private:
Expand All @@ -243,9 +245,9 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
StateThreadData(const StateThreadData&) = delete;
virtual ~StateThreadData() noexcept { beammp_debug("\"" + mStateId + "\" destroyed"); }
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(const TLuaChunk& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName, const std::vector<TLuaValue>& Args, const std::string& EventName);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCallFromCustomEvent(const std::string& FunctionName, const std::vector<TLuaValue>& Args, const std::string& EventName, CallStrategy Strategy);
void RegisterEvent(const std::string& EventName, const std::string& FunctionName);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const LuaFunction& FunctionObject, const std::vector<TLuaValue>& Args, const std::string& EventName);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCallFromCustomEvent(const LuaFunction& FunctionObject, const std::vector<TLuaValue>& Args, const std::string& EventName, CallStrategy Strategy);
void RegisterEvent(const std::string& EventName, const LuaFunction& FunctionObject) const;
void AddPath(const fs::path& Path); // to be added to path and cpath
void operator()() override;
sol::state_view State() { return sol::state_view(mState); }
Expand All @@ -255,7 +257,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {

// Debug functions, slow
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> Debug_GetStateExecuteQueue();
std::vector<TLuaEngine::QueuedFunction> Debug_GetStateFunctionQueue();
std::deque<TLuaEngine::QueuedFunction> Debug_GetStateFunctionQueue();

private:
sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs);
Expand All @@ -281,7 +283,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
std::thread mThread;
std::queue<std::pair<TLuaChunk, std::shared_ptr<TLuaResult>>> mStateExecuteQueue;
std::recursive_mutex mStateExecuteQueueMutex;
std::vector<QueuedFunction> mStateFunctionQueue;
std::deque<QueuedFunction> mStateFunctionQueue; //This has been changed from vector to deque; it has been benchmarked and improves the queue performance by a lot
std::mutex mStateFunctionQueueMutex;
std::condition_variable mStateFunctionQueueCond;
TLuaEngine* mEngine;
Expand Down Expand Up @@ -309,7 +311,7 @@ class TLuaEngine : public std::enable_shared_from_this<TLuaEngine>, IThreaded {
std::vector<std::shared_ptr<TLuaPlugin>> mLuaPlugins;
std::unordered_map<TLuaStateId, std::unique_ptr<StateThreadData>> mLuaStates;
std::recursive_mutex mLuaStatesMutex;
std::unordered_map<std::string /* event name */, std::unordered_map<TLuaStateId, std::set<std::string>>> mLuaEvents;
std::unordered_map<std::string, std::unordered_map<TLuaStateId, std::set<LuaFunction>>> mLuaEvents;
std::recursive_mutex mLuaEventsMutex;
std::vector<TimedEvent> mTimedEvents;
std::recursive_mutex mTimedEventsMutex;
Expand Down
9 changes: 9 additions & 0 deletions src/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include "CustomAssert.h"
#include "Http.h"

#include <sol/forward.hpp>

void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) {
std::unique_lock Lock(mShutdownHandlersMutex);
if (Handler) {
Expand Down Expand Up @@ -455,3 +457,10 @@ std::vector<uint8_t> Comp(std::span<const uint8_t> input) {
output.resize(output_size);
return output;
}

std::string GetFunctionName(const LuaFunction& cb) {
if (const std::string* name = std::get_if<std::string>(&cb)) {
return *name;
}
return "anonymous";
}
6 changes: 5 additions & 1 deletion src/LuaAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,11 @@ void LuaAPI::MP::PrintRaw(sol::variadic_args Args) {
}

int LuaAPI::PanicHandler(lua_State* State) {
beammp_lua_error("PANIC: " + sol::stack::get<std::string>(State, 1));
std::optional<std::string> message = sol::stack::get<std::optional<std::string>>(State, -1);

if (message) {
beammp_lua_error("PANIC: " + *message);
}
return 0;
}

Expand Down
33 changes: 17 additions & 16 deletions src/TConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,36 +732,37 @@ void TConsole::HandleLuaInternalCommand(const std::string& cmd) {
} 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.erase(QueuedFunctions.begin());
FunctionsInOrder.push_back(Tuple.FunctionName);
FunctionsCount[Tuple.FunctionName] += 1;
size_t FunctionsCount = QueuedFunctions.size();
std::vector<LuaFunction> FunctionsInOrder;
for (int i = 0; i < FunctionsCount; ++i) {
FunctionsInOrder.push_back(QueuedFunctions[i].FunctionObject);
}
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)");
std::vector<LuaFunction> Uniques;
int Index = 0;
for (const LuaFunction Function : FunctionsInOrder) {
if (!(std::find(Uniques.begin(), Uniques.end(), Function) == Uniques.end())) {
std::string FunctionName = GetFunctionName(Function);
Uniques.push_back(Function);
if (Index != 0) {
Application::Console().WriteRaw(" " + FunctionName + " (" + std::to_string(Index) + "x)");
} else {
Application::Console().WriteRaw(" " + Function);
Application::Console().WriteRaw(" " + FunctionName);
}
}
}
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") + ")");
std::string FunctionName = GetFunctionName(Function.Function);;
Application::Console().WriteRaw(" '" + FunctionName + "' (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);
std::string FunctionName = GetFunctionName(Handler);;
Application::Console().WriteRaw(" " + FunctionName);
}
}
} else if (cmd == "help") {
Expand Down
Loading