Merge branch 'develop', read more

The trigger system has been fully implemented, as well as a few other
tweaks as the occasional thought came to mind.

Multiple rooms are now fully functional, mostly as a way to test the
triggers. Although there are still no real generation algorithms, a
utility for creating door pairs between given rooms is included in the
scripts directory.

Other changes in this merge include:

* Network updates via lua
* Entity types can be determined in lua
* Database columns are now order independant

It should be noted that only two types of userdata will work as far as
entity names are concerned: Characters and Monsters. I tried getting it to
work for all objects passed to lua, but it proved to be too obtuse.

In theory, I could create a teleport puzzle using what I've written here.
That might be a side project, or a way to test saving & loading systems. I
don't see any reason to delay monsters any longer; hopefully, I can get
them going soon too.
This commit is contained in:
Kayne Ruse
2015-03-13 21:28:05 +11:00
70 changed files with 1010 additions and 868 deletions
+1 -1
View File
@@ -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) {
+28 -14
View File
@@ -67,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
@@ -109,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;
@@ -120,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) {
@@ -146,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) {
@@ -170,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()
}
//-------------------------
+3 -3
View File
@@ -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()
}
+1 -2
View File
@@ -91,10 +91,9 @@ void World::SendDisconnectRequest() {
}
void World::SendAdminDisconnectForced() {
//TODO: (9) empty
//TODO: (9) World::SendAdminDisconnectForced()
}
void World::SendAdminShutdownRequest() {
ClientPacket newPacket;
+2 -9
View File
@@ -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;
@@ -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;
}
+4 -4
View File
@@ -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()
}
+4 -3
View File
@@ -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
}
//-------------------------
-55
View File
@@ -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;
}
-30
View File
@@ -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 MAPSYSTEMAPI_HPP_
#define MAPSYSTEMAPI_APP_
#include "lua.hpp"
#define TORTUGA_MAP_SYSTEM_API "map_system"
LUAMOD_API int openMapSystemAPI(lua_State* L);
#endif
+1 -1
View File
@@ -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
+1
View File
@@ -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));
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -34,7 +34,7 @@
typedef SerialPacketBase SerialPacket;
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20150221;
constexpr int NETWORK_VERSION = 20150304;
union MaxPacket {
CharacterPacket a;
+63
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
+20 -30
View File
@@ -1,46 +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")
characterSystem = require("character_system")
networkSystem = require("network")
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
roomSystem.RoomManager.SetOnCreate(function(room, index)
print("", "Creating room: ", roomSystem.Room.GetName(room), index)
roomManagerAPI.SetOnCreate(function(room, index)
print("", "Creating room: ", roomAPI.GetName(room), index)
--called ~60 times per second
roomSystem.Room.SetOnTick(room, function(room)
--[[
local character = characterSystem.CharacterManager.GetCharacter("handle")
if character ~= nil then
--debugging
local originX, originY = characterSystem.Character.GetOrigin(character)
local motionX, motionY = characterSystem.Character.GetMotion(character)
if motionY < 0 then
characterSystem.Character.SetMotion(character, motionX, 0)
networkSystem.PumpCharacterUpdate(character)
print("Sending: ", motionX, motionY)
end
end
--]]
roomAPI.SetOnTick(room, function(room)
roomAPI.ForEachCharacter(room, function(character)
--
end)
end)
end)
roomSystem.RoomManager.SetOnUnload(function(room, index)
print("", "Unloading room: ", roomSystem.Room.GetName(room), index)
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")
+7 -3
View File
@@ -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),
+23 -7
View File
@@ -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
+58 -7
View File
@@ -22,8 +22,58 @@
#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));
@@ -44,6 +94,7 @@ static int getAvatar(lua_State* L) {
}
static const luaL_Reg characterLib[] = {
{"SetRoom", setRoom},
// {"GetOwner", getOwner}, //unusable without account API
{"GetHandle", getHandle},
{"GetAvatar", getAvatar},
@@ -51,27 +102,27 @@ static const luaL_Reg characterLib[] = {
};
LUAMOD_API int openCharacterAPI(lua_State* L) {
//the local table
luaL_newlib(L, characterLib);
//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, 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 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;
+4
View File
@@ -21,6 +21,10 @@
*/
#include "character_data.hpp"
CharacterData::CharacterData(): Entity("character") {
//EMPTY
}
int CharacterData::GetOwner() {
return owner;
}
+2 -2
View File
@@ -32,7 +32,7 @@
class CharacterData: public Entity {
public:
CharacterData() = default;
CharacterData();
~CharacterData() = default;
//database stuff
@@ -43,7 +43,7 @@ public:
private:
friend class CharacterManager;
int owner;
int owner = -1;
std::string handle;
std::string avatar;
};
+56 -6
View File
@@ -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...
+25 -7
View File
@@ -23,24 +23,29 @@
#include "character_manager.hpp"
#include <sstream>
#include <stdexcept>
//TODO: (1) character hooks?
static int setOnCreate(lua_State* L) {
//TODO: (9) empty
//TODO: (9) setOnCreate()
}
static int setOnLoad(lua_State* L) {
//TODO: (9) empty
//TODO: (9) setOnLoad()
}
static int setOnSave(lua_State* L) {
//TODO: (9) empty
//TODO: (9) setOnSave()
}
static int setOnUnload(lua_State* L) {
//TODO: (9) empty
//TODO: (9) setOnUnload()
}
static int setOnDelete(lua_State* L) {
//TODO: (9) empty
//TODO: (9) setOnDelete()
}
static int getCharacter(lua_State* L) {
@@ -75,7 +80,20 @@ static int getLoadedCount(lua_State* L) {
}
static int forEach(lua_State* L) {
//TODO: (1) find a way to update the clients when a script alters a character's data
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[] = {
@@ -86,7 +104,7 @@ static const luaL_Reg characterManagerLib[] = {
// {"SetOnDelete", setOnDelete},
{"GetCharacter", getCharacter},
{"GetLoadedCount", getLoadedCount},
// {"ForEach", forEach},
{"ForEach", forEach},
{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 "character_system_api.hpp"
//all character API headers
#include "character_api.hpp"
#include "character_manager_api.hpp"
//useful "globals"
//...
//This mimics linit.c to create a nested collection of all character modules.
static const luaL_Reg funcs[] = {
{nullptr, nullptr}
};
static const luaL_Reg libs[] = {
{"Character", openCharacterAPI},
{"CharacterManager", openCharacterManagerAPI},
{nullptr, nullptr}
};
int openCharacterSystemAPI(lua_State* L) {
//create the table
luaL_newlibtable(L, libs);
//push the "global" functions
luaL_setfuncs(L, funcs, 0);
//push the substable
for (const luaL_Reg* lib = libs; lib->func; lib++) {
lib->func(L);
lua_setfield(L, -2, lib->name);
}
return 1;
}
@@ -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 CHARACTERSYSTEMAPI_HPP_
#define CHARACTERSYSTEMAPI_HPP_
#include "lua.hpp"
#define TORTUGA_CHARACTER_SYSTEM_API "character_system"
LUAMOD_API int openCharacterSystemAPI(lua_State* L);
#endif
+1 -1
View File
@@ -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))
+20
View File
@@ -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;
}
+14 -3
View File
@@ -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
+29
View File
@@ -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());
@@ -61,13 +72,31 @@ static int getMotion(lua_State* L) {
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}
};
+20 -10
View File
@@ -37,12 +37,17 @@
#include "lua.hpp"
#include "entity_api.hpp"
#include "character_system_api.hpp"
#include "map_system_api.hpp"
#include "monster_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_system_api.hpp"
#include "waypoint_system_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[] = {
@@ -63,12 +68,17 @@ static const luaL_Reg loadedlibs[] = {
//these libs are preloaded and must be required before used
static const luaL_Reg preloadedlibs[] = {
{TORTUGA_ENTITY_API, openEntityAPI}, //required by derived classes
{TORTUGA_CHARACTER_SYSTEM_API, openCharacterSystemAPI},
{TORTUGA_MAP_SYSTEM_API, openMapSystemAPI},
{TORTUGA_MONSTER_SYSTEM_API, openMonsterSystemAPI},
{TORTUGA_CHARACTER_API, openCharacterAPI},
{TORTUGA_CHARACTER_MANAGER_API, openCharacterManagerAPI},
{TORTUGA_MONSTER_API, openMonsterAPI},
{TORTUGA_MONSTER_MANAGER_API, openMonsterManagerAPI},
{TORTUGA_NETWORK_API, openNetworkAPI},
{TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI},
{TORTUGA_WAYPOINT_SYSTEM_API, openWaypointSystemAPI},
{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}
};
-1
View File
@@ -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
View File
@@ -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)
+6 -6
View File
@@ -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;
+4
View File
@@ -21,6 +21,10 @@
*/
#include "monster_data.hpp"
MonsterData::MonsterData(): Entity("monster") {
//EMPTY
}
std::string MonsterData::SetAvatar(std::string s) {
return avatar = s;
}
+4 -2
View File
@@ -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
+11 -11
View File
@@ -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()
}
-55
View File
@@ -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;
}
-30
View File
@@ -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 MONSTERSYSTEMAPI_HPP_
#define MONSTERSYSTEMAPI_HPP_
#include "lua.hpp"
#define TORTUGA_MONSTER_SYSTEM_API "monster_system"
LUAMOD_API int openMonsterSystemAPI(lua_State* L);
#endif
+1 -1
View File
@@ -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))
+32 -3
View File
@@ -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,14 +62,31 @@ 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());
@@ -74,6 +94,12 @@ static int setOnTick(lua_State* L) {
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;
}
static int initialize(lua_State* L) {
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
@@ -95,9 +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}
+73 -9
View File
@@ -21,19 +21,83 @@
*/
#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)) {
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);
return;
}
//call the tick function, with this as a parameter
lua_pushlightuserdata(lua, this);
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
//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();
}
}
@@ -61,8 +125,8 @@ MonsterManager* RoomData::GetMonsterMgr() {
return &monsterMgr;
}
WaypointManager* RoomData::GetWaypointMgr() {
return &waypointMgr;
TriggerManager* RoomData::GetTriggerMgr() {
return &triggerMgr;
}
std::list<CharacterData*>* RoomData::GetCharacterList() {
@@ -73,7 +137,7 @@ lua_State* RoomData::SetLuaState(lua_State* L) {
lua = L;
pager.SetLuaState(lua);
monsterMgr.SetLuaState(lua);
waypointMgr.SetLuaState(lua);
triggerMgr.SetLuaState(lua);
return lua;
}
+3 -3
View File
@@ -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"
@@ -48,7 +48,7 @@ public:
RegionPagerLua* GetPager();
MonsterManager* GetMonsterMgr();
WaypointManager* GetWaypointMgr();
TriggerManager* GetTriggerMgr();
std::list<CharacterData*>* GetCharacterList();
//API interfaces
@@ -70,7 +70,7 @@ private:
//members
RegionPagerLua pager;
MonsterManager monsterMgr;
WaypointManager waypointMgr;
TriggerManager triggerMgr;
std::list<CharacterData*> characterList;
//API
-55
View File
@@ -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;
}
+8 -17
View File
@@ -205,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());
//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());
//send the delete & create messages
pumpAndChangeRooms(characterData, argPacket->roomIndex, argPacket->characterIndex);
}
//if not moving between rooms
else {
@@ -243,9 +234,9 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
}
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()
}
+3 -3
View File
@@ -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()
}
+5 -5
View File
@@ -76,21 +76,21 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
}
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()
}
+2 -2
View File
@@ -30,7 +30,7 @@
//-------------------------
void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) {
//TODO: (9) empty
//TODO: (9) ServerApplication::hAdminDisconnectForced()
}
void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
@@ -85,5 +85,5 @@ void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
}
void ServerApplication::SaveServerState() {
//TODO: (9) empty
//TODO: (3) Periodic mass server saves
}
+1 -1
View File
@@ -22,5 +22,5 @@
#include "server_application.hpp"
void ServerApplication::hMonsterDamage(MonsterPacket* const argPacket) {
//TODO: (9) empty
//TODO: (9) ServerApplication::hMonsterDamage()
}
+1 -1
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=. ../accounts ../characters ../clients ../entities ../monsters ../rooms ../waypoints ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
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))
@@ -140,6 +140,10 @@ void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
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);
@@ -148,4 +152,31 @@ void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
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());
}
@@ -22,14 +22,20 @@
#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
+126
View File
@@ -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 WAYPOINTAPI_HPP_
#define WAYPOINTAPI_HPP_
#ifndef TRIGGERAPI_HPP_
#define TRIGGERAPI_HPP_
#include "lua.hpp"
#define TORTUGA_WAYPOINT_API "waypoint"
LUAMOD_API int openWaypointAPI(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;
};
+148
View File
@@ -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 ROOMSYSTEMAPI_HPP_
#define ROOMSYSTEMAPI_HPP_
#ifndef TRIGGERMANAGERAPI_HPP_
#define TRIGGERMANAGERAPI_HPP_
#include "lua.hpp"
#define TORTUGA_ROOM_SYSTEM_API "room_system"
LUAMOD_API int openRoomSystemAPI(lua_State* L);
#define TORTUGA_TRIGGER_MANAGER_API "trigger_manager"
LUAMOD_API int openTriggerManagerAPI(lua_State* L);
#endif
-91
View File
@@ -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;
}
-59
View File
@@ -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;
}
-30
View File
@@ -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
-55
View File
@@ -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;
}
-30
View File
@@ -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
+4 -8
View File
@@ -1,21 +1,19 @@
TODO: upgrade to lua 5.3
TODO: Split config.cfg in two, one for the server and the client
TODO: In need of script APIs (list)
* Characters
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
* 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
@@ -24,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