Merge branch 'develop'
Changes: * "ticking" rooms * character API * bare-bones character manager API * bounds checking in serial_utility.cpp I have an idea for swapping the existing utility/singleton classes for namesapces, as I think this would reduce the verbosity that I have to deal with.
This commit is contained in:
@@ -34,7 +34,7 @@
|
|||||||
typedef SerialPacketBase SerialPacket;
|
typedef SerialPacketBase SerialPacket;
|
||||||
|
|
||||||
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
|
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
|
||||||
constexpr int NETWORK_VERSION = 20150214;
|
constexpr int NETWORK_VERSION = 20150221;
|
||||||
|
|
||||||
union MaxPacket {
|
union MaxPacket {
|
||||||
CharacterPacket a;
|
CharacterPacket a;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
/* DOCS: The headers indicate what packet type is used for each message
|
/* DOCS: The headers indicate what packet type is used for each message
|
||||||
* different messages under the same header will carry different amounts of
|
* different messages under the same header will carry different amounts of
|
||||||
* valid data, but it will still be carried in that packet's format.
|
* valid data, but it will still be carried in that packet's format.
|
||||||
|
* FORMAT_* is for internal use, deviding the different format bounds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class SerialPacketType {
|
enum class SerialPacketType {
|
||||||
@@ -36,6 +37,8 @@ enum class SerialPacketType {
|
|||||||
// name, player count, version
|
// name, player count, version
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_SERVER,
|
||||||
|
|
||||||
//heartbeat
|
//heartbeat
|
||||||
PING,
|
PING,
|
||||||
PONG,
|
PONG,
|
||||||
@@ -44,11 +47,15 @@ enum class SerialPacketType {
|
|||||||
BROADCAST_REQUEST,
|
BROADCAST_REQUEST,
|
||||||
BROADCAST_RESPONSE,
|
BROADCAST_RESPONSE,
|
||||||
|
|
||||||
|
FORMAT_END_SERVER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//ClientPacket
|
//ClientPacket
|
||||||
// client index, account index, username
|
// client index, account index, username
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_CLIENT,
|
||||||
|
|
||||||
//Connecting to a server as a client
|
//Connecting to a server as a client
|
||||||
JOIN_REQUEST,
|
JOIN_REQUEST,
|
||||||
JOIN_RESPONSE,
|
JOIN_RESPONSE,
|
||||||
@@ -69,15 +76,21 @@ enum class SerialPacketType {
|
|||||||
//shut down the server
|
//shut down the server
|
||||||
ADMIN_SHUTDOWN_REQUEST,
|
ADMIN_SHUTDOWN_REQUEST,
|
||||||
|
|
||||||
|
FORMAT_END_CLIENT,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//RegionPacket
|
//RegionPacket
|
||||||
// room index, x, y, raw data
|
// room index, x, y, raw data
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_REGION,
|
||||||
|
|
||||||
//map data
|
//map data
|
||||||
REGION_REQUEST,
|
REGION_REQUEST,
|
||||||
REGION_CONTENT,
|
REGION_CONTENT,
|
||||||
|
|
||||||
|
FORMAT_END_REGION,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//CharacterPacket
|
//CharacterPacket
|
||||||
// character index,
|
// character index,
|
||||||
@@ -86,6 +99,11 @@ enum class SerialPacketType {
|
|||||||
// room index, origin, motion
|
// room index, origin, motion
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_CHARACTER,
|
||||||
|
|
||||||
|
//full data update
|
||||||
|
CHARACTER_UPDATE,
|
||||||
|
|
||||||
//character management
|
//character management
|
||||||
CHARACTER_CREATE,
|
CHARACTER_CREATE,
|
||||||
CHARACTER_DELETE,
|
CHARACTER_DELETE,
|
||||||
@@ -97,7 +115,7 @@ enum class SerialPacketType {
|
|||||||
QUERY_CHARACTER_STATS,
|
QUERY_CHARACTER_STATS,
|
||||||
QUERY_CHARACTER_LOCATION,
|
QUERY_CHARACTER_LOCATION,
|
||||||
|
|
||||||
//set the info in the server
|
//actions taken
|
||||||
CHARACTER_MOVEMENT,
|
CHARACTER_MOVEMENT,
|
||||||
CHARACTER_ATTACK,
|
CHARACTER_ATTACK,
|
||||||
CHARACTER_DAMAGE,
|
CHARACTER_DAMAGE,
|
||||||
@@ -105,6 +123,8 @@ enum class SerialPacketType {
|
|||||||
//admin control
|
//admin control
|
||||||
// ADMIN_SET_CHARACTER_ORIGIN,
|
// ADMIN_SET_CHARACTER_ORIGIN,
|
||||||
|
|
||||||
|
FORMAT_END_CHARACTER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//MonsterPacket
|
//MonsterPacket
|
||||||
// monster index,
|
// monster index,
|
||||||
@@ -113,22 +133,34 @@ enum class SerialPacketType {
|
|||||||
// room index, origin, motion
|
// room index, origin, motion
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_MONSTER,
|
||||||
|
|
||||||
|
//full data update
|
||||||
|
MONSTER_UPDATE,
|
||||||
|
|
||||||
|
//character management
|
||||||
MONSTER_CREATE,
|
MONSTER_CREATE,
|
||||||
MONSTER_DELETE,
|
MONSTER_DELETE,
|
||||||
|
|
||||||
|
//find out info from the server
|
||||||
QUERY_MONSTER_EXISTS,
|
QUERY_MONSTER_EXISTS,
|
||||||
QUERY_MONSTER_STATS,
|
QUERY_MONSTER_STATS,
|
||||||
QUERY_MONSTER_LOCATION,
|
QUERY_MONSTER_LOCATION,
|
||||||
|
|
||||||
|
//actions taken
|
||||||
MONSTER_MOVEMENT,
|
MONSTER_MOVEMENT,
|
||||||
MONSTER_ATTACK,
|
MONSTER_ATTACK,
|
||||||
MONSTER_DAMAGE,
|
MONSTER_DAMAGE,
|
||||||
|
|
||||||
|
FORMAT_END_MONSTER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//TextPacket
|
//TextPacket
|
||||||
// name, text
|
// name, text
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_TEXT,
|
||||||
|
|
||||||
//general speech
|
//general speech
|
||||||
TEXT_BROADCAST,
|
TEXT_BROADCAST,
|
||||||
TEXT_SPEECH,
|
TEXT_SPEECH,
|
||||||
@@ -143,6 +175,8 @@ enum class SerialPacketType {
|
|||||||
SHUTDOWN_REJECTION,
|
SHUTDOWN_REJECTION,
|
||||||
QUERY_REJECTION,
|
QUERY_REJECTION,
|
||||||
|
|
||||||
|
FORMAT_END_TEXT,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//not used
|
//not used
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
//macros
|
||||||
|
#define BOUNDS(type, lower, upper) ((type) > (lower) && (type) < (upper))
|
||||||
|
|
||||||
//raw memory copy
|
//raw memory copy
|
||||||
void serialCopy(void** buffer, void* data, int size) {
|
void serialCopy(void** buffer, void* data, int size) {
|
||||||
memcpy(*buffer, data, size);
|
memcpy(*buffer, data, size);
|
||||||
@@ -46,63 +49,28 @@ void deserialCopy(void** buffer, void* data, int size) {
|
|||||||
|
|
||||||
//main switch functions
|
//main switch functions
|
||||||
void serializePacket(void* buffer, SerialPacketBase* packet) {
|
void serializePacket(void* buffer, SerialPacketBase* packet) {
|
||||||
switch(packet->type) {
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||||
case SerialPacketType::PING:
|
|
||||||
case SerialPacketType::PONG:
|
|
||||||
case SerialPacketType::BROADCAST_REQUEST:
|
|
||||||
case SerialPacketType::BROADCAST_RESPONSE:
|
|
||||||
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::JOIN_REQUEST:
|
|
||||||
case SerialPacketType::JOIN_RESPONSE:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||||
case SerialPacketType::DISCONNECT_REQUEST:
|
|
||||||
case SerialPacketType::DISCONNECT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
|
|
||||||
case SerialPacketType::LOGIN_REQUEST:
|
|
||||||
case SerialPacketType::LOGIN_RESPONSE:
|
|
||||||
case SerialPacketType::LOGOUT_REQUEST:
|
|
||||||
case SerialPacketType::LOGOUT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST:
|
|
||||||
serializeClient(buffer, static_cast<ClientPacket*>(packet));
|
serializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::REGION_REQUEST:
|
|
||||||
case SerialPacketType::REGION_CONTENT:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||||
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::CHARACTER_CREATE:
|
|
||||||
case SerialPacketType::CHARACTER_DELETE:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||||
case SerialPacketType::CHARACTER_LOAD:
|
|
||||||
case SerialPacketType::CHARACTER_UNLOAD:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_LOCATION:
|
|
||||||
case SerialPacketType::CHARACTER_MOVEMENT:
|
|
||||||
case SerialPacketType::CHARACTER_ATTACK:
|
|
||||||
case SerialPacketType::CHARACTER_DAMAGE:
|
|
||||||
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::MONSTER_CREATE:
|
|
||||||
case SerialPacketType::MONSTER_DELETE:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||||
case SerialPacketType::QUERY_MONSTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_LOCATION:
|
|
||||||
case SerialPacketType::MONSTER_MOVEMENT:
|
|
||||||
case SerialPacketType::MONSTER_ATTACK:
|
|
||||||
case SerialPacketType::MONSTER_DAMAGE:
|
|
||||||
serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::TEXT_BROADCAST:
|
|
||||||
case SerialPacketType::TEXT_SPEECH:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||||
case SerialPacketType::TEXT_WHISPER:
|
|
||||||
case SerialPacketType::JOIN_REJECTION:
|
|
||||||
case SerialPacketType::LOGIN_REJECTION:
|
|
||||||
case SerialPacketType::REGION_REJECTION:
|
|
||||||
case SerialPacketType::CHARACTER_REJECTION:
|
|
||||||
case SerialPacketType::MONSTER_REJECTION:
|
|
||||||
case SerialPacketType::SHUTDOWN_REJECTION:
|
|
||||||
case SerialPacketType::QUERY_REJECTION:
|
|
||||||
serializeText(buffer, static_cast<TextPacket*>(packet));
|
serializeText(buffer, static_cast<TextPacket*>(packet));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,62 +79,27 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
|
|||||||
SerialPacketType type;
|
SerialPacketType type;
|
||||||
memcpy(&type, buffer, sizeof(SerialPacketType));
|
memcpy(&type, buffer, sizeof(SerialPacketType));
|
||||||
|
|
||||||
switch(type) {
|
if (BOUNDS(type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||||
case SerialPacketType::PING:
|
|
||||||
case SerialPacketType::PONG:
|
|
||||||
case SerialPacketType::BROADCAST_REQUEST:
|
|
||||||
case SerialPacketType::BROADCAST_RESPONSE:
|
|
||||||
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::JOIN_REQUEST:
|
|
||||||
case SerialPacketType::JOIN_RESPONSE:
|
if (BOUNDS(type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||||
case SerialPacketType::DISCONNECT_REQUEST:
|
|
||||||
case SerialPacketType::DISCONNECT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
|
|
||||||
case SerialPacketType::LOGIN_REQUEST:
|
|
||||||
case SerialPacketType::LOGIN_RESPONSE:
|
|
||||||
case SerialPacketType::LOGOUT_REQUEST:
|
|
||||||
case SerialPacketType::LOGOUT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST:
|
|
||||||
deserializeClient(buffer, static_cast<ClientPacket*>(packet));
|
deserializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::REGION_REQUEST:
|
|
||||||
case SerialPacketType::REGION_CONTENT:
|
if (BOUNDS(type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||||
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::CHARACTER_CREATE:
|
|
||||||
case SerialPacketType::CHARACTER_DELETE:
|
if (BOUNDS(type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||||
case SerialPacketType::CHARACTER_LOAD:
|
|
||||||
case SerialPacketType::CHARACTER_UNLOAD:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_LOCATION:
|
|
||||||
case SerialPacketType::CHARACTER_MOVEMENT:
|
|
||||||
case SerialPacketType::CHARACTER_ATTACK:
|
|
||||||
case SerialPacketType::CHARACTER_DAMAGE:
|
|
||||||
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::MONSTER_CREATE:
|
|
||||||
case SerialPacketType::MONSTER_DELETE:
|
if (BOUNDS(type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||||
case SerialPacketType::QUERY_MONSTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_LOCATION:
|
|
||||||
case SerialPacketType::MONSTER_MOVEMENT:
|
|
||||||
case SerialPacketType::MONSTER_ATTACK:
|
|
||||||
case SerialPacketType::MONSTER_DAMAGE:
|
|
||||||
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::TEXT_BROADCAST:
|
|
||||||
case SerialPacketType::TEXT_SPEECH:
|
if (BOUNDS(type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||||
case SerialPacketType::TEXT_WHISPER:
|
|
||||||
case SerialPacketType::JOIN_REJECTION:
|
|
||||||
case SerialPacketType::LOGIN_REJECTION:
|
|
||||||
case SerialPacketType::REGION_REJECTION:
|
|
||||||
case SerialPacketType::CHARACTER_REJECTION:
|
|
||||||
case SerialPacketType::MONSTER_REJECTION:
|
|
||||||
case SerialPacketType::SHUTDOWN_REJECTION:
|
|
||||||
case SerialPacketType::QUERY_REJECTION:
|
|
||||||
deserializeText(buffer, static_cast<TextPacket*>(packet));
|
deserializeText(buffer, static_cast<TextPacket*>(packet));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ print("Lua script check")
|
|||||||
mapMaker = require("map_maker")
|
mapMaker = require("map_maker")
|
||||||
mapSaver = require("map_saver")
|
mapSaver = require("map_saver")
|
||||||
roomSystem = require("room_system")
|
roomSystem = require("room_system")
|
||||||
|
characterSystem = require("character_system")
|
||||||
|
|
||||||
local function dumpTable(t)
|
local function dumpTable(t)
|
||||||
print(t)
|
print(t)
|
||||||
@@ -11,6 +12,25 @@ local function dumpTable(t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--test the room hooks
|
||||||
|
roomSystem.RoomManager.SetOnCreate(function(room, index)
|
||||||
|
print("", "Creating room: ", roomSystem.Room.GetName(room), index)
|
||||||
|
|
||||||
|
--called ~60 times per second
|
||||||
|
roomSystem.Room.SetOnTick(room, function(room)
|
||||||
|
local character = characterSystem.CharacterManager.GetCharacter("handle")
|
||||||
|
if character ~= nil then
|
||||||
|
--debugging
|
||||||
|
local x, y = characterSystem.Character.GetOrigin(character)
|
||||||
|
print("character.Origin(x, y): ", x, y)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
roomSystem.RoomManager.SetOnUnload(function(room, index)
|
||||||
|
print("", "Unloading room: ", roomSystem.Room.GetName(room), index)
|
||||||
|
end)
|
||||||
|
|
||||||
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
||||||
local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld", "overworld.bmp")
|
local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld", "overworld.bmp")
|
||||||
roomSystem.Room.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
roomSystem.Room.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
||||||
|
|||||||
@@ -23,11 +23,56 @@
|
|||||||
|
|
||||||
#include "character_data.hpp"
|
#include "character_data.hpp"
|
||||||
|
|
||||||
|
#include "entity_api.hpp"
|
||||||
|
|
||||||
|
static int getOwner(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, character->GetOwner());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getHandle(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, character->GetHandle().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getAvatar(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, character->GetAvatar().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg characterLib[] = {
|
static const luaL_Reg characterLib[] = {
|
||||||
|
// {"GetOwner", getOwner}, //unusable without account API
|
||||||
|
{"GetHandle", getHandle},
|
||||||
|
{"GetAvatar", getAvatar},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
||||||
|
//the local table
|
||||||
luaL_newlib(L, characterLib);
|
luaL_newlib(L, characterLib);
|
||||||
|
|
||||||
|
//get the parent table
|
||||||
|
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||||
|
|
||||||
|
//clone the parent table into the local table
|
||||||
|
lua_pushnil(L); //first key
|
||||||
|
while(lua_next(L, -2)) {
|
||||||
|
//copy the key-value pair
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
|
||||||
|
//push the copy to the local table
|
||||||
|
lua_settable(L, -6);
|
||||||
|
|
||||||
|
//pop the original value before continuing
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove the parent table, leaving the expanded child table
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -35,9 +35,6 @@ public:
|
|||||||
CharacterData() = default;
|
CharacterData() = default;
|
||||||
~CharacterData() = default;
|
~CharacterData() = default;
|
||||||
|
|
||||||
//accessors and mutators
|
|
||||||
//...
|
|
||||||
|
|
||||||
//database stuff
|
//database stuff
|
||||||
int GetOwner();
|
int GetOwner();
|
||||||
std::string GetHandle();
|
std::string GetHandle();
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ void CharacterManager::Unload(int uid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CharacterManager::Delete(int uid) {
|
void CharacterManager::Delete(int uid) {
|
||||||
|
//TODO: when deleting a character, move it to an archive table
|
||||||
//delete this character from the database, then remove it from memory
|
//delete this character from the database, then remove it from memory
|
||||||
sqlite3_stmt* statement = nullptr;
|
sqlite3_stmt* statement = nullptr;
|
||||||
|
|
||||||
@@ -252,6 +253,15 @@ CharacterData* CharacterManager::Get(int uid) {
|
|||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CharacterData* CharacterManager::Get(std::string handle) {
|
||||||
|
for (std::map<int, CharacterData>::iterator it = elementMap.begin(); it != elementMap.end(); ++it) {
|
||||||
|
if (it->second.GetHandle() == handle) {
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int CharacterManager::GetLoadedCount() {
|
int CharacterManager::GetLoadedCount() {
|
||||||
return elementMap.size();
|
return elementMap.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,13 +44,18 @@ public:
|
|||||||
|
|
||||||
//accessors and mutators
|
//accessors and mutators
|
||||||
CharacterData* Get(int uid);
|
CharacterData* Get(int uid);
|
||||||
|
CharacterData* Get(std::string handle);
|
||||||
int GetLoadedCount();
|
int GetLoadedCount();
|
||||||
int GetTotalCount();
|
int GetTotalCount();
|
||||||
std::map<int, CharacterData>* GetContainer();
|
std::map<int, CharacterData>* GetContainer();
|
||||||
|
|
||||||
|
//API interface
|
||||||
sqlite3* SetDatabase(sqlite3* db);
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
sqlite3* GetDatabase();
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
//TODO: character hooks
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Singleton<CharacterManager>;
|
friend Singleton<CharacterManager>;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,70 @@
|
|||||||
|
|
||||||
#include "character_manager.hpp"
|
#include "character_manager.hpp"
|
||||||
|
|
||||||
|
static int setOnCreate(lua_State* L) {
|
||||||
|
//TODO: (9) empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnLoad(lua_State* L) {
|
||||||
|
//TODO: (9) empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnSave(lua_State* L) {
|
||||||
|
//TODO: (9) empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnUnload(lua_State* L) {
|
||||||
|
//TODO: (9) empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnDelete(lua_State* L) {
|
||||||
|
//TODO: (9) empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getCharacter(lua_State* L) {
|
||||||
|
//integer vs name
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
CharacterData* characterData = nullptr;
|
||||||
|
|
||||||
|
switch(lua_type(L, 1)) {
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
characterData = characterMgr.Get(lua_tointeger(L, 1));
|
||||||
|
break;
|
||||||
|
case LUA_TSTRING:
|
||||||
|
//access characters via their handles
|
||||||
|
characterData = characterMgr.Get(lua_tostring(L, 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (characterData) {
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(characterData));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getLoadedCount(lua_State* L) {
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
lua_pushinteger(L, characterMgr.GetLoadedCount());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int forEach(lua_State* L) {
|
||||||
|
//TODO: (1) find a way to update the clients when a script alters a character's data
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg characterManagerLib[] = {
|
static const luaL_Reg characterManagerLib[] = {
|
||||||
|
// {"SetOnCreate", setOnCreate},
|
||||||
|
// {"SetOnLoad", setOnLoad},
|
||||||
|
// {"SetOnSave", setOnSave},
|
||||||
|
// {"SetOnUnload", setOnUnload},
|
||||||
|
// {"SetOnDelete", setOnDelete},
|
||||||
|
{"GetCharacter", getCharacter},
|
||||||
|
{"GetLoadedCount", getLoadedCount},
|
||||||
|
// {"ForEach", forEach},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*/
|
||||||
|
#include "character_system_api.hpp"
|
||||||
|
|
||||||
|
//all character API headers
|
||||||
|
#include "character_api.hpp"
|
||||||
|
#include "character_manager_api.hpp"
|
||||||
|
|
||||||
|
//useful "globals"
|
||||||
|
//...
|
||||||
|
|
||||||
|
//This mimics linit.c to create a nested collection of all character modules.
|
||||||
|
static const luaL_Reg funcs[] = {
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const luaL_Reg libs[] = {
|
||||||
|
{"Character", openCharacterAPI},
|
||||||
|
{"CharacterManager", openCharacterManagerAPI},
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
int openCharacterSystemAPI(lua_State* L) {
|
||||||
|
//create the table
|
||||||
|
luaL_newlibtable(L, libs);
|
||||||
|
|
||||||
|
//push the "global" functions
|
||||||
|
luaL_setfuncs(L, funcs, 0);
|
||||||
|
|
||||||
|
//push the substable
|
||||||
|
for (const luaL_Reg* lib = libs; lib->func; lib++) {
|
||||||
|
lib->func(L);
|
||||||
|
lua_setfield(L, -2, lib->name);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*/
|
||||||
|
#ifndef CHARACTERSYSTEMAPI_HPP_
|
||||||
|
#define CHARACTERSYSTEMAPI_HPP_
|
||||||
|
|
||||||
|
#include "lua.hpp"
|
||||||
|
|
||||||
|
#define TORTUGA_CHARACTER_SYSTEM_API "character_system"
|
||||||
|
LUAMOD_API int openCharacterSystemAPI(lua_State* L);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,11 +21,15 @@
|
|||||||
*/
|
*/
|
||||||
#include "client_manager.hpp"
|
#include "client_manager.hpp"
|
||||||
|
|
||||||
|
#include "ip_operators.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
int ClientManager::CheckConnections() {
|
std::list<int> ClientManager::CheckConnections() {
|
||||||
|
//list of clients to disconnect
|
||||||
|
std::list<int> returnList;
|
||||||
|
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
//3 seconds between beats
|
//3 seconds between beats
|
||||||
if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
|
if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
|
||||||
@@ -38,21 +42,17 @@ int ClientManager::CheckConnections() {
|
|||||||
|
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
if (it.second.GetAttempts() > 2) {
|
if (it.second.GetAttempts() > 2) {
|
||||||
int ret = it.first;
|
returnList.push_back(it.first);
|
||||||
// elementMap.erase(it.first);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::HandlePong(ServerPacket* const argPacket) {
|
void ClientManager::HandlePong(ServerPacket* const argPacket) {
|
||||||
//find and update the specified client
|
//find and update the specified client
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
if (it.second.GetAddress().host == argPacket->srcAddress.host &&
|
if (it.second.GetAddress() == argPacket->srcAddress) {
|
||||||
it.second.GetAddress().port == argPacket->srcAddress.port
|
|
||||||
) {
|
|
||||||
it.second.ResetAttempts();
|
it.second.ResetAttempts();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,13 @@
|
|||||||
#include "SDL/SDL_net.h"
|
#include "SDL/SDL_net.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class ClientManager: public Singleton<ClientManager> {
|
class ClientManager: public Singleton<ClientManager> {
|
||||||
public:
|
public:
|
||||||
//methods
|
//methods
|
||||||
int CheckConnections();
|
std::list<int> CheckConnections();
|
||||||
void HandlePong(ServerPacket* const argPacket);
|
void HandlePong(ServerPacket* const argPacket);
|
||||||
|
|
||||||
//common public methods
|
//common public methods
|
||||||
|
|||||||
+5
-2
@@ -37,8 +37,10 @@
|
|||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#include "entity_api.hpp"
|
#include "entity_api.hpp"
|
||||||
|
#include "character_system_api.hpp"
|
||||||
#include "map_system_api.hpp"
|
#include "map_system_api.hpp"
|
||||||
#include "monster_system_api.hpp"
|
#include "monster_system_api.hpp"
|
||||||
|
#include "network_api.hpp"
|
||||||
#include "room_system_api.hpp"
|
#include "room_system_api.hpp"
|
||||||
#include "waypoint_system_api.hpp"
|
#include "waypoint_system_api.hpp"
|
||||||
|
|
||||||
@@ -58,12 +60,13 @@ static const luaL_Reg loadedlibs[] = {
|
|||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//these libs are preloaded and must be required before used
|
//these libs are preloaded and must be required before used
|
||||||
static const luaL_Reg preloadedlibs[] = {
|
static const luaL_Reg preloadedlibs[] = {
|
||||||
{TORTUGA_ENTITY_API, openEntityAPI},
|
{TORTUGA_ENTITY_API, openEntityAPI}, //required by derived classes
|
||||||
|
{TORTUGA_CHARACTER_SYSTEM_API, openCharacterSystemAPI},
|
||||||
{TORTUGA_MAP_SYSTEM_API, openMapSystemAPI},
|
{TORTUGA_MAP_SYSTEM_API, openMapSystemAPI},
|
||||||
{TORTUGA_MONSTER_SYSTEM_API, openMonsterSystemAPI},
|
{TORTUGA_MONSTER_SYSTEM_API, openMonsterSystemAPI},
|
||||||
|
{TORTUGA_NETWORK_API, openNetworkAPI},
|
||||||
{TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI},
|
{TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI},
|
||||||
{TORTUGA_WAYPOINT_SYSTEM_API, openWaypointSystemAPI},
|
{TORTUGA_WAYPOINT_SYSTEM_API, openWaypointSystemAPI},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*/
|
||||||
|
#include "network_api.hpp"
|
||||||
|
|
||||||
|
static int pumpCharacterUpdate(lua_State* L) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg networkLib[] = {
|
||||||
|
{"PumpCharacterUpdate", pumpCharacterUpdate},
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
LUAMOD_API int openNetworkAPI(lua_State* L) {
|
||||||
|
luaL_newlib(L, networkLib);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013-2015
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*/
|
||||||
|
#ifndef NETWORKAPI_HPP_
|
||||||
|
#define NETWORKAPI_HPP_
|
||||||
|
|
||||||
|
#include "lua.hpp"
|
||||||
|
|
||||||
|
#define TORTUGA_NETWORK_API "network"
|
||||||
|
LUAMOD_API int openNetworkAPI(lua_State* L);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -65,6 +65,15 @@ static int getWaypointMgr(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: character list
|
||||||
|
|
||||||
|
static int setOnTick(lua_State* L) {
|
||||||
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, room->GetTickReference());
|
||||||
|
room->SetTickReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int initialize(lua_State* L) {
|
static int initialize(lua_State* L) {
|
||||||
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
|
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
|
||||||
@@ -88,6 +97,8 @@ static const luaL_Reg roomLib[] = {
|
|||||||
{"GetMonsterMgr",getMonsterMgr},
|
{"GetMonsterMgr",getMonsterMgr},
|
||||||
{"GetWaypointMgr",getWaypointMgr},
|
{"GetWaypointMgr",getWaypointMgr},
|
||||||
|
|
||||||
|
{"SetOnTick", setOnTick},
|
||||||
|
|
||||||
{"Initialize", initialize},
|
{"Initialize", initialize},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,22 @@
|
|||||||
*/
|
*/
|
||||||
#include "room_data.hpp"
|
#include "room_data.hpp"
|
||||||
|
|
||||||
|
void RoomData::RunFrame() {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
||||||
|
|
||||||
|
if (lua_isnil(lua, -1)) {
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the tick function, with this as a parameter
|
||||||
|
lua_pushlightuserdata(lua, this);
|
||||||
|
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string RoomData::SetName(std::string s) {
|
std::string RoomData::SetName(std::string s) {
|
||||||
return roomName = s;
|
return roomName = s;
|
||||||
}
|
}
|
||||||
@@ -52,3 +68,33 @@ WaypointManager* RoomData::GetWaypointMgr() {
|
|||||||
std::list<CharacterData*>* RoomData::GetCharacterList() {
|
std::list<CharacterData*>* RoomData::GetCharacterList() {
|
||||||
return &characterList;
|
return &characterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_State* RoomData::SetLuaState(lua_State* L) {
|
||||||
|
lua = L;
|
||||||
|
pager.SetLuaState(lua);
|
||||||
|
monsterMgr.SetLuaState(lua);
|
||||||
|
waypointMgr.SetLuaState(lua);
|
||||||
|
return lua;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State* RoomData::GetLuaState() {
|
||||||
|
return lua;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* RoomData::SetDatabase(sqlite3* db) {
|
||||||
|
database = db;
|
||||||
|
monsterMgr.SetDatabase(database);
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* RoomData::GetDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomData::SetTickReference(int i) {
|
||||||
|
return tickRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomData::GetTickReference() {
|
||||||
|
return tickRef;
|
||||||
|
}
|
||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
RoomData() = default;
|
RoomData() = default;
|
||||||
~RoomData() = default;
|
~RoomData() = default;
|
||||||
|
|
||||||
|
void RunFrame();
|
||||||
|
|
||||||
//accessors and mutators
|
//accessors and mutators
|
||||||
std::string SetName(std::string);
|
std::string SetName(std::string);
|
||||||
std::string GetName();
|
std::string GetName();
|
||||||
@@ -49,19 +51,34 @@ public:
|
|||||||
WaypointManager* GetWaypointMgr();
|
WaypointManager* GetWaypointMgr();
|
||||||
std::list<CharacterData*>* GetCharacterList();
|
std::list<CharacterData*>* GetCharacterList();
|
||||||
|
|
||||||
//TODO: triggers for unload, save, per-second, player enter, player exit, etc.
|
//API interfaces
|
||||||
|
lua_State* SetLuaState(lua_State* L);
|
||||||
|
lua_State* GetLuaState();
|
||||||
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int SetTickReference(int i);
|
||||||
|
int GetTickReference();
|
||||||
|
//TODO: other triggers like player entry & exit, etc.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RoomManager;
|
//metadata
|
||||||
|
|
||||||
//members
|
|
||||||
std::string roomName;
|
std::string roomName;
|
||||||
std::string tilesetName;
|
std::string tilesetName;
|
||||||
|
|
||||||
|
//members
|
||||||
RegionPagerLua pager;
|
RegionPagerLua pager;
|
||||||
MonsterManager monsterMgr;
|
MonsterManager monsterMgr;
|
||||||
WaypointManager waypointMgr;
|
WaypointManager waypointMgr;
|
||||||
std::list<CharacterData*> characterList;
|
std::list<CharacterData*> characterList;
|
||||||
|
|
||||||
|
//API
|
||||||
|
lua_State* lua = nullptr;
|
||||||
|
sqlite3* database = nullptr;
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int tickRef = LUA_NOREF;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,29 +35,79 @@ int RoomManager::Create(std::string roomName, std::string tileset) {
|
|||||||
newRoom->SetName(roomName);
|
newRoom->SetName(roomName);
|
||||||
newRoom->SetTileset(tileset);
|
newRoom->SetTileset(tileset);
|
||||||
|
|
||||||
newRoom->pager.SetLuaState(lua);
|
newRoom->SetLuaState(lua);
|
||||||
newRoom->monsterMgr.SetLuaState(lua);
|
newRoom->SetDatabase(database);
|
||||||
newRoom->monsterMgr.SetDatabase(database);
|
|
||||||
newRoom->waypointMgr.SetLuaState(lua);
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef);
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
lua_pushlightuserdata(lua, newRoom);
|
||||||
|
lua_pushinteger(lua, counter);
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//finish the routine
|
//finish the routine
|
||||||
return counter++;
|
return counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::UnloadAll() {
|
void RoomManager::UnloadAll() {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
//pass each room to the hook
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
lua_pushvalue(lua, -1); //copy the hook
|
||||||
|
lua_pushlightuserdata(lua, &it.second);
|
||||||
|
lua_pushinteger(lua, it.first);
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pop the hook or nil
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
|
||||||
elementMap.clear();
|
elementMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn) {
|
void RoomManager::UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn) {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
|
||||||
|
|
||||||
|
//get the element
|
||||||
std::map<int, RoomData>::iterator it = elementMap.begin();
|
std::map<int, RoomData>::iterator it = elementMap.begin();
|
||||||
|
|
||||||
|
//jenky pattern
|
||||||
while (it != elementMap.end()) {
|
while (it != elementMap.end()) {
|
||||||
if (fn(*it)) {
|
if (fn(*it)) {
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
lua_pushvalue(lua, -1); //copy the hook
|
||||||
|
lua_pushlightuserdata(lua, &it->second);
|
||||||
|
lua_pushinteger(lua, it->first);
|
||||||
|
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
it = elementMap.erase(it);
|
it = elementMap.erase(it);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pop the hook or nil
|
||||||
|
lua_pop(lua, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::PushCharacter(CharacterData* character) {
|
void RoomManager::PushCharacter(CharacterData* character) {
|
||||||
@@ -71,7 +121,7 @@ void RoomManager::PushCharacter(CharacterData* character) {
|
|||||||
throw(std::runtime_error("Failed to push an character to a non-existant room"));
|
throw(std::runtime_error("Failed to push an character to a non-existant room"));
|
||||||
}
|
}
|
||||||
|
|
||||||
room->characterList.push_back(character);
|
room->GetCharacterList()->push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::PopCharacter(CharacterData const* character) {
|
void RoomManager::PopCharacter(CharacterData const* character) {
|
||||||
@@ -86,7 +136,7 @@ void RoomManager::PopCharacter(CharacterData const* character) {
|
|||||||
throw(std::runtime_error("Failed to pop an character to a non-existant room"));
|
throw(std::runtime_error("Failed to pop an character to a non-existant room"));
|
||||||
}
|
}
|
||||||
|
|
||||||
room->characterList.remove_if([character](CharacterData* ptr) {
|
room->GetCharacterList()->remove_if([character](CharacterData* ptr) {
|
||||||
return character == ptr;
|
return character == ptr;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -119,7 +169,11 @@ std::map<int, RoomData>* RoomManager::GetContainer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lua_State* RoomManager::SetLuaState(lua_State* L) {
|
lua_State* RoomManager::SetLuaState(lua_State* L) {
|
||||||
return lua = L;
|
lua = L;
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
it.second.SetLuaState(lua);
|
||||||
|
}
|
||||||
|
return lua;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* RoomManager::GetLuaState() {
|
lua_State* RoomManager::GetLuaState() {
|
||||||
@@ -127,9 +181,29 @@ lua_State* RoomManager::GetLuaState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* RoomManager::SetDatabase(sqlite3* db) {
|
sqlite3* RoomManager::SetDatabase(sqlite3* db) {
|
||||||
return database = db;
|
database = db;
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
it.second.SetDatabase(database);
|
||||||
|
}
|
||||||
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* RoomManager::GetDatabase() {
|
sqlite3* RoomManager::GetDatabase() {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RoomManager::SetCreateReference(int i) {
|
||||||
|
return createRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::SetUnloadReference(int i) {
|
||||||
|
return unloadRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::GetCreateReference() {
|
||||||
|
return createRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::GetUnloadReference() {
|
||||||
|
return unloadRef;
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,12 +49,19 @@ public:
|
|||||||
int GetLoadedCount();
|
int GetLoadedCount();
|
||||||
std::map<int, RoomData>* GetContainer();
|
std::map<int, RoomData>* GetContainer();
|
||||||
|
|
||||||
//hooks
|
//API interfaces
|
||||||
lua_State* SetLuaState(lua_State* L);
|
lua_State* SetLuaState(lua_State* L);
|
||||||
lua_State* GetLuaState();
|
lua_State* GetLuaState();
|
||||||
sqlite3* SetDatabase(sqlite3* db);
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
sqlite3* GetDatabase();
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int SetCreateReference(int i);
|
||||||
|
int SetUnloadReference(int i);
|
||||||
|
|
||||||
|
int GetCreateReference();
|
||||||
|
int GetUnloadReference();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Singleton<RoomManager>;
|
friend Singleton<RoomManager>;
|
||||||
|
|
||||||
@@ -63,9 +70,15 @@ private:
|
|||||||
|
|
||||||
//members
|
//members
|
||||||
std::map<int, RoomData> elementMap;
|
std::map<int, RoomData> elementMap;
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
//API
|
||||||
lua_State* lua = nullptr;
|
lua_State* lua = nullptr;
|
||||||
sqlite3* database = nullptr;
|
sqlite3* database = nullptr;
|
||||||
int counter = 0;
|
|
||||||
|
//hooks
|
||||||
|
int createRef = LUA_NOREF;
|
||||||
|
int unloadRef = LUA_NOREF;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,10 +96,26 @@ int getRoom(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setOnCreate(lua_State* L) {
|
||||||
|
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetCreateReference());
|
||||||
|
roomMgr.SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnUnload(lua_State* L) {
|
||||||
|
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetUnloadReference());
|
||||||
|
roomMgr.SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg roomManagerLib[] = {
|
static const luaL_Reg roomManagerLib[] = {
|
||||||
{"CreateRoom", createRoom},
|
{"CreateRoom", createRoom},
|
||||||
{"UnloadRoom", unloadRoom},
|
{"UnloadRoom", unloadRoom},
|
||||||
{"GetRoom", getRoom},
|
{"GetRoom", getRoom},
|
||||||
|
{"SetOnCreate", setOnCreate},
|
||||||
|
{"SetOnUnload", setOnUnload},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+31
-10
@@ -28,6 +28,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -161,9 +162,16 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Proc() {
|
void ServerApplication::Proc() {
|
||||||
|
//network buffer
|
||||||
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
||||||
memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer
|
memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer
|
||||||
|
|
||||||
|
//time system
|
||||||
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
|
Clock::time_point simTime = Clock::now();
|
||||||
|
Clock::time_point realTime;
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
//suck in the waiting packets & process them
|
//suck in the waiting packets & process them
|
||||||
while(network.Receive(packetBuffer)) {
|
while(network.Receive(packetBuffer)) {
|
||||||
@@ -173,21 +181,34 @@ void ServerApplication::Proc() {
|
|||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
memset(packetBuffer, 0, MAX_PACKET_SIZE); //reset the buffer
|
//reset the buffer
|
||||||
}
|
memset(packetBuffer, 0, MAX_PACKET_SIZE);
|
||||||
//update the internals
|
|
||||||
//...
|
|
||||||
|
|
||||||
//Check connections
|
|
||||||
int disconnected = clientMgr.CheckConnections();
|
|
||||||
if (disconnected != -1) {
|
|
||||||
FullClientUnload(disconnected);
|
|
||||||
std::cerr << "Client dropped: " << disconnected << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check client connections
|
||||||
|
std::list<int> disconnections = clientMgr.CheckConnections();
|
||||||
|
for(auto const& it : disconnections) {
|
||||||
|
FullClientUnload(it);
|
||||||
|
std::cerr << "Client dropped: " << it << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//"tick" the internals
|
||||||
|
realTime = Clock::now();
|
||||||
|
|
||||||
|
if (simTime < realTime) {
|
||||||
|
while(simTime < realTime) {
|
||||||
|
for (auto& it : *roomMgr.GetContainer()) {
|
||||||
|
it.second.RunFrame();
|
||||||
|
}
|
||||||
|
//~60 FPS
|
||||||
|
simTime += std::chrono::duration<int, std::milli>(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
//give the machine a break
|
//give the machine a break
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
delete reinterpret_cast<char*>(packetBuffer);
|
delete reinterpret_cast<char*>(packetBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
TODO: upgrade to lua 5.3
|
||||||
|
TODO: Split config.cfg in two, one for the server and the client
|
||||||
|
|
||||||
TODO: In need of script APIs (list)
|
TODO: In need of script APIs (list)
|
||||||
* Characters
|
* Characters
|
||||||
|
|
||||||
@@ -9,7 +12,6 @@ TODO: Account passwords (list)
|
|||||||
|
|
||||||
TODO: Features
|
TODO: Features
|
||||||
* Make sure login errors are sent to the client
|
* Make sure login errors are sent to the client
|
||||||
* Split config.cfg in two, one for the server and the client
|
|
||||||
* Add the "home" parameter to the server's config file
|
* Add the "home" parameter to the server's config file
|
||||||
* Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc.
|
* Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc.
|
||||||
* Fix shoddy movement
|
* Fix shoddy movement
|
||||||
|
|||||||
Reference in New Issue
Block a user