Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48bec25336 | |||
| 39f03b2da8 | |||
| 9a5c447d0c | |||
| 29ccb982e6 | |||
| 0efb541074 | |||
| 4ae58550b5 | |||
| d82e3a8b79 | |||
| 954213f1ff | |||
| d2bb3575fc | |||
| ca6afb72ad | |||
| 670ab22e96 | |||
| 4d71d4cc40 | |||
| 81b3769188 | |||
| c3c6d42a80 | |||
| 3d8ee25ae7 | |||
| decc77e21c | |||
| 501b1e9814 | |||
| 01502372c9 | |||
| a8c309ec9d | |||
| 41d6314beb | |||
| 74ed93ddc7 | |||
| 18a7143926 | |||
| bd68af5875 | |||
| b8806cc209 | |||
| edcb6f05ce | |||
| cb63c9b07c | |||
| a00ddb3142 | |||
| 3431d323e5 | |||
| 84c4dd0497 | |||
| 3e6a05307e | |||
| c45bda645b | |||
| 1210d2d24f | |||
| 4630b7e403 | |||
| 067bf40be7 | |||
| d8045ae339 | |||
| 46df0f17b7 | |||
| ddedc06e47 | |||
| 6a999a8a72 | |||
| 8a97cb8c2c | |||
| e011e6bdc5 | |||
| a106134dd1 | |||
| a538cf73d5 | |||
| b273b4c04a | |||
| 248d142c2b | |||
| 2cc7260552 |
@@ -169,6 +169,7 @@ void ClientApplication::Quit() {
|
||||
//-------------------------
|
||||
|
||||
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||
//BUG: #16 Resources are being reloaded between scenes
|
||||
UnloadScene();
|
||||
switch(sceneIndex) {
|
||||
//add scene creation calls here
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "config_utility.hpp"
|
||||
|
||||
void BaseMonster::CorrectSprite() {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) BaseMonster::CorrectSprite()
|
||||
}
|
||||
|
||||
std::string BaseMonster::SetHandle(std::string s) {
|
||||
|
||||
@@ -96,6 +96,7 @@ protected:
|
||||
void UpdateMap();
|
||||
|
||||
//character management
|
||||
void hCharacterUpdate(CharacterPacket* const);
|
||||
void hCharacterCreate(CharacterPacket* const);
|
||||
void hCharacterDelete(CharacterPacket* const);
|
||||
void hQueryCharacterExists(CharacterPacket* const);
|
||||
|
||||
@@ -35,6 +35,24 @@
|
||||
//DOCS: new characters will result in create messages
|
||||
//DOCS: this client's character will exist in both (skipped)
|
||||
|
||||
void World::hCharacterUpdate(CharacterPacket* const argPacket) {
|
||||
//TODO: (1) Authentication
|
||||
//NOTE: applies to the local character too
|
||||
|
||||
//check that this character exists
|
||||
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
|
||||
if (characterIt != characterMap.end()) {
|
||||
//update the origin and motion, if there's a difference
|
||||
if (characterIt->second.GetOrigin() != argPacket->origin) {
|
||||
characterIt->second.SetOrigin(argPacket->origin);
|
||||
}
|
||||
if (characterIt->second.GetMotion() != argPacket->motion) {
|
||||
characterIt->second.SetMotion(argPacket->motion);
|
||||
characterIt->second.CorrectSprite(); //only correct the sprite if the motion changes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
//prevent double message
|
||||
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
|
||||
@@ -49,25 +67,35 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
BaseCharacter* character = &characterMap[argPacket->characterIndex];
|
||||
|
||||
//fill the character's info
|
||||
character->SetOrigin(argPacket->origin);
|
||||
character->SetMotion(argPacket->motion);
|
||||
character->SetBounds({CHARACTER_BOUNDS_X, CHARACTER_BOUNDS_Y, CHARACTER_BOUNDS_WIDTH, CHARACTER_BOUNDS_HEIGHT}); //TODO: (1) send the bounds from the server
|
||||
character->SetHandle(argPacket->handle);
|
||||
character->SetAvatar(argPacket->avatar);
|
||||
character->SetOwner(argPacket->accountIndex);
|
||||
character->SetOrigin(argPacket->origin);
|
||||
character->SetMotion(argPacket->motion);
|
||||
character->SetBounds(argPacket->bounds);
|
||||
|
||||
character->CorrectSprite();
|
||||
|
||||
//check for this player's character
|
||||
if (character->GetOwner() == accountIndex) {
|
||||
localCharacter = static_cast<LocalCharacter*>(character);
|
||||
|
||||
//focus the camera on this character
|
||||
//focus the camera on this character's sprite
|
||||
camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
||||
camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
||||
|
||||
//focus on this character's info
|
||||
characterIndex = argPacket->characterIndex;
|
||||
roomIndex = argPacket->roomIndex;
|
||||
|
||||
//query the world state (room)
|
||||
CharacterPacket newPacket;
|
||||
memset(&newPacket, 0, MAX_PACKET_SIZE);
|
||||
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
newPacket.roomIndex = roomIndex;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
}
|
||||
|
||||
//debug
|
||||
@@ -91,10 +119,14 @@ void World::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||
|
||||
//clear the room
|
||||
roomIndex = -1;
|
||||
regionPager.UnloadAll();
|
||||
characterMap.clear();
|
||||
monsterMap.clear();
|
||||
}
|
||||
else {
|
||||
//remove this character
|
||||
characterMap.erase(characterIt);
|
||||
}
|
||||
|
||||
//remove this character
|
||||
characterMap.erase(characterIt);
|
||||
|
||||
//debug
|
||||
std::cout << "Character Delete, total: " << characterMap.size() << std::endl;
|
||||
@@ -102,9 +134,9 @@ void World::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||
|
||||
void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
||||
//prevent a double message about this player's character
|
||||
if (argPacket->accountIndex == accountIndex) {
|
||||
return;
|
||||
}
|
||||
// if (argPacket->accountIndex == accountIndex) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
//ignore characters in a different room (sub-optimal)
|
||||
if (argPacket->roomIndex != roomIndex) {
|
||||
@@ -128,11 +160,11 @@ void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hQueryCharacterStats()
|
||||
}
|
||||
|
||||
void World::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hQueryCharacterLocation()
|
||||
}
|
||||
|
||||
void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
@@ -152,11 +184,11 @@ void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hCharacterAttack(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hCharacterAttack()
|
||||
}
|
||||
|
||||
void World::hCharacterDamage(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hCharacterDamage()
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
//-------------------------
|
||||
|
||||
void World::hTextBroadcast(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hTextBroadcast()
|
||||
}
|
||||
|
||||
void World::hTextSpeech(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hTextSpeech()
|
||||
}
|
||||
|
||||
void World::hTextWhisper(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hTextWhisper()
|
||||
}
|
||||
|
||||
|
||||
@@ -91,10 +91,9 @@ void World::SendDisconnectRequest() {
|
||||
}
|
||||
|
||||
void World::SendAdminDisconnectForced() {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::SendAdminDisconnectForced()
|
||||
}
|
||||
|
||||
|
||||
void World::SendAdminShutdownRequest() {
|
||||
ClientPacket newPacket;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
|
||||
shutDownButton.SetText("Shut Down");
|
||||
|
||||
//load the tilesheet
|
||||
//TODO: (1) Tile size and tile sheet should be loaded elsewhere
|
||||
//TODO: (2) Tile size and tile sheet should be loaded elsewhere
|
||||
tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32);
|
||||
|
||||
//Send the character data
|
||||
@@ -71,13 +71,6 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
|
||||
newPacket.accountIndex = accountIndex;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
|
||||
//query the world state
|
||||
memset(&newPacket, 0, MAX_PACKET_SIZE);
|
||||
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS;
|
||||
network.SendTo(Channels::SERVER, &newPacket);
|
||||
|
||||
//set the camera's values
|
||||
camera.width = GetScreen()->w;
|
||||
camera.height = GetScreen()->h;
|
||||
@@ -173,7 +166,7 @@ void World::Render(SDL_Surface* const screen) {
|
||||
|
||||
//draw the entities
|
||||
for (auto& it : characterMap) {
|
||||
//TODO: (1) depth ordering
|
||||
//BUG: #29 Characters (and other entities) are drawn out of order
|
||||
it.second.DrawTo(screen, camera.x, camera.y);
|
||||
}
|
||||
for (auto& it : monsterMap) {
|
||||
@@ -221,7 +214,7 @@ void World::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//hotkeys
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
//TODO: (1) the escape key should actually control menus and stuff
|
||||
//TODO: (3) the escape key should actually control menus and stuff
|
||||
SendLogoutRequest();
|
||||
return;
|
||||
}
|
||||
@@ -335,6 +328,9 @@ void World::HandlePacket(SerialPacket* const argPacket) {
|
||||
break;
|
||||
|
||||
//character management
|
||||
case SerialPacketType::CHARACTER_UPDATE:
|
||||
hCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_CREATE:
|
||||
hCharacterCreate(static_cast<CharacterPacket*>(argPacket));
|
||||
break;
|
||||
|
||||
@@ -99,11 +99,11 @@ void World::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hQueryMonsterStats()
|
||||
}
|
||||
|
||||
void World::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hQueryMonsterLocation()
|
||||
}
|
||||
|
||||
void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
||||
@@ -118,9 +118,9 @@ void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void World::hMonsterAttack(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hMonsterAttack()
|
||||
}
|
||||
|
||||
void World::hMonsterDamage(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) World::hMonsterDamage()
|
||||
}
|
||||
@@ -107,7 +107,8 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
|
||||
join.DrawTo(screen);
|
||||
back.DrawTo(screen);
|
||||
|
||||
//TODO: (1) draw headers for the server list
|
||||
//TODO: (3) draw headers for the server list
|
||||
//TODO: (3) ping/delay displayed in the server list
|
||||
for (int i = 0; i < serverInfo.size(); i++) {
|
||||
//draw the selected server's highlight
|
||||
if (selection == &serverInfo[i]) {
|
||||
@@ -252,11 +253,11 @@ void LobbyMenu::HandleLoginResponse(ClientPacket* const argPacket) {
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) LobbyMenu::HandleJoinRejection()
|
||||
}
|
||||
|
||||
void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) LobbyMenu::HandleLoginRejection
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/* 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 "map_system_api.hpp"
|
||||
|
||||
//all map API headers
|
||||
#include "region_api.hpp"
|
||||
#include "region_pager_api.hpp"
|
||||
|
||||
//useful "globals"
|
||||
//...
|
||||
|
||||
//This mimics linit.c to create a nested collection of all map modules.
|
||||
static const luaL_Reg funcs[] = {
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const luaL_Reg libs[] = {
|
||||
{"Region", openRegionAPI},
|
||||
{"RegionPager", openRegionPagerAPI},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
int openMapSystemAPI(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;
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_REGION_NAME "region"
|
||||
#define TORTUGA_REGION_API "region"
|
||||
LUAMOD_API int openRegionAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "region.hpp"
|
||||
|
||||
//DOCS: These glue functions simply wrap RegionPagerLua's methods
|
||||
//NOTE: zero indexing is used here, but not in the region API
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_REGION_PAGER_NAME "region_pager"
|
||||
#define TORTUGA_REGION_PAGER_API "region_pager"
|
||||
LUAMOD_API int openRegionPagerAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,11 +36,18 @@ void serializeCharacter(void* buffer, CharacterPacket* packet) {
|
||||
|
||||
//location
|
||||
serialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
||||
|
||||
serialCopy(&buffer, &packet->origin.x, sizeof(double));
|
||||
serialCopy(&buffer, &packet->origin.y, sizeof(double));
|
||||
|
||||
serialCopy(&buffer, &packet->motion.x, sizeof(double));
|
||||
serialCopy(&buffer, &packet->motion.y, sizeof(double));
|
||||
|
||||
serialCopy(&buffer, &packet->bounds.x, sizeof(int));
|
||||
serialCopy(&buffer, &packet->bounds.y, sizeof(int));
|
||||
serialCopy(&buffer, &packet->bounds.w, sizeof(int));
|
||||
serialCopy(&buffer, &packet->bounds.h, sizeof(int));
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
}
|
||||
|
||||
@@ -57,10 +64,17 @@ void deserializeCharacter(void* buffer, CharacterPacket* packet) {
|
||||
|
||||
//location
|
||||
deserialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
||||
|
||||
deserialCopy(&buffer, &packet->origin.x, sizeof(double));
|
||||
deserialCopy(&buffer, &packet->origin.y, sizeof(double));
|
||||
|
||||
deserialCopy(&buffer, &packet->motion.x, sizeof(double));
|
||||
deserialCopy(&buffer, &packet->motion.y, sizeof(double));
|
||||
|
||||
deserialCopy(&buffer, &packet->bounds.x, sizeof(int));
|
||||
deserialCopy(&buffer, &packet->bounds.y, sizeof(int));
|
||||
deserialCopy(&buffer, &packet->bounds.w, sizeof(int));
|
||||
deserialCopy(&buffer, &packet->bounds.h, sizeof(int));
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "serial_packet_base.hpp"
|
||||
|
||||
#include "bounding_box.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
struct CharacterPacket : SerialPacketBase {
|
||||
@@ -39,6 +40,7 @@ struct CharacterPacket : SerialPacketBase {
|
||||
int roomIndex;
|
||||
Vector2 origin;
|
||||
Vector2 motion;
|
||||
BoundingBox bounds;
|
||||
};
|
||||
|
||||
void serializeCharacter(void* buffer, CharacterPacket* packet);
|
||||
|
||||
@@ -28,7 +28,7 @@ struct ClientPacket : SerialPacketBase {
|
||||
int clientIndex;
|
||||
int accountIndex;
|
||||
char username[PACKET_STRING_SIZE];
|
||||
//TODO: (9) password, auth token
|
||||
//TODO: (3) password, auth token
|
||||
};
|
||||
|
||||
void serializeClient(void* buffer, ClientPacket* packet);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
typedef SerialPacketBase SerialPacket;
|
||||
|
||||
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
|
||||
constexpr int NETWORK_VERSION = 20150214;
|
||||
constexpr int NETWORK_VERSION = 20150304;
|
||||
|
||||
union MaxPacket {
|
||||
CharacterPacket a;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
/* DOCS: The headers indicate what packet type is used for each message
|
||||
* different messages under the same header will carry different amounts of
|
||||
* 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 {
|
||||
@@ -36,6 +37,8 @@ enum class SerialPacketType {
|
||||
// name, player count, version
|
||||
//-------------------------
|
||||
|
||||
FORMAT_SERVER,
|
||||
|
||||
//heartbeat
|
||||
PING,
|
||||
PONG,
|
||||
@@ -44,11 +47,15 @@ enum class SerialPacketType {
|
||||
BROADCAST_REQUEST,
|
||||
BROADCAST_RESPONSE,
|
||||
|
||||
FORMAT_END_SERVER,
|
||||
|
||||
//-------------------------
|
||||
//ClientPacket
|
||||
// client index, account index, username
|
||||
//-------------------------
|
||||
|
||||
FORMAT_CLIENT,
|
||||
|
||||
//Connecting to a server as a client
|
||||
JOIN_REQUEST,
|
||||
JOIN_RESPONSE,
|
||||
@@ -69,15 +76,21 @@ enum class SerialPacketType {
|
||||
//shut down the server
|
||||
ADMIN_SHUTDOWN_REQUEST,
|
||||
|
||||
FORMAT_END_CLIENT,
|
||||
|
||||
//-------------------------
|
||||
//RegionPacket
|
||||
// room index, x, y, raw data
|
||||
//-------------------------
|
||||
|
||||
FORMAT_REGION,
|
||||
|
||||
//map data
|
||||
REGION_REQUEST,
|
||||
REGION_CONTENT,
|
||||
|
||||
FORMAT_END_REGION,
|
||||
|
||||
//-------------------------
|
||||
//CharacterPacket
|
||||
// character index,
|
||||
@@ -86,6 +99,11 @@ enum class SerialPacketType {
|
||||
// room index, origin, motion
|
||||
//-------------------------
|
||||
|
||||
FORMAT_CHARACTER,
|
||||
|
||||
//full data update
|
||||
CHARACTER_UPDATE,
|
||||
|
||||
//character management
|
||||
CHARACTER_CREATE,
|
||||
CHARACTER_DELETE,
|
||||
@@ -97,7 +115,7 @@ enum class SerialPacketType {
|
||||
QUERY_CHARACTER_STATS,
|
||||
QUERY_CHARACTER_LOCATION,
|
||||
|
||||
//set the info in the server
|
||||
//actions taken
|
||||
CHARACTER_MOVEMENT,
|
||||
CHARACTER_ATTACK,
|
||||
CHARACTER_DAMAGE,
|
||||
@@ -105,6 +123,8 @@ enum class SerialPacketType {
|
||||
//admin control
|
||||
// ADMIN_SET_CHARACTER_ORIGIN,
|
||||
|
||||
FORMAT_END_CHARACTER,
|
||||
|
||||
//-------------------------
|
||||
//MonsterPacket
|
||||
// monster index,
|
||||
@@ -113,22 +133,34 @@ enum class SerialPacketType {
|
||||
// room index, origin, motion
|
||||
//-------------------------
|
||||
|
||||
FORMAT_MONSTER,
|
||||
|
||||
//full data update
|
||||
MONSTER_UPDATE,
|
||||
|
||||
//character management
|
||||
MONSTER_CREATE,
|
||||
MONSTER_DELETE,
|
||||
|
||||
//find out info from the server
|
||||
QUERY_MONSTER_EXISTS,
|
||||
QUERY_MONSTER_STATS,
|
||||
QUERY_MONSTER_LOCATION,
|
||||
|
||||
//actions taken
|
||||
MONSTER_MOVEMENT,
|
||||
MONSTER_ATTACK,
|
||||
MONSTER_DAMAGE,
|
||||
|
||||
FORMAT_END_MONSTER,
|
||||
|
||||
//-------------------------
|
||||
//TextPacket
|
||||
// name, text
|
||||
//-------------------------
|
||||
|
||||
FORMAT_TEXT,
|
||||
|
||||
//general speech
|
||||
TEXT_BROADCAST,
|
||||
TEXT_SPEECH,
|
||||
@@ -143,6 +175,8 @@ enum class SerialPacketType {
|
||||
SHUTDOWN_REJECTION,
|
||||
QUERY_REJECTION,
|
||||
|
||||
FORMAT_END_TEXT,
|
||||
|
||||
//-------------------------
|
||||
//not used
|
||||
//-------------------------
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
//macros
|
||||
#define BOUNDS(type, lower, upper) ((type) > (lower) && (type) < (upper))
|
||||
|
||||
//raw memory copy
|
||||
void serialCopy(void** buffer, void* data, int size) {
|
||||
memcpy(*buffer, data, size);
|
||||
@@ -46,63 +49,28 @@ void deserialCopy(void** buffer, void* data, int size) {
|
||||
|
||||
//main switch functions
|
||||
void serializePacket(void* buffer, SerialPacketBase* packet) {
|
||||
switch(packet->type) {
|
||||
case SerialPacketType::PING:
|
||||
case SerialPacketType::PONG:
|
||||
case SerialPacketType::BROADCAST_REQUEST:
|
||||
case SerialPacketType::BROADCAST_RESPONSE:
|
||||
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||
break;
|
||||
case SerialPacketType::JOIN_REQUEST:
|
||||
case SerialPacketType::JOIN_RESPONSE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::REGION_REQUEST:
|
||||
case SerialPacketType::REGION_CONTENT:
|
||||
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_CREATE:
|
||||
case SerialPacketType::CHARACTER_DELETE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_CREATE:
|
||||
case SerialPacketType::MONSTER_DELETE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::TEXT_BROADCAST:
|
||||
case SerialPacketType::TEXT_SPEECH:
|
||||
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));
|
||||
break;
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||
serializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||
serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(packet->type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||
serializeText(buffer, static_cast<TextPacket*>(packet));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,62 +79,27 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
|
||||
SerialPacketType type;
|
||||
memcpy(&type, buffer, sizeof(SerialPacketType));
|
||||
|
||||
switch(type) {
|
||||
case SerialPacketType::PING:
|
||||
case SerialPacketType::PONG:
|
||||
case SerialPacketType::BROADCAST_REQUEST:
|
||||
case SerialPacketType::BROADCAST_RESPONSE:
|
||||
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||
break;
|
||||
case SerialPacketType::JOIN_REQUEST:
|
||||
case SerialPacketType::JOIN_RESPONSE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::REGION_REQUEST:
|
||||
case SerialPacketType::REGION_CONTENT:
|
||||
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||
break;
|
||||
case SerialPacketType::CHARACTER_CREATE:
|
||||
case SerialPacketType::CHARACTER_DELETE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::MONSTER_CREATE:
|
||||
case SerialPacketType::MONSTER_DELETE:
|
||||
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));
|
||||
break;
|
||||
case SerialPacketType::TEXT_BROADCAST:
|
||||
case SerialPacketType::TEXT_SPEECH:
|
||||
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));
|
||||
break;
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||
deserializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||
}
|
||||
|
||||
if (BOUNDS(type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||
deserializeText(buffer, static_cast<TextPacket*>(packet));
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ release: clean all package
|
||||
#For use on my machine ONLY
|
||||
package:
|
||||
rar a -r -ep Tortuga.rar $(OUTDIR)/*.exe $(OUTDIR)/*.dll
|
||||
rar a -r Tortuga.rar rsc/* copyright.txt README.txt
|
||||
rar a -r Tortuga.rar rsc/* copyright.txt instructions.txt
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
local doorUtility = {}
|
||||
|
||||
roomAPI = require("room")
|
||||
regionPagerAPI = require("region_pager")
|
||||
|
||||
triggerAPI = require("trigger")
|
||||
triggerManagerAPI = require("trigger_manager")
|
||||
|
||||
entityAPI = require("entity")
|
||||
characterAPI = require("character")
|
||||
|
||||
networkAPI = require("network")
|
||||
|
||||
function doorUtility.createTrigger(handle, room, x, y, script)
|
||||
local pager = roomAPI.GetPager(room)
|
||||
|
||||
--place the indicator tile
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 0, mapMaker.dirt)
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 1, mapMaker.blank)
|
||||
regionPagerAPI.SetTile(pager, x / 32, y / 32, 2, mapMaker.blank)
|
||||
|
||||
--create the trigger object
|
||||
triggerManagerAPI.Create(
|
||||
roomAPI.GetTriggerMgr(room), handle, x, y,
|
||||
0, 0, 32, 32, --size of the tiles
|
||||
script
|
||||
)
|
||||
end
|
||||
|
||||
function doorUtility.createDoorPair(handle, roomOne, Xone, Yone, roomTwo, Xtwo, Ytwo)
|
||||
--create the scripts
|
||||
local function scriptOne(entity)
|
||||
if entityAPI.GetType(entity) ~= "character" then return end
|
||||
|
||||
--move the character
|
||||
characterAPI.SetRoom(entity, roomTwo)
|
||||
characterAPI.SetOrigin(entity, Xtwo, Ytwo-16)
|
||||
networkAPI.PumpCharacterUpdate(entity)
|
||||
|
||||
--disable the other trigger
|
||||
local triggerTwo = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomTwo), handle)
|
||||
triggerAPI.PushExclusionEntity(triggerTwo, entity)
|
||||
end
|
||||
|
||||
local function scriptTwo(entity)
|
||||
if entityAPI.GetType(entity) ~= "character" then return end
|
||||
|
||||
--move the character
|
||||
characterAPI.SetRoom(entity, roomOne)
|
||||
characterAPI.SetOrigin(entity, Xone, Yone-16) --NOTE: the 16 pixel margin for presentation
|
||||
networkAPI.PumpCharacterUpdate(entity)
|
||||
|
||||
--disable the other trigger
|
||||
local triggerOne = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomOne), handle)
|
||||
triggerAPI.PushExclusionEntity(triggerOne, entity)
|
||||
end
|
||||
|
||||
--create the triggers proper
|
||||
doorUtility.createTrigger(handle, roomOne, Xone, Yone, scriptOne)
|
||||
doorUtility.createTrigger(handle, roomTwo, Xtwo, Ytwo, scriptTwo)
|
||||
end
|
||||
|
||||
return doorUtility
|
||||
+39
-25
@@ -1,4 +1,4 @@
|
||||
local Region = require("map_system").Region
|
||||
local regionAPI = require("region")
|
||||
|
||||
local mapMaker = {}
|
||||
|
||||
@@ -7,6 +7,7 @@ function mapMaker.Sqr(x) return x*x end
|
||||
function mapMaker.Dist(x, y, i, j) return math.sqrt(mapMaker.Sqr(x - i) + mapMaker.Sqr(y - j)) end
|
||||
|
||||
--tile macros, mapped to the tilesheet "overworld.bmp"
|
||||
mapMaker.blank = 0
|
||||
mapMaker.water = 18 + 3 * 0
|
||||
mapMaker.sand = 18 + 3 * 1
|
||||
mapMaker.plains = 18 + 3 * 2
|
||||
@@ -20,42 +21,43 @@ mapMaker.edges.south = 16
|
||||
mapMaker.edges.east = 1
|
||||
mapMaker.edges.west = -1
|
||||
|
||||
--TODO: (1) path system
|
||||
--use these macros (mapped to "overworld.bmp" for now) to smooth the region's edges
|
||||
function mapMaker.SmoothEdgesSimple(r)
|
||||
--make and pad an array to use
|
||||
local shiftArray = {}
|
||||
for i = 1, Region.GetWidth(r) do
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
shiftArray[i] = {}
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
shiftArray[i][j] = 0
|
||||
end
|
||||
end
|
||||
|
||||
--build the array
|
||||
for i = 1, Region.GetWidth(r) do
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
--if (not region edge) and (west tile < this tile), etc.
|
||||
if i > 1 and Region.GetTile(r, i - 1, j, 1) < Region.GetTile(r, i, j, 1) then
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
--if (not regionAPI edge) and (west tile < this tile), etc.
|
||||
if i > 1 and regionAPI.GetTile(r, i - 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.west
|
||||
end
|
||||
if j > 1 and Region.GetTile(r, i, j - 1, 1) < Region.GetTile(r, i, j, 1) then
|
||||
if j > 1 and regionAPI.GetTile(r, i, j - 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.north
|
||||
end
|
||||
if i < Region.GetWidth(r) and Region.GetTile(r, i + 1, j, 1) < Region.GetTile(r, i, j, 1) then
|
||||
if i < regionAPI.GetWidth(r) and regionAPI.GetTile(r, i + 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.east
|
||||
end
|
||||
if j < Region.GetHeight(r) and Region.GetTile(r, i, j + 1, 1) < Region.GetTile(r, i, j, 1) then
|
||||
if j < regionAPI.GetHeight(r) and regionAPI.GetTile(r, i, j + 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.south
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--finally apply this
|
||||
for i = 1, Region.GetWidth(r) do
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
if shiftArray[i][j] ~= 0 then
|
||||
Region.SetTile(r, i, j, 2, Region.GetTile(r, i, j, 1) + shiftArray[i][j])
|
||||
Region.SetTile(r, i, j, 1, Region.GetTile(r, i, j, 1) - 3)
|
||||
regionAPI.SetTile(r, i, j, 2, regionAPI.GetTile(r, i, j, 1) + shiftArray[i][j])
|
||||
regionAPI.SetTile(r, i, j, 1, regionAPI.GetTile(r, i, j, 1) - 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -64,27 +66,27 @@ end
|
||||
--custom generation systems here
|
||||
function mapMaker.DebugIsland(r)
|
||||
--basic distance check for each tile, placing an island around the world origin
|
||||
for i = 1, Region.GetWidth(r) do
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
local dist = mapMaker.Dist(0, 0, i + Region.GetX(r) -1, j + Region.GetY(r) -1)
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
local dist = mapMaker.Dist(0, 0, i + regionAPI.GetX(r) -1, j + regionAPI.GetY(r) -1)
|
||||
if dist < 10 then
|
||||
Region.SetTile(r, i, j, 1, mapMaker.plains)
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.plains)
|
||||
elseif dist < 12 then
|
||||
Region.SetTile(r, i, j, 1, mapMaker.sand)
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.sand)
|
||||
else
|
||||
Region.SetTile(r, i, j, 1, mapMaker.water)
|
||||
Region.SetSolid(r, i, j, true)
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.water)
|
||||
regionAPI.SetSolid(r, i, j, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--examples of the smoothing function NOT working correctly
|
||||
--[[
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
Region.SetTile(r, 3, j, 1, mapMaker.dirt)
|
||||
Region.SetTile(r, 4, j, 1, mapMaker.dirt)
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
regionAPI.SetTile(r, 3, j, 1, mapMaker.dirt)
|
||||
regionAPI.SetTile(r, 4, j, 1, mapMaker.dirt)
|
||||
|
||||
Region.SetTile(r, 10, j, 1, mapMaker.dirt)
|
||||
regionAPI.SetTile(r, 10, j, 1, mapMaker.dirt)
|
||||
end
|
||||
--]]
|
||||
|
||||
@@ -92,4 +94,16 @@ function mapMaker.DebugIsland(r)
|
||||
mapMaker.SmoothEdgesSimple(r)
|
||||
end
|
||||
|
||||
function mapMaker.DebugGrassland(r)
|
||||
--all dirt
|
||||
for i = 1, regionAPI.GetWidth(r) do
|
||||
for j = 1, regionAPI.GetHeight(r) do
|
||||
regionAPI.SetTile(r, i, j, 1, mapMaker.grass)
|
||||
end
|
||||
end
|
||||
|
||||
--A generic edge system
|
||||
-- mapMaker.SmoothEdgesSimple(r)
|
||||
end
|
||||
|
||||
return mapMaker
|
||||
@@ -1,15 +1,15 @@
|
||||
local Region = require("map_system").Region
|
||||
local region = require("region")
|
||||
|
||||
local mapSaver = {}
|
||||
|
||||
function mapSaver.Load(r)
|
||||
--empty
|
||||
io.write("map_saver:Load(", Region.GetX(r), ", ", Region.GetY(r), ")\n")
|
||||
io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||
end
|
||||
function mapSaver.Save(r)
|
||||
--empty
|
||||
io.write("map_saver:Save(", Region.GetX(r), ", ", Region.GetY(r), ")\n")
|
||||
io.write("map_saver:Save(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||
end
|
||||
|
||||
--TODO: (9) create a flexible saving & loading system
|
||||
--TODO: (3) create a flexible saving & loading system
|
||||
return mapSaver
|
||||
@@ -1,18 +1,36 @@
|
||||
print("Lua script check")
|
||||
|
||||
--requirements
|
||||
roomManagerAPI = require("room_manager")
|
||||
roomAPI = require("room")
|
||||
|
||||
mapMaker = require("map_maker")
|
||||
mapSaver = require("map_saver")
|
||||
roomSystem = require("room_system")
|
||||
|
||||
local function dumpTable(t)
|
||||
print(t)
|
||||
for k, v in pairs(t) do
|
||||
print("",k,v)
|
||||
end
|
||||
end
|
||||
doorUtility = require("door_utility")
|
||||
|
||||
--test the room hooks
|
||||
roomManagerAPI.SetOnCreate(function(room, index)
|
||||
print("", "Creating room: ", roomAPI.GetName(room), index)
|
||||
|
||||
roomAPI.SetOnTick(room, function(room)
|
||||
roomAPI.ForEachCharacter(room, function(character)
|
||||
--
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
roomManagerAPI.SetOnUnload(function(room, index)
|
||||
print("", "Unloading room: ", roomAPI.GetName(room), index)
|
||||
end)
|
||||
|
||||
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
||||
local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld", "overworld.bmp")
|
||||
roomSystem.Room.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
||||
local overworld, uidOne = roomManagerAPI.CreateRoom("overworld", "overworld.bmp")
|
||||
roomAPI.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
||||
local underworld, uidTwo = roomManagerAPI.CreateRoom("underworld", "overworld.bmp")
|
||||
roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save)
|
||||
|
||||
--call the monstrosity
|
||||
doorUtility.createDoorPair("pair 1", overworld, 0, -64, underworld, 0, 0)
|
||||
|
||||
print("Finished the lua script")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
--TODO: (9) An archive table of all dead characters
|
||||
--TODO: (3) An archive table of all dead characters
|
||||
|
||||
CREATE TABLE IF NOT EXISTS Accounts (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username varchar(100) UNIQUE, --TODO: (9) Swap username for email address
|
||||
username varchar(100) UNIQUE, --TODO: (3) Swap username for email address
|
||||
|
||||
--server-client security
|
||||
-- passhash varchar(100),
|
||||
@@ -24,10 +24,14 @@ CREATE TABLE IF NOT EXISTS Characters (
|
||||
avatar varchar(100),
|
||||
birth timestamp NOT NULL DEFAULT (datetime()),
|
||||
|
||||
--position in the world
|
||||
--physically exists in the world
|
||||
roomIndex INTEGER DEFAULT 0,
|
||||
originX INTEGER DEFAULT 0,
|
||||
originY INTEGER DEFAULT 0,
|
||||
boundsX INTEGER DEFAULT 0,
|
||||
boundsY INTEGER DEFAULT 0,
|
||||
boundsW INTEGER DEFAULT 0,
|
||||
boundsH INTEGER DEFAULT 0,
|
||||
|
||||
--statistics
|
||||
baseStats INTEGER REFERENCES StatisticSets(uid),
|
||||
|
||||
@@ -28,15 +28,31 @@
|
||||
//-------------------------
|
||||
|
||||
static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES (?);";
|
||||
static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;";
|
||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3, mod = ?4, admin = ?5 WHERE uid = ?1;";
|
||||
|
||||
static const char* LOAD_USER_ACCOUNT = "SELECT "
|
||||
"uid, "
|
||||
"blacklisted, "
|
||||
"whitelisted, "
|
||||
"mod, "
|
||||
"admin "
|
||||
" FROM Accounts WHERE username = ?;";
|
||||
|
||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET "
|
||||
"blacklisted = ?2, "
|
||||
"whitelisted = ?3, "
|
||||
"mod = ?4, "
|
||||
"admin = ?5 "
|
||||
"WHERE uid = ?1;";
|
||||
|
||||
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
|
||||
|
||||
static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM Accounts;";
|
||||
|
||||
//-------------------------
|
||||
//Define the public methods
|
||||
//-------------------------
|
||||
|
||||
//TODO: (1) block blacklisted accounts
|
||||
int AccountManager::Create(std::string username, int clientIndex) {
|
||||
//create this user account, failing if it exists, leave this account in memory
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
@@ -94,11 +110,11 @@ int AccountManager::Load(std::string username, int clientIndex) {
|
||||
|
||||
//extract the data into memory
|
||||
AccountData& newAccount = elementMap[uid];
|
||||
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
|
||||
newAccount.blackListed = sqlite3_column_int(statement, 2);
|
||||
newAccount.whiteListed = sqlite3_column_int(statement, 3);
|
||||
newAccount.mod = sqlite3_column_int(statement, 4);
|
||||
newAccount.admin = sqlite3_column_int(statement, 5);
|
||||
newAccount.username = username;
|
||||
newAccount.blackListed = sqlite3_column_int(statement, 1);
|
||||
newAccount.whiteListed = sqlite3_column_int(statement, 2);
|
||||
newAccount.mod = sqlite3_column_int(statement, 3);
|
||||
newAccount.admin = sqlite3_column_int(statement, 4);
|
||||
newAccount.clientIndex = clientIndex;
|
||||
|
||||
//finish the routine
|
||||
|
||||
@@ -22,12 +22,108 @@
|
||||
#include "character_api.hpp"
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "character_manager.hpp"
|
||||
#include "entity_api.hpp"
|
||||
#include "room_manager.hpp"
|
||||
#include "server_utilities.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
static int setRoom(lua_State* L) {
|
||||
//reverse engineer the character index
|
||||
int characterIndex = -1;
|
||||
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
|
||||
for (auto& it : *characterMgr.GetContainer()) {
|
||||
if (character == &it.second) {
|
||||
characterIndex = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//error checking
|
||||
if (characterIndex == -1) {
|
||||
throw(std::runtime_error("Lua Error: Failed to find character index by reference"));
|
||||
}
|
||||
|
||||
//get the room index, depending on the parameter type
|
||||
int roomIndex = -1;
|
||||
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||
switch(lua_type(L, 2)) {
|
||||
case LUA_TNUMBER:
|
||||
roomIndex = lua_tointeger(L, 2);
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
//reverse engineer the room index
|
||||
for (auto& it : *roomMgr.GetContainer()) {
|
||||
if (lua_touserdata(L, 2) == &it.second) {
|
||||
roomIndex = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//error checking
|
||||
if (roomIndex == -1) {
|
||||
throw(std::runtime_error("Lua Error: Failed to find room index by reference"));
|
||||
}
|
||||
|
||||
//send the delete & create messages
|
||||
pumpAndChangeRooms(character, roomIndex, characterIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
{"SetRoom", setRoom},
|
||||
// {"GetOwner", getOwner}, //unusable without account API
|
||||
{"GetHandle", getHandle},
|
||||
{"GetAvatar", getAvatar},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
||||
//get the parent table
|
||||
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||
|
||||
//the local table
|
||||
luaL_newlib(L, characterLib);
|
||||
|
||||
//merge the local table into the parent 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 parent table
|
||||
lua_settable(L, -6);
|
||||
|
||||
//pop the original value before continuing
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
//remove the local table, leaving the expanded parent table
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -21,6 +21,10 @@
|
||||
*/
|
||||
#include "character_data.hpp"
|
||||
|
||||
CharacterData::CharacterData(): Entity("character") {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
int CharacterData::GetOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,9 @@
|
||||
|
||||
class CharacterData: public Entity {
|
||||
public:
|
||||
CharacterData() = default;
|
||||
CharacterData();
|
||||
~CharacterData() = default;
|
||||
|
||||
//accessors and mutators
|
||||
//...
|
||||
|
||||
//database stuff
|
||||
int GetOwner();
|
||||
std::string GetHandle();
|
||||
@@ -46,7 +43,7 @@ public:
|
||||
private:
|
||||
friend class CharacterManager;
|
||||
|
||||
int owner;
|
||||
int owner = -1;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#include "character_defines.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -30,10 +32,45 @@
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, avatar) VALUES (?, ?, ?);";
|
||||
static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;";
|
||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET roomIndex = ?2, originX = ?3, originY = ?4 WHERE uid = ?1;";
|
||||
//NOTE: Programmer set variables are NOT zero-indexed
|
||||
//NOTE: SQLite3 returned variables (i.e. loading) ARE zero-indexed
|
||||
|
||||
static const char* CREATE_CHARACTER = "INSERT INTO Characters ("
|
||||
"owner, "
|
||||
"handle, "
|
||||
"avatar, "
|
||||
"boundsX, "
|
||||
"boundsY, "
|
||||
"boundsW, "
|
||||
"boundsH"
|
||||
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
|
||||
|
||||
static const char* LOAD_CHARACTER = "SELECT "
|
||||
"uid, "
|
||||
"owner, "
|
||||
"handle, "
|
||||
"avatar, "
|
||||
"roomIndex, "
|
||||
"originX, "
|
||||
"originY, "
|
||||
"boundsX, "
|
||||
"boundsY, "
|
||||
"boundsW, "
|
||||
"boundsH "
|
||||
"FROM Characters WHERE handle = ?;";
|
||||
|
||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET "
|
||||
"roomIndex = ?2, "
|
||||
"originX = ?3, "
|
||||
"originY = ?4, "
|
||||
"boundsX = ?5, "
|
||||
"boundsY = ?6, "
|
||||
"boundsW = ?7, "
|
||||
"boundsH = ?8 "
|
||||
"WHERE uid = ?1;";
|
||||
|
||||
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
|
||||
|
||||
static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM Characters;";
|
||||
|
||||
//-------------------------
|
||||
@@ -55,6 +92,10 @@ int CharacterManager::Create(int owner, std::string handle, std::string avatar)
|
||||
ret |= sqlite3_bind_int(statement, 1, owner);
|
||||
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
|
||||
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
|
||||
ret |= sqlite3_bind_int(statement, 4, CHARACTER_BOUNDS_X);
|
||||
ret |= sqlite3_bind_int(statement, 5, CHARACTER_BOUNDS_Y);
|
||||
ret |= sqlite3_bind_int(statement, 6, CHARACTER_BOUNDS_WIDTH);
|
||||
ret |= sqlite3_bind_int(statement, 7, CHARACTER_BOUNDS_HEIGHT);
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
@@ -121,9 +162,14 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) {
|
||||
//Don't cache the birth
|
||||
|
||||
//world origin
|
||||
newChar.roomIndex = sqlite3_column_int(statement, 5);
|
||||
newChar.origin.x = (double)sqlite3_column_int(statement, 6);
|
||||
newChar.origin.y = (double)sqlite3_column_int(statement, 7);
|
||||
newChar.roomIndex = sqlite3_column_int(statement, 4);
|
||||
newChar.origin.x = (double)sqlite3_column_int(statement, 5);
|
||||
newChar.origin.y = (double)sqlite3_column_int(statement, 6);
|
||||
//bounds
|
||||
newChar.bounds.x = (int)sqlite3_column_int(statement, 7);
|
||||
newChar.bounds.y = (int)sqlite3_column_int(statement, 8);
|
||||
newChar.bounds.w = (int)sqlite3_column_int(statement, 9);
|
||||
newChar.bounds.h = (int)sqlite3_column_int(statement, 10);
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
|
||||
@@ -165,6 +211,10 @@ int CharacterManager::Save(int uid) {
|
||||
ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 5, character.bounds.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 6, character.bounds.y) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 7, character.bounds.w) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 8, character.bounds.h) != SQLITE_OK;
|
||||
|
||||
//gameplay components: equipment, items, buffs, debuffs...
|
||||
|
||||
@@ -193,6 +243,7 @@ void CharacterManager::Unload(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
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
@@ -252,6 +303,15 @@ CharacterData* CharacterManager::Get(int uid) {
|
||||
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() {
|
||||
return elementMap.size();
|
||||
}
|
||||
|
||||
@@ -44,13 +44,18 @@ public:
|
||||
|
||||
//accessors and mutators
|
||||
CharacterData* Get(int uid);
|
||||
CharacterData* Get(std::string handle);
|
||||
int GetLoadedCount();
|
||||
int GetTotalCount();
|
||||
std::map<int, CharacterData>* GetContainer();
|
||||
|
||||
//API interface
|
||||
sqlite3* SetDatabase(sqlite3* db);
|
||||
sqlite3* GetDatabase();
|
||||
|
||||
//hooks
|
||||
//TODO: character hooks
|
||||
|
||||
private:
|
||||
friend Singleton<CharacterManager>;
|
||||
|
||||
|
||||
@@ -23,7 +23,88 @@
|
||||
|
||||
#include "character_manager.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
//TODO: (1) character hooks?
|
||||
|
||||
static int setOnCreate(lua_State* L) {
|
||||
//TODO: (9) setOnCreate()
|
||||
}
|
||||
|
||||
static int setOnLoad(lua_State* L) {
|
||||
//TODO: (9) setOnLoad()
|
||||
}
|
||||
|
||||
static int setOnSave(lua_State* L) {
|
||||
//TODO: (9) setOnSave()
|
||||
}
|
||||
|
||||
static int setOnUnload(lua_State* L) {
|
||||
//TODO: (9) setOnUnload()
|
||||
}
|
||||
|
||||
static int setOnDelete(lua_State* L) {
|
||||
//TODO: (9) setOnDelete()
|
||||
}
|
||||
|
||||
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) {
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
//pass each character to the given function
|
||||
for (auto& it : *characterMgr.GetContainer()) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushlightuserdata(L, static_cast<void*>(&it.second));
|
||||
//call each iteration, throwing an exception if something happened
|
||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||
std::ostringstream os;
|
||||
os << "Lua error: ";
|
||||
os << lua_tostring(L, -1);
|
||||
throw(std::runtime_error(os.str()));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg characterManagerLib[] = {
|
||||
// {"SetOnCreate", setOnCreate},
|
||||
// {"SetOnLoad", setOnLoad},
|
||||
// {"SetOnSave", setOnSave},
|
||||
// {"SetOnUnload", setOnUnload},
|
||||
// {"SetOnDelete", setOnDelete},
|
||||
{"GetCharacter", getCharacter},
|
||||
{"GetLoadedCount", getLoadedCount},
|
||||
{"ForEach", forEach},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=. ../entities ../server_utilities ../../common/gameplay ../../common/utilities
|
||||
INCLUDES+=. ../entities ../monsters ../rooms ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
*/
|
||||
#include "client_manager.hpp"
|
||||
|
||||
#include "ip_operators.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
int ClientManager::CheckConnections() {
|
||||
std::list<int> ClientManager::CheckConnections() {
|
||||
//list of clients to disconnect
|
||||
std::list<int> returnList;
|
||||
|
||||
for (auto& it : elementMap) {
|
||||
//3 seconds between beats
|
||||
if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
|
||||
@@ -38,21 +42,17 @@ int ClientManager::CheckConnections() {
|
||||
|
||||
for (auto& it : elementMap) {
|
||||
if (it.second.GetAttempts() > 2) {
|
||||
int ret = it.first;
|
||||
// elementMap.erase(it.first);
|
||||
return ret;
|
||||
returnList.push_back(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return returnList;
|
||||
}
|
||||
|
||||
void ClientManager::HandlePong(ServerPacket* const argPacket) {
|
||||
//find and update the specified client
|
||||
for (auto& it : elementMap) {
|
||||
if (it.second.GetAddress().host == argPacket->srcAddress.host &&
|
||||
it.second.GetAddress().port == argPacket->srcAddress.port
|
||||
) {
|
||||
if (it.second.GetAddress() == argPacket->srcAddress) {
|
||||
it.second.ResetAttempts();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,13 @@
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class ClientManager: public Singleton<ClientManager> {
|
||||
public:
|
||||
//methods
|
||||
int CheckConnections();
|
||||
std::list<int> CheckConnections();
|
||||
void HandlePong(ServerPacket* const argPacket);
|
||||
|
||||
//common public methods
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
*/
|
||||
#include "entity.hpp"
|
||||
|
||||
Entity::Entity(const char* _type): type(_type) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void Entity::Update() {
|
||||
origin += motion;
|
||||
}
|
||||
|
||||
int Entity::SetRoomIndex(int i) {
|
||||
return roomIndex = i;
|
||||
}
|
||||
@@ -33,6 +41,10 @@ Vector2 Entity::SetMotion(Vector2 v) {
|
||||
return motion = v;
|
||||
}
|
||||
|
||||
BoundingBox Entity::SetBounds(BoundingBox b) {
|
||||
return bounds = b;
|
||||
}
|
||||
|
||||
int Entity::GetRoomIndex() const {
|
||||
return roomIndex;
|
||||
}
|
||||
@@ -43,4 +55,12 @@ Vector2 Entity::GetOrigin() const {
|
||||
|
||||
Vector2 Entity::GetMotion() const {
|
||||
return motion;
|
||||
}
|
||||
|
||||
BoundingBox Entity::GetBounds() const {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
const char* Entity::GetType() const {
|
||||
return type;
|
||||
}
|
||||
@@ -22,27 +22,38 @@
|
||||
#ifndef ENTITY_HPP_
|
||||
#define ENTITY_HPP_
|
||||
|
||||
#include "bounding_box.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
//The base class for all objects in the world
|
||||
class Entity {
|
||||
public:
|
||||
virtual void Update();
|
||||
|
||||
//accessors & mutators
|
||||
int SetRoomIndex(int i);
|
||||
Vector2 SetOrigin(Vector2 v);
|
||||
Vector2 SetMotion(Vector2 v);
|
||||
BoundingBox SetBounds(BoundingBox b);
|
||||
|
||||
int GetRoomIndex() const;
|
||||
Vector2 GetOrigin() const;
|
||||
Vector2 GetMotion() const;
|
||||
BoundingBox GetBounds() const;
|
||||
|
||||
const char* GetType() const;
|
||||
|
||||
protected:
|
||||
Entity() = default;
|
||||
Entity(const char*);
|
||||
virtual ~Entity() = default;
|
||||
|
||||
int roomIndex = -1;
|
||||
Vector2 origin;
|
||||
Vector2 motion;
|
||||
Vector2 origin = {0, 0};
|
||||
Vector2 motion = {0, 0};
|
||||
BoundingBox bounds = {0, 0, 0, 0};
|
||||
const char* type;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -41,6 +41,17 @@ static int setMotion(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setBounds(lua_State* L) {
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||
entity->SetBounds({
|
||||
lua_tointeger(L, 2),
|
||||
lua_tointeger(L, 3),
|
||||
lua_tointeger(L, 4),
|
||||
lua_tointeger(L, 5)
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getRoomIndex(lua_State* L) {
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, entity->GetRoomIndex());
|
||||
@@ -56,18 +67,36 @@ static int getOrigin(lua_State* L) {
|
||||
|
||||
static int getMotion(lua_State* L) {
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||
lua_pushnumber(L, entity->GetOrigin().x);
|
||||
lua_pushnumber(L, entity->GetOrigin().y);
|
||||
lua_pushnumber(L, entity->GetMotion().x);
|
||||
lua_pushnumber(L, entity->GetMotion().y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int getBounds(lua_State* L) {
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, entity->GetBounds().x);
|
||||
lua_pushinteger(L, entity->GetBounds().y);
|
||||
lua_pushinteger(L, entity->GetBounds().w);
|
||||
lua_pushinteger(L, entity->GetBounds().h);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int getType(lua_State* L) {
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||
lua_pushstring(L, entity->GetType());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg entityLib[] = {
|
||||
{"SetRoomIndex", setRoomIndex},
|
||||
{"SetOrigin", setOrigin},
|
||||
{"SetMotion", setMotion},
|
||||
{"SetBounds", setBounds},
|
||||
{"GetRoomIndex", getRoomIndex},
|
||||
{"GetOrigin", getOrigin},
|
||||
{"GetMotion", getMotion},
|
||||
{"GetBounds", getBounds},
|
||||
{"GetType", getType},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
|
||||
+23
-10
@@ -37,10 +37,17 @@
|
||||
#include "lua.hpp"
|
||||
|
||||
#include "entity_api.hpp"
|
||||
#include "map_system_api.hpp"
|
||||
#include "monster_system_api.hpp"
|
||||
#include "room_system_api.hpp"
|
||||
#include "waypoint_system_api.hpp"
|
||||
#include "character_api.hpp"
|
||||
#include "character_manager_api.hpp"
|
||||
#include "region_api.hpp"
|
||||
#include "region_pager_api.hpp"
|
||||
#include "monster_api.hpp"
|
||||
#include "monster_manager_api.hpp"
|
||||
#include "network_api.hpp"
|
||||
#include "room_api.hpp"
|
||||
#include "room_manager_api.hpp"
|
||||
#include "trigger_api.hpp"
|
||||
#include "trigger_manager_api.hpp"
|
||||
|
||||
//these libs are loaded by lua.c and are readily available to any Lua program
|
||||
static const luaL_Reg loadedlibs[] = {
|
||||
@@ -58,14 +65,20 @@ static const luaL_Reg loadedlibs[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
//these libs are preloaded and must be required before used
|
||||
static const luaL_Reg preloadedlibs[] = {
|
||||
{TORTUGA_ENTITY_API, openEntityAPI},
|
||||
{TORTUGA_MAP_SYSTEM_API, openMapSystemAPI},
|
||||
{TORTUGA_MONSTER_SYSTEM_API, openMonsterSystemAPI},
|
||||
{TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI},
|
||||
{TORTUGA_WAYPOINT_SYSTEM_API, openWaypointSystemAPI},
|
||||
{TORTUGA_ENTITY_API, openEntityAPI}, //required by derived classes
|
||||
{TORTUGA_CHARACTER_API, openCharacterAPI},
|
||||
{TORTUGA_CHARACTER_MANAGER_API, openCharacterManagerAPI},
|
||||
{TORTUGA_MONSTER_API, openMonsterAPI},
|
||||
{TORTUGA_MONSTER_MANAGER_API, openMonsterManagerAPI},
|
||||
{TORTUGA_NETWORK_API, openNetworkAPI},
|
||||
{TORTUGA_REGION_API, openRegionAPI},
|
||||
{TORTUGA_REGION_PAGER_API, openRegionPagerAPI},
|
||||
{TORTUGA_ROOM_API, openRoomAPI},
|
||||
{TORTUGA_ROOM_MANAGER_API, openRoomManagerAPI},
|
||||
{TORTUGA_TRIGGER_API, openTriggerAPI},
|
||||
{TORTUGA_TRIGGER_MANAGER_API, openTriggerManagerAPI},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "config_utility.hpp"
|
||||
#include "room_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "waypoint_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
#include directories
|
||||
INCLUDES+=. accounts characters clients entities monsters rooms server_utilities waypoints ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities
|
||||
INCLUDES+=. accounts characters clients entities monsters rooms server_utilities triggers ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities
|
||||
|
||||
#libraries
|
||||
#the order of the $(LIBS) is important, at least for MinGW
|
||||
@@ -32,7 +32,7 @@ all: $(OBJ) $(OUT)
|
||||
$(MAKE) -C monsters
|
||||
$(MAKE) -C rooms
|
||||
$(MAKE) -C server_utilities
|
||||
$(MAKE) -C waypoints
|
||||
$(MAKE) -C triggers
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
@@ -61,27 +61,27 @@ static const luaL_Reg monsterLib[] = {
|
||||
};
|
||||
|
||||
LUAMOD_API int openMonsterAPI(lua_State* L) {
|
||||
//the local table
|
||||
luaL_newlib(L, monsterLib);
|
||||
|
||||
//get the parent table
|
||||
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||
|
||||
//clone the parent table into the local table
|
||||
//the local table
|
||||
luaL_newlib(L, monsterLib);
|
||||
|
||||
//merge the local table into the parent 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
|
||||
//push the copy to the parent table
|
||||
lua_settable(L, -6);
|
||||
|
||||
//pop the original value before continuing
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
//remove the parent table, leaving the expanded child table
|
||||
//remove the local table, leaving the expanded parent table
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
*/
|
||||
#include "monster_data.hpp"
|
||||
|
||||
MonsterData::MonsterData(): Entity("monster") {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
std::string MonsterData::SetAvatar(std::string s) {
|
||||
return avatar = s;
|
||||
}
|
||||
|
||||
@@ -24,11 +24,13 @@
|
||||
|
||||
#include "entity.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class MonsterData: public Entity {
|
||||
public:
|
||||
MonsterData() = default;
|
||||
MonsterData();
|
||||
~MonsterData() = default;
|
||||
|
||||
std::string SetAvatar(std::string);
|
||||
@@ -41,7 +43,7 @@ private:
|
||||
friend class MonsterManager;
|
||||
|
||||
std::string avatar;
|
||||
int scriptRef;
|
||||
int scriptRef = LUA_NOREF;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -30,45 +30,45 @@ MonsterManager::~MonsterManager() {
|
||||
}
|
||||
|
||||
int MonsterManager::Create(std::string) {
|
||||
//Create
|
||||
//TODO: (9) MonsterManager::Create()
|
||||
}
|
||||
|
||||
void MonsterManager::Unload(int uid) {
|
||||
//Unload
|
||||
//TODO: (9) MonsterManager::Unload()
|
||||
}
|
||||
|
||||
void MonsterManager::UnloadAll() {
|
||||
//UnloadAll
|
||||
//TODO: (9) MonsterManager::UnloadAll()
|
||||
}
|
||||
|
||||
void MonsterManager::UnloadIf(std::function<bool(std::pair<const int, MonsterData const&>)> fn) {
|
||||
//UnloadIf
|
||||
//TODO: (9) MonsterManager::UnloadIf()
|
||||
}
|
||||
|
||||
MonsterData* MonsterManager::Get(int uid) {
|
||||
//Get
|
||||
//TODO: (9) MonsterManager::Get()
|
||||
}
|
||||
|
||||
int MonsterManager::GetLoadedCount() {
|
||||
//GetLoadedCount
|
||||
//TODO: (9) MonsterManager::GetLoadedCount()
|
||||
}
|
||||
|
||||
std::map<int, MonsterData>* MonsterManager::GetContainer() {
|
||||
//GetContainer
|
||||
//TODO: (9) MonsterManager::GetContainer()
|
||||
}
|
||||
|
||||
lua_State* MonsterManager::SetLuaState(lua_State* L) {
|
||||
//SetLuaState
|
||||
//TODO: (9) MonsterManager::SetLuaState()
|
||||
}
|
||||
|
||||
lua_State* MonsterManager::GetLuaState() {
|
||||
//GetLuaState
|
||||
//TODO: (9) MonsterManager::GetLuaState()
|
||||
}
|
||||
|
||||
sqlite3* MonsterManager::SetDatabase(sqlite3* db) {
|
||||
//SetDatabase
|
||||
//TODO: (9) MonsterManager::SetDatabase()
|
||||
}
|
||||
|
||||
sqlite3* MonsterManager::GetDatabase() {
|
||||
//GetDatabase
|
||||
//TODO: (9) MonsterManager::GetDatabase()
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/* 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 "monster_system_api.hpp"
|
||||
|
||||
//all monster API headers
|
||||
#include "monster_api.hpp"
|
||||
#include "monster_manager_api.hpp"
|
||||
|
||||
//useful "globals"
|
||||
//...
|
||||
|
||||
//This mimics linit.c to create a nested collection of all monster modules.
|
||||
static const luaL_Reg funcs[] = {
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const luaL_Reg libs[] = {
|
||||
{"Monster", openMonsterAPI},
|
||||
{"MonsterManager", openMonsterManagerAPI},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
int openMonsterSystemAPI(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;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=. ../characters ../entities ../monsters ../server_utilities ../waypoints ../../common/gameplay ../../common/map ../../common/utilities
|
||||
INCLUDES+=. ../characters ../entities ../monsters ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
#include "room_data.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
static int setRoomName(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
room->SetName(lua_tostring(L, 2));
|
||||
@@ -59,9 +62,41 @@ static int getMonsterMgr(lua_State* L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getWaypointMgr(lua_State* L) {
|
||||
static int getTriggerMgr(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetWaypointMgr()) );
|
||||
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetTriggerMgr()) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
//TODO: character list
|
||||
|
||||
static int forEachCharacter(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
//pass each character to the given function
|
||||
for (auto& it : *room->GetCharacterList()) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushlightuserdata(L, static_cast<void*>(it));
|
||||
//call each iteration, throwing an exception if something happened
|
||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||
std::ostringstream os;
|
||||
os << "Lua error: ";
|
||||
os << lua_tostring(L, -1);
|
||||
throw(std::runtime_error(os.str()));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 getOnTick(lua_State* L) {
|
||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, room->GetTickReference());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -86,7 +121,12 @@ static const luaL_Reg roomLib[] = {
|
||||
|
||||
{"GetPager",getPager},
|
||||
{"GetMonsterMgr",getMonsterMgr},
|
||||
{"GetWaypointMgr",getWaypointMgr},
|
||||
{"GetTriggerMgr",getTriggerMgr},
|
||||
|
||||
{"ForEachCharacter", forEachCharacter},
|
||||
|
||||
{"SetOnTick", setOnTick},
|
||||
{"GetOnTick", getOnTick},
|
||||
|
||||
{"Initialize", initialize},
|
||||
{nullptr, nullptr}
|
||||
|
||||
+112
-2
@@ -21,6 +21,86 @@
|
||||
*/
|
||||
#include "room_data.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
|
||||
void RoomData::RunFrame() {
|
||||
//get the hook
|
||||
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
||||
|
||||
if (!lua_isnil(lua, -1)) {
|
||||
//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) ));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_pop(lua, 1);
|
||||
}
|
||||
|
||||
//update the entities in the room
|
||||
for (auto& it : characterList) {
|
||||
it->Update();
|
||||
}
|
||||
//TODO: (3) iterate through the monster map
|
||||
//TODO: (3) trigger script for monsters
|
||||
|
||||
//build a list of game entities
|
||||
std::stack<Entity*> entityStack;
|
||||
for (auto& it : characterList) {
|
||||
entityStack.push(it);
|
||||
}
|
||||
//TODO: (3) push the monster entities
|
||||
|
||||
//compare the triggers to the entities, using their real hitboxes
|
||||
//NOTE: this stack solution should prevent problems when modifying the various lists
|
||||
while(entityStack.size()) {
|
||||
//get the entity & hitbox
|
||||
Entity* entity = entityStack.top();
|
||||
BoundingBox entityBox = entity->GetBounds() + entity->GetOrigin();
|
||||
|
||||
//get the trigger pair & hitbox
|
||||
for (auto& triggerPair : *triggerMgr.GetContainer()) {
|
||||
BoundingBox triggerBox = triggerPair.second.GetBoundingBox() + triggerPair.second.GetOrigin();
|
||||
|
||||
//find all collisions
|
||||
if (entityBox.CheckOverlap(triggerBox)) {
|
||||
//skip members of the exclusion list
|
||||
if (std::any_of(triggerPair.second.GetExclusionList()->begin(), triggerPair.second.GetExclusionList()->end(), [entity](Entity* ptr) -> bool {
|
||||
return entity == ptr;
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//run the trigger script
|
||||
lua_rawgeti(lua, LUA_REGISTRYINDEX, triggerPair.second.GetScriptReference());
|
||||
lua_pushlightuserdata(lua, entity);
|
||||
|
||||
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
|
||||
//error
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||
}
|
||||
|
||||
//push to the exclusion list
|
||||
triggerPair.second.GetExclusionList()->push_back(entity);
|
||||
}
|
||||
else {
|
||||
//remove members of the exclusion list
|
||||
//NOTE: characters in different rooms won't be removed, but that shouldn't be a problem
|
||||
triggerPair.second.GetExclusionList()->remove_if([entity](Entity* ptr) -> bool {
|
||||
return entity == ptr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//next
|
||||
entityStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
std::string RoomData::SetName(std::string s) {
|
||||
return roomName = s;
|
||||
}
|
||||
@@ -45,10 +125,40 @@ MonsterManager* RoomData::GetMonsterMgr() {
|
||||
return &monsterMgr;
|
||||
}
|
||||
|
||||
WaypointManager* RoomData::GetWaypointMgr() {
|
||||
return &waypointMgr;
|
||||
TriggerManager* RoomData::GetTriggerMgr() {
|
||||
return &triggerMgr;
|
||||
}
|
||||
|
||||
std::list<CharacterData*>* RoomData::GetCharacterList() {
|
||||
return &characterList;
|
||||
}
|
||||
|
||||
lua_State* RoomData::SetLuaState(lua_State* L) {
|
||||
lua = L;
|
||||
pager.SetLuaState(lua);
|
||||
monsterMgr.SetLuaState(lua);
|
||||
triggerMgr.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;
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "character_data.hpp"
|
||||
#include "monster_manager.hpp"
|
||||
#include "region_pager_lua.hpp"
|
||||
#include "waypoint_manager.hpp"
|
||||
#include "trigger_manager.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
RoomData() = default;
|
||||
~RoomData() = default;
|
||||
|
||||
void RunFrame();
|
||||
|
||||
//accessors and mutators
|
||||
std::string SetName(std::string);
|
||||
std::string GetName();
|
||||
@@ -46,22 +48,37 @@ public:
|
||||
|
||||
RegionPagerLua* GetPager();
|
||||
MonsterManager* GetMonsterMgr();
|
||||
WaypointManager* GetWaypointMgr();
|
||||
TriggerManager* GetTriggerMgr();
|
||||
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:
|
||||
friend class RoomManager;
|
||||
|
||||
//members
|
||||
//metadata
|
||||
std::string roomName;
|
||||
std::string tilesetName;
|
||||
|
||||
//members
|
||||
RegionPagerLua pager;
|
||||
MonsterManager monsterMgr;
|
||||
WaypointManager waypointMgr;
|
||||
TriggerManager triggerMgr;
|
||||
std::list<CharacterData*> characterList;
|
||||
|
||||
//API
|
||||
lua_State* lua = nullptr;
|
||||
sqlite3* database = nullptr;
|
||||
|
||||
//hooks
|
||||
int tickRef = LUA_NOREF;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,29 +35,79 @@ int RoomManager::Create(std::string roomName, std::string tileset) {
|
||||
newRoom->SetName(roomName);
|
||||
newRoom->SetTileset(tileset);
|
||||
|
||||
newRoom->pager.SetLuaState(lua);
|
||||
newRoom->monsterMgr.SetLuaState(lua);
|
||||
newRoom->monsterMgr.SetDatabase(database);
|
||||
newRoom->waypointMgr.SetLuaState(lua);
|
||||
newRoom->SetLuaState(lua);
|
||||
newRoom->SetDatabase(database);
|
||||
|
||||
//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
|
||||
return counter++;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
//jenky pattern
|
||||
while (it != elementMap.end()) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//pop the hook or nil
|
||||
lua_pop(lua, 1);
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
room->characterList.push_back(character);
|
||||
room->GetCharacterList()->push_back(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"));
|
||||
}
|
||||
|
||||
room->characterList.remove_if([character](CharacterData* ptr) {
|
||||
room->GetCharacterList()->remove_if([character](CharacterData* ptr) {
|
||||
return character == ptr;
|
||||
});
|
||||
}
|
||||
@@ -119,7 +169,11 @@ std::map<int, RoomData>* RoomManager::GetContainer() {
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -127,9 +181,29 @@ lua_State* RoomManager::GetLuaState() {
|
||||
}
|
||||
|
||||
sqlite3* RoomManager::SetDatabase(sqlite3* db) {
|
||||
return database = db;
|
||||
database = db;
|
||||
for (auto& it : elementMap) {
|
||||
it.second.SetDatabase(database);
|
||||
}
|
||||
return database;
|
||||
}
|
||||
|
||||
sqlite3* RoomManager::GetDatabase() {
|
||||
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();
|
||||
std::map<int, RoomData>* GetContainer();
|
||||
|
||||
//hooks
|
||||
//API interfaces
|
||||
lua_State* SetLuaState(lua_State* L);
|
||||
lua_State* GetLuaState();
|
||||
sqlite3* SetDatabase(sqlite3* db);
|
||||
sqlite3* GetDatabase();
|
||||
|
||||
//hooks
|
||||
int SetCreateReference(int i);
|
||||
int SetUnloadReference(int i);
|
||||
|
||||
int GetCreateReference();
|
||||
int GetUnloadReference();
|
||||
|
||||
private:
|
||||
friend Singleton<RoomManager>;
|
||||
|
||||
@@ -63,9 +70,15 @@ private:
|
||||
|
||||
//members
|
||||
std::map<int, RoomData> elementMap;
|
||||
int counter = 0;
|
||||
|
||||
//API
|
||||
lua_State* lua = nullptr;
|
||||
sqlite3* database = nullptr;
|
||||
int counter = 0;
|
||||
|
||||
//hooks
|
||||
int createRef = LUA_NOREF;
|
||||
int unloadRef = LUA_NOREF;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -96,10 +96,26 @@ int getRoom(lua_State* L) {
|
||||
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[] = {
|
||||
{"CreateRoom", createRoom},
|
||||
{"UnloadRoom", unloadRoom},
|
||||
{"GetRoom", getRoom},
|
||||
{"SetOnCreate", setOnCreate},
|
||||
{"SetOnUnload", setOnUnload},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/* 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 "room_system_api.hpp"
|
||||
|
||||
//all room API headers
|
||||
#include "room_api.hpp"
|
||||
#include "room_manager_api.hpp"
|
||||
|
||||
//useful "globals"
|
||||
//...
|
||||
|
||||
//This mimics linit.c to create a nested collection of all room modules.
|
||||
static const luaL_Reg funcs[] = {
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const luaL_Reg libs[] = {
|
||||
{"Room", openRoomAPI},
|
||||
{"RoomManager", openRoomManagerAPI},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
int openRoomSystemAPI(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;
|
||||
}
|
||||
@@ -38,6 +38,9 @@
|
||||
#include "serial_packet.hpp"
|
||||
#include "singleton.hpp"
|
||||
|
||||
//server utilities
|
||||
#include "server_utilities.hpp"
|
||||
|
||||
//APIs
|
||||
#include "lua.hpp"
|
||||
#include "sqlite3.h"
|
||||
@@ -111,13 +114,7 @@ private:
|
||||
void hTextWhisper(TextPacket* const);
|
||||
|
||||
//utility methods
|
||||
void PumpPacket(SerialPacket* const);
|
||||
void PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance);
|
||||
void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex);
|
||||
void SaveServerState();
|
||||
void FullClientUnload(int index);
|
||||
void FullAccountUnload(int index);
|
||||
void FullCharacterUnload(int index);
|
||||
|
||||
//APIs and utilities
|
||||
sqlite3* database = nullptr;
|
||||
|
||||
@@ -46,13 +46,14 @@ void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
//push to the rooms
|
||||
roomMgr.PushCharacter(characterMgr.Get(characterIndex));
|
||||
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||
roomMgr.PushCharacter(characterData);
|
||||
|
||||
//pump this character to all clients
|
||||
CharacterPacket newPacket;
|
||||
CopyCharacterToPacket(&newPacket, characterIndex);
|
||||
copyCharacterToPacket(&newPacket, characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||
PumpPacket(&newPacket);
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
}
|
||||
|
||||
void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||
@@ -90,16 +91,17 @@ void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
//pop from the rooms
|
||||
roomMgr.PopCharacter(characterMgr.Get(characterIndex));
|
||||
|
||||
//delete the character
|
||||
characterMgr.Delete(characterIndex);
|
||||
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||
roomMgr.PopCharacter(characterData);
|
||||
|
||||
//pump character delete
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
newPacket.characterIndex = characterIndex;
|
||||
PumpPacket(static_cast<SerialPacket*>(&newPacket));
|
||||
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
|
||||
|
||||
//delete the character
|
||||
characterMgr.Delete(characterIndex);
|
||||
}
|
||||
|
||||
void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
|
||||
@@ -126,13 +128,14 @@ void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
|
||||
}
|
||||
|
||||
//push to the rooms
|
||||
roomMgr.PushCharacter(characterMgr.Get(characterIndex));
|
||||
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||
roomMgr.PushCharacter(characterData);
|
||||
|
||||
//pump this character to all clients
|
||||
CharacterPacket newPacket;
|
||||
CopyCharacterToPacket(&newPacket, characterIndex);
|
||||
copyCharacterToPacket(&newPacket, characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||
PumpPacket(&newPacket);
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
}
|
||||
|
||||
void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
||||
@@ -161,14 +164,14 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
||||
//pop from the rooms
|
||||
roomMgr.PopCharacter(characterData);
|
||||
|
||||
//unload the character
|
||||
characterMgr.Unload(argPacket->characterIndex);
|
||||
|
||||
//pump character delete
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
newPacket.characterIndex = argPacket->characterIndex;
|
||||
PumpPacket(static_cast<SerialPacket*>(&newPacket));
|
||||
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
|
||||
|
||||
//unload the character
|
||||
characterMgr.Unload(argPacket->characterIndex);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
@@ -180,10 +183,15 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
||||
void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
//get the specified objects
|
||||
AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
|
||||
|
||||
if (!accountData) {
|
||||
throw(std::runtime_error("Failed to move a character, missing account"));
|
||||
}
|
||||
|
||||
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
|
||||
|
||||
if (!accountData || !characterData) {
|
||||
throw(std::runtime_error("Failed to move a character, missing data"));
|
||||
if (!characterData) {
|
||||
throw(std::runtime_error("Failed to move a character, missing character"));
|
||||
}
|
||||
|
||||
//get this account's client
|
||||
@@ -197,28 +205,19 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
|
||||
//check if allowed
|
||||
if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) {
|
||||
//TODO: (2) send to the client?
|
||||
//TODO: (3) send to the client?
|
||||
std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//check if moving rooms
|
||||
if (characterData->GetRoomIndex() != argPacket->roomIndex) {
|
||||
//delete from the old room
|
||||
CharacterPacket newPacket;
|
||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
||||
//set the character's origin and motion
|
||||
characterData->SetOrigin(argPacket->origin);
|
||||
characterData->SetMotion(argPacket->motion);
|
||||
|
||||
//move the character between rooms
|
||||
roomMgr.PopCharacter(characterData);
|
||||
characterData->SetRoomIndex(argPacket->roomIndex);
|
||||
roomMgr.PushCharacter(characterData);
|
||||
|
||||
//create in the new room
|
||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
||||
//send the delete & create messages
|
||||
pumpAndChangeRooms(characterData, argPacket->roomIndex, argPacket->characterIndex);
|
||||
}
|
||||
//if not moving between rooms
|
||||
else {
|
||||
@@ -228,16 +227,16 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||
|
||||
//update the clients
|
||||
CharacterPacket newPacket;
|
||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
||||
copyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
|
||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hCharacterAttack()
|
||||
}
|
||||
|
||||
void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hCharacterDamage()
|
||||
}
|
||||
@@ -22,13 +22,13 @@
|
||||
#include "server_application.hpp"
|
||||
|
||||
void ServerApplication::hTextBroadcast(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hTextBroadcast()
|
||||
}
|
||||
|
||||
void ServerApplication::hTextSpeech(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hTextSpeech()
|
||||
}
|
||||
|
||||
void ServerApplication::hTextWhisper(TextPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hTextWhisper()
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ void ServerApplication::hLogoutRequest(ClientPacket* const argPacket) {
|
||||
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
||||
|
||||
//save and unload this account and it's characters
|
||||
FullAccountUnload(argPacket->accountIndex);
|
||||
fullAccountUnload(argPacket->accountIndex);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "New logout, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
|
||||
@@ -165,7 +165,7 @@ void ServerApplication::hDisconnectRequest(ClientPacket* const argPacket) {
|
||||
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
||||
|
||||
//unload the client, it's accounts, and their characters
|
||||
FullClientUnload(argPacket->clientIndex);
|
||||
fullClientUnload(argPacket->clientIndex);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "New disconnection, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
|
||||
|
||||
@@ -69,28 +69,28 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
|
||||
if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) {
|
||||
continue;
|
||||
}
|
||||
CopyCharacterToPacket(&newPacket, it.first);
|
||||
copyCharacterToPacket(&newPacket, it.first);
|
||||
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hQueryCharacterStats()
|
||||
}
|
||||
|
||||
void ServerApplication::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hQueryCharacterLocation()
|
||||
}
|
||||
|
||||
void ServerApplication::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hQueryMonsterExists()
|
||||
}
|
||||
|
||||
void ServerApplication::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hQueryMonsterStats()
|
||||
}
|
||||
|
||||
void ServerApplication::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hQueryMonsterLocation()
|
||||
}
|
||||
|
||||
+39
-12
@@ -23,11 +23,13 @@
|
||||
|
||||
//utility functions
|
||||
#include "sql_tools.hpp"
|
||||
#include "userdata.hpp"
|
||||
|
||||
//std & STL
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
@@ -77,6 +79,11 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
||||
|
||||
std::cout << "Initialized lua" << std::endl;
|
||||
|
||||
//create the userdata metatable
|
||||
createUserdataMetatable(luaState);
|
||||
|
||||
std::cout << "\tCreated userdata metatable" << std::endl;
|
||||
|
||||
//append config["dir.scripts"] to the module path
|
||||
if (config["dir.scripts"].size() > 0) {
|
||||
//get the original path
|
||||
@@ -161,9 +168,16 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
void ServerApplication::Proc() {
|
||||
//network buffer
|
||||
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
||||
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) {
|
||||
//suck in the waiting packets & process them
|
||||
while(network.Receive(packetBuffer)) {
|
||||
@@ -173,20 +187,33 @@ void ServerApplication::Proc() {
|
||||
catch(std::exception& e) {
|
||||
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
||||
}
|
||||
memset(packetBuffer, 0, MAX_PACKET_SIZE); //reset the buffer
|
||||
}
|
||||
//update the internals
|
||||
//...
|
||||
|
||||
//Check connections
|
||||
int disconnected = clientMgr.CheckConnections();
|
||||
if (disconnected != -1) {
|
||||
FullClientUnload(disconnected);
|
||||
std::cerr << "Client dropped: " << disconnected << std::endl;
|
||||
//reset the buffer
|
||||
memset(packetBuffer, 0, MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
//give the machine a break
|
||||
SDL_Delay(10);
|
||||
//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
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
delete reinterpret_cast<char*>(packetBuffer);
|
||||
}
|
||||
|
||||
+3
-118
@@ -30,7 +30,7 @@
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hAdminDisconnectForced()
|
||||
}
|
||||
|
||||
void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
|
||||
@@ -78,127 +78,12 @@ void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
|
||||
TextPacket newPacket;
|
||||
newPacket.type = SerialPacketType::ADMIN_DISCONNECT_FORCED;
|
||||
strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE);
|
||||
PumpPacket(&newPacket);
|
||||
pumpPacket(&newPacket);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "Shutdown signal accepted" << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::SaveServerState() {
|
||||
//TODO: (9) empty
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//full unload methods
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::FullClientUnload(int index) {
|
||||
clientMgr.UnloadIf([&](std::pair<const int, ClientData const&> client) -> bool {
|
||||
//skip the wrong clients
|
||||
if (client.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//unload associated accounts
|
||||
for (std::map<int, AccountData>::iterator it = accountMgr.GetContainer()->begin(); it != accountMgr.GetContainer()->end(); /* EMPTY */) {
|
||||
if (it->second.GetClientIndex() == index) {
|
||||
FullAccountUnload(it->first);
|
||||
it = accountMgr.GetContainer()->begin();
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//unload this client
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void ServerApplication::FullAccountUnload(int index) {
|
||||
accountMgr.UnloadIf([&](std::pair<const int, AccountData const&> account) -> bool {
|
||||
//skip the wrong accounts
|
||||
if (account.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//unload associated characters
|
||||
for (std::map<int, CharacterData>::iterator it = characterMgr.GetContainer()->begin(); it != characterMgr.GetContainer()->end(); /* EMPTY */) {
|
||||
if (it->second.GetOwner() == index) {
|
||||
FullCharacterUnload(it->first);
|
||||
it = characterMgr.GetContainer()->begin();
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//unload this account
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void ServerApplication::FullCharacterUnload(int index) {
|
||||
characterMgr.UnloadIf([&](std::pair<const int, CharacterData const&> character) -> bool {
|
||||
//skip the wrong characters
|
||||
if (character.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//pop from the rooms
|
||||
roomMgr.PopCharacter(&character.second);
|
||||
|
||||
//pump character unload
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
newPacket.characterIndex = character.first;
|
||||
//NOTE: more character info as needed
|
||||
|
||||
PumpPacket(&newPacket);
|
||||
|
||||
//unload this character
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//utility methods
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::PumpPacket(SerialPacket* const argPacket) {
|
||||
for (auto& it : *clientMgr.GetContainer()) {
|
||||
network.SendTo(it.second.GetAddress(), argPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance) {
|
||||
RoomData* room = roomMgr.Get(roomIndex);
|
||||
|
||||
if (!room) {
|
||||
throw(std::runtime_error("Failed to pump to a non-existant room"));
|
||||
}
|
||||
|
||||
for (auto& character : *room->GetCharacterList()) {
|
||||
if (distance == -1 || (character->GetOrigin() - position).Length() <= distance) {
|
||||
AccountData* account = accountMgr.Get(character->GetOwner());
|
||||
ClientData* client = clientMgr.Get(account->GetClientIndex());
|
||||
network.SendTo(client->GetAddress(), argPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
|
||||
CharacterData* character = characterMgr.Get(characterIndex);
|
||||
if (!character) {
|
||||
throw(std::runtime_error("Failed to copy a character to a packet"));
|
||||
}
|
||||
|
||||
//NOTE: keep this up to date when the character changes
|
||||
packet->characterIndex = characterIndex;
|
||||
strncpy(packet->handle, character->GetHandle().c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet->avatar, character->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
||||
packet->accountIndex = character->GetOwner();
|
||||
packet->roomIndex = character->GetRoomIndex();
|
||||
packet->origin = character->GetOrigin();
|
||||
packet->motion = character->GetMotion();
|
||||
//TODO: (3) Periodic mass server saves
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@
|
||||
#include "server_application.hpp"
|
||||
|
||||
void ServerApplication::hMonsterDamage(MonsterPacket* const argPacket) {
|
||||
//TODO: (9) empty
|
||||
//TODO: (9) ServerApplication::hMonsterDamage()
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
INCLUDES+=. ../accounts ../characters ../clients ../entities ../monsters ../rooms ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/* 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"
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "character_manager.hpp"
|
||||
#include "server_utilities.hpp"
|
||||
|
||||
static int pumpCharacterUpdate(lua_State* L) {
|
||||
CharacterData* characterData = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||
|
||||
//determine the character's index
|
||||
int index = -1;
|
||||
for (auto const& it : *CharacterManager::GetSingleton().GetContainer()) {
|
||||
if(characterData == &it.second) {
|
||||
index = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//signal an error
|
||||
if (index == -1) {
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//fill the packet with all of this character's data
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
|
||||
newPacket.characterIndex = index;
|
||||
strncpy(newPacket.handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(newPacket.avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
||||
newPacket.accountIndex = characterData->GetOwner();
|
||||
newPacket.roomIndex = characterData->GetRoomIndex();
|
||||
newPacket.origin = characterData->GetOrigin();
|
||||
newPacket.motion = characterData->GetMotion();
|
||||
|
||||
//pump to the room
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
|
||||
//signal success
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg networkLib[] = {
|
||||
{"PumpCharacterUpdate", pumpCharacterUpdate},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openNetworkAPI(lua_State* L) {
|
||||
luaL_newlib(L, networkLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef WAYPOINTAPI_HPP_
|
||||
#define WAYPOINTAPI_HPP_
|
||||
#ifndef NETWORKAPI_HPP_
|
||||
#define NETWORKAPI_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_WAYPOINT_API "waypoint"
|
||||
LUAMOD_API int openWaypointAPI(lua_State* L);
|
||||
#define TORTUGA_NETWORK_API "network"
|
||||
LUAMOD_API int openNetworkAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
/* 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 "server_utilities.hpp"
|
||||
|
||||
#include "account_manager.hpp"
|
||||
#include "character_manager.hpp"
|
||||
#include "client_manager.hpp"
|
||||
#include "room_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//-------------------------
|
||||
//manager unload functions
|
||||
//-------------------------
|
||||
|
||||
void fullClientUnload(int index) {
|
||||
ClientManager::GetSingleton().UnloadIf([index](std::pair<const int, ClientData const&> clientPair) -> bool {
|
||||
//skip the wrong clients
|
||||
if (clientPair.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AccountManager& accountMgr = AccountManager::GetSingleton();
|
||||
|
||||
//unload associated accounts
|
||||
for (std::map<int, AccountData>::iterator it = accountMgr.GetContainer()->begin(); it != accountMgr.GetContainer()->end(); /* EMPTY */) {
|
||||
if (it->second.GetClientIndex() == index) {
|
||||
fullAccountUnload(it->first);
|
||||
it = accountMgr.GetContainer()->begin();
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//unload this client
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void fullAccountUnload(int index) {
|
||||
AccountManager::GetSingleton().UnloadIf([index](std::pair<const int, AccountData const&> accountPair) -> bool {
|
||||
//skip the wrong accounts
|
||||
if (accountPair.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||
|
||||
//unload associated characters
|
||||
for (std::map<int, CharacterData>::iterator it = characterMgr.GetContainer()->begin(); it != characterMgr.GetContainer()->end(); /* EMPTY */) {
|
||||
if (it->second.GetOwner() == index) {
|
||||
fullCharacterUnload(it->first);
|
||||
it = characterMgr.GetContainer()->begin();
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//unload this account
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void fullCharacterUnload(int index) {
|
||||
CharacterManager::GetSingleton().UnloadIf([index](std::pair<const int, CharacterData const&> characterPair) -> bool {
|
||||
//skip the wrong characters
|
||||
if (characterPair.first != index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//pop from the rooms
|
||||
RoomManager::GetSingleton().PopCharacter(&characterPair.second);
|
||||
|
||||
//pump character unload
|
||||
CharacterPacket newPacket;
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
newPacket.characterIndex = characterPair.first;
|
||||
//NOTE: more character info as needed
|
||||
|
||||
//TODO: proximity?
|
||||
pumpPacketProximity(&newPacket, characterPair.second.GetRoomIndex());
|
||||
|
||||
//unload this character
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//utility functions
|
||||
//-------------------------
|
||||
|
||||
void pumpPacket(SerialPacket* const argPacket) {
|
||||
for (auto& it : *ClientManager::GetSingleton().GetContainer()) {
|
||||
UDPNetworkUtility::GetSingleton().SendTo(it.second.GetAddress(), argPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance) {
|
||||
RoomData* roomData = RoomManager::GetSingleton().Get(roomIndex);
|
||||
|
||||
if (!roomData) {
|
||||
throw(std::runtime_error("Failed to pump to a non-existant room"));
|
||||
}
|
||||
|
||||
AccountData* accountData = nullptr;
|
||||
ClientData* clientData = nullptr;
|
||||
|
||||
for (auto& characterIt : *roomData->GetCharacterList()) {
|
||||
if (distance == -1 || (characterIt->GetOrigin() - position).Length() <= distance) {
|
||||
accountData = AccountManager::GetSingleton().Get(characterIt->GetOwner());
|
||||
clientData = ClientManager::GetSingleton().Get(accountData->GetClientIndex());
|
||||
UDPNetworkUtility::GetSingleton().SendTo(clientData->GetAddress(), argPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
|
||||
CharacterData* characterData = CharacterManager::GetSingleton().Get(characterIndex);
|
||||
if (!characterData) {
|
||||
throw(std::runtime_error("Failed to copy a character to a packet"));
|
||||
}
|
||||
|
||||
copyCharacterToPacket(packet, characterData, characterIndex);
|
||||
}
|
||||
|
||||
void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex) {
|
||||
//NOTE: keep this up to date when the character changes
|
||||
packet->characterIndex = characterIndex;
|
||||
strncpy(packet->handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet->avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
||||
packet->accountIndex = characterData->GetOwner();
|
||||
packet->roomIndex = characterData->GetRoomIndex();
|
||||
packet->origin = characterData->GetOrigin();
|
||||
packet->motion = characterData->GetMotion();
|
||||
packet->bounds = characterData->GetBounds();
|
||||
}
|
||||
|
||||
void pumpAndChangeRooms(int characterIndex, int newRoomIndex) {
|
||||
//get the character object
|
||||
CharacterData* character = CharacterManager::GetSingleton().Get(characterIndex);
|
||||
|
||||
//pass ownwards
|
||||
pumpAndChangeRooms(character, newRoomIndex, characterIndex);
|
||||
}
|
||||
|
||||
void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex) {
|
||||
//delete from the old room
|
||||
CharacterPacket newPacket;
|
||||
copyCharacterToPacket(&newPacket, characterData, characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
|
||||
//move the character between rooms
|
||||
RoomManager::GetSingleton().PopCharacter(characterData);
|
||||
characterData->SetRoomIndex(newRoomIndex);
|
||||
RoomManager::GetSingleton().PushCharacter(characterData);
|
||||
|
||||
//create in the new room
|
||||
copyCharacterToPacket(&newPacket, characterData, characterIndex);
|
||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* 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 SERVERUTILITIES_HPP_
|
||||
#define SERVERUTILITIES_HPP_
|
||||
|
||||
#include "character_data.hpp"
|
||||
#include "serial_packet.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
void fullClientUnload(int index);
|
||||
void fullAccountUnload(int index);
|
||||
void fullCharacterUnload(int index);
|
||||
|
||||
void pumpPacket(SerialPacket* const argPacket);
|
||||
void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position = {0, 0}, int distance = -1);
|
||||
|
||||
void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex);
|
||||
void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex);
|
||||
void pumpAndChangeRooms(int characterIndex, int newRoomIndex);
|
||||
void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
/* 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 "userdata.hpp"
|
||||
|
||||
#define METAMETA "__metameta"
|
||||
|
||||
static int index(lua_State* L) {
|
||||
//get __metameta
|
||||
lua_getmetatable(L, 1); //get the userdata metatable
|
||||
lua_pushstring(L, METAMETA); //push the __metameta name
|
||||
lua_gettable(L, -2); //get the __metameta field from the metatable
|
||||
|
||||
//get __metameta[userdata]
|
||||
lua_pushvalue(L, 1); //copy of the userdata
|
||||
lua_gettable(L, -2); //get the table at __metameta[userdata]
|
||||
|
||||
//table doesn't exist yet
|
||||
if (lua_isnil(L, -1)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//get the value at __metameta[userdata][key]
|
||||
lua_pushvalue(L, 2); //copy the key
|
||||
lua_gettable(L, -2); //get value from the deepest table
|
||||
|
||||
//return
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int newindex(lua_State* L) {
|
||||
//get __metameta
|
||||
lua_getmetatable(L, 1); //get the userdata metatable
|
||||
lua_pushstring(L, METAMETA); //push the __metameta name
|
||||
lua_gettable(L, -2); //get the __metameta field from the metatable
|
||||
|
||||
//get __metameta[userdata]
|
||||
lua_pushvalue(L, 1); //copy of the userdata
|
||||
lua_gettable(L, -2); //get the table at __metameta[userdata]
|
||||
|
||||
//if this table doesn't exist yet
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); //pop nil
|
||||
|
||||
lua_pushvalue(L, 1); //copy userdata (key)
|
||||
lua_createtable(L, 0, 0); //new table (value)
|
||||
lua_settable(L, -3); //create the new table in __metameta
|
||||
|
||||
lua_pushvalue(L, 1); //copy userdata (key)
|
||||
lua_gettable(L, -2); //get the newly created table
|
||||
}
|
||||
|
||||
//set the value at __metameta[userdata][key] = value
|
||||
lua_pushvalue(L, 2); //copy the key
|
||||
lua_pushvalue(L, 3); //copy the value
|
||||
lua_settable(L, -3); //set value in the deepest table
|
||||
|
||||
//return
|
||||
return 0;
|
||||
}
|
||||
|
||||
static luaL_Reg metatable[] = {
|
||||
{"__index", index},
|
||||
{"__newindex", newindex},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
int createUserdataMetatable(lua_State* L) {
|
||||
//create the userdata metatable
|
||||
lua_pushlightuserdata(L, nullptr); //anon userdata
|
||||
lua_createtable(L, 0, 0); //table
|
||||
|
||||
//insert meta-metatable
|
||||
lua_pushstring(L, METAMETA);
|
||||
lua_createtable(L, 0, 0);
|
||||
lua_settable(L, -3);
|
||||
|
||||
//insert metatable blocker
|
||||
lua_pushstring(L, "__metatable");
|
||||
lua_createtable(L, 0, 0);
|
||||
lua_settable(L, -3);
|
||||
|
||||
//insert metamethods
|
||||
for (luaL_Reg* it = metatable; it->name; it++) {
|
||||
lua_pushstring(L, it->name);
|
||||
lua_pushcfunction(L, it->func);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
//set in the object & pop the anon userdata
|
||||
lua_setmetatable(L, -2); //set the metatable for userdata
|
||||
lua_pop(L, 1); //pop the anon userdata
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -19,12 +19,11 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef ROOMSYSTEMAPI_HPP_
|
||||
#define ROOMSYSTEMAPI_HPP_
|
||||
#ifndef METATABLES_HPP_
|
||||
#define METATABLES_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_ROOM_SYSTEM_API "room_system"
|
||||
LUAMOD_API int openRoomSystemAPI(lua_State* L);
|
||||
int createUserdataMetatable(lua_State* L);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
/* 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 "trigger_api.hpp"
|
||||
|
||||
#include "trigger_data.hpp"
|
||||
|
||||
//hamdle
|
||||
static int setHandle(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
trigger->SetHandle(lua_tostring(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getHandle(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
lua_pushstring(L, trigger->GetHandle().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//origin
|
||||
static int setOrigin(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
trigger->SetOrigin(Vector2(lua_tonumber(L, 2), lua_tonumber(L, 3)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getOrigin(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
lua_pushnumber(L, trigger->GetOrigin().x);
|
||||
lua_pushnumber(L, trigger->GetOrigin().y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//bounds
|
||||
static int setBoundingBox(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
trigger->SetBoundingBox(BoundingBox(
|
||||
lua_tonumber(L, 2),
|
||||
lua_tonumber(L, 3),
|
||||
lua_tonumber(L, 4),
|
||||
lua_tonumber(L, 5)
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getBoundingBox(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, trigger->GetBoundingBox().x);
|
||||
lua_pushinteger(L, trigger->GetBoundingBox().y);
|
||||
lua_pushinteger(L, trigger->GetBoundingBox().w);
|
||||
lua_pushinteger(L, trigger->GetBoundingBox().h);
|
||||
return 4;
|
||||
}
|
||||
|
||||
//triggers
|
||||
static int setReference(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, trigger->GetScriptReference());
|
||||
trigger->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getReference(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, trigger->GetScriptReference());
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pushExclusionEntity(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
trigger->GetExclusionList()->push_back(static_cast<Entity*>(lua_touserdata(L, 2)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int removeExclusionEntity(lua_State* L) {
|
||||
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 2));
|
||||
trigger->GetExclusionList()->remove_if([entity](Entity* ptr){
|
||||
return entity == ptr;
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg triggerLib[] = {
|
||||
{"SetHandle", setHandle},
|
||||
{"GetHandle", getHandle},
|
||||
|
||||
{"SetOrigin",setOrigin},
|
||||
{"GetOrigin",getOrigin},
|
||||
|
||||
{"SetBounds",setBoundingBox},
|
||||
{"GetBounds",getBoundingBox},
|
||||
|
||||
{"SetScript",setReference},
|
||||
{"GetScript",getReference},
|
||||
|
||||
{"PushExclusionEntity", pushExclusionEntity},
|
||||
{"RemoveExclusionEntity", removeExclusionEntity},
|
||||
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openTriggerAPI(lua_State* L) {
|
||||
luaL_newlib(L, triggerLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MAPSYSTEMAPI_HPP_
|
||||
#define MAPSYSTEMAPI_APP_
|
||||
#ifndef TRIGGERAPI_HPP_
|
||||
#define TRIGGERAPI_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_MAP_SYSTEM_API "map_system"
|
||||
LUAMOD_API int openMapSystemAPI(lua_State* L);
|
||||
#define TORTUGA_TRIGGER_API "trigger"
|
||||
LUAMOD_API int openTriggerAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -19,28 +19,40 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "waypoint_data.hpp"
|
||||
#include "trigger_data.hpp"
|
||||
|
||||
int WaypointData::SetTriggerReference(int i) {
|
||||
return triggerRef = i;
|
||||
std::string TriggerData::SetHandle(std::string s) {
|
||||
return handle = s;
|
||||
}
|
||||
|
||||
int WaypointData::GetTriggerReference() {
|
||||
return triggerRef;
|
||||
std::string TriggerData::GetHandle() const {
|
||||
return handle;
|
||||
}
|
||||
|
||||
BoundingBox WaypointData::SetBoundingBox(BoundingBox b) {
|
||||
return bounds = b;
|
||||
}
|
||||
|
||||
BoundingBox WaypointData::GetBoundingBox() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
Vector2 WaypointData::SetOrigin(Vector2 v) {
|
||||
Vector2 TriggerData::SetOrigin(Vector2 v) {
|
||||
return origin = v;
|
||||
}
|
||||
|
||||
Vector2 WaypointData::GetOrigin() {
|
||||
Vector2 TriggerData::GetOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
BoundingBox TriggerData::SetBoundingBox(BoundingBox b) {
|
||||
return bounds = b;
|
||||
}
|
||||
|
||||
BoundingBox TriggerData::GetBoundingBox() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
int TriggerData::SetScriptReference(int i) {
|
||||
return scriptRef = i;
|
||||
}
|
||||
|
||||
int TriggerData::GetScriptReference() {
|
||||
return scriptRef;
|
||||
}
|
||||
|
||||
std::list<Entity*>* TriggerData::GetExclusionList() {
|
||||
return &exclusionList;
|
||||
}
|
||||
@@ -19,20 +19,25 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef WAYPOINTDATA_HPP_
|
||||
#define WAYPOINTDATA_HPP_
|
||||
#ifndef TRIGGERDATA_HPP_
|
||||
#define TRIGGERDATA_HPP_
|
||||
|
||||
#include "bounding_box.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
class WaypointData {
|
||||
class TriggerData {
|
||||
public:
|
||||
WaypointData() = default;
|
||||
~WaypointData() = default;
|
||||
TriggerData() = default;
|
||||
~TriggerData() = default;
|
||||
|
||||
std::string SetHandle(std::string);
|
||||
std::string GetHandle() const;
|
||||
|
||||
Vector2 SetOrigin(Vector2 v);
|
||||
Vector2 GetOrigin();
|
||||
@@ -40,15 +45,17 @@ public:
|
||||
BoundingBox SetBoundingBox(BoundingBox b);
|
||||
BoundingBox GetBoundingBox();
|
||||
|
||||
int SetTriggerReference(int i);
|
||||
int GetTriggerReference();
|
||||
int SetScriptReference(int i);
|
||||
int GetScriptReference();
|
||||
|
||||
std::list<Entity*>* GetExclusionList();
|
||||
|
||||
private:
|
||||
friend class WaypointManager;
|
||||
|
||||
std::string handle;
|
||||
Vector2 origin;
|
||||
BoundingBox bounds;
|
||||
int triggerRef = LUA_NOREF;
|
||||
int scriptRef = LUA_NOREF;
|
||||
std::list<Entity*> exclusionList;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,47 +19,36 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "waypoint_manager.hpp"
|
||||
#include "trigger_manager.hpp"
|
||||
|
||||
WaypointManager::WaypointManager() {
|
||||
TriggerManager::TriggerManager() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
WaypointManager::~WaypointManager() {
|
||||
TriggerManager::~TriggerManager() {
|
||||
UnloadAll();
|
||||
}
|
||||
|
||||
int WaypointManager::Create() {
|
||||
int TriggerManager::Create(std::string handle) {
|
||||
//implicitly creates the element
|
||||
WaypointData& waypointData = elementMap[counter];
|
||||
TriggerData& triggerData = elementMap[counter];
|
||||
|
||||
//no real values set
|
||||
waypointData.origin = {0, 0};
|
||||
waypointData.bounds = {0, 0, 0, 0};
|
||||
triggerData.SetHandle(handle);
|
||||
|
||||
return counter++;
|
||||
}
|
||||
|
||||
int WaypointManager::Create(Vector2 origin, BoundingBox bounds) {
|
||||
//implicitly creates the element
|
||||
WaypointData& waypointData = elementMap[counter];
|
||||
|
||||
waypointData.origin = origin;
|
||||
waypointData.bounds = bounds;
|
||||
|
||||
return counter++;
|
||||
}
|
||||
|
||||
void WaypointManager::Unload(int uid) {
|
||||
void TriggerManager::Unload(int uid) {
|
||||
elementMap.erase(uid);
|
||||
}
|
||||
|
||||
void WaypointManager::UnloadAll() {
|
||||
void TriggerManager::UnloadAll() {
|
||||
//TODO: save?
|
||||
elementMap.clear();
|
||||
}
|
||||
|
||||
void WaypointManager::UnloadIf(std::function<bool(std::pair<const int, WaypointData const&>)> fn) {
|
||||
std::map<int, WaypointData>::iterator it = elementMap.begin();
|
||||
void TriggerManager::UnloadIf(std::function<bool(std::pair<const int, TriggerData const&>)> fn) {
|
||||
std::map<int, TriggerData>::iterator it = elementMap.begin();
|
||||
while (it != elementMap.end()) {
|
||||
if (fn(*it)) {
|
||||
it = elementMap.erase(it);
|
||||
@@ -70,8 +59,8 @@ void WaypointManager::UnloadIf(std::function<bool(std::pair<const int, WaypointD
|
||||
}
|
||||
}
|
||||
|
||||
WaypointData* WaypointManager::Get(int uid) {
|
||||
std::map<int, WaypointData>::iterator it = elementMap.find(uid);
|
||||
TriggerData* TriggerManager::Get(int uid) {
|
||||
std::map<int, TriggerData>::iterator it = elementMap.find(uid);
|
||||
|
||||
if (it == elementMap.end()) {
|
||||
return nullptr;
|
||||
@@ -80,19 +69,28 @@ WaypointData* WaypointManager::Get(int uid) {
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
int WaypointManager::GetLoadedCount() {
|
||||
TriggerData* TriggerManager::Get(std::string handle) {
|
||||
for (std::map<int, TriggerData>::iterator it = elementMap.begin(); it != elementMap.end(); ++it) {
|
||||
if (it->second.GetHandle() == handle) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int TriggerManager::GetLoadedCount() {
|
||||
return elementMap.size();
|
||||
}
|
||||
|
||||
std::map<int, WaypointData>* WaypointManager::GetContainer() {
|
||||
std::map<int, TriggerData>* TriggerManager::GetContainer() {
|
||||
return &elementMap;
|
||||
}
|
||||
|
||||
//hooks
|
||||
lua_State* WaypointManager::SetLuaState(lua_State* L) {
|
||||
lua_State* TriggerManager::SetLuaState(lua_State* L) {
|
||||
return lua = L;
|
||||
}
|
||||
|
||||
lua_State* WaypointManager::GetLuaState() {
|
||||
lua_State* TriggerManager::GetLuaState() {
|
||||
return lua;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef WAYPOINTMANAGER_HPP_
|
||||
#define WAYPOINTMANAGER_HPP_
|
||||
#ifndef TRIGGERMANAGER_HPP_
|
||||
#define TRIGGERMANAGER_HPP_
|
||||
|
||||
#include "bounding_box.hpp"
|
||||
#include "vector2.hpp"
|
||||
#include "waypoint_data.hpp"
|
||||
#include "trigger_data.hpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
@@ -32,23 +32,23 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class WaypointManager {
|
||||
class TriggerManager {
|
||||
public:
|
||||
WaypointManager();
|
||||
~WaypointManager();
|
||||
TriggerManager();
|
||||
~TriggerManager();
|
||||
|
||||
//common public methods
|
||||
int Create();
|
||||
int Create(Vector2 origin, BoundingBox bounds);
|
||||
int Create(std::string handle);
|
||||
void Unload(int uid);
|
||||
|
||||
void UnloadAll();
|
||||
void UnloadIf(std::function<bool(std::pair<const int, WaypointData const&>)> fn);
|
||||
void UnloadIf(std::function<bool(std::pair<const int, TriggerData const&>)> fn);
|
||||
|
||||
//accessors & mutators
|
||||
WaypointData* Get(int uid);
|
||||
TriggerData* Get(int uid);
|
||||
TriggerData* Get(std::string handle);
|
||||
int GetLoadedCount();
|
||||
std::map<int, WaypointData>* GetContainer();
|
||||
std::map<int, TriggerData>* GetContainer();
|
||||
|
||||
//hooks
|
||||
lua_State* SetLuaState(lua_State* L);
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
|
||||
private:
|
||||
//members
|
||||
std::map<int, WaypointData> elementMap;
|
||||
std::map<int, TriggerData> elementMap;
|
||||
lua_State* lua = nullptr;
|
||||
int counter = 0;
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
/* 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 "trigger_manager_api.hpp"
|
||||
|
||||
#include "trigger_manager.hpp"
|
||||
|
||||
static int create(lua_State* L) {
|
||||
//DOCS: params: create(triggerMgr, name[, originX, originY[, boundsX, boundsY, boundsW, boundsH]][, script])
|
||||
|
||||
//get the trigger manager
|
||||
TriggerManager* mgr = static_cast<TriggerManager*>(lua_touserdata(L, 1));
|
||||
|
||||
//create the trigger
|
||||
int index = mgr->Create(lua_tostring(L, 2));
|
||||
TriggerData* triggerData = mgr->Get(index);
|
||||
|
||||
//origin
|
||||
if (lua_gettop(L) >= 4) {
|
||||
triggerData->SetOrigin({lua_tonumber(L, 3), lua_tonumber(L, 4)}); //vectorX, vectorY
|
||||
}
|
||||
|
||||
//bounds
|
||||
if (lua_gettop(L) >= 8) {
|
||||
triggerData->SetBoundingBox({
|
||||
lua_tointeger(L, 5), //boundsX
|
||||
lua_tointeger(L, 6), //boundsY
|
||||
lua_tointeger(L, 7), //boundsW
|
||||
lua_tointeger(L, 8) //boundsH
|
||||
});
|
||||
}
|
||||
|
||||
//if the parameter list isn't capped with a script, append a nil instead
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
//set the script reference (may be nil)
|
||||
triggerData->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||
|
||||
//push to the scipts
|
||||
lua_pushlightuserdata(L, static_cast<void*>(triggerData));
|
||||
lua_pushinteger(L, index);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int unload(lua_State* L) {
|
||||
TriggerManager* mgr = static_cast<TriggerManager*>(lua_touserdata(L, 1));
|
||||
int count = 0; //the number removed
|
||||
|
||||
//based on the type
|
||||
switch(lua_type(L, 2)) {
|
||||
//unload this index
|
||||
case LUA_TNUMBER:
|
||||
mgr->UnloadIf([L, &count](std::pair<int, TriggerData const&> it) -> bool {
|
||||
if (it.first == lua_tointeger(L, 2)) {
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
//unload this name
|
||||
case LUA_TSTRING:
|
||||
mgr->UnloadIf([L, &count](std::pair<int, TriggerData const&> it) -> bool {
|
||||
if (it.second.GetHandle() == lua_tostring(L, 2)) {
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
//return the number removed
|
||||
lua_pushinteger(L, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getTrigger(lua_State* L) {
|
||||
TriggerManager* mgr = static_cast<TriggerManager*>(lua_touserdata(L, 1));
|
||||
TriggerData* triggerData = nullptr;
|
||||
|
||||
switch(lua_type(L, 2)) {
|
||||
case LUA_TNUMBER:
|
||||
triggerData = mgr->Get(lua_tointeger(L, 2));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
triggerData = mgr->Get(lua_tostring(L, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
if (triggerData) {
|
||||
lua_pushlightuserdata(L, static_cast<void*>(triggerData));
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int forEach(lua_State* L) {
|
||||
//TODO: (9) forEach()
|
||||
}
|
||||
|
||||
static int getLoadedCount(lua_State* L) {
|
||||
TriggerManager* mgr = static_cast<TriggerManager*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, mgr->GetLoadedCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg triggerManagerLib[] = {
|
||||
{"Create",create},
|
||||
{"Unload",unload},
|
||||
{"GetTrigger",getTrigger},
|
||||
{"GetCount",getLoadedCount},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openTriggerManagerAPI(lua_State* L) {
|
||||
luaL_newlib(L, triggerManagerLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MONSTERSYSTEMAPI_HPP_
|
||||
#define MONSTERSYSTEMAPI_HPP_
|
||||
#ifndef TRIGGERMANAGERAPI_HPP_
|
||||
#define TRIGGERMANAGERAPI_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_MONSTER_SYSTEM_API "monster_system"
|
||||
LUAMOD_API int openMonsterSystemAPI(lua_State* L);
|
||||
#define TORTUGA_TRIGGER_MANAGER_API "trigger_manager"
|
||||
LUAMOD_API int openTriggerManagerAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -1,91 +0,0 @@
|
||||
/* 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 "waypoint_api.hpp"
|
||||
|
||||
#include "waypoint_data.hpp"
|
||||
|
||||
//origin
|
||||
static int setOrigin(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
waypoint->SetOrigin(Vector2(lua_tonumber(L, 2), lua_tonumber(L, 3)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getOrigin(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
lua_pushnumber(L, waypoint->GetOrigin().x);
|
||||
lua_pushnumber(L, waypoint->GetOrigin().y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//bounds
|
||||
static int setBoundingBox(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
waypoint->SetBoundingBox(BoundingBox(
|
||||
lua_tonumber(L, 2),
|
||||
lua_tonumber(L, 3),
|
||||
lua_tonumber(L, 4),
|
||||
lua_tonumber(L, 5)
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getBoundingBox(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
lua_pushnumber(L, waypoint->GetBoundingBox().x);
|
||||
lua_pushnumber(L, waypoint->GetBoundingBox().y);
|
||||
lua_pushnumber(L, waypoint->GetBoundingBox().w);
|
||||
lua_pushnumber(L, waypoint->GetBoundingBox().h);
|
||||
return 4;
|
||||
}
|
||||
|
||||
//triggers
|
||||
static int setTriggerReference(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, waypoint->GetTriggerReference());
|
||||
waypoint->SetTriggerReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getTriggerReference(lua_State* L) {
|
||||
WaypointData* waypoint = static_cast<WaypointData*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, waypoint->GetTriggerReference());
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg waypointLib[] = {
|
||||
{"SetOrigin",setOrigin},
|
||||
{"GetOrigin",getOrigin},
|
||||
|
||||
{"SetBounds",setBoundingBox},
|
||||
{"GetBounds",getBoundingBox},
|
||||
|
||||
{"SetTrigger",setTriggerReference},
|
||||
{"GetTrigger",getTriggerReference},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openWaypointAPI(lua_State* L) {
|
||||
luaL_newlib(L, waypointLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* 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 "waypoint_manager_api.hpp"
|
||||
|
||||
#include "waypoint_manager.hpp"
|
||||
|
||||
//TODO: figure out a way to iterate through elements of managers from lua
|
||||
|
||||
static int create(lua_State* L) {
|
||||
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
|
||||
}
|
||||
|
||||
static int unload(lua_State* L) {
|
||||
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
|
||||
}
|
||||
|
||||
static int getWaypoint(lua_State* L) {
|
||||
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
|
||||
lua_pushlightuserdata(L, mgr->Get(lua_tointeger(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getLoadedCount(lua_State* L) {
|
||||
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, mgr->GetLoadedCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg waypointManagerLib[] = {
|
||||
{"Create",create},
|
||||
{"Unload",unload},
|
||||
{"GetWaypoint",getWaypoint},
|
||||
{"GetCount",getLoadedCount},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openWaypointManagerAPI(lua_State* L) {
|
||||
luaL_newlib(L, waypointManagerLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/* 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 WAYPOINTMANAGERAPI_HPP_
|
||||
#define WAYPOINTMANAGERAPI_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_WAYPOINT_MANAGER_API "waypoint_manager"
|
||||
LUAMOD_API int openWaypointManagerAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
/* 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 "waypoint_system_api.hpp"
|
||||
|
||||
//all waypoint API headers
|
||||
#include "waypoint_api.hpp"
|
||||
#include "waypoint_manager_api.hpp"
|
||||
|
||||
//useful "globals"
|
||||
//...
|
||||
|
||||
//This mimics linit.c to create a nested collection of all waypoint modules.
|
||||
static const luaL_Reg funcs[] = {
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const luaL_Reg libs[] = {
|
||||
{"Waypoint", openWaypointAPI},
|
||||
{"WaypointManager", openWaypointManagerAPI},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
int openWaypointSystemAPI(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;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/* 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 WAYPOINTSYSTEMAPI_HPP_
|
||||
#define WAYPOINTSYSTEMAPI_HPP_
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#define TORTUGA_WAYPOINT_SYSTEM_API "waypoint_system"
|
||||
LUAMOD_API int openWaypointSystemAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -1,19 +1,19 @@
|
||||
TODO: In need of script APIs (list)
|
||||
* Characters
|
||||
TODO: upgrade to lua 5.3
|
||||
TODO: Split config.cfg in two, one for the server and the client
|
||||
TODO: Consistency for bounds names
|
||||
|
||||
TODO: Account passwords (list)
|
||||
* backbone account server OR
|
||||
* social network login OR
|
||||
* ...
|
||||
* salts & hashes
|
||||
* login screen prompting for username & password
|
||||
|
||||
TODO: Features
|
||||
* 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
|
||||
* 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. (trigger system)
|
||||
* Fix shoddy movement
|
||||
* Periodic mass server saves
|
||||
* Remove the big "Shut Down" button (currently broken...)
|
||||
* Make a way for the server owner to control the server directly
|
||||
* The TileSheet class should implement the surface itself
|
||||
@@ -22,6 +22,4 @@ TODO: Features
|
||||
* Fix the const-ness of accessors
|
||||
* Add a screenshot of the game to README.md
|
||||
* joystick/gamepad support
|
||||
* add the tilesheet to the map system
|
||||
* ping/delay displayed in the lobby
|
||||
* login screen prompting for username & password
|
||||
* add the tilesheet to the map system
|
||||
Reference in New Issue
Block a user