BeamMP-Server/src/Lua System/LuaSystem.cpp
2020-07-03 00:58:00 +03:00

369 lines
12 KiB
C++

///
/// Created by Anonymous275 on 5/19/2020
///
#include "../Network 2.0/Client.hpp"
#include "LuaSystem.hpp"
#include "../logger.h"
#include <iostream>
#include <future>
LuaArg* CreateArg(lua_State *L,int T){
LuaArg* temp = new LuaArg;
for(int C = 2;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;
}
int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg){
int R = 0;
for(Lua*Script : PluginEngine){
if(Script->IsRegistered(Event)){
if(local){
if (Script->GetPluginName() == Caller->GetPluginName()){
R += Script->CallFunction(Script->GetRegistered(Event),arg);
}
}else R += Script->CallFunction(Script->GetRegistered(Event),arg);
}
}
return R;
}
bool CheckLua(lua_State *L, int r)
{
if (r != LUA_OK)
{
std::string errormsg = lua_tostring(L, -1);
std::cout << errormsg << std::endl;
return false;
}
return true;
}
Lua* GetScript(lua_State *L){
for(Lua*Script : PluginEngine){
if (Script->GetState() == L)return Script;
}
return nullptr;
}
void SendError(lua_State *L,const std::string&msg){
Lua* Script = GetScript(L);
error(Script->GetFileName() + " | Incorrect Call of " +msg);
}
int lua_RegisterEvent(lua_State *L)
{
int Args = lua_gettop(L);
Lua* Script = GetScript(L);
if(Args == 2 && lua_isstring(L,1) && lua_isstring(L,2)){
Script->RegisterEvent(lua_tostring(L,1),lua_tostring(L,2));
}else SendError(L,"RegisterEvent invalid argument count expected 2 got " + std::to_string(Args));
return 0;
}
int lua_TriggerEventL(lua_State *L)
{
int Args = lua_gettop(L);
Lua* Script = GetScript(L);
if(Args > 0){
if(lua_isstring(L,1)) {
TriggerLuaEvent(lua_tostring(L, 1), true, Script, CreateArg(L,Args));
}else{
SendError(L,"TriggerLocalEvent wrong argument [1] need string");
}
}else{
SendError(L,"TriggerLocalEvent not enough arguments expected 1 got 0");
}
return 0;
}
int lua_TriggerEventG(lua_State *L)
{
int Args = lua_gettop(L);
Lua* Script = GetScript(L);
if(Args > 0){
if(lua_isstring(L,1)) {
TriggerLuaEvent(lua_tostring(L, 1), false, Script, CreateArg(L,Args));
}else SendError(L,"TriggerGlobalEvent wrong argument [1] need string");
}else{
SendError(L,"TriggerGlobalEvent not enough arguments");
}
return 0;
}
void CallAsync(Lua* lua,const std::string& FuncName,LuaArg* args){
if(lua->HasThread){
SendError(lua->GetState(),"CreateThread there is a thread already running");
return;
}
lua->HasThread = true;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
lua_getglobal(lua->GetState(), FuncName.c_str());
if(lua_isfunction(lua->GetState(), -1)) {
int Size = 0;
if(args != nullptr){
Size = args->args.size();
args->PushArgs(lua->GetState());
}
CheckLua(lua->GetState(), lua_pcall(lua->GetState(), Size, 0, 0));
}
lua->HasThread = false;
}
int lua_CreateThread(lua_State *L){
int Args = lua_gettop(L);
if(Args > 0){
if(lua_isstring(L,1)) {
std::string STR = lua_tostring(L,1);
std::thread t1(CallAsync,GetScript(L),STR,CreateArg(L,Args));
t1.detach();
//auto s = std::async();
///TODO FIGURE OUT THREAD
}else SendError(L,"CreateThread wrong argument [1] need string");
}else SendError(L,"CreateThread not enough arguments");
return 0;
}
int lua_Sleep(lua_State *L){
if(lua_isnumber(L,1)){
int t = lua_tonumber(L, 1);
std::this_thread::sleep_for(std::chrono::milliseconds(t));
}else{
SendError(L,"Sleep not enough arguments");
return 0;
}
return 1;
}
Client* GetClient(int ID){
for(Client*c:Clients) {
if(c->GetID() == ID)return c;
}
return nullptr;
}
int lua_isConnected(lua_State *L)
{
if(lua_isnumber(L,1)){
int ID = lua_tonumber(L, 1);
Client*c = GetClient(ID);
if(c != nullptr)lua_pushboolean(L, c->isConnected());
else return 0;
}else{
SendError(L,"CreateThread not enough arguments");
return 0;
}
return 1;
}
int lua_GetPlayerName(lua_State *L){
if(lua_isnumber(L,1)){
int ID = lua_tonumber(L, 1);
Client*c = GetClient(ID);
if(c != nullptr)lua_pushstring(L, c->GetName().c_str());
else return 0;
}else{
SendError(L,"CreateThread not enough arguments");
return 0;
}
return 1;
}
int lua_GetPlayerCount(lua_State *L){
lua_pushinteger(L, Clients.size());
return 1;
}
int lua_GetDID(lua_State *L){
if(lua_isnumber(L,1)){
int ID = lua_tonumber(L, 1);
Client*c = GetClient(ID);
if(c != nullptr)lua_pushstring(L, c->GetDID().c_str());
else return 0;
}else{
SendError(L,"GetDID not enough arguments");
return 0;
}
return 1;
}
int lua_GetAllPlayers(lua_State *L){
lua_newtable(L);
int i = 1;
for (Client *c : Clients) {
lua_pushinteger(L, c->GetID());
lua_pushstring(L, c->GetName().c_str());
lua_settable(L,-3);
i++;
}
if(Clients.empty())return 0;
return 1;
}
int lua_GetCars(lua_State *L){
if(lua_isnumber(L,1)){
int ID = lua_tonumber(L, 1);
Client*c = GetClient(ID);
if(c != nullptr){
int i = 1;
for (const std::pair<int,std::string> &a : c->GetAllCars()) {
lua_pushinteger(L, a.first);
lua_pushstring(L, a.second.substr(3).c_str());
lua_settable(L,-3);
i++;
}
if(c->GetAllCars().empty())return 0;
}else return 0;
}else{
SendError(L,"GetPlayerVehicles not enough arguments");
return 0;
}
return 1;
}
void Respond(Client*c, const std::string& MSG, bool Rel);
int lua_dropPlayer(lua_State *L){
int Args = lua_gettop(L);
if(lua_isnumber(L,1)){
int ID = lua_tonumber(L, 1);
Client*c = GetClient(ID);
if(c == nullptr)return 0;
if(c->GetRole() == "MDEV")return 0;
std::string Reason;
if(Args > 1 && lua_isstring(L,2)){
Reason = std::string(" Reason : ")+lua_tostring(L,2);
}
Respond(c,"C:Server:You have been Kicked from the server!" + Reason,true);
c->SetStatus(-2);
closesocket(c->GetTCPSock());
}else SendError(L,"DropPlayer not enough arguments");
return 0;
}
void SendToAll(Client*c, const std::string& Data, bool Self, bool Rel);
int lua_sendChat(lua_State *L){
if(lua_isinteger(L,1) || lua_isnumber(L,1)){
if(lua_isstring(L,2)){
int ID = lua_tointeger(L,1);
if(ID == -1){
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
SendToAll(nullptr,Packet,true,true);
}else{
Client*c = GetClient(ID);
if(c != nullptr) {
std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2));
Respond(c, Packet, true);
}else SendError(L,"SendChatMessage invalid argument [1] invalid ID");
}
}else SendError(L,"SendChatMessage invalid argument [2] expected string");
}else SendError(L,"SendChatMessage invalid argument [1] expected number");
return 0;
}
int lua_RemoveVehicle(lua_State *L){
int Args = lua_gettop(L);
if(Args != 2){
SendError(L,"RemoveVehicle invalid argument count expected 2 got " + std::to_string(Args));
return 0;
}
if((lua_isinteger(L,1) || lua_isnumber(L,1)) && (lua_isinteger(L,2) || lua_isnumber(L,2))){
int PID = lua_tointeger(L,1);
int VID = lua_tointeger(L,2);
Client *c = GetClient(PID);
if(c == nullptr){
SendError(L,"RemoveVehicle invalid Player ID");
return 0;
}
if(c->GetRole() == "MDEV")return 0;
if(!c->GetCarData(VID).empty()){
std::string Destroy = "Od:" + std::to_string(PID)+"-"+std::to_string(VID);
SendToAll(nullptr,Destroy,true,true);
c->DeleteCar(VID);
}
}else SendError(L,"RemoveVehicle invalid argument expected number");
return 0;
}
int lua_HWID(lua_State *L){
lua_pushinteger(L, -1);
return 1;
}
void Lua::Init(){
luaL_openlibs(luaState);
lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG);
lua_register(luaState,"TriggerLocalEvent",lua_TriggerEventL);
lua_register(luaState,"GetPlayerCount",lua_GetPlayerCount);
lua_register(luaState,"isPlayerConnected",lua_isConnected);
lua_register(luaState,"RegisterEvent",lua_RegisterEvent);
lua_register(luaState,"GetPlayerName",lua_GetPlayerName);
lua_register(luaState,"RemoveVehicle",lua_RemoveVehicle);
lua_register(luaState,"GetPlayerDiscordID",lua_GetDID);
lua_register(luaState,"GetPlayerVehicles",lua_GetCars);
lua_register(luaState,"CreateThread",lua_CreateThread);
lua_register(luaState,"SendChatMessage",lua_sendChat);
lua_register(luaState,"GetPlayers",lua_GetAllPlayers);
lua_register(luaState,"DropPlayer",lua_dropPlayer);
lua_register(luaState,"GetPlayerHWID",lua_HWID);
lua_register(luaState,"Sleep",lua_Sleep);
Reload();
}
void Lua::Reload(){
if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){
CallFunction("onInit",{});
}
}
int Lua::CallFunction(const std::string& FuncName,LuaArg* Arg){
lua_getglobal(luaState, FuncName.c_str());
if(lua_isfunction(luaState, -1)) {
int Size = 0;
if(Arg != nullptr){
Size = Arg->args.size();
Arg->PushArgs(luaState);
}
if (CheckLua(luaState, lua_pcall(luaState, Size, 1, 0))) {
if (lua_isnumber(luaState, -1)) {
return lua_tointeger(luaState, -1);
}
}
}
return 0;
}
void Lua::SetPluginName(const std::string&Name){
PluginName = Name;
}
void Lua::SetFileName(const std::string&Name){
FileName = Name;
}
void Lua::RegisterEvent(const std::string& Event,const std::string& FunctionName){
RegisteredEvents.insert(std::make_pair(Event,FunctionName));
}
void Lua::UnRegisterEvent(const std::string&Event){
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
if(a.first == Event) {
RegisteredEvents.erase(a);
break;
}
}
}
bool Lua::IsRegistered(const std::string&Event){
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
if(a.first == Event)return true;
}
return false;
}
std::string Lua::GetRegistered(const std::string&Event){
for(const std::pair<std::string,std::string>& a : RegisteredEvents){
if(a.first == Event)return a.second;
}
return "";
}
std::string Lua::GetFileName(){
return FileName;
}
std::string Lua::GetPluginName(){
return PluginName;
}
lua_State* Lua::GetState(){
return luaState;
}
void Lua::SetLastWrite(fs::file_time_type time){
LastWrote = time;
}
fs::file_time_type Lua::GetLastWrite(){
return LastWrote;
}