Added World, Entity & Player wrappers

- LuaWrapper.cpp/lua_autopush was updated to support CNSocket*
- Added basic getters added for Entity, (x, y, z & type)
- Added basic getter for Player, (name)
- Added bases getter for World, (version)
- Added World.onPlayerAdded & World.onPlayerRemoved events
This commit is contained in:
CPunch 2021-04-15 21:30:18 -05:00 committed by gsemaj
parent 2aa23a83de
commit 80f0ff7479
13 changed files with 559 additions and 3 deletions

View File

@ -45,6 +45,9 @@ CXXSRC=\
src/servers/Monitor.cpp\ src/servers/Monitor.cpp\
src/lua/LuaManager.cpp\ src/lua/LuaManager.cpp\
src/lua/EventWrapper.cpp\ src/lua/EventWrapper.cpp\
src/lua/WorldWrapper.cpp\
src/lua/EntityWrapper.cpp\
src/lua/PlayerWrapper.cpp\
src/db/init.cpp\ src/db/init.cpp\
src/db/login.cpp\ src/db/login.cpp\
src/db/shard.cpp\ src/db/shard.cpp\
@ -91,6 +94,9 @@ CXXHDR=\
src/lua/LuaManager.hpp\ src/lua/LuaManager.hpp\
src/lua/LuaWrapper.hpp\ src/lua/LuaWrapper.hpp\
src/lua/EventWrapper.hpp\ src/lua/EventWrapper.hpp\
src/lua/WorldWrapper.hpp\
src/lua/EntityWrapper.hpp\
src/lua/PlayerWrapper.hpp\
src/db/Database.hpp\ src/db/Database.hpp\
src/db/internal.hpp\ src/db/internal.hpp\
vendor/bcrypt/BCrypt.hpp\ vendor/bcrypt/BCrypt.hpp\

View File

@ -1,3 +1,8 @@
print("Hello world!") print("Hello world!")
World.onPlayerAdded:listen(function(plr)
print(plr.type .. " " .. plr.name .. " joined from LUA!!")
end)
wait(2) wait(2)
print("Hello world ~2 seconds later!") print("Hello world ~2 seconds later! running protcol version " .. World.version)

View File

@ -18,6 +18,8 @@
#include "settings.hpp" #include "settings.hpp"
#include "lua/LuaManager.hpp"
#include <assert.h> #include <assert.h>
#include <algorithm> #include <algorithm>
@ -40,12 +42,18 @@ static void addPlayer(CNSocket* key, Player plr) {
std::cout << getPlayerName(p) << " has joined!" << std::endl; std::cout << getPlayerName(p) << " has joined!" << std::endl;
std::cout << players.size() << " players" << std::endl; std::cout << players.size() << " players" << std::endl;
// call events
LuaManager::playerAdded(key);
} }
void PlayerManager::removePlayer(CNSocket* key) { void PlayerManager::removePlayer(CNSocket* key) {
Player* plr = getPlayer(key); Player* plr = getPlayer(key);
uint64_t fromInstance = plr->instanceID; uint64_t fromInstance = plr->instanceID;
// call events
LuaManager::playerRemoved(key);
Groups::groupKickPlayer(plr); Groups::groupKickPlayer(plr);
// remove player's bullets // remove player's bullets

174
src/lua/EntityWrapper.cpp Normal file
View File

@ -0,0 +1,174 @@
#include "lua/LuaWrapper.hpp"
#include "lua/LuaManager.hpp"
#include "lua/EntityWrapper.hpp"
#include "Entities.hpp"
#define LIBNAME "Entity"
#define SUPERTBL "__entSUPERCLASSES"
#define ENTYGONESTR "Entity doesn't exist anymore!"
EntityRef* grabBaseEntityRef(lua_State *state, int indx) {
// first, make sure its a userdata
luaL_checktype(state, indx, LUA_TUSERDATA);
// grab the super class table
lua_getfield(state, LUA_REGISTRYINDEX, SUPERTBL);
// grab the userdata
EntityRef *data = (EntityRef*)lua_touserdata(state, indx);
// check if it doesn't have a metatable
if (!lua_getmetatable(state, indx)) {
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// index the super class table
lua_gettable(state, -2);
// if the index was nil, it doesn't exist
if (lua_isnil(state, -1)) {
lua_pop(state, 1);
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// it's good :)
lua_pop(state, 1);
return data;
}
// check at index
EntityRef* grabEntityRef(lua_State *state, int indx) {
EntityRef *ref = grabBaseEntityRef(state, indx);
if (ref == NULL || !ref->isValid())
return NULL;
return ref;
}
// =============================================== [[ GETTERS ]] ===============================================
static int ent_getX(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->x);
return 1;
}
static int ent_getY(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->y);
return 1;
}
static int ent_getZ(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
lua_pushnumber(state, ref->getEntity()->z);
return 1;
}
static int ent_getType(lua_State *state) {
EntityRef *ref = grabEntityRef(state, 1);
if (ref == NULL)
return 0;
// push the type string
switch(ref->type) {
case EntityType::PLAYER:
lua_pushstring(state, "Player");
break;
case EntityType::MOB:
lua_pushstring(state, "Mob");
break;
case EntityType::EGG:
lua_pushstring(state, "Egg");
break;
case EntityType::BUS:
lua_pushstring(state, "Bus");
break;
default: // INVALID, COMBAT_NPC, SIMPLE_NPC
lua_pushstring(state, "Entity");
break;
}
return 1;
}
static luaL_Reg ent_getters[] = {
{"x", ent_getX},
{"y", ent_getY},
{"z", ent_getZ},
{"type", ent_getType},
{0, 0}
};
// =============================================== [[ METHODS ]] ===============================================
static int ent_exists(lua_State *state) {
EntityRef *data = (EntityRef*)grabBaseEntityRef(state, 1);
lua_pushboolean(state, data == NULL || !data->isValid());
return 1;
}
static luaL_Reg ent_methods[] = {
{"exists", ent_exists},
{0, 0}
};
void LuaManager::Entity::init(lua_State *state) {
// register our library as a global (and leave it on the stack)
luaL_register(state, LIBNAME, ent_methods);
lua_pop(state, 1); // pop library table
// will hold our super classes
lua_pushstring(state, SUPERTBL);
lua_newtable(state);
lua_rawset(state, LUA_REGISTRYINDEX);
}
void LuaManager::Entity::registerSuper(lua_State *state, const char *tname) {
// grab the super class table
lua_getfield(state, LUA_REGISTRYINDEX, SUPERTBL);
// grab the metatable
lua_getfield(state, LUA_REGISTRYINDEX, tname);
lua_pushboolean(state, 1);
// finally, set the index
lua_rawset(state, -3);
lua_pop(state, 1); // pop the super class table
}
void LuaManager::Entity::addGetters(lua_State *state) {
luaL_register(state, NULL, ent_getters);
}
void LuaManager::Entity::addMethods(lua_State *state) {
luaL_register(state, NULL, ent_methods);
}
void LuaManager::Entity::push(lua_State *state, EntityRef ref, const char *tname) {
// creates the udata and copies the reference to the udata
EntityRef *ent = (EntityRef*)lua_newuserdata(state, sizeof(EntityRef));
*ent = ref;
// attaches our metatable from the registry to the udata
luaL_getmetatable(state, tname);
lua_setmetatable(state, -2);
}

19
src/lua/EntityWrapper.hpp Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "lua/LuaWrapper.hpp"
#include "lua/LuaManager.hpp"
#include "Entities.hpp"
namespace LuaManager {
namespace Entity {
void init(lua_State *state);
void registerSuper(lua_State *state, const char *tname);
void addGetters(lua_State *state);
void addMethods(lua_State *state);
void push(lua_State *state, EntityRef ref, const char *tname);
}
}

View File

@ -7,8 +7,8 @@
#include <unordered_set> #include <unordered_set>
#define LIBNAME "event" #define LIBNAME "Event"
#define LISTNR "listener" #define LISTNR "Listener"
typedef lEvent* eventData; typedef lEvent* eventData;

View File

@ -1,6 +1,8 @@
#include "lua/LuaManager.hpp" #include "lua/LuaManager.hpp"
#include "lua/LuaWrapper.hpp" #include "lua/LuaWrapper.hpp"
#include "lua/EventWrapper.hpp" #include "lua/EventWrapper.hpp"
#include "lua/WorldWrapper.hpp"
#include "lua/PlayerWrapper.hpp"
#include "servers/CNShardServer.hpp" #include "servers/CNShardServer.hpp"
#include "settings.hpp" #include "settings.hpp"
@ -113,6 +115,9 @@ void LuaManager::init() {
// register our libraries // register our libraries
Event::init(global); Event::init(global);
World::init(global);
Entity::init(global);
Player::init(global);
activeScripts = std::map<lua_State*, Script*>(); activeScripts = std::map<lua_State*, Script*>();
@ -155,4 +160,12 @@ void LuaManager::loadScripts() {
void LuaManager::clearState(lua_State *state) { void LuaManager::clearState(lua_State *state) {
// TODO // TODO
}
void LuaManager::playerAdded(CNSocket *sock) {
World::playerAdded(sock);
}
void LuaManager::playerRemoved(CNSocket *sock) {
World::playerRemoved(sock);
} }

View File

@ -23,4 +23,6 @@ namespace LuaManager {
// unregisters the events tied to this state with all wrappers // unregisters the events tied to this state with all wrappers
void clearState(lua_State *state); void clearState(lua_State *state);
void playerAdded(CNSocket *sock);
void playerRemoved(CNSocket *sock);
} }

View File

@ -10,6 +10,7 @@
#include <cassert> #include <cassert>
#include "lua/LuaManager.hpp" #include "lua/LuaManager.hpp"
#include "lua/PlayerWrapper.hpp"
#define yieldCall(state, nargs) \ #define yieldCall(state, nargs) \
int _retCode = lua_resume(state, nargs); \ int _retCode = lua_resume(state, nargs); \
@ -29,6 +30,7 @@ inline static int lua_autoPush(lua_State* state, int nargs) {
char* or const char* : LUA_TSTRING char* or const char* : LUA_TSTRING
bool : LUA_TBOOLEAN bool : LUA_TBOOLEAN
lRegistry : grabs the object from the lua registry and pushes it onto the stack lRegistry : grabs the object from the lua registry and pushes it onto the stack
CNSocket* : Pushes the Player Entity
*/ */
template<typename T, class... Rest> template<typename T, class... Rest>
inline static int lua_autoPush(lua_State* state, int nargs, T arg, Rest... rest) { inline static int lua_autoPush(lua_State* state, int nargs, T arg, Rest... rest) {
@ -40,6 +42,8 @@ inline static int lua_autoPush(lua_State* state, int nargs, T arg, Rest... rest)
} else if constexpr(std::is_same<T, lRegistry>::value) { } else if constexpr(std::is_same<T, lRegistry>::value) {
// grab the value from the registry // grab the value from the registry
lua_rawgeti(state, LUA_REGISTRYINDEX, (int)arg); lua_rawgeti(state, LUA_REGISTRYINDEX, (int)arg);
} else if constexpr(std::is_same<T, CNSocket*>::value) { // pushes a Player Entity
LuaManager::Player::push(state, arg);
} else if constexpr(std::is_same<T, bool>::value) { } else if constexpr(std::is_same<T, bool>::value) {
lua_pushboolean(state, arg); lua_pushboolean(state, arg);
} }

171
src/lua/PlayerWrapper.cpp Normal file
View File

@ -0,0 +1,171 @@
#include "lua/EntityWrapper.hpp"
#include "lua/PlayerWrapper.hpp"
#include "core/CNProtocol.hpp"
#include "Player.hpp"
#include "PlayerManager.hpp"
#define LIBNAME "Player"
#define PLRGONESTR "Player doesn't exist anymore, they left!"
#define GETTERTBL "__plrGETTERS"
#define SETTERTBL "__plrSETTERS"
#define METHODTBL "__plrMETHODS"
static Player* grabPlayer(lua_State *state, int indx) {
// first, make sure its a userdata
luaL_checktype(state, indx, LUA_TUSERDATA);
// now, check and make sure its our library's metatable attached to this userdata
EntityRef *ref = (EntityRef*)luaL_checkudata(state, indx, LIBNAME);
if (ref == NULL) {
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// check if the player exists still & return NULL if it doesn't
if (!ref->isValid()) {
luaL_argerror(state, indx, PLRGONESTR);
return NULL;
}
return (Player*)ref->getEntity();
}
static CNSocket* grabSock(lua_State *state, int indx) {
// first, make sure its a userdata
luaL_checktype(state, indx, LUA_TUSERDATA);
// now, check and make sure its our library's metatable attached to this userdata
EntityRef *ref = (EntityRef*)luaL_checkudata(state, indx, LIBNAME);
if (ref == NULL) {
luaL_typerror(state, indx, LIBNAME);
return NULL;
}
// check if the player exists still & return NULL if it doesn't
if (!ref->isValid()) {
luaL_argerror(state, indx, PLRGONESTR);
return NULL;
}
return ref->sock;
}
// =============================================== [[ GETTERS ]] ===============================================
static int plr_getName(lua_State *state) {
Player *plr = grabPlayer(state, 1);
if (plr == NULL)
return 0;
lua_pushstring(state, PlayerManager::getPlayerName(plr).c_str());
return 1;
}
static const luaL_Reg plr_getters[] = {
{"name", plr_getName},
{0, 0}
};
// =============================================== [[ SETTERS ]] ===============================================
static const luaL_Reg plr_setters[] = {
{0, 0}
};
// =============================================== [[ METHODS ]] ===============================================
static const luaL_Reg plr_methods[] = {
{0, 0}
};
// in charge of calling the correct getter method
static int plr_index(lua_State *state) {
// grab the function from the getters lookup table
lua_pushstring(state, GETTERTBL);
lua_rawget(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2);
lua_rawget(state, -2);
// if it's not nil, call it and run the getter method
if (!lua_isnil(state, -1)) {
// push userdata & call the function
lua_pushvalue(state, 1);
lua_call(state, 1, 1);
// return # of results
return 1;
}
// grab the function from the methods lookup table
lua_pop(state, 1);
lua_pushstring(state, METHODTBL);
lua_rawget(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2);
lua_rawget(state, -2);
// return result
return 1;
}
// in charge of calling the correct setter method
static int plr_newindex(lua_State *state) {
// grab the function from the getters lookup table
lua_pushstring(state, SETTERTBL);
lua_rawget(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2);
lua_rawget(state, -2);
// if it's nil return
if (lua_isnil(state, -1))
return 0;
// push userdata & call the function
lua_pushvalue(state, 1);
lua_call(state, 1, 0);
// return # of results
return 0;
}
void LuaManager::Player::init(lua_State *state) {
// register our library as a global (and leave it on the stack)
luaL_register(state, LIBNAME, plr_methods);
// create the meta table and populate it with our functions
luaL_newmetatable(state, LIBNAME);
lua_pushstring(state, "__index");
lua_pushcfunction(state, plr_index);
lua_rawset(state, -3); // sets meta.__index = plr_index
lua_pushstring(state, "__newindex");
lua_pushcfunction(state, plr_newindex);
lua_rawset(state, -3); // sets meta.__newindex = plr_newindex
lua_pop(state, 2); // pop meta & library table
// create the methods table
lua_pushstring(state, METHODTBL);
lua_newtable(state);
Entity::addMethods(state); // register the base Entity methods
luaL_register(state, NULL, plr_methods);
lua_rawset(state, LUA_REGISTRYINDEX);
// create the getters table
lua_pushstring(state, GETTERTBL);
lua_newtable(state);
Entity::addGetters(state); // register the base Entity getters
luaL_register(state, NULL, plr_getters);
lua_rawset(state, LUA_REGISTRYINDEX);
// create the setters table
lua_pushstring(state, SETTERTBL);
lua_newtable(state);
luaL_register(state, NULL, plr_setters);
lua_rawset(state, LUA_REGISTRYINDEX);
LuaManager::Entity::registerSuper(state, LIBNAME);
}
void LuaManager::Player::push(lua_State *state, CNSocket *sock) {
Entity::push(state, EntityRef(sock), LIBNAME);
}

11
src/lua/PlayerWrapper.hpp Normal file
View File

@ -0,0 +1,11 @@
#include "lua/LuaWrapper.hpp"
#include "lua/LuaManager.hpp"
#include "lua/EntityWrapper.hpp"
namespace LuaManager {
namespace Player {
void init(lua_State *state);
void push(lua_State *state, CNSocket *sock);
}
}

130
src/lua/WorldWrapper.cpp Normal file
View File

@ -0,0 +1,130 @@
#include "lua/LuaManager.hpp"
#include "lua/LuaWrapper.hpp"
#include "lua/EventWrapper.hpp"
#include "lua/WorldWrapper.hpp"
#include "core/CNStructs.hpp"
#include "PlayerManager.hpp"
static lEvent *addedEvent;
static lEvent *removedEvent;
#define LIBNAME "World"
#define GETTERTBL "__wrldGETTERS"
#define METHODTBL "__wrldMETHODS"
// =============================================== [[ GETTERS ]] ===============================================
int wrld_getPlrAdded(lua_State *state) {
LuaManager::Event::push(state, addedEvent);
return 1;
}
int wrld_getPlrRemoved(lua_State *state) {
LuaManager::Event::push(state, removedEvent);
return 1;
}
int wrld_getVersion(lua_State *state) {
lua_pushnumber(state, PROTOCOL_VERSION);
return 1;
}
int wrld_getPlayers(lua_State *state) {
// create a new lua table and push it onto the stack
int entries = 0;
lua_newtable(state);
// walk through the current list of players and add them to the table
for (auto pair : PlayerManager::players) {
lua_pushinteger(state, ++entries);
LuaManager::Player::push(state, pair.first);
lua_rawset(state, -3);
}
// returns the player table :)
return 1;
}
// =============================================== [[ METHODS ]] ===============================================
int wrld_index(lua_State *state) {
// grab the function from the getters lookup table
lua_pushstring(state, GETTERTBL);
lua_rawget(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2);
lua_rawget(state, -2);
// if it's not nil, call it and run the getter method
if (!lua_isnil(state, -1)) {
// push userdata & call the function
lua_pushvalue(state, 1);
lua_call(state, 1, 1);
// return # of results
return 1;
}
// grab the function from the methods lookup table
lua_pop(state, 1);
lua_pushstring(state, METHODTBL);
lua_rawget(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2);
lua_rawget(state, -2);
// return result
return 1;
}
static const luaL_Reg getters[] {
{"onPlayerAdded", wrld_getPlrAdded},
{"onPlayerRemoved", wrld_getPlrRemoved},
{"players", wrld_getPlayers},
{"version", wrld_getVersion},
{0, 0}
};
// TODO
static const luaL_Reg methods[] = {
//{"getNearbyPlayers", wrld_getNPlrs},
{0, 0}
};
void LuaManager::World::init(lua_State *state) {
lua_newtable(state);
luaL_newmetatable(state, LIBNAME);
lua_pushstring(state, "__index");
lua_pushcfunction(state, wrld_index);
lua_rawset(state, -3); // sets meta.__index = wrld_index
lua_setmetatable(state, -2); // sets world.__metatable = meta
lua_setglobal(state, LIBNAME);
// setup the __wrldGETTERS table in the registry
lua_pushstring(state, GETTERTBL);
lua_newtable(state);
luaL_register(state, NULL, getters);
lua_rawset(state, LUA_REGISTRYINDEX);
// setup the __wrldMETHODS table in the registry
lua_pushstring(state, METHODTBL);
lua_newtable(state);
luaL_register(state, NULL, methods);
lua_rawset(state, LUA_REGISTRYINDEX);
addedEvent = new lEvent();
removedEvent = new lEvent();
}
void LuaManager::World::clearState(lua_State *state) {
addedEvent->clear(state);
removedEvent->clear(state);
}
void LuaManager::World::playerAdded(CNSocket *sock) {
addedEvent->call(sock);
}
void LuaManager::World::playerRemoved(CNSocket *sock) {
removedEvent->call(sock);
}

13
src/lua/WorldWrapper.hpp Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "lua/LuaManager.hpp"
namespace LuaManager {
namespace World {
void init(lua_State *state);
void clearState(lua_State *state);
void playerAdded(CNSocket *sock);
void playerRemoved(CNSocket *sock);
}
}