mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-03 16:25:35 +00:00
Begin Lua Rewrite
The idea is to move everything to TLuaEngine.
This commit is contained in:
parent
1228c2fabe
commit
3805d7ce6c
12
.gitignore
vendored
12
.gitignore
vendored
@ -468,3 +468,15 @@ cmake-build-debug/include/commandline/Makefile
|
|||||||
*.manifest
|
*.manifest
|
||||||
*.rc
|
*.rc
|
||||||
*.res
|
*.res
|
||||||
|
changelog-2.0.txt
|
||||||
|
compile_commands.json
|
||||||
|
err.html
|
||||||
|
file.c
|
||||||
|
log.txt
|
||||||
|
nohup.out
|
||||||
|
notes/
|
||||||
|
patch.patch
|
||||||
|
new-backend.txt
|
||||||
|
sanitizer.txt
|
||||||
|
speedcc.fit
|
||||||
|
socket.txt
|
||||||
|
@ -9,30 +9,42 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
struct TLuaArgs final {
|
||||||
|
std::vector<std::any> Args;
|
||||||
|
};
|
||||||
|
|
||||||
class TLuaEngine : public IThreaded {
|
class TLuaEngine : public IThreaded {
|
||||||
public:
|
public:
|
||||||
explicit TLuaEngine(TServer& Server, TNetwork& Network);
|
explicit TLuaEngine(TServer& Server, TNetwork& Network);
|
||||||
|
|
||||||
using TSetOfLuaFile = std::set<std::unique_ptr<TLuaFile>>;
|
using TSetOfLuaFile = std::vector<std::shared_ptr<TLuaFile>>;
|
||||||
|
|
||||||
void operator()() override;
|
void operator()() override;
|
||||||
|
|
||||||
[[nodiscard]] const TSetOfLuaFile& LuaFiles() const { return mLuaFiles; }
|
std::any TriggerLuaEvent(const std::string& Event, bool local, std::weak_ptr<TLuaFile> Caller, std::shared_ptr<TLuaArgs> arg, bool Wait);
|
||||||
|
|
||||||
[[nodiscard]] TServer& Server() { return mServer; }
|
[[nodiscard]] TServer& Server() { return mServer; }
|
||||||
[[nodiscard]] const TServer& Server() const { return mServer; }
|
[[nodiscard]] const TServer& Server() const { return mServer; }
|
||||||
[[nodiscard]] TNetwork& Network() { return mNetwork; }
|
[[nodiscard]] TNetwork& Network() { return mNetwork; }
|
||||||
[[nodiscard]] const TNetwork& Network() const { return mNetwork; }
|
[[nodiscard]] const TNetwork& Network() const { return mNetwork; }
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<TLuaFile>> GetScript(lua_State* L);
|
void UnregisterScript(std::shared_ptr<TLuaFile> Script);
|
||||||
|
std::shared_ptr<TLuaFile> GetLuaFileOfScript(lua_State* L);
|
||||||
|
std::shared_ptr<TLuaFile> InsertNewLuaFile(const fs::path& FileName, const std::string& PluginName);
|
||||||
|
void SendError(lua_State* L, const std::string& msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FolderList(const std::string& Path, bool HotSwap);
|
void FolderList(const std::string& Path, bool HotSwap);
|
||||||
void RegisterFiles(const std::string& Path, bool HotSwap);
|
void RegisterFiles(const fs::path& Path, bool HotSwap);
|
||||||
bool NewFile(const std::string& Path);
|
bool IsNewFile(const std::string& Path);
|
||||||
|
|
||||||
TNetwork& mNetwork;
|
TNetwork& mNetwork;
|
||||||
TServer& mServer;
|
TServer& mServer;
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
bool mShutdown { false };
|
bool mShutdown { false };
|
||||||
|
mutable std::mutex mLuaFilesMutex;
|
||||||
TSetOfLuaFile mLuaFiles;
|
TSetOfLuaFile mLuaFiles;
|
||||||
};
|
};
|
||||||
|
7
include/TLuaEvent.h
Normal file
7
include/TLuaEvent.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class TLuaEvent final {
|
||||||
|
};
|
@ -11,15 +11,14 @@
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
struct TLuaArg {
|
|
||||||
std::vector<std::any> args;
|
|
||||||
void PushArgs(lua_State* State);
|
|
||||||
};
|
|
||||||
|
|
||||||
class TLuaEngine;
|
class TLuaEngine;
|
||||||
|
class TLuaArgs;
|
||||||
|
|
||||||
class TLuaFile {
|
class TLuaFile {
|
||||||
public:
|
public:
|
||||||
|
explicit TLuaFile(TLuaEngine& Engine, bool Console = false);
|
||||||
|
~TLuaFile();
|
||||||
|
|
||||||
void RegisterEvent(const std::string& Event, const std::string& FunctionName);
|
void RegisterEvent(const std::string& Event, const std::string& FunctionName);
|
||||||
void UnRegisterEvent(const std::string& Event);
|
void UnRegisterEvent(const std::string& Event);
|
||||||
void SetLastWrite(fs::file_time_type time);
|
void SetLastWrite(fs::file_time_type time);
|
||||||
@ -30,11 +29,8 @@ public:
|
|||||||
fs::file_time_type GetLastWrite();
|
fs::file_time_type GetLastWrite();
|
||||||
lua_State* GetState();
|
lua_State* GetState();
|
||||||
std::string GetOrigin();
|
std::string GetOrigin();
|
||||||
std::mutex Lock;
|
|
||||||
void Reload();
|
void Reload();
|
||||||
void Init(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote);
|
void Init(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote);
|
||||||
explicit TLuaFile(TLuaEngine& Engine, bool Console = false);
|
|
||||||
~TLuaFile();
|
|
||||||
void SetStopThread(bool StopThread) { mStopThread = StopThread; }
|
void SetStopThread(bool StopThread) { mStopThread = StopThread; }
|
||||||
TLuaEngine& Engine() { return mEngine; }
|
TLuaEngine& Engine() { return mEngine; }
|
||||||
[[nodiscard]] std::string GetPluginName() const;
|
[[nodiscard]] std::string GetPluginName() const;
|
||||||
@ -43,8 +39,14 @@ public:
|
|||||||
[[nodiscard]] bool GetStopThread() const { return mStopThread; }
|
[[nodiscard]] bool GetStopThread() const { return mStopThread; }
|
||||||
[[nodiscard]] const TLuaEngine& Engine() const { return mEngine; }
|
[[nodiscard]] const TLuaEngine& Engine() const { return mEngine; }
|
||||||
[[nodiscard]] std::string GetRegistered(const std::string& Event) const;
|
[[nodiscard]] std::string GetRegistered(const std::string& Event) const;
|
||||||
|
void PushArgs(const TLuaArgs& args);
|
||||||
|
|
||||||
|
bool operator==(const TLuaFile& Other) const;
|
||||||
|
|
||||||
|
void Load();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::mutex Lock;
|
||||||
TLuaEngine& mEngine;
|
TLuaEngine& mEngine;
|
||||||
std::set<std::pair<std::string, std::string>> mRegisteredEvents;
|
std::set<std::pair<std::string, std::string>> mRegisteredEvents;
|
||||||
lua_State* mLuaState { nullptr };
|
lua_State* mLuaState { nullptr };
|
||||||
@ -53,9 +55,6 @@ private:
|
|||||||
std::string mFileName {};
|
std::string mFileName {};
|
||||||
bool mStopThread = false;
|
bool mStopThread = false;
|
||||||
bool mConsole = false;
|
bool mConsole = false;
|
||||||
void Load();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr<TLuaArg> arg, bool Wait);
|
|
||||||
|
|
||||||
#endif // TLUAFILE_H
|
#endif // TLUAFILE_H
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
|
#include "Client.h"
|
||||||
|
#include "CustomAssert.h"
|
||||||
#include "TLuaFile.h"
|
#include "TLuaFile.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <lua.hpp>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
extern TLuaEngine* TheLuaEngine;
|
||||||
|
|
||||||
// necessary as lua relies on global state
|
|
||||||
TLuaEngine* TheEngine;
|
|
||||||
|
|
||||||
TLuaEngine::TLuaEngine(TServer& Server, TNetwork& Network)
|
TLuaEngine::TLuaEngine(TServer& Server, TNetwork& Network)
|
||||||
: mNetwork(Network)
|
: mNetwork(Network)
|
||||||
, mServer(Server) {
|
, mServer(Server) {
|
||||||
TheEngine = this;
|
TheLuaEngine = this;
|
||||||
if (!fs::exists(Application::Settings.Resource)) {
|
if (!fs::exists(Application::Settings.Resource)) {
|
||||||
fs::create_directory(Application::Settings.Resource);
|
fs::create_directory(Application::Settings.Resource);
|
||||||
}
|
}
|
||||||
@ -31,16 +29,27 @@ TLuaEngine::TLuaEngine(TServer& Server, TNetwork& Network)
|
|||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TLuaEngine::UnregisterScript(std::shared_ptr<TLuaFile> Script) {
|
||||||
|
std::unique_lock Lock(mLuaFilesMutex);
|
||||||
|
auto Iter = std::find_if(mLuaFiles.begin(), mLuaFiles.end(), [&](const auto& ScriptPtr) {
|
||||||
|
return *Script == *ScriptPtr;
|
||||||
|
});
|
||||||
|
if (Iter != mLuaFiles.end()) {
|
||||||
|
// found!
|
||||||
|
mLuaFiles.erase(Iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TLuaEngine::operator()() {
|
void TLuaEngine::operator()() {
|
||||||
RegisterThread("LuaEngine");
|
RegisterThread("LuaEngine");
|
||||||
info("Lua system online");
|
info("Lua system online");
|
||||||
while (!mShutdown) {
|
while (!mShutdown) {
|
||||||
if (!mLuaFiles.empty()) {
|
if (!mLuaFiles.empty()) {
|
||||||
for (auto& Script : mLuaFiles) {
|
for (auto& Script : mLuaFiles) {
|
||||||
struct stat Info { };
|
const auto& filename = Script->GetFileName();
|
||||||
if (stat(Script->GetFileName().c_str(), &Info) != 0) {
|
if (!fs::is_regular_file(filename)) {
|
||||||
Script->SetStopThread(true);
|
Script->SetStopThread(true);
|
||||||
mLuaFiles.erase(Script);
|
UnregisterScript(Script);
|
||||||
info(("[HOTSWAP] Removed removed script due to delete"));
|
info(("[HOTSWAP] Removed removed script due to delete"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -57,47 +66,178 @@ void TLuaEngine::operator()() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<TLuaFile>> TLuaEngine::GetScript(lua_State* L) {
|
std::any TLuaEngine::TriggerLuaEvent(const std::string& Event, bool local, std::weak_ptr<TLuaFile> Caller, std::shared_ptr<TLuaArgs> arg, bool Wait) {
|
||||||
|
std::any R;
|
||||||
|
std::string Type;
|
||||||
|
int Ret = 0;
|
||||||
|
// TODO: lock
|
||||||
|
for (auto& Script : mLuaFiles) {
|
||||||
|
if (Script->IsRegistered(Event)) {
|
||||||
|
if (local) {
|
||||||
|
if (Script->GetPluginName() == Caller->GetPluginName()) {
|
||||||
|
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
||||||
|
Type = R.type().name();
|
||||||
|
if (Type.find("int") != std::string::npos) {
|
||||||
|
if (std::any_cast<int>(R))
|
||||||
|
Ret++;
|
||||||
|
} else if (Event == "onPlayerAuth")
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
||||||
|
Type = R.type().name();
|
||||||
|
if (Type.find("int") != std::string::npos) {
|
||||||
|
if (std::any_cast<int>(R))
|
||||||
|
Ret++;
|
||||||
|
} else if (Event == "onPlayerAuth")
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<TLuaFile> TLuaEngine::GetLuaFileOfScript(lua_State* L) {
|
||||||
|
std::unique_lock Lock(mLuaFilesMutex);
|
||||||
for (auto& Script : mLuaFiles) {
|
for (auto& Script : mLuaFiles) {
|
||||||
if (Script->GetState() == L)
|
if (Script->GetState() == L)
|
||||||
return *Script;
|
return Script;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLuaEngine::FolderList(const std::string& Path, bool HotSwap) {
|
void TLuaEngine::FolderList(const std::string& Path, bool HotSwap) {
|
||||||
for (const auto& entry : fs::directory_iterator(Path)) {
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
auto pos = entry.path().filename().string().find('.');
|
if (fs::is_directory(entry)) {
|
||||||
if (pos == std::string::npos) {
|
RegisterFiles(entry.path(), HotSwap);
|
||||||
RegisterFiles(entry.path().string(), HotSwap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLuaEngine::RegisterFiles(const std::string& Path, bool HotSwap) {
|
void TLuaEngine::RegisterFiles(const fs::path& Path, bool HotSwap) {
|
||||||
std::string Name = Path.substr(Path.find_last_of('\\') + 1);
|
std::string Name = Path.filename();
|
||||||
if (!HotSwap)
|
if (!HotSwap) {
|
||||||
info(("Loading plugin : ") + Name);
|
info(("Loading plugin : ") + Name);
|
||||||
|
}
|
||||||
for (const auto& entry : fs::directory_iterator(Path)) {
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
auto pos = entry.path().string().find((".lua"));
|
if (entry.is_regular_file() && entry.path().extension() == ".lua") {
|
||||||
if (pos != std::string::npos && entry.path().string().length() - pos == 4) {
|
if (!HotSwap || IsNewFile(entry.path().string())) {
|
||||||
if (!HotSwap || NewFile(entry.path().string())) {
|
InsertNewLuaFile(entry.path(), Path.filename());
|
||||||
auto FileName = entry.path().string();
|
if (HotSwap) {
|
||||||
std::unique_ptr<TLuaFile> ScriptToInsert(new TLuaFile(*this));
|
info(("[HOTSWAP] Added : ") + entry.path().filename().string());
|
||||||
auto& Script = *ScriptToInsert;
|
}
|
||||||
mLuaFiles.insert(std::move(ScriptToInsert));
|
|
||||||
Script.Init(Name, FileName, fs::last_write_time(FileName));
|
|
||||||
if (HotSwap)
|
|
||||||
info(("[HOTSWAP] Added : ") + Script.GetFileName().substr(Script.GetFileName().find('\\')));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TLuaEngine::NewFile(const std::string& Path) {
|
bool TLuaEngine::IsNewFile(const std::string& Path) {
|
||||||
|
std::unique_lock Lock(mLuaFilesMutex);
|
||||||
for (auto& Script : mLuaFiles) {
|
for (auto& Script : mLuaFiles) {
|
||||||
|
// TODO: use std::any_of
|
||||||
if (Path == Script->GetFileName())
|
if (Path == Script->GetFileName())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TLuaEngine::SendError(lua_State* L, const std::string& msg) {
|
||||||
|
Assert(L);
|
||||||
|
auto MaybeS = GetLuaFileOfScript(L);
|
||||||
|
std::string a;
|
||||||
|
if (!MaybeS) {
|
||||||
|
a = ("_Console");
|
||||||
|
} else {
|
||||||
|
// FIXME: GetFileName already returns the filename. This is redundant.
|
||||||
|
a = fs::path(MaybeS->GetFileName()).filename().string();
|
||||||
|
}
|
||||||
|
warn(a + (" | Incorrect call of ") + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////
|
||||||
|
// ////////// LUA *ONLY* BELOW //////////////////
|
||||||
|
// //////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::shared_ptr<TClient> GetClient(TServer& Server, int ID) {
|
||||||
|
std::shared_ptr<TClient> MaybeClient = nullptr;
|
||||||
|
Server.ForEachClient([&](std::weak_ptr<TClient> CPtr) -> bool {
|
||||||
|
ReadLock Lock(Server.GetClientMutex());
|
||||||
|
if (!CPtr.expired()) {
|
||||||
|
auto C = CPtr.lock();
|
||||||
|
if (C->GetID() == ID) {
|
||||||
|
MaybeClient = C;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return MaybeClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ServerLua_GetIdentifiers(lua_State* L) {
|
||||||
|
Assert(TheLuaEngine);
|
||||||
|
Assert(L);
|
||||||
|
if (lua_isnumber(L, 1)) {
|
||||||
|
// do not store this
|
||||||
|
// FIXME: should this not be lua_tointeger?!
|
||||||
|
auto MaybeClient = GetClient(TheLuaEngine->Server(), int(lua_tonumber(L, 1)));
|
||||||
|
if (MaybeClient) {
|
||||||
|
auto IDs = MaybeClient->GetIdentifiers();
|
||||||
|
if (IDs.empty())
|
||||||
|
return 0;
|
||||||
|
// FIXME: What does this entire thing do? Add comments.
|
||||||
|
lua_newtable(L);
|
||||||
|
for (const std::string& ID : IDs) {
|
||||||
|
lua_pushstring(L, ID.substr(0, ID.find(':')).c_str());
|
||||||
|
lua_pushstring(L, ID.c_str());
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
SendError(*TheLuaEngine, L, "lua_GetIdentifiers wrong arguments");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// LEAVE THIS AT THE **VERY** BOTTOM OF THE FILE
|
||||||
|
|
||||||
|
std::shared_ptr<TLuaFile> TLuaEngine::InsertNewLuaFile(const fs::path& FileName, const std::string& PluginName) {
|
||||||
|
std::shared_ptr<TLuaFile> Script(new TLuaFile(*this));
|
||||||
|
mLuaFiles.push_back(Script);
|
||||||
|
Script->SetPluginName(PluginName);
|
||||||
|
Script->SetFileName(FileName);
|
||||||
|
Script->SetLastWrite(fs::last_write_time(FileName));
|
||||||
|
lua_State* State = Script->GetState();
|
||||||
|
luaL_openlibs(State);
|
||||||
|
lua_register(State, "GetPlayerIdentifiers", ServerLua_GetIdentifiers);
|
||||||
|
lua_register(State, "TriggerGlobalEvent", lua_TriggerEventG);
|
||||||
|
lua_register(State, "TriggerLocalEvent", lua_TriggerEventL);
|
||||||
|
lua_register(State, "TriggerClientEvent", lua_RemoteEvent);
|
||||||
|
lua_register(State, "GetPlayerCount", lua_GetPlayerCount);
|
||||||
|
lua_register(State, "isPlayerConnected", lua_isConnected);
|
||||||
|
lua_register(State, "RegisterEvent", lua_RegisterEvent);
|
||||||
|
lua_register(State, "GetPlayerName", lua_GetPlayerName);
|
||||||
|
lua_register(State, "RemoveVehicle", lua_RemoveVehicle);
|
||||||
|
lua_register(State, "GetPlayerDiscordID", lua_TempFix);
|
||||||
|
lua_register(State, "CreateThread", lua_CreateThread);
|
||||||
|
lua_register(State, "GetPlayerVehicles", lua_GetCars);
|
||||||
|
lua_register(State, "SendChatMessage", lua_sendChat);
|
||||||
|
lua_register(State, "GetPlayers", lua_GetAllPlayers);
|
||||||
|
lua_register(State, "GetPlayerGuest", lua_GetGuest);
|
||||||
|
lua_register(State, "StopThread", lua_StopThread);
|
||||||
|
lua_register(State, "DropPlayer", lua_dropPlayer);
|
||||||
|
lua_register(State, "GetPlayerHWID", lua_HWID);
|
||||||
|
lua_register(State, "exit", lua_ServerExit);
|
||||||
|
lua_register(State, "Sleep", lua_Sleep);
|
||||||
|
lua_register(State, "print", lua_Print);
|
||||||
|
lua_register(State, "Set", lua_Set);
|
||||||
|
if (!Script->IsConsole()) {
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
debug("inserted new lua file: " + PluginName + " - " + FileName.string());
|
||||||
|
return Script;
|
||||||
|
}
|
||||||
|
2
src/TLuaEvent.cpp
Normal file
2
src/TLuaEvent.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "TLuaEvent.h"
|
||||||
|
|
176
src/TLuaFile.cpp
176
src/TLuaFile.cpp
@ -12,41 +12,13 @@
|
|||||||
// TODO: REWRITE
|
// TODO: REWRITE
|
||||||
|
|
||||||
void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg);
|
void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg);
|
||||||
std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr<TLuaArg> Arg);
|
std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr<TLuaArgs> Arg);
|
||||||
std::any TriggerLuaEvent(TLuaEngine& Engine, const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr<TLuaArg> arg, bool Wait);
|
std::any TriggerLuaEvent(TLuaEngine& Engine, const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr<TLuaArgs> arg, bool Wait);
|
||||||
|
|
||||||
extern TLuaEngine* TheEngine;
|
std::any Trigger(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArgs> arg) {
|
||||||
|
|
||||||
static TLuaEngine& Engine() {
|
|
||||||
Assert(TheEngine);
|
|
||||||
return *TheEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TLuaArg> CreateArg(lua_State* L, int T, int S) {
|
|
||||||
if (S > T)
|
|
||||||
return nullptr;
|
|
||||||
std::shared_ptr<TLuaArg> temp(new TLuaArg);
|
|
||||||
for (int C = S; C <= T; C++) {
|
|
||||||
if (lua_isstring(L, C)) {
|
|
||||||
temp->args.emplace_back(std::string(lua_tostring(L, C)));
|
|
||||||
} else if (lua_isinteger(L, C)) {
|
|
||||||
temp->args.emplace_back(int(lua_tointeger(L, C)));
|
|
||||||
} else if (lua_isboolean(L, C)) {
|
|
||||||
temp->args.emplace_back(bool(lua_toboolean(L, C)));
|
|
||||||
} else if (lua_isnumber(L, C)) {
|
|
||||||
temp->args.emplace_back(float(lua_tonumber(L, C)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
void ClearStack(lua_State* L) {
|
|
||||||
lua_settop(L, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::any Trigger(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArg> arg) {
|
|
||||||
RegisterThread(lua->GetFileName());
|
RegisterThread(lua->GetFileName());
|
||||||
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
std::lock_guard<std::mutex> lockGuard(lua->Lock);
|
||||||
std::packaged_task<std::any(std::shared_ptr<TLuaArg>)> task([lua, R](std::shared_ptr<TLuaArg> arg) { return CallFunction(lua, R, arg); });
|
std::packaged_task<std::any(std::shared_ptr<TLuaArg>)> task([lua, R](std::shared_ptr<TLuaArgs> arg) { return CallFunction(lua, R, arg); });
|
||||||
std::future<std::any> f1 = task.get_future();
|
std::future<std::any> f1 = task.get_future();
|
||||||
std::thread t(std::move(task), arg);
|
std::thread t(std::move(task), arg);
|
||||||
t.detach();
|
t.detach();
|
||||||
@ -56,9 +28,9 @@ std::any Trigger(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArg> a
|
|||||||
SendError(lua->Engine(), lua->GetState(), R + " took too long to respond");
|
SendError(lua->Engine(), lua->GetState(), R + " took too long to respond");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::any FutureWait(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArg> arg, bool Wait) {
|
std::any FutureWait(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArgs> arg, bool Wait) {
|
||||||
Assert(lua);
|
Assert(lua);
|
||||||
std::packaged_task<std::any(std::shared_ptr<TLuaArg>)> task([lua, R](std::shared_ptr<TLuaArg> arg) { return Trigger(lua, R, arg); });
|
std::packaged_task<std::any(std::shared_ptr<TLuaArg>)> task([lua, R](std::shared_ptr<TLuaArgs> arg) { return Trigger(lua, R, arg); });
|
||||||
std::future<std::any> f1 = task.get_future();
|
std::future<std::any> f1 = task.get_future();
|
||||||
std::thread t(std::move(task), arg);
|
std::thread t(std::move(task), arg);
|
||||||
t.detach();
|
t.detach();
|
||||||
@ -70,35 +42,6 @@ std::any FutureWait(TLuaFile* lua, const std::string& R, std::shared_ptr<TLuaArg
|
|||||||
return f1.get();
|
return f1.get();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr<TLuaArg> arg, bool Wait) {
|
|
||||||
std::any R;
|
|
||||||
std::string Type;
|
|
||||||
int Ret = 0;
|
|
||||||
for (auto& Script : Engine().LuaFiles()) {
|
|
||||||
if (Script->IsRegistered(Event)) {
|
|
||||||
if (local) {
|
|
||||||
if (Script->GetPluginName() == Caller->GetPluginName()) {
|
|
||||||
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
|
||||||
Type = R.type().name();
|
|
||||||
if (Type.find("int") != std::string::npos) {
|
|
||||||
if (std::any_cast<int>(R))
|
|
||||||
Ret++;
|
|
||||||
} else if (Event == "onPlayerAuth")
|
|
||||||
return R;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait);
|
|
||||||
Type = R.type().name();
|
|
||||||
if (Type.find("int") != std::string::npos) {
|
|
||||||
if (std::any_cast<int>(R))
|
|
||||||
Ret++;
|
|
||||||
} else if (Event == "onPlayerAuth")
|
|
||||||
return R;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
bool ConsoleCheck(lua_State* L, int r) {
|
bool ConsoleCheck(lua_State* L, int r) {
|
||||||
if (r != LUA_OK) {
|
if (r != LUA_OK) {
|
||||||
std::string msg = lua_tostring(L, -1);
|
std::string msg = lua_tostring(L, -1);
|
||||||
@ -230,21 +173,7 @@ int lua_Sleep(lua_State* L) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::optional<std::weak_ptr<TClient>> GetClient(TServer& Server, int ID) {
|
|
||||||
std::optional<std::weak_ptr<TClient>> MaybeClient { std::nullopt };
|
|
||||||
Server.ForEachClient([&](std::weak_ptr<TClient> CPtr) -> bool {
|
|
||||||
ReadLock Lock(Server.GetClientMutex());
|
|
||||||
if (!CPtr.expired()) {
|
|
||||||
auto C = CPtr.lock();
|
|
||||||
if (C->GetID() == ID) {
|
|
||||||
MaybeClient = CPtr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return MaybeClient;
|
|
||||||
}
|
|
||||||
// CONTINUE
|
// CONTINUE
|
||||||
int lua_isConnected(lua_State* L) {
|
int lua_isConnected(lua_State* L) {
|
||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
@ -311,27 +240,6 @@ int lua_GetAllPlayers(lua_State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lua_GetIdentifiers(lua_State* L) {
|
|
||||||
if (lua_isnumber(L, 1)) {
|
|
||||||
auto MaybeClient = GetClient(Engine().Server(), int(lua_tonumber(L, 1)));
|
|
||||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
|
||||||
auto IDs = MaybeClient.value().lock()->GetIdentifiers();
|
|
||||||
if (IDs.empty())
|
|
||||||
return 0;
|
|
||||||
lua_newtable(L);
|
|
||||||
for (const std::string& ID : IDs) {
|
|
||||||
lua_pushstring(L, ID.substr(0, ID.find(':')).c_str());
|
|
||||||
lua_pushstring(L, ID.c_str());
|
|
||||||
lua_settable(L, -3);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
SendError(Engine(), L, "lua_GetIdentifiers wrong arguments");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lua_GetCars(lua_State* L) {
|
int lua_GetCars(lua_State* L) {
|
||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
@ -590,19 +498,7 @@ int lua_Print(lua_State* L) {
|
|||||||
int lua_TempFix(lua_State* L);
|
int lua_TempFix(lua_State* L);
|
||||||
|
|
||||||
void TLuaFile::Init(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote) {
|
void TLuaFile::Init(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote) {
|
||||||
// set global engine for lua_* functions
|
|
||||||
if (!TheEngine) {
|
|
||||||
TheEngine = &mEngine;
|
|
||||||
}
|
|
||||||
Assert(mLuaState);
|
Assert(mLuaState);
|
||||||
if (!PluginName.empty()) {
|
|
||||||
SetPluginName(PluginName);
|
|
||||||
}
|
|
||||||
if (!FileName.empty()) {
|
|
||||||
SetFileName(FileName);
|
|
||||||
}
|
|
||||||
SetLastWrite(LastWrote);
|
|
||||||
Load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TLuaFile::TLuaFile(TLuaEngine& Engine, bool Console)
|
TLuaFile::TLuaFile(TLuaEngine& Engine, bool Console)
|
||||||
@ -628,7 +524,7 @@ std::string TLuaFile::GetOrigin() {
|
|||||||
return fs::path(GetFileName()).filename().string();
|
return fs::path(GetFileName()).filename().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr<TLuaArg> Arg) {
|
std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr<TLuaArgs> Arg) {
|
||||||
RegisterThread(lua->GetFileName());
|
RegisterThread(lua->GetFileName());
|
||||||
lua_State* luaState = lua->GetState();
|
lua_State* luaState = lua->GetState();
|
||||||
lua_getglobal(luaState, FuncName.c_str());
|
lua_getglobal(luaState, FuncName.c_str());
|
||||||
@ -660,32 +556,6 @@ void TLuaFile::SetFileName(const std::string& Name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TLuaFile::Load() {
|
void TLuaFile::Load() {
|
||||||
Assert(mLuaState);
|
|
||||||
luaL_openlibs(mLuaState);
|
|
||||||
lua_register(mLuaState, "GetPlayerIdentifiers", lua_GetIdentifiers);
|
|
||||||
lua_register(mLuaState, "TriggerGlobalEvent", lua_TriggerEventG);
|
|
||||||
lua_register(mLuaState, "TriggerLocalEvent", lua_TriggerEventL);
|
|
||||||
lua_register(mLuaState, "TriggerClientEvent", lua_RemoteEvent);
|
|
||||||
lua_register(mLuaState, "GetPlayerCount", lua_GetPlayerCount);
|
|
||||||
lua_register(mLuaState, "isPlayerConnected", lua_isConnected);
|
|
||||||
lua_register(mLuaState, "RegisterEvent", lua_RegisterEvent);
|
|
||||||
lua_register(mLuaState, "GetPlayerName", lua_GetPlayerName);
|
|
||||||
lua_register(mLuaState, "RemoveVehicle", lua_RemoveVehicle);
|
|
||||||
lua_register(mLuaState, "GetPlayerDiscordID", lua_TempFix);
|
|
||||||
lua_register(mLuaState, "CreateThread", lua_CreateThread);
|
|
||||||
lua_register(mLuaState, "GetPlayerVehicles", lua_GetCars);
|
|
||||||
lua_register(mLuaState, "SendChatMessage", lua_sendChat);
|
|
||||||
lua_register(mLuaState, "GetPlayers", lua_GetAllPlayers);
|
|
||||||
lua_register(mLuaState, "GetPlayerGuest", lua_GetGuest);
|
|
||||||
lua_register(mLuaState, "StopThread", lua_StopThread);
|
|
||||||
lua_register(mLuaState, "DropPlayer", lua_dropPlayer);
|
|
||||||
lua_register(mLuaState, "GetPlayerHWID", lua_HWID);
|
|
||||||
lua_register(mLuaState, "exit", lua_ServerExit);
|
|
||||||
lua_register(mLuaState, "Sleep", lua_Sleep);
|
|
||||||
lua_register(mLuaState, "print", lua_Print);
|
|
||||||
lua_register(mLuaState, "Set", lua_Set);
|
|
||||||
if (!mConsole)
|
|
||||||
Reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLuaFile::RegisterEvent(const std::string& Event, const std::string& FunctionName) {
|
void TLuaFile::RegisterEvent(const std::string& Event, const std::string& FunctionName) {
|
||||||
@ -713,6 +583,12 @@ std::string TLuaFile::GetRegistered(const std::string& Event) const {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TLuaFile::operator==(const TLuaFile& Other) const {
|
||||||
|
return mPluginName == Other.mPluginName
|
||||||
|
&& mFileName == Other.mFileName;
|
||||||
|
}
|
||||||
|
|
||||||
std::string TLuaFile::GetFileName() const {
|
std::string TLuaFile::GetFileName() const {
|
||||||
return mFileName;
|
return mFileName;
|
||||||
}
|
}
|
||||||
@ -739,18 +615,6 @@ TLuaFile::~TLuaFile() {
|
|||||||
lua_close(mLuaState);
|
lua_close(mLuaState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg) {
|
|
||||||
Assert(L);
|
|
||||||
auto MaybeS = Engine.GetScript(L);
|
|
||||||
std::string a;
|
|
||||||
if (!MaybeS.has_value()) {
|
|
||||||
a = ("_Console");
|
|
||||||
} else {
|
|
||||||
TLuaFile& S = MaybeS.value();
|
|
||||||
a = fs::path(S.GetFileName()).filename().string();
|
|
||||||
}
|
|
||||||
warn(a + (" | Incorrect Call of ") + msg);
|
|
||||||
}
|
|
||||||
int lua_TempFix(lua_State* L) {
|
int lua_TempFix(lua_State* L) {
|
||||||
if (lua_isnumber(L, 1)) {
|
if (lua_isnumber(L, 1)) {
|
||||||
int ID = int(lua_tonumber(L, 1));
|
int ID = int(lua_tonumber(L, 1));
|
||||||
@ -769,22 +633,22 @@ int lua_TempFix(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLuaArg::PushArgs(lua_State* State) {
|
void TLuaFile::PushArgs(const TLuaArgs& args) {
|
||||||
for (std::any arg : args) {
|
for (const std::any& arg : args.Args) {
|
||||||
if (!arg.has_value())
|
if (!arg.has_value())
|
||||||
return;
|
return;
|
||||||
std::string Type = arg.type().name();
|
std::string Type = arg.type().name();
|
||||||
if (Type.find("bool") != std::string::npos) {
|
if (Type.find("bool") != std::string::npos) {
|
||||||
lua_pushboolean(State, std::any_cast<bool>(arg));
|
lua_pushboolean(mLuaState, std::any_cast<bool>(arg));
|
||||||
}
|
}
|
||||||
if (Type.find("basic_string") != std::string::npos || Type.find("char") != std::string::npos) {
|
if (Type.find("basic_string") != std::string::npos || Type.find("char") != std::string::npos) {
|
||||||
lua_pushstring(State, std::any_cast<std::string>(arg).c_str());
|
lua_pushstring(mLuaState, std::any_cast<std::string>(arg).c_str());
|
||||||
}
|
}
|
||||||
if (Type.find("int") != std::string::npos) {
|
if (Type.find("int") != std::string::npos) {
|
||||||
lua_pushinteger(State, std::any_cast<int>(arg));
|
lua_pushinteger(mLuaState, std::any_cast<int>(arg));
|
||||||
}
|
}
|
||||||
if (Type.find("float") != std::string::npos) {
|
if (Type.find("float") != std::string::npos) {
|
||||||
lua_pushnumber(State, std::any_cast<float>(arg));
|
lua_pushnumber(mLuaState, std::any_cast<float>(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
TLuaEngine* TheLuaEngine = nullptr;
|
||||||
|
|
||||||
#ifdef __unix
|
#ifdef __unix
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user