Merge branch 'develop'

This commit is contained in:
Kayne Ruse
2014-08-19 04:19:21 +10:00
53 changed files with 647 additions and 896 deletions
+4 -4
View File
@@ -21,14 +21,14 @@
*/
#include "character.hpp"
void Character::Update(double delta) {
void Character::Update() {
if (motion.x && motion.y) {
origin += motion * delta * CHARACTER_WALKING_MOD;
origin += motion * CHARACTER_WALKING_MOD;
}
else if (motion != 0) {
origin += motion * delta;
origin += motion;
}
sprite.Update(delta);
sprite.Update(0.016);
}
void Character::DrawTo(SDL_Surface* const dest, int camX, int camY) {
+1 -1
View File
@@ -40,7 +40,7 @@ public:
Character() = default;
~Character() = default;
void Update(double delta);
void Update();
//graphics
void DrawTo(SDL_Surface* const, int camX, int camY);
+3 -3
View File
@@ -120,7 +120,6 @@ void ClientApplication::Proc() {
//prepare the time system
typedef std::chrono::steady_clock Clock;
std::chrono::duration<int, std::milli> delta(16);
Clock::time_point simTime = Clock::now();
Clock::time_point realTime;
@@ -138,8 +137,9 @@ void ClientApplication::Proc() {
//simulate game time
while (simTime < realTime) {
//call each user defined function
activeScene->RunFrame(double(delta.count()) / std::chrono::duration<int, std::milli>::period::den);
simTime += delta;
activeScene->RunFrame();
//~60 FPS
simTime += std::chrono::duration<int, std::milli>(16);
}
//draw the game to the screen
+3 -2
View File
@@ -75,10 +75,10 @@ SceneList BaseScene::GetNextScene() const {
//Frame loop
//-------------------------
void BaseScene::RunFrame(double delta) {
void BaseScene::RunFrame() {
FrameStart();
HandleEvents();
Update(delta);
Update();
FrameEnd();
}
@@ -86,6 +86,7 @@ void BaseScene::RenderFrame() {
SDL_FillRect(screen, 0, 0);
Render(screen);
SDL_Flip(screen);
SDL_Delay(10);
}
//-------------------------
+2 -2
View File
@@ -40,13 +40,13 @@ public:
SceneList GetNextScene() const;
//Frame loop
virtual void RunFrame(double delta);
virtual void RunFrame();
virtual void RenderFrame();
protected:
virtual void FrameStart() {}
virtual void HandleEvents();
virtual void Update(double delta) {}
virtual void Update() {}
virtual void FrameEnd() {}
virtual void Render(SDL_Surface* const screen) {}
+2 -9
View File
@@ -80,22 +80,15 @@ CleanUp::~CleanUp() {
//Frame loop
//-------------------------
void CleanUp::Update(double delta) {
void CleanUp::Update() {
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(10)) {
QuitEvent();
SetNextScene(SceneList::MAINMENU);
}
//BUGFIX: Eat incoming packets
while(network.Receive());
}
void CleanUp::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void CleanUp::Render(SDL_Surface* const screen) {
backButton.DrawTo(screen);
font.DrawStringTo("You have been disconnected.", screen, 50, 30);
+2 -8
View File
@@ -30,12 +30,8 @@
#include "raster_font.hpp"
#include "button.hpp"
//common
#include "frame_rate.hpp"
#include "character.hpp"
//client
#include "character.hpp"
#include "base_scene.hpp"
//std namespace
@@ -54,8 +50,7 @@ public:
protected:
//Frame loop
void Update(double delta);
void RenderFrame();
void Update();
void Render(SDL_Surface* const);
//Event handlers
@@ -79,7 +74,6 @@ protected:
//UI
Button backButton;
FrameRate fps;
//auto return
std::chrono::steady_clock::time_point startTick;
+11 -6
View File
@@ -92,17 +92,17 @@ void InWorld::FrameStart() {
//
}
void InWorld::Update(double delta) {
void InWorld::Update() {
//suck in and process all waiting packets
SerialPacket* packetBuffer = static_cast<SerialPacket*>(malloc(MAX_PACKET_SIZE));
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
free(static_cast<void*>(packetBuffer));
delete reinterpret_cast<char*>(packetBuffer);
//update the characters
for (auto& it : characterMap) {
it.second.Update(delta);
it.second.Update();
}
//check the map
@@ -129,7 +129,7 @@ void InWorld::Update(double delta) {
}
if ((localCharacter->GetOrigin() + localCharacter->GetBounds()).CheckOverlap(wallBounds)) {
localCharacter->SetOrigin(localCharacter->GetOrigin() - (localCharacter->GetMotion() * delta));
localCharacter->SetOrigin(localCharacter->GetOrigin() - (localCharacter->GetMotion()));
localCharacter->SetMotion({0,0});
localCharacter->CorrectSprite();
SendPlayerUpdate();
@@ -312,7 +312,12 @@ void InWorld::HandleCharacterNew(CharacterPacket* const argPacket) {
newCharacter.SetOrigin(argPacket->origin);
newCharacter.SetMotion(argPacket->motion);
newCharacter.SetBounds({0, 16, 32, 32}); //TODO: magic numbers, fix this
newCharacter.SetBounds({
CHARACTER_BOUNDS_X,
CHARACTER_BOUNDS_Y,
CHARACTER_BOUNDS_WIDTH,
CHARACTER_BOUNDS_HEIGHT
});
(*newCharacter.GetStats()) = argPacket->stats;
+1 -1
View File
@@ -59,7 +59,7 @@ public:
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void RenderFrame();
void Render(SDL_Surface* const);
+3 -3
View File
@@ -82,13 +82,13 @@ void LobbyMenu::FrameStart() {
//
}
void LobbyMenu::Update(double delta) {
void LobbyMenu::Update() {
//suck in and process all waiting packets
SerialPacket* packetBuffer = static_cast<SerialPacket*>(malloc(MAX_PACKET_SIZE));
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
free(static_cast<void*>(packetBuffer));
delete reinterpret_cast<char*>(packetBuffer);
}
void LobbyMenu::FrameEnd() {
+1 -1
View File
@@ -47,7 +47,7 @@ public:
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void Render(SDL_Surface* const);
+1 -1
View File
@@ -72,7 +72,7 @@ void MainMenu::FrameStart() {
//
}
void MainMenu::Update(double delta) {
void MainMenu::Update() {
//
}
+1 -1
View File
@@ -37,7 +37,7 @@ public:
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void Render(SDL_Surface* const);
+1 -1
View File
@@ -59,7 +59,7 @@ void OptionsMenu::FrameStart() {
//
}
void OptionsMenu::Update(double delta) {
void OptionsMenu::Update() {
//
}
+1 -1
View File
@@ -38,7 +38,7 @@ public:
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void Render(SDL_Surface* const);
+1 -1
View File
@@ -40,7 +40,7 @@ SplashScreen::~SplashScreen() {
//Frame loop
//-------------------------
void SplashScreen::Update(double delta) {
void SplashScreen::Update() {
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(1)) {
SetNextScene(SceneList::MAINMENU);
}
+1 -1
View File
@@ -36,7 +36,7 @@ public:
protected:
//Frame loop
void Update(double delta);
void Update();
void Render(SDL_Surface* const);
//members
+6 -4
View File
@@ -25,11 +25,13 @@
#include <cmath>
//the speeds that the characters move
constexpr double CHARACTER_WALKING_SPEED = 140.0;
constexpr double CHARACTER_WALKING_SPEED = 2.24;
constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0);
//the bounding boxes for the characters
constexpr double CHARACTER_BOUNDS_WIDTH = 32.0;
constexpr double CHARACTER_BOUNDS_HEIGHT = 32.0;
//the bounds for the character objects, mapped to the default sprites
constexpr int CHARACTER_BOUNDS_X = 0;
constexpr int CHARACTER_BOUNDS_Y = 16;
constexpr int CHARACTER_BOUNDS_WIDTH = 32;
constexpr int CHARACTER_BOUNDS_HEIGHT = 32;
#endif
-25
View File
@@ -78,27 +78,6 @@ static int getDepth(lua_State* L) {
return 1;
}
static int load(lua_State* L) {
//EMPTY
lua_pushboolean(L, false);
return 1;
}
static int save(lua_State* L) {
//EMPTY
return 0;
}
static int create(lua_State* L) {
//EMPTY
return 0;
}
static int unload(lua_State* L) {
//EMPTY
return 0;
}
static const luaL_Reg regionLib[] = {
{"SetTile",setTile},
{"GetTile",getTile},
@@ -109,10 +88,6 @@ static const luaL_Reg regionLib[] = {
{"GetWidth",getWidth},
{"GetHeight",getHeight},
{"GetDepth",getDepth},
{"Load",load},
{"Save",save},
{"Create",create},
{"Unload",unload},
{nullptr, nullptr}
};
+39
View File
@@ -90,16 +90,55 @@ static int unloadRegion(lua_State* L) {
return 0;
}
static int setOnLoad(lua_State* L) {
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
luaL_unref(L, LUA_REGISTRYINDEX, pager->GetLoadReference());
pager->SetLoadReference(luaL_ref(L, LUA_REGISTRYINDEX));
return 0;
}
static int setOnSave(lua_State* L) {
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
luaL_unref(L, LUA_REGISTRYINDEX, pager->GetSaveReference());
pager->SetSaveReference(luaL_ref(L, LUA_REGISTRYINDEX));
return 0;
}
static int setOnCreate(lua_State* L) {
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
luaL_unref(L, LUA_REGISTRYINDEX, pager->GetCreateReference());
pager->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX));
return 0;
}
static int setOnUnload(lua_State* L) {
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
luaL_unref(L, LUA_REGISTRYINDEX, pager->GetUnloadReference());
pager->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX));
return 0;
}
static const luaL_Reg regionPagerLib[] = {
//curry
{"SetTile", setTile},
{"GetTile", getTile},
{"SetSolid", setSolid},
{"GetSolid", getSolid},
//access and control
{"GetRegion", getRegion},
{"LoadRegion", loadRegion},
{"SaveRegion", saveRegion},
{"CreateRegion", createRegion},
{"UnloadRegion", unloadRegion},
//triggers
{"SetOnLoad",setOnLoad},
{"SetOnSave",setOnSave},
{"SetOnCreate",setOnCreate},
{"SetOnUnload",setOnUnload},
//sentinel
{nullptr, nullptr}
};
+94 -34
View File
@@ -25,43 +25,71 @@
#include <stdexcept>
//TODO: Could I push the pager to the API functions too?
Region* RegionPagerLua::LoadRegion(int x, int y) {
//load the region if possible
//get the pager's function from the registry
lua_rawgeti(lua, LUA_REGISTRYINDEX, loadRef);
//check if this function is available
if (lua_isnil(lua, -1)) {
lua_pop(lua, 1);
return nullptr;
}
//something to work on
Region tmpRegion(x, y);
//API hook
lua_getglobal(lua, "Region");
lua_getfield(lua, -1, "Load");
lua_pushlightuserdata(lua, &tmpRegion);
//call the funtion, 1 arg, 1 return
if (lua_pcall(lua, 1, 1, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
//success or failure
if (!lua_toboolean(lua, -1)) {
lua_pop(lua, 2);
//check the return value, success or failure
if (lua_toboolean(lua, -1)) {
lua_pop(lua, 1);
regionList.push_front(tmpRegion);
return &regionList.front();
}
else {
lua_pop(lua, 1);
return nullptr;
}
lua_pop(lua, 2);
regionList.push_front(tmpRegion);
return &regionList.front();
}
Region* RegionPagerLua::SaveRegion(int x, int y) {
//find & save the region
Region* ptr = FindRegion(x, y);
if (ptr) {
//API hook
lua_getglobal(lua, "Region");
lua_getfield(lua, -1, "Save");
lua_pushlightuserdata(lua, ptr);
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
//get the pager's function from the registry
lua_rawgeti(lua, LUA_REGISTRYINDEX, saveRef);
//check if this function is available
if (lua_isnil(lua, -1)) {
lua_pop(lua, 1);
return nullptr;
}
//find the specified region
Region* ptr = FindRegion(x, y);
if (!ptr) {
lua_pop(lua, 1);
return nullptr;
}
lua_pushlightuserdata(lua, ptr);
//call the function, 1 arg, 1 return
if (lua_pcall(lua, 1, 1, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
//check the return value, success or failure
if (lua_toboolean(lua, -1)) {
lua_pop(lua, 1);
return ptr;
}
else {
lua_pop(lua, 1);
return nullptr;
}
return ptr;
}
Region* RegionPagerLua::CreateRegion(int x, int y) {
@@ -69,55 +97,87 @@ Region* RegionPagerLua::CreateRegion(int x, int y) {
throw(std::logic_error("Cannot overwrite an existing region"));
}
//get the pager's function from the registry
lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef);
//check if this function is available
if (lua_isnil(lua, -1)) {
lua_pop(lua, 1);
return nullptr;
}
//something to work on
Region tmpRegion(x, y);
//API hook
lua_getglobal(lua, "Region");
lua_getfield(lua, -1, "Create");
lua_pushlightuserdata(lua, &tmpRegion);
//TODO: parameters
//call the function, 1 arg, 0 return
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
lua_pop(lua, 1);
//return the new region
regionList.push_front(tmpRegion);
return &regionList.front();
}
void RegionPagerLua::UnloadRegion(int x, int y) {
lua_getglobal(lua, "Region");
//get the pager's function from the registry
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
//check if this function is available
if (lua_isnil(lua, -1)) {
lua_pop(lua, 1);
return;
}
//run each region through this lambda
regionList.remove_if([&](Region& region) -> bool {
if (region.GetX() == x && region.GetY() == y) {
//API hook
lua_getfield(lua, -1, "Unload");
//push a copy of the function onto the stack with the region
lua_pushvalue(lua, -1);
lua_pushlightuserdata(lua, &region);
//call the function, 1 arg, 0 return
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
//signal to the container
return true;
}
//signal to the container
return false;
});
//pop the base copy of the function
lua_pop(lua, 1);
}
void RegionPagerLua::UnloadAll() {
lua_getglobal(lua, "Region");
//get the pager's function from the registry
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
//check if this function is available
if (lua_isnil(lua, -1)) {
lua_pop(lua, 1);
return;
}
for (auto& it : regionList) {
//API hook
lua_getfield(lua, -1, "Unload");
//push a copy of the function onto the stack with the region
lua_pushvalue(lua, -1);
lua_pushlightuserdata(lua, &it);
//call the function, 1 arg, 0 return
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
}
}
//pop the base copy of the function
lua_pop(lua, 1);
//remove from memory
regionList.clear();
}
+17
View File
@@ -44,8 +44,25 @@ public:
//accessors & mutators
lua_State* SetLuaState(lua_State* L) { return lua = L; }
lua_State* GetLuaState() { return lua; }
//utilities for the API
int SetLoadReference(int i) { return loadRef = i; }
int SetSaveReference(int i) { return saveRef = i; }
int SetCreateReference(int i) { return createRef = i; }
int SetUnloadReference(int i) { return unloadRef = i; }
int GetLoadReference() { return loadRef; }
int GetSaveReference() { return saveRef; }
int GetCreateReference() { return createRef; }
int GetUnloadReference() { return unloadRef; }
protected:
lua_State* lua = nullptr;
int loadRef = LUA_NOREF;
int saveRef = LUA_NOREF;
int createRef = LUA_NOREF;
int unloadRef = LUA_NOREF;
};
#endif
+15
View File
@@ -0,0 +1,15 @@
Future versions (to be determined) may be released under a modified version of the Uplink Developer's License.
The current version of Tortuga is released under the zlib license.
Copyright (c) 2013, 2014 Kayne Ruse
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.
+6 -1
View File
@@ -19,7 +19,12 @@ debug: export CXXFLAGS+=-g
debug: clean all
release: export CXXFLAGS+=-static-libgcc -static-libstdc++
release: clean all
release: clean all package
#For use on my machine ONLY
package:
rar a -r -ep Tortuga.rar out/*.exe out/*.dll
rar a -r Tortuga.rar rsc/* copyright.txt
$(OUTDIR):
mkdir $(OUTDIR)
+12 -6
View File
@@ -15,10 +15,11 @@ tiles = {
water = base + shift * 4
}
--could set custom generation systems here, that differ from the global generators, etc.
function Region.Create(region)
for i = 1, Region.GetWidth() do
for j = 1, Region.GetHeight() do
--custom generation systems here
function islandGenerator(region)
io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n")
for i = 1, Region.GetWidth(region) do
for j = 1, Region.GetHeight(region) do
local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1)
if dist < 10 then
Region.SetTile(region, i, j, 1, tiles.plains)
@@ -33,14 +34,19 @@ function Region.Create(region)
end
--Get some regions
--BUG: The server fails without this
newRoom = RoomMgr.CreateRoom("overworld")
--BUG: The server fails without at least one room
--TODO: Create rooms with names?
newRoom = RoomManager.CreateRoom()
pager = Room.GetPager(newRoom)
RegionPager.SetOnCreate(pager, islandGenerator)
--[[
regionTable = {
RegionPager.GetRegion(pager, Region.GetWidth() * 0, Region.GetHeight() * 0),
RegionPager.GetRegion(pager, Region.GetWidth() *-1, Region.GetHeight() * 0),
RegionPager.GetRegion(pager, Region.GetWidth() * 0, Region.GetHeight() *-1),
RegionPager.GetRegion(pager, Region.GetWidth() *-1, Region.GetHeight() *-1)
}
]]
print("Finished the lua script")
+23 -3
View File
@@ -24,15 +24,35 @@
#include <string>
struct AccountData {
class AccountData {
public:
AccountData() = default;
~AccountData() = default;
//accessors and mutators
int SetClientIndex(int i) { return clientIndex = i; }
int GetClientIndex() { return clientIndex; }
std::string SetUsername(std::string s) { return username = s; }
std::string GetUsername() { return username; }
//database stuff
bool GetBlackListed() { return blackListed; }
bool GetWhiteListed() { return whiteListed; }
bool GetModerator() { return mod; }
bool GetAdministrator() { return admin; }
private:
friend class AccountManager;
int clientIndex;
std::string username;
//TODO: password
bool blackListed = false;
bool whiteListed = true;
bool mod = false;
bool admin = false;
int clientIndex;
};
#endif
+7 -4
View File
@@ -23,16 +23,14 @@
#define ACCOUNTMANAGER_HPP_
#include "account_data.hpp"
#include "singleton.hpp"
#include "sqlite3/sqlite3.h"
#include <map>
class AccountManager {
class AccountManager : public Singleton<AccountManager> {
public:
AccountManager() = default;
~AccountManager() { UnloadAll(); };
//public access methods
int CreateAccount(std::string username, int clientIndex);
int LoadAccount(std::string username, int clientIndex);
@@ -50,6 +48,11 @@ public:
sqlite3* GetDatabase();
private:
friend Singleton<AccountManager>;
AccountManager() = default;
~AccountManager() = default;
std::map<int, AccountData> accountMap;
sqlite3* database = nullptr;
};
+1 -1
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=.
INCLUDES+=. ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+28 -14
View File
@@ -31,27 +31,41 @@
#include <string>
#include <cmath>
struct CharacterData {
//metadata
int owner;
std::string handle;
std::string avatar;
class CharacterData {
public:
CharacterData() = default;
~CharacterData() = default;
//location and movement
int SetRoomIndex(int i) { return roomIndex = i; }
Vector2 SetOrigin(Vector2 v) { return origin = v; }
Vector2 SetMotion(Vector2 v) { return motion = v; }
int GetRoomIndex() { return roomIndex; }
Vector2 GetOrigin() { return origin; }
Vector2 GetMotion() { return motion; }
//accessors and mutators
Statistics* GetBaseStats() { return &baseStats; }
//database stuff
int GetOwner() { return owner; }
std::string GetHandle() { return handle; }
std::string GetAvatar() { return avatar; }
private:
friend class CharacterManager;
//world position
int roomIndex = 0;
Vector2 origin = {0.0,0.0};
Vector2 motion = {0.0,0.0};
//base statistics
Statistics stats;
Statistics baseStats;
//TODO: gameplay components: equipment, items, buffs, debuffs
//active gameplay members
//NOTE: these are lost when unloaded
bool inCombat = false;
int atbGauge = 0;
//TODO: stored command
int owner;
std::string handle;
std::string avatar;
};
#endif
+29 -29
View File
@@ -58,7 +58,7 @@ static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
//Define the methods
//-------------------------
//NOTE: default stats as a parameter would be good for different beggining states or multiple classes
//NOTE: default baseStats as a parameter would be good for different beggining states or multiple classes
int CharacterManager::CreateCharacter(int owner, std::string handle, std::string avatar) {
//Create the character, failing if it exists
sqlite3_stmt* statement = nullptr;
@@ -142,20 +142,20 @@ int CharacterManager::LoadCharacter(int owner, std::string handle, std::string a
newChar.origin.y = (double)sqlite3_column_int(statement, 7);
//statistics
newChar.stats.level = sqlite3_column_int(statement, 8);
newChar.stats.exp = sqlite3_column_int(statement, 9);
newChar.stats.maxHP = sqlite3_column_int(statement, 10);
newChar.stats.health = sqlite3_column_int(statement, 11);
newChar.stats.maxMP = sqlite3_column_int(statement, 12);
newChar.stats.mana = sqlite3_column_int(statement, 13);
newChar.stats.attack = sqlite3_column_int(statement, 14);
newChar.stats.defence = sqlite3_column_int(statement, 15);
newChar.stats.intelligence = sqlite3_column_int(statement, 16);
newChar.stats.resistance = sqlite3_column_int(statement, 17);
newChar.stats.speed = sqlite3_column_int(statement, 18);
newChar.stats.accuracy = sqlite3_column_double(statement, 19);
newChar.stats.evasion = sqlite3_column_double(statement, 20);
newChar.stats.luck = sqlite3_column_double(statement, 21);
newChar.baseStats.level = sqlite3_column_int(statement, 8);
newChar.baseStats.exp = sqlite3_column_int(statement, 9);
newChar.baseStats.maxHP = sqlite3_column_int(statement, 10);
newChar.baseStats.health = sqlite3_column_int(statement, 11);
newChar.baseStats.maxMP = sqlite3_column_int(statement, 12);
newChar.baseStats.mana = sqlite3_column_int(statement, 13);
newChar.baseStats.attack = sqlite3_column_int(statement, 14);
newChar.baseStats.defence = sqlite3_column_int(statement, 15);
newChar.baseStats.intelligence = sqlite3_column_int(statement, 16);
newChar.baseStats.resistance = sqlite3_column_int(statement, 17);
newChar.baseStats.speed = sqlite3_column_int(statement, 18);
newChar.baseStats.accuracy = sqlite3_column_double(statement, 19);
newChar.baseStats.evasion = sqlite3_column_double(statement, 20);
newChar.baseStats.luck = sqlite3_column_double(statement, 21);
//TODO: gameplay components: equipment, items, buffs, debuffs
@@ -199,20 +199,20 @@ int CharacterManager::SaveCharacter(int uid) {
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
//statistics
ret |= sqlite3_bind_int(statement, 5, character.stats.level) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 6, character.stats.exp) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 7, character.stats.maxHP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 8, character.stats.health) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 9, character.stats.maxMP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 10, character.stats.mana) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 11, character.stats.attack) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 12, character.stats.defence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 13, character.stats.intelligence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 14, character.stats.resistance) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 15, character.stats.speed) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 16, character.stats.accuracy) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 17, character.stats.evasion) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 18, character.stats.luck) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 5, character.baseStats.level) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 6, character.baseStats.exp) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 7, character.baseStats.maxHP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 8, character.baseStats.health) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 9, character.baseStats.maxMP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 10, character.baseStats.mana) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 11, character.baseStats.attack) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 12, character.baseStats.defence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 13, character.baseStats.intelligence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 14, character.baseStats.resistance) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 15, character.baseStats.speed) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 16, character.baseStats.accuracy) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 17, character.baseStats.evasion) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 18, character.baseStats.luck) != SQLITE_OK;
//TODO: gameplay components: equipment, items, buffs, debuffs
+7 -4
View File
@@ -23,17 +23,15 @@
#define CHARACTERMANAGER_HPP_
#include "character_data.hpp"
#include "singleton.hpp"
#include "sqlite3/sqlite3.h"
#include <map>
#include <functional>
class CharacterManager {
class CharacterManager : public Singleton<CharacterManager> {
public:
CharacterManager() = default;
~CharacterManager() { UnloadAll(); };
//public access methods
int CreateCharacter(int owner, std::string handle, std::string avatar);
int LoadCharacter(int owner, std::string handle, std::string avatar);
@@ -53,6 +51,11 @@ public:
sqlite3* GetDatabase();
private:
friend Singleton<CharacterManager>;
CharacterManager() = default;
~CharacterManager() = default;
std::map<int, CharacterData> characterMap;
sqlite3* database = nullptr;
};
-52
View File
@@ -1,52 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 COMBATDATA_HPP_
#define COMBATDATA_HPP_
#include "vector2.hpp"
#include "combat_defines.hpp"
//gameplay members
#include "character_data.hpp"
#include "enemy_data.hpp"
//std namespace
#include <chrono>
#include <array>
#include <utility>
struct CombatData {
typedef std::chrono::steady_clock Clock;
std::array<CharacterData, COMBAT_MAX_CHARACTERS> characterArray;
std::array<EnemyData, COMBAT_MAX_ENEMIES> enemyArray;
//world interaction
int mapIndex = 0;
Vector2 origin = {0.0,0.0};
Vector2 bounds = {0.0,0.0};
//time interval
Clock::time_point lastTick = Clock::now();
};
#endif
-54
View File
@@ -1,54 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "combat_manager.hpp"
//-------------------------
//public access methods
//-------------------------
//TODO
//-------------------------
//accessors and mutators
//-------------------------
CombatData* CombatManager::GetCombat(int uid) {
std::map<int, CombatData>::iterator it = combatMap.find(uid);
if (it == combatMap.end()) {
return nullptr;
}
return &it->second;
}
std::map<int, CombatData>* CombatManager::GetContainer() {
return &combatMap;
}
lua_State* CombatManager::SetLuaState(lua_State* L) {
return luaState = L;
}
lua_State* CombatManager::GetLuaState() {
return luaState;
}
-51
View File
@@ -1,51 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 COMBATMANAGER_HPP_
#define COMBATMANAGER_HPP_
#include "combat_data.hpp"
#include "lua/lua.hpp"
#include <map>
class CombatManager {
public:
CombatManager() = default;
~CombatManager() = default;
//public access methods
//TODO
//accessors and mutators
CombatData* GetCombat(int uid);
std::map<int, CombatData>* GetContainer();
lua_State* SetLuaState(lua_State*);
lua_State* GetLuaState();
private:
std::map<int, CombatData> combatMap;
lua_State* luaState = nullptr;
};
#endif
-37
View File
@@ -1,37 +0,0 @@
#config
INCLUDES+=. ../../common/gameplay ../../common/utilities ../characters ../enemies
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=..
OUT=$(addprefix $(OUTDIR)/,server.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
-47
View File
@@ -1,47 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 ENEMYDATA_HPP_
#define ENEMYDATA_HPP_
#include "vector2.hpp"
#include "statistics.hpp"
//std namespace
#include <string>
struct EnemyData {
//metadata
std::string handle;
std::string avatar;
//gameplay
Statistics stats;
//TODO: gameplay components: equipment, items, buffs, debuffs, rewards
//active gameplay members
//NOTE: these are lost when unloaded
int tableIndex;
int atbGauge = 0;
};
#endif
-54
View File
@@ -1,54 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 "enemy_manager.hpp"
//-------------------------
//public access methods
//-------------------------
//TODO
//-------------------------
//accessors and mutators
//-------------------------
EnemyData* EnemyManager::GetEnemy(int uid) {
std::map<int, EnemyData>::iterator it = enemyMap.find(uid);
if (it == enemyMap.end()) {
return nullptr;
}
return &it->second;
}
std::map<int, EnemyData>* EnemyManager::GetContainer() {
return &enemyMap;
}
lua_State* EnemyManager::SetLuaState(lua_State* L) {
return luaState = L;
}
lua_State* EnemyManager::GetLuaState() {
return luaState;
}
-51
View File
@@ -1,51 +0,0 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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 ENEMYMANAGER_HPP_
#define ENEMYMANAGER_HPP_
#include "enemy_data.hpp"
#include "lua/lua.hpp"
#include <map>
class EnemyManager {
public:
EnemyManager() = default;
~EnemyManager() = default;
//public access methods
//TODO
//accessors and mutators
EnemyData* GetEnemy(int uid);
std::map<int, EnemyData>* GetContainer();
lua_State* SetLuaState(lua_State*);
lua_State* GetLuaState();
private:
std::map<int, EnemyData> enemyMap;
lua_State* luaState = nullptr;
};
#endif
-37
View File
@@ -1,37 +0,0 @@
#config
INCLUDES+=. ../mapgen ../../common/gameplay ../../common/map ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=..
OUT=$(addprefix $(OUTDIR)/,server.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+2 -2
View File
@@ -40,7 +40,7 @@
#include "region_pager_api.hpp"
#include "tile_sheet_api.hpp"
#include "room_api.hpp"
#include "room_mgr_api.hpp"
#include "room_manager_api.hpp"
//these libs are loaded by lua.c and are readily available to any Lua program
static const luaL_Reg loadedlibs[] = {
@@ -61,7 +61,7 @@ static const luaL_Reg loadedlibs[] = {
{TORTUGA_REGION_PAGER_NAME, openRegionPagerAPI},
{TORTUGA_TILE_SHEET_NAME, openTileSheetAPI},
{TORTUGA_ROOM_NAME, openRoomAPI},
{TORTUGA_ROOM_MGR_NAME, openRoomMgrAPI},
{TORTUGA_ROOM_MANAGER_NAME, openRoomManagerAPI},
{NULL, NULL}
};
+6
View File
@@ -33,7 +33,10 @@ using namespace std;
int main(int argc, char** argv) {
try {
//create the singletons
AccountManager::Create();
CharacterManager::Create();
ConfigUtility::Create();
RoomManager::Create();
UDPNetworkUtility::Create();
//call the server's routines
@@ -47,7 +50,10 @@ int main(int argc, char** argv) {
ServerApplication::Delete();
//delete the singletons
AccountManager::Delete();
CharacterManager::Delete();
ConfigUtility::Delete();
RoomManager::Delete();
UDPNetworkUtility::Delete();
}
catch(exception& e) {
+1 -3
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=. accounts characters combat enemies mapgen mapgen/generators rooms ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet ../common/network/serial ../common/utilities
INCLUDES+=. accounts characters rooms ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet ../common/network/serial ../common/utilities
LIBS+=server.a ../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
@@ -18,8 +18,6 @@ OUT=$(addprefix $(OUTDIR)/,server)
all: $(OBJ) $(OUT)
$(MAKE) -C accounts
$(MAKE) -C characters
$(MAKE) -C combat
$(MAKE) -C enemies
$(MAKE) -C rooms
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
+1 -1
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=. ../mapgen ../mapgen/generators ../../common/map
INCLUDES+=. ../../common/map ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+8 -9
View File
@@ -25,26 +25,25 @@
static int getPager(lua_State* L) {
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
lua_pushlightuserdata(L, reinterpret_cast<void*>(&room->pager));
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetPager()) );
return 1;
}
static int onCreate(lua_State* L) {
//TODO: onCreate()
static int create(lua_State* L) {
//EMPTY
//NOTE: This can be used to set defaults for the pager
return 0;
}
static int onUnload(lua_State* L) {
//TODO: onUnload()
static int unload(lua_State* L) {
//EMPTY
return 0;
}
//TODO: parameters
static const luaL_Reg roomLib[] = {
{"GetPager",getPager},
{"OnCreate", onCreate},
{"OnUnload", onUnload},
{"Create", create},
{"Unload", unload},
{nullptr, nullptr}
};
+11 -4
View File
@@ -25,12 +25,19 @@
//map system
#include "region_pager_lua.hpp"
struct RoomData {
class RoomData {
public:
RoomData() = default;
~RoomData() = default;
//accessors and mutators
RegionPagerLua* GetPager() { return &pager; }
private:
friend class RoomManager;
//members
RegionPagerLua pager;
//TODO: collision map
//TODO: NPCs?
};
#endif
+12 -14
View File
@@ -21,27 +21,25 @@
*/
#include "room_manager.hpp"
#include "room_api.hpp"
#include <stdexcept>
//-------------------------
//public access methods
//-------------------------
RoomData* RoomManager::CreateRoom() {
int RoomManager::CreateRoom() {
//create the room
RoomData* newRoom = new RoomData();
//set the state
if (luaState) {
newRoom->pager.SetLuaState(luaState);
}
newRoom->pager.SetLuaState(luaState);
//register the room
roomMap[counter++] = newRoom;
roomMap[counter] = newRoom;
//API hook
lua_getglobal(luaState, "Room");
lua_getfield(luaState, -1, "OnCreate");
lua_getglobal(luaState, TORTUGA_ROOM_NAME);
lua_getfield(luaState, -1, "Create");
lua_pushlightuserdata(luaState, newRoom);
if (lua_pcall(luaState, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(luaState, -1) ));
@@ -49,7 +47,7 @@ RoomData* RoomManager::CreateRoom() {
lua_pop(luaState, 1);
//finish the routine
return newRoom;
return counter++;
}
void RoomManager::UnloadRoom(int uid) {
@@ -60,8 +58,8 @@ void RoomManager::UnloadRoom(int uid) {
}
//API hook
lua_getglobal(luaState, "Room");
lua_getfield(luaState, -1, "OnUnload");
lua_getglobal(luaState, TORTUGA_ROOM_NAME);
lua_getfield(luaState, -1, "Unload");
lua_pushlightuserdata(luaState, room);
if (lua_pcall(luaState, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(luaState, -1) ));
@@ -92,11 +90,11 @@ int RoomManager::PushRoom(RoomData* room) {
}
void RoomManager::UnloadAll() {
lua_getglobal(luaState, "Room");
lua_getglobal(luaState, TORTUGA_ROOM_NAME);
for (auto& it : roomMap) {
//API hook
lua_getfield(luaState, -1, "OnUnload");
lua_getfield(luaState, -1, "Unload");
lua_pushlightuserdata(luaState, it.second);
if (lua_pcall(luaState, 1, 0, 0) != LUA_OK) {
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(luaState, -1) ));
+8 -7
View File
@@ -23,20 +23,16 @@
#define ROOMMANAGER_HPP_
#include "room_data.hpp"
#include "singleton.hpp"
#include "lua/lua.hpp"
#include <map>
#define ROOM_MANAGER_PSEUDOINDEX "RoomManager"
class RoomManager {
class RoomManager : public Singleton<RoomManager> {
public:
RoomManager() = default;
~RoomManager() = default;
//public access methods
RoomData* CreateRoom();
int CreateRoom();
void UnloadRoom(int uid);
RoomData* GetRoom(int uid);
@@ -52,6 +48,11 @@ public:
lua_State* GetLuaState() { return luaState; }
private:
friend Singleton<RoomManager>;
RoomManager() = default;
~RoomManager() = default;
std::map<int, RoomData*> roomMap;
lua_State* luaState = nullptr;
int counter = 0;
@@ -19,61 +19,42 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "room_mgr_api.hpp"
#include "room_manager_api.hpp"
#include "room_api.hpp"
#include "room_manager.hpp"
#include "room_data.hpp"
#include <string>
static int getRoom(lua_State* L) {
//get the room manager
lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX);
lua_gettable(L, LUA_REGISTRYINDEX);
RoomManager* roomMgr = reinterpret_cast<RoomManager*>(lua_touserdata(L, -1));
//push the room and return it
lua_pushlightuserdata(L, reinterpret_cast<void*>( roomMgr->GetRoom(lua_tointeger(L, -2)) ));
//find, push and return the room
RoomData* room = RoomManager::GetSingleton().GetRoom(lua_tointeger(L, -2));
lua_pushlightuserdata(L, reinterpret_cast<void*>(room));
return 1;
}
static int createRoom(lua_State* L) {
//TODO: check parameter count for the glue functions
//get the room manager
lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX);
lua_gettable(L, LUA_REGISTRYINDEX);
RoomManager* roomMgr = reinterpret_cast<RoomManager*>(lua_touserdata(L, -1));
//create the room
RoomData* newRoom = roomMgr->CreateRoom();
//return the new room
lua_pushlightuserdata(L, newRoom);
//create, find and return the room
int uid = RoomManager::GetSingleton().CreateRoom();
lua_pushlightuserdata(L, RoomManager::GetSingleton().FindRoom(uid));
return 1;
}
static int unloadRoom(lua_State* L) {
//get the room manager
lua_pushstring(L, ROOM_MANAGER_PSEUDOINDEX);
lua_gettable(L, LUA_REGISTRYINDEX);
RoomManager* roomMgr = reinterpret_cast<RoomManager*>(lua_touserdata(L, -1));
//unload the specified room
roomMgr->UnloadRoom(lua_tointeger(L, -2));
RoomManager::GetSingleton().UnloadRoom(lua_tointeger(L, -2));
return 0;
}
static const luaL_Reg roomMgrLib[] = {
static const luaL_Reg roomManagerLib[] = {
{"GetRoom",getRoom},
{"CreateRoom",createRoom},
{"UnloadRoom",unloadRoom},
{nullptr, nullptr}
};
LUAMOD_API int openRoomMgrAPI(lua_State* L) {
luaL_newlib(L, roomMgrLib);
LUAMOD_API int openRoomManagerAPI(lua_State* L) {
luaL_newlib(L, roomManagerLib);
return 1;
}
@@ -19,12 +19,12 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef ROOMMGRAPI_HPP_
#define ROOMMGRAPI_HPP_
#ifndef ROOMMANAGERAPI_HPP_
#define ROOMMANAGERAPI_HPP_
#include "lua/lua.hpp"
#define TORTUGA_ROOM_MGR_NAME "RoomMgr"
LUAMOD_API int openRoomMgrAPI(lua_State* L);
#define TORTUGA_ROOM_MANAGER_NAME "RoomManager"
LUAMOD_API int openRoomManagerAPI(lua_State* L);
#endif
+4 -4
View File
@@ -92,13 +92,13 @@ private:
std::map<int, ClientData> clientMap;
//managers
AccountManager accountMgr;
CharacterManager characterMgr;
RoomManager roomMgr;
AccountManager& accountMgr = AccountManager::GetSingleton();
CharacterManager& characterMgr = CharacterManager::GetSingleton();
RoomManager& roomMgr = RoomManager::GetSingleton();
//misc
bool running = true;
int clientUID = 0;
int clientIndex = 0;
};
#endif
+233
View File
@@ -0,0 +1,233 @@
/* Copyright: (c) Kayne Ruse 2014
*
* 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_application.hpp"
//for PACKET_BUFFER_SIZE
#include "serial.hpp"
//utility functions
#include "sql_utility.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <iostream>
#include <string>
//-------------------------
//public methods
//-------------------------
void ServerApplication::Init(int argc, char** argv) {
//NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed.
std::cout << "Beginning " << argv[0] << std::endl;
//load the prerequisites
config.Load("rsc\\config.cfg");
//-------------------------
//Initialize the APIs
//-------------------------
//Init SDL
if (SDL_Init(0)) {
throw(std::runtime_error("Failed to initialize SDL"));
}
std::cout << "Initialized SDL" << std::endl;
//Init SDL_net
if (SDLNet_Init()) {
throw(std::runtime_error("Failed to initialize SDL_net"));
}
network.Open(config.Int("server.port"));
std::cout << "Initialized SDL_net" << std::endl;
//Init SQL
int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
if (ret != SQLITE_OK || !database) {
throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
}
std::cout << "Initialized SQL" << std::endl;
//Init lua
luaState = luaL_newstate();
if (!luaState) {
throw(std::runtime_error("Failed to initialize lua"));
}
luaL_openlibs(luaState);
std::cout << "Initialized lua" << std::endl;
//-------------------------
//Setup the objects
//-------------------------
//set the hooks
accountMgr.SetDatabase(database);
characterMgr.SetDatabase(database);
roomMgr.SetLuaState(luaState);
std::cout << "Internal managers initialized" << std::endl;
//-------------------------
//Run the startup scripts
//-------------------------
//setup the database
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
throw(std::runtime_error("Failed to initialize SQL's setup script"));
}
std::cout << "Completed SQL's setup script" << std::endl;
//run lua's startup script
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
}
std::cout << "Completed lua's setup script" << std::endl;
//-------------------------
//debug output
//-------------------------
//TODO: enable/disable these with a switch
#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl;
std::cout << "Internal sizes:" << std::endl;
DEBUG_OUTPUT_VAR(sizeof(Region::type_t));
DEBUG_OUTPUT_VAR(sizeof(Region));
DEBUG_OUTPUT_VAR(REGION_WIDTH);
DEBUG_OUTPUT_VAR(REGION_HEIGHT);
DEBUG_OUTPUT_VAR(REGION_DEPTH);
DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_FOOTPRINT);
DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE);
DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE);
#undef DEBUG_OUTPUT_VAR
//-------------------------
//finalize the startup
//-------------------------
std::cout << "Startup completed successfully" << std::endl;
//-------------------------
//debugging
//-------------------------
//...
}
void ServerApplication::Proc() {
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
while(running) {
//suck in the waiting packets & process them
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
//update the internals
//BUG: #30 Update the internals i.e. player positions
//give the computer a break
SDL_Delay(10);
}
delete reinterpret_cast<char*>(packetBuffer);
}
void ServerApplication::Quit() {
std::cout << "Shutting down" << std::endl;
//close the managers
clientMap.clear();
accountMgr.UnloadAll();
characterMgr.UnloadAll();
//TODO: unload combats
//TODO: unload enemies
roomMgr.UnloadAll();
//APIs
lua_close(luaState);
sqlite3_close_v2(database);
network.Close();
SDLNet_Quit();
SDL_Quit();
std::cout << "Clean exit" << std::endl;
}
//-------------------------
//direct incoming traffic
//-------------------------
void ServerApplication::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
//basic connections
case SerialPacketType::BROADCAST_REQUEST:
HandleBroadcastRequest(static_cast<SerialPacket*>(argPacket));
break;
case SerialPacketType::JOIN_REQUEST:
HandleJoinRequest(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::DISCONNECT:
HandleDisconnect(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::SHUTDOWN:
HandleShutdown(static_cast<SerialPacket*>(argPacket));
break;
//map management
case SerialPacketType::REGION_REQUEST:
HandleRegionRequest(static_cast<RegionPacket*>(argPacket));
break;
//combat management
//TODO: combat management
//character management
case SerialPacketType::CHARACTER_NEW:
HandleCharacterNew(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DELETE:
HandleCharacterDelete(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
HandleCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
break;
//enemy management
//TODO: enemy management
//mismanagement
case SerialPacketType::SYNCHRONIZE:
HandleSynchronize(static_cast<ClientPacket*>(argPacket));
break;
//handle errors
default: {
std::string msg = "Unknown SerialPacketType encountered in the server: ";
msg += to_string_custom(static_cast<int>(argPacket->type));
throw(std::runtime_error(msg));
}
break;
}
}
@@ -21,220 +21,7 @@
*/
#include "server_application.hpp"
//for PACKET_BUFFER_SIZE
#include "serial.hpp"
//utility functions
#include "sql_utility.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <iostream>
#include <string>
//-------------------------
//public methods
//-------------------------
void ServerApplication::Init(int argc, char** argv) {
//NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed.
std::cout << "Beginning " << argv[0] << std::endl;
//load the prerequisites
config.Load("rsc\\config.cfg");
//-------------------------
//Initialize the APIs
//-------------------------
//Init SDL
if (SDL_Init(0)) {
throw(std::runtime_error("Failed to initialize SDL"));
}
std::cout << "Initialized SDL" << std::endl;
//Init SDL_net
if (SDLNet_Init()) {
throw(std::runtime_error("Failed to initialize SDL_net"));
}
network.Open(config.Int("server.port"));
std::cout << "Initialized SDL_net" << std::endl;
//Init SQL
int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
if (ret != SQLITE_OK || !database) {
throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
}
std::cout << "Initialized SQL" << std::endl;
//Init lua
luaState = luaL_newstate();
if (!luaState) {
throw(std::runtime_error("Failed to initialize lua"));
}
luaL_openlibs(luaState);
std::cout << "Initialized lua" << std::endl;
//-------------------------
//Setup the objects
//-------------------------
//set the hooks
accountMgr.SetDatabase(database);
characterMgr.SetDatabase(database);
roomMgr.SetLuaState(luaState);
std::cout << "Internal managers set" << std::endl;
//register the "globals"
lua_pushstring(luaState, ROOM_MANAGER_PSEUDOINDEX);
lua_pushlightuserdata(luaState, &roomMgr);
lua_settable(luaState, LUA_REGISTRYINDEX);
std::cout << "Internal managers registered with lua" << std::endl;
//-------------------------
//Run the startup scripts
//-------------------------
//setup the database
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
throw(std::runtime_error("Failed to initialize SQL's setup script"));
}
std::cout << "Completed SQL's setup script" << std::endl;
//run lua's startup script
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
}
std::cout << "Completed lua's setup script" << std::endl;
//-------------------------
//debug output
//-------------------------
//TODO: enable/disable these with a switch
#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl;
std::cout << "Internal sizes:" << std::endl;
DEBUG_OUTPUT_VAR(sizeof(Region::type_t));
DEBUG_OUTPUT_VAR(sizeof(Region));
DEBUG_OUTPUT_VAR(REGION_WIDTH);
DEBUG_OUTPUT_VAR(REGION_HEIGHT);
DEBUG_OUTPUT_VAR(REGION_DEPTH);
DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_FOOTPRINT);
DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE);
DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE);
#undef DEBUG_OUTPUT_VAR
//-------------------------
//finalize the startup
//-------------------------
std::cout << "Startup completed successfully" << std::endl;
//-------------------------
//debugging
//-------------------------
//...
}
void ServerApplication::Proc() {
SerialPacket* packetBuffer = static_cast<SerialPacket*>(malloc(MAX_PACKET_SIZE));
while(running) {
//suck in the waiting packets & process them
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
//update the internals
//BUG: #30 Update the internals i.e. player positions
//give the computer a break
SDL_Delay(10);
}
free(static_cast<void*>(packetBuffer));
}
void ServerApplication::Quit() {
std::cout << "Shutting down" << std::endl;
//close the managers
clientMap.clear();
accountMgr.UnloadAll();
characterMgr.UnloadAll();
//TODO: unload combats
//TODO: unload enemies
roomMgr.UnloadAll();
//APIs
lua_close(luaState);
sqlite3_close_v2(database);
network.Close();
SDLNet_Quit();
SDL_Quit();
std::cout << "Clean exit" << std::endl;
}
//-------------------------
//handle incoming traffic
//-------------------------
void ServerApplication::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
//basic connections
case SerialPacketType::BROADCAST_REQUEST:
HandleBroadcastRequest(static_cast<SerialPacket*>(argPacket));
break;
case SerialPacketType::JOIN_REQUEST:
HandleJoinRequest(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::DISCONNECT:
HandleDisconnect(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::SHUTDOWN:
HandleShutdown(static_cast<SerialPacket*>(argPacket));
break;
//map management
case SerialPacketType::REGION_REQUEST:
HandleRegionRequest(static_cast<RegionPacket*>(argPacket));
break;
//combat management
//TODO: combat management
//character management
case SerialPacketType::CHARACTER_NEW:
HandleCharacterNew(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DELETE:
HandleCharacterDelete(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
HandleCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
break;
//enemy management
//TODO: enemy management
//mismanagement
case SerialPacketType::SYNCHRONIZE:
HandleSynchronize(static_cast<ClientPacket*>(argPacket));
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in the server: " + to_string_custom(static_cast<int>(argPacket->type)) ));
break;
}
}
//-------------------------
//basic connections
@@ -259,7 +46,7 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//load the user account
//TODO: handle passwords
int accountIndex = accountMgr.LoadAccount(argPacket->username, clientUID);
int accountIndex = accountMgr.LoadAccount(argPacket->username, clientIndex);
if (accountIndex < 0) {
//TODO: send rejection packet
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
@@ -269,13 +56,13 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//send the client their info
ClientPacket newPacket;
newPacket.type = SerialPacketType::JOIN_RESPONSE;
newPacket.clientIndex = clientUID;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
network.SendTo(&newClient.address, static_cast<SerialPacket*>(&newPacket));
//finished this routine
clientMap[clientUID++] = newClient;
clientMap[clientIndex++] = newClient;
std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
@@ -291,17 +78,16 @@ void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) {
if neither of the above is true, then output a warning to the console, and return
*/
//forward to the specified client
network.SendTo(
&clientMap[ accountMgr.GetAccount(argPacket->accountIndex)->clientIndex ].address,
&clientMap[ accountMgr.GetAccount(argPacket->accountIndex)->GetClientIndex() ].address,
static_cast<SerialPacket*>(argPacket)
);
//save and unload this account's characters
//pump the unload message to all remaining clients
characterMgr.UnloadCharacterIf([&](std::map<int, CharacterData>::iterator it) -> bool {
if (argPacket->accountIndex == it->second.owner) {
if (argPacket->accountIndex == it->second.GetOwner()) {
PumpCharacterUnload(it->first);
return true;
}
@@ -309,7 +95,7 @@ void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) {
});
//erase the in-memory stuff
clientMap.erase(accountMgr.GetAccount(argPacket->accountIndex)->clientIndex);
clientMap.erase(accountMgr.GetAccount(argPacket->accountIndex)->GetClientIndex());
accountMgr.UnloadAccount(argPacket->accountIndex);
//finished this routine
@@ -349,7 +135,7 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) {
newPacket.x = argPacket->x;
newPacket.y = argPacket->y;
newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->pager.GetRegion(argPacket->x, argPacket->y);
newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->GetPager()->GetRegion(argPacket->x, argPacket->y);
//send the content
network.SendTo(&argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
@@ -422,11 +208,11 @@ void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket)
}
//accept client-side logic
character->roomIndex = argPacket->roomIndex;
character->origin = argPacket->origin;
character->motion = argPacket->motion;
character->SetRoomIndex(argPacket->roomIndex);
character->SetOrigin(argPacket->origin);
character->SetMotion(argPacket->motion);
character->stats = argPacket->stats;
*character->GetBaseStats() = argPacket->stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
@@ -485,11 +271,11 @@ void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int
//TODO: keep this up to date when the character changes
packet->characterIndex = characterIndex;
strncpy(packet->handle, character->handle.c_str(), PACKET_STRING_SIZE);
strncpy(packet->avatar, character->avatar.c_str(), PACKET_STRING_SIZE);
packet->accountIndex = character->owner;
packet->roomIndex = character->roomIndex;
packet->origin = character->origin;
packet->motion = character->motion;
packet->stats = character->stats;
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();
packet->stats = *character->GetBaseStats();
}
+5 -32
View File
@@ -1,41 +1,14 @@
TODO: encapsulate the data structures
TODO: Get the rooms working
TODO: A proper logging system
TODO: Ping-pong and keep alive system
TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times
TODO: Get the rooms working, even if only via hotkeys
TODO: Rejection messages
TODO: Fix shoddy movement
TODO: make the whole thing more fault tolerant
TODO: Authentication
TODO: server is slaved to the client
TODO: Time delay for requesting region packets
TODO: command line parameters overriding config.cfg settings
--Requirements--
The enemies need AI scripts
The scripts need to be able to generate other enemies (frog king).
The characters need a flag to show if they're in a combat instance or not, to signify of they should be unloaded client-side
On each game loop, the server should envoke each combat instance's update function
Each combat instance invokes each enemy's and character's update functions
These update functions increase the ATB guagues
if an ATB guage is full
than the stored command is executed
the players issue their commands during the build up
if there isn't a command ready, then the player is still choosing
for the enemies, the stored commands are driven by scripts, so when the enemies need to attack, their attached scripts are called.
after the commands are called, the ATB is reset to 0.
etc...
--Enemy API--
enemyTables -- The global store of enemy tables. Only accessed by C++ code (unless you want to break something).
enemy.new(parameters) -- return a new enemy object
table.logic: the AI logic. If null, do nothing
table.ref: reference to the enemy itself, for use by API functions, set by constructor?
combat -- the combat API
combat.new(mapIndex, x, y) -- return combat instance's index
combat.pushenemy(c, enemy) -- return the enemy's position
combat.popenemy(c, position) --