mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-04-03 06:16:04 +00:00
Lua: Implement most API functions
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
@@ -98,3 +99,5 @@ private:
|
||||
int mID = -1;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> mLastPingTime;
|
||||
};
|
||||
|
||||
std::optional<std::weak_ptr<TClient>> GetClient(class TServer& Server, int ID);
|
||||
|
||||
@@ -10,5 +10,14 @@ namespace MP {
|
||||
|
||||
std::string GetOSName();
|
||||
std::tuple<int, int, int> GetServerVersion();
|
||||
bool TriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data);
|
||||
size_t GetPlayerCount() { return Engine->Server().ClientCount(); }
|
||||
void DropPlayer(int ID, std::optional<std::string> MaybeReason);
|
||||
void SendChatMessage(int ID, const std::string& Message);
|
||||
void RemoveVehicle(int PlayerID, int VehicleID);
|
||||
void Set(int ConfigID, sol::object NewValue);
|
||||
bool GetPlayerGuest(int ID);
|
||||
bool IsPlayerConnected(int ID);
|
||||
void Sleep(size_t Ms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ public:
|
||||
|
||||
void operator()() override;
|
||||
|
||||
TNetwork& Network() { return mNetwork; }
|
||||
TServer& Server() { return mServer; }
|
||||
|
||||
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script);
|
||||
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName);
|
||||
void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false);
|
||||
@@ -70,11 +73,13 @@ private:
|
||||
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName);
|
||||
void RegisterEvent(const std::string& EventName, const std::string& FunctionName);
|
||||
void operator()() override;
|
||||
|
||||
|
||||
private:
|
||||
sol::table Lua_TriggerGlobalEvent(const std::string& EventName);
|
||||
sol::table Lua_TriggerLocalEvent(const std::string& EventName);
|
||||
|
||||
sol::table Lua_GetPlayerIdentifiers(int ID);
|
||||
sol::table Lua_GetPlayers();
|
||||
|
||||
std::string mName;
|
||||
std::atomic_bool& mShutdown;
|
||||
TLuaStateId mStateId;
|
||||
@@ -85,6 +90,7 @@ private:
|
||||
std::queue<std::pair<std::string, std::shared_ptr<TLuaResult>>> mStateFunctionQueue;
|
||||
std::recursive_mutex mStateFunctionQueueMutex;
|
||||
TLuaEngine* mEngine;
|
||||
sol::state_view mStateView { mState };
|
||||
};
|
||||
|
||||
TNetwork& mNetwork;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "Client.h"
|
||||
|
||||
#include "CustomAssert.h"
|
||||
#include "TServer.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
// FIXME: add debug prints
|
||||
|
||||
@@ -100,3 +102,19 @@ int TClient::SecondsSinceLastPing() {
|
||||
.count();
|
||||
return int(seconds);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "LuaAPI.h"
|
||||
#include "Client.h"
|
||||
#include "TLuaEngine.h"
|
||||
|
||||
static std::string LuaToString(const sol::object& Value, size_t Indent = 1) {
|
||||
@@ -63,3 +64,71 @@ void LuaAPI::Print(sol::variadic_args Args) {
|
||||
}
|
||||
luaprint(ToPrint);
|
||||
}
|
||||
|
||||
bool LuaAPI::MP::TriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data) {
|
||||
std::string Packet = "E:" + EventName + ":" + Data;
|
||||
if (PlayerID == -1)
|
||||
Engine->Network().SendToAll(nullptr, Packet, true, true);
|
||||
else {
|
||||
auto MaybeClient = GetClient(Engine->Server(), PlayerID);
|
||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
||||
beammp_lua_error("TriggerClientEvent invalid Player ID");
|
||||
return false;
|
||||
}
|
||||
auto c = MaybeClient.value().lock();
|
||||
if (!Engine->Network().Respond(*c, Packet, true)) {
|
||||
beammp_lua_error("Respond failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaAPI::MP::DropPlayer(int ID, std::optional<std::string> MaybeReason) {
|
||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||
if (!MaybeClient || MaybeClient.value().expired()) {
|
||||
return;
|
||||
}
|
||||
auto c = MaybeClient.value().lock();
|
||||
if (!Engine->Network().Respond(*c, "C:Server:You have been Kicked from the server! Reason: " + MaybeReason.value_or("No reason"), true)) {
|
||||
// Ignore
|
||||
}
|
||||
c->SetStatus(-2);
|
||||
beammp_info("Closing socket due to kick");
|
||||
CloseSocketProper(c->GetTCPSock());
|
||||
}
|
||||
|
||||
void LuaAPI::MP::SendChatMessage(int ID, const std::string& Message) {
|
||||
std::string Packet = "C:Server: " + Message;
|
||||
if (ID == -1) {
|
||||
//LogChatMessage("<Server> (to everyone) ", -1, Message);
|
||||
Engine->Network().SendToAll(nullptr, Packet, true, true);
|
||||
} else {
|
||||
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
||||
auto c = MaybeClient.value().lock();
|
||||
if (!c->IsSynced())
|
||||
return;
|
||||
//LogChatMessage("<Server> (to \"" + c->GetName() + "\")", -1, msg);
|
||||
Engine->Network().Respond(*c, Packet, true);
|
||||
} else {
|
||||
beammp_lua_error("SendChatMessage invalid argument [1] invalid ID");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LuaAPI::MP::RemoveVehicle(int PlayerID, int VehicleID) {
|
||||
}
|
||||
|
||||
void LuaAPI::MP::Set(int ConfigID, sol::object NewValue) {
|
||||
}
|
||||
|
||||
void LuaAPI::MP::Sleep(size_t Ms) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(Ms));
|
||||
}
|
||||
|
||||
bool LuaAPI::MP::IsPlayerConnected(int ID) {
|
||||
}
|
||||
|
||||
bool LuaAPI::MP::GetPlayerGuest(int ID) {
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "TLuaEngine.h"
|
||||
#include "Client.h"
|
||||
#include "CustomAssert.h"
|
||||
#include "TLuaPlugin.h"
|
||||
|
||||
#include "LuaAPI.h"
|
||||
#include "TLuaPlugin.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
@@ -185,10 +185,9 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string
|
||||
}
|
||||
|
||||
sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string& EventName) {
|
||||
sol::state_view StateView(mState);
|
||||
sol::table Result = StateView.create_table();
|
||||
sol::table Result = mStateView.create_table();
|
||||
for (const auto& Handler : mEngine->GetEventHandlersForState(EventName, mStateId)) {
|
||||
auto Fn = StateView[Handler];
|
||||
auto Fn = mStateView[Handler];
|
||||
if (Fn.valid() && Fn.get_type() == sol::type::function) {
|
||||
Result.add(Fn());
|
||||
}
|
||||
@@ -196,6 +195,34 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string&
|
||||
return Result;
|
||||
}
|
||||
|
||||
sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) {
|
||||
auto MaybeClient = GetClient(mEngine->Server(), ID);
|
||||
if (MaybeClient && !MaybeClient.value().expired()) {
|
||||
auto IDs = MaybeClient.value().lock()->GetIdentifiers();
|
||||
if (IDs.empty()) {
|
||||
return sol::nil;
|
||||
}
|
||||
sol::table Result = mStateView.create_table();
|
||||
for (const auto& Pair : IDs) {
|
||||
Result[Pair.first] = Pair.second;
|
||||
}
|
||||
return Result;
|
||||
} else {
|
||||
return sol::nil;
|
||||
}
|
||||
}
|
||||
sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() {
|
||||
sol::table Result = mStateView.create_table();
|
||||
mEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||
if (!Client.expired()) {
|
||||
auto locked = Client.lock();
|
||||
Result[locked->GetID()] = locked->GetName();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return Result;
|
||||
}
|
||||
|
||||
TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine)
|
||||
: mName(Name)
|
||||
, mShutdown(Shutdown)
|
||||
@@ -206,21 +233,38 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
|
||||
sol::state_view StateView(mState);
|
||||
// StateView.globals()["package"].get()
|
||||
StateView.set_function("print", &LuaAPI::Print);
|
||||
StateView.set_function("exit", &Application::GracefullyShutdown);
|
||||
auto Table = StateView.create_named_table("MP");
|
||||
Table.set_function("GetOSName", &LuaAPI::MP::GetOSName);
|
||||
Table.set_function("GetServerVersion", &LuaAPI::MP::GetServerVersion);
|
||||
Table.set_function("RegisterEvent",
|
||||
[this](const std::string& EventName, const std::string& FunctionName) {
|
||||
RegisterEvent(EventName, FunctionName);
|
||||
});
|
||||
Table.set_function("TriggerGlobalEvent",
|
||||
[&](const std::string& EventName) -> sol::table {
|
||||
return Lua_TriggerGlobalEvent(EventName);
|
||||
});
|
||||
Table.set_function("TriggerLocalEvent",
|
||||
[&](const std::string& EventName) -> sol::table {
|
||||
return Lua_TriggerLocalEvent(EventName);
|
||||
});
|
||||
Table.set_function("RegisterEvent", [this](const std::string& EventName, const std::string& FunctionName) {
|
||||
RegisterEvent(EventName, FunctionName);
|
||||
});
|
||||
Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName) -> sol::table {
|
||||
return Lua_TriggerGlobalEvent(EventName);
|
||||
});
|
||||
Table.set_function("TriggerLocalEvent", [&](const std::string& EventName) -> sol::table {
|
||||
return Lua_TriggerLocalEvent(EventName);
|
||||
});
|
||||
Table.set_function("TriggerClientEvent", &LuaAPI::MP::TriggerClientEvent);
|
||||
Table.set_function("GetPlayerCount", &LuaAPI::MP::GetPlayerCount);
|
||||
Table.set_function("IsPlayerConnected", &LuaAPI::MP::IsPlayerConnected);
|
||||
Table.set_function("GetPlayerName", &LuaAPI::MP::GetPlayerName);
|
||||
Table.set_function("RemoveVehicle", &LuaAPI::MP::RemoveVehicle);
|
||||
Table.set_function("GetPlayerVehicles", &LuaAPI::MP::GetPlayerVehicles);
|
||||
Table.set_function("SendChatMessage", &LuaAPI::MP::SendChatMessage);
|
||||
Table.set_function("GetPlayers", [&]() -> sol::table {
|
||||
return Lua_GetPlayers();
|
||||
});
|
||||
Table.set_function("GetPlayerGuest", &LuaAPI::MP::GetPlayerGuest);
|
||||
Table.set_function("DropPlayer", &LuaAPI::MP::DropPlayer);
|
||||
Table.set_function("GetPlayerIdentifiers", [&](int ID) -> sol::table {
|
||||
return Lua_GetPlayerIdentifiers(ID);
|
||||
});
|
||||
Table.set_function("Sleep", &LuaAPI::MP::Sleep);
|
||||
Table.set_function("Set", &LuaAPI::MP::Set);
|
||||
//Table.set_function("HttpsGET", &LuaAPI::MP::HttpsGET);
|
||||
//Table.set_function("HttpsPOST", &LuaAPI::MP::HttpsPOST);
|
||||
Table.create_named("Settings",
|
||||
"Debug", 0,
|
||||
"Private", 1,
|
||||
|
||||
Reference in New Issue
Block a user