Compare commits

..

38 Commits

Author SHA1 Message Date
Kayne Ruse 59963a05f3 Tried, failed. I give up 2014-08-31 04:29:40 +10:00
Kayne Ruse 7d4d7817f2 I've adjusted the naming conventions for the serial code (read more)
It looks like this whole branch is fucking useless, considering that I'll
need to reimplement that massive switch statement again just to determine
which overwritten method to use. I might as well not have bothered.
2014-08-31 02:58:47 +10:00
Kayne Ruse 1c1b1e0a1f I'm trying something to fix this stupid segfault 2014-08-30 22:27:52 +10:00
Kayne Ruse 895671e30f Fixed reference error 2014-08-30 21:36:25 +10:00
Kayne Ruse cfe82c0625 BUG: Receive() is failing 2014-08-28 22:28:37 +10:00
Kayne Ruse b5ca9dc729 Updated the client to use the packet methods 2014-08-28 22:05:21 +10:00
Kayne Ruse 164247de4f Updated the server to use the packet methods 2014-08-28 21:48:29 +10:00
Kayne Ruse ac799bc583 Finished tedious encapsulation of the packet classes 2014-08-27 20:35:04 +10:00
Kayne Ruse b8bd5f9cea Changed the internal serialization conventions 2014-08-27 16:04:14 +10:00
Kayne Ruse 4b5194918b Encapsulated SerialPacket, and made adjustments to accomodate it 2014-08-27 15:35:04 +10:00
Kayne Ruse 426c3a52c2 Made a few more adjustments, the file structure should be correct now 2014-08-27 14:57:33 +10:00
Kayne Ruse 16b2a60373 Renamed serial source files 2014-08-27 14:52:36 +10:00
Kayne Ruse 6cdc3080a2 Moved packet and serial files into the same directory 2014-08-27 14:38:13 +10:00
Kayne Ruse 6f4334f84d Moved serialization globals 2014-08-25 00:07:17 +10:00
Kayne Ruse 4ed512e0e2 Moved the snapToBase() utility function to region.*pp
I've also adjusted the TODO file, which really shouldn't be committed.
Still, it's there now, so it stays. I don't think the logger is going to
be possible any time soon, so I'll probably look into the disconnection
handler.
2014-08-24 13:23:50 +10:00
Kayne Ruse af8e7b70a0 Merge branch 'refactor-server' into develop
This is mostly just back end refactoring.
2014-08-19 04:14:34 +10:00
Kayne Ruse 8bc1326fef Added the "package" target to the root makefile 2014-08-19 04:11:12 +10:00
Kayne Ruse dfe8c108de Minor tweaks 2014-08-19 03:42:55 +10:00
Kayne Ruse 61337e29f6 Split the ServerApplication's source into two files 2014-08-19 03:22:25 +10:00
Kayne Ruse 5dea53ad50 Removed delta time system from the framework 2014-08-19 02:52:15 +10:00
Kayne Ruse f52a022e64 Bugfixes, read more
* Manual modifications to the database caused the map to act unusual
* The server's packet must be created and deleted as a char array
* removed UnloadAll() from several singleton destructors
* added SDL_Delay() to BaseScene::RenderFrame(), to reduce heavy CPU use in menus
2014-08-19 01:48:48 +10:00
Kayne Ruse 0fdaa90a83 Minor code tweaks 2014-08-17 11:46:02 +10:00
Kayne Ruse e7ba097e6a Converted the server's managers to singletons 2014-08-17 10:06:29 +10:00
Kayne Ruse 3b409a8608 Merge branch 'refactor-server' into develop, read more
This branch connects unique functions to the indevidual pagers, hopefully
allowing multiple different rooms in the future. That of course, will
require more work, but hopefully I can get that done soon.
2014-08-15 10:04:53 +10:00
Kayne Ruse ce97245131 Project builds, and runs with no obvious differences 2014-08-15 09:39:17 +10:00
Kayne Ruse 59c9ba698f Implemented the new system in the startup script, needs testing 2014-08-15 09:12:22 +10:00
Kayne Ruse 52ab9f0087 Minor tweaks 2014-08-15 08:53:41 +10:00
Kayne Ruse 4ea1f8b016 Added glue functions to set the pager triggers 2014-08-15 08:34:33 +10:00
Kayne Ruse f1080151e3 Minor preemptive bugfixes 2014-08-15 08:19:22 +10:00
Kayne Ruse 5af0a7999c Recoded the pager to use lua registry functions, needs testing 2014-08-15 07:10:27 +10:00
Kayne Ruse 1e9ac9815b Merge branch 'develop' into refactor-server 2014-08-14 01:04:22 +10:00
Kayne Ruse 98ffcb8cd3 Encapsulated RoomData, did some other refactoring 2014-08-14 00:13:19 +10:00
Kayne Ruse 1b041d7771 Tied region_pager_lua.cpp to region_api.hpp 2014-08-14 00:03:22 +10:00
Kayne Ruse 6d98bab000 Began refactoring the server (read more)
* deleted the enemy and combat stubs
* encapsulated the character and account stubs

TODO:

* The remaining managers should be singletons
2014-08-13 09:45:54 +10:00
Kayne Ruse b6c70cbc0d Tweaked the bounds values 2014-08-13 09:05:26 +10:00
Kayne Ruse 1776583e01 Added the escape hotkey, refined BoundingBox a bit
LobbyMenu also searches for a server as soon as you enter, so you don't
have to press an extra button, a good feature.
2014-08-13 08:08:16 +10:00
Kayne Ruse 74f809a801 UDPNetworkUtility is a singleton, disabled InCombat scene
I found incombat to be way too finicky to keep up to date, so I disabled
it for now.
2014-08-13 06:53:47 +10:00
Kayne Ruse 182101b592 Minor tweaks 2014-08-13 06:19:07 +10:00
98 changed files with 1746 additions and 2669 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);
+13 -14
View File
@@ -21,7 +21,6 @@
*/
#include "client_application.hpp"
#include "serial.hpp"
#include "config_utility.hpp"
#include <stdexcept>
@@ -38,7 +37,7 @@
#include "options_menu.hpp"
#include "lobby_menu.hpp"
#include "in_world.hpp"
#include "in_combat.hpp"
//#include "in_combat.hpp"
#include "clean_up.hpp"
//-------------------------
@@ -66,7 +65,7 @@ void ClientApplication::Init(int argc, char** argv) {
if (SDLNet_Init()) {
throw(std::runtime_error("Failed to initialize SDL_net"));
}
network.Open(0);
UDPNetworkUtility::GetSingleton().Open(0);
std::cout << "Initialized SDL_net" << std::endl;
//-------------------------
@@ -94,8 +93,8 @@ void ClientApplication::Init(int argc, char** argv) {
DEBUG_OUTPUT_VAR(REGION_WIDTH);
DEBUG_OUTPUT_VAR(REGION_HEIGHT);
DEBUG_OUTPUT_VAR(REGION_DEPTH);
DEBUG_OUTPUT_VAR(REGION_TILE_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_FOOTPRINT);
DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE);
DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE);
@@ -120,7 +119,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 +136,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
@@ -151,7 +150,7 @@ void ClientApplication::Proc() {
void ClientApplication::Quit() {
std::cout << "Shutting down" << std::endl;
network.Close();
UDPNetworkUtility::GetSingleton().Close();
SDLNet_Quit();
SDL_Quit();
std::cout << "Clean exit" << std::endl;
@@ -176,16 +175,16 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
activeScene = new OptionsMenu();
break;
case SceneList::LOBBYMENU:
activeScene = new LobbyMenu(&network, &clientIndex, &accountIndex);
activeScene = new LobbyMenu(&clientIndex, &accountIndex);
break;
case SceneList::INWORLD:
activeScene = new InWorld(&network, &clientIndex, &accountIndex, &characterIndex, &characterMap);
break;
case SceneList::INCOMBAT:
activeScene = new InCombat(&network, &clientIndex, &accountIndex, &characterIndex, &characterMap);
activeScene = new InWorld(&clientIndex, &accountIndex, &characterIndex, &characterMap);
break;
// case SceneList::INCOMBAT:
// activeScene = new InCombat(&clientIndex, &accountIndex, &characterIndex, &characterMap);
// break;
case SceneList::CLEANUP:
activeScene = new CleanUp(&network, &clientIndex, &accountIndex, &characterIndex, &characterMap);
activeScene = new CleanUp(&clientIndex, &accountIndex, &characterIndex, &characterMap);
break;
default:
throw(std::logic_error("Failed to recognize the scene index"));
-1
View File
@@ -52,7 +52,6 @@ private:
BaseScene* activeScene = nullptr;
//shared parameters
UDPNetworkUtility network;
int clientIndex = -1;
int accountIndex = -1;
int characterIndex = -1;
+7 -2
View File
@@ -23,6 +23,7 @@
//singletons
#include "config_utility.hpp"
#include "udp_network_utility.hpp"
#include <stdexcept>
#include <iostream>
@@ -32,18 +33,22 @@ using namespace std;
int main(int argc, char** argv) {
try {
//create the singletons
ClientApplication::Create();
ConfigUtility::Create();
UDPNetworkUtility::Create();
//call the server's routines
ClientApplication::Create();
ClientApplication& app = ClientApplication::GetSingleton();
app.Init(argc, argv);
app.Proc();
app.Quit();
ClientApplication::Delete();
//delete the singletons
ConfigUtility::Delete();
ClientApplication::Delete();
UDPNetworkUtility::Delete();
}
catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl;
+1 -1
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=. scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet ../common/network/serial ../common/ui ../common/utilities
INCLUDES+=. scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities
LIBS+=client.a ../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+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) {}
+7 -12
View File
@@ -31,13 +31,11 @@
//-------------------------
CleanUp::CleanUp(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
CharacterMap* argCharacterMap
):
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex),
@@ -82,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);
@@ -126,7 +117,11 @@ void CleanUp::MouseButtonUp(SDL_MouseButtonEvent const& button) {
}
void CleanUp::KeyDown(SDL_KeyboardEvent const& key) {
//
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
}
}
void CleanUp::KeyUp(SDL_KeyboardEvent const& key) {
+3 -10
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
@@ -45,7 +41,6 @@ class CleanUp : public BaseScene {
public:
//Public access members
CleanUp(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
@@ -55,8 +50,7 @@ public:
protected:
//Frame loop
void Update(double delta);
void RenderFrame();
void Update();
void Render(SDL_Surface* const);
//Event handlers
@@ -68,7 +62,7 @@ protected:
void KeyUp(SDL_KeyboardEvent const&);
//shared parameters
UDPNetworkUtility& network;
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
int& clientIndex;
int& accountIndex;
int& characterIndex;
@@ -80,7 +74,6 @@ protected:
//UI
Button backButton;
FrameRate fps;
//auto return
std::chrono::steady_clock::time_point startTick;
-220
View File
@@ -1,220 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 "in_combat.hpp"
#include "channels.hpp"
#include "utility.hpp"
#include "config_utility.hpp"
#include <stdexcept>
//-------------------------
//Public access members
//-------------------------
InCombat::InCombat(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
CharacterMap* argCharacterMap
):
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex),
characterMap(*argCharacterMap)
{
/* //setup the utility objects
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
buttonImage.SetClipH(buttonImage.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
backButton.SetImage(&buttonImage);
backButton.SetFont(&font);
//set the button positions
backButton.SetX(50);
backButton.SetY(50 + buttonImage.GetClipH() * 0);
//set the button texts
backButton.SetText("Back");
//request a sync
RequestSynchronize();
*/
//debug
//
}
InCombat::~InCombat() {
//
}
//-------------------------
//Frame loop
//-------------------------
void InCombat::FrameStart() {
//
}
void InCombat::Update(double delta) {
//suck in and process all waiting packets
SerialPacket* packetBuffer = static_cast<SerialPacket*>(malloc(MAX_PACKET_SIZE));
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
free(static_cast<void*>(packetBuffer));
//TODO: more
}
void InCombat::FrameEnd() {
//
}
void InCombat::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void InCombat::Render(SDL_Surface* const screen) {
//TODO: draw the background
//TODO: draw the characters
//TODO: draw the enemies
//TODO: draw the UI
}
//-------------------------
//Event handlers
//-------------------------
void InCombat::QuitEvent() {
//exit the game AND the server
RequestDisconnect();
SetNextScene(SceneList::QUIT);
}
void InCombat::MouseMotion(SDL_MouseMotionEvent const& motion) {
//
}
void InCombat::MouseButtonDown(SDL_MouseButtonEvent const& button) {
//
}
void InCombat::MouseButtonUp(SDL_MouseButtonEvent const& button) {
//
}
void InCombat::KeyDown(SDL_KeyboardEvent const& key) {
//
}
void InCombat::KeyUp(SDL_KeyboardEvent const& key) {
//
}
//-------------------------
//Network handlers
//-------------------------
void InCombat::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
case SerialPacketType::DISCONNECT:
HandleDisconnect(argPacket);
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in InCombat: " + to_string_custom(static_cast<int>(argPacket->type)) ));
break;
}
}
void InCombat::HandleDisconnect(SerialPacket* const) {
SetNextScene(SceneList::CLEANUP);
}
//TODO: more network handlers
//-------------------------
//Server control
//-------------------------
void InCombat::RequestSynchronize() {
ClientPacket newPacket;
//request a sync
newPacket.type = SerialPacketType::SYNCHRONIZE;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void InCombat::SendPlayerUpdate() {
CharacterPacket newPacket;
//pack the packet
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
newPacket.characterIndex = characterIndex;
//handle, avatar
newPacket.accountIndex = accountIndex;
// newPacket.roomIndex = localCharacter->roomIndex;
// newPacket.origin = localCharacter->origin;
// newPacket.motion = localCharacter->motion;
// newPacket.stats = localCharacter->stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
network.SendTo(Channels::SERVER, &newPacket);
}
void InCombat::RequestDisconnect() {
ClientPacket newPacket;
//send a disconnect request
newPacket.type = SerialPacketType::DISCONNECT;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void InCombat::RequestShutdown() {
ClientPacket newPacket;
//send a shutdown request
newPacket.type = SerialPacketType::SHUTDOWN;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
-94
View File
@@ -1,94 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 INCOMBAT_HPP_
#define INCOMBAT_HPP_
//network
#include "udp_network_utility.hpp"
//graphics
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
//common
#include "frame_rate.hpp"
#include "character.hpp"
//client
#include "base_scene.hpp"
class InCombat : public BaseScene {
public:
//Public access members
InCombat(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
CharacterMap* argCharacterMap
);
~InCombat();
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void FrameEnd();
void RenderFrame();
void Render(SDL_Surface* const);
//Event handlers
void QuitEvent();
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&);
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
//Network handlers
void HandlePacket(SerialPacket* const);
void HandleDisconnect(SerialPacket* const);
//Server control
void RequestSynchronize();
void SendPlayerUpdate();
void RequestDisconnect();
void RequestShutdown();
//shared parameters
UDPNetworkUtility& network;
int& clientIndex;
int& accountIndex;
int& characterIndex;
CharacterMap& characterMap;
//graphics
//TODO: graphics
//UI
//TODO: UI
FrameRate fps;
};
#endif
+60 -50
View File
@@ -35,13 +35,11 @@
//-------------------------
InWorld::InWorld(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
CharacterMap* argCharacterMap
):
network(*argNetwork),
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
characterIndex(*argCharacterIndex),
@@ -94,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
@@ -131,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();
@@ -207,6 +205,13 @@ void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
return;
}
//hotkeys
switch(key.keysym.sym) {
case SDLK_ESCAPE:
RequestDisconnect();
break;
}
//player movement
Vector2 motion = localCharacter->GetMotion();
switch(key.keysym.sym) {
@@ -264,7 +269,7 @@ void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
//-------------------------
void InWorld::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
switch(argPacket->GetType()) {
case SerialPacketType::DISCONNECT:
HandleDisconnect(argPacket);
break;
@@ -282,7 +287,7 @@ void InWorld::HandlePacket(SerialPacket* const argPacket) {
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in InWorld: " + to_string_custom(static_cast<int>(argPacket->type)) ));
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in InWorld: " + to_string_custom(static_cast<int>(argPacket->GetType())) ));
break;
}
}
@@ -292,31 +297,36 @@ void InWorld::HandleDisconnect(SerialPacket* const argPacket) {
}
void InWorld::HandleCharacterNew(CharacterPacket* const argPacket) {
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
if (characterMap.find(argPacket->GetCharacterIndex()) != characterMap.end()) {
throw(std::runtime_error("Cannot create duplicate characters"));
}
//create the character object
Character& newCharacter = characterMap[argPacket->characterIndex];
Character& newCharacter = characterMap[argPacket->GetCharacterIndex()];
//fill out the character's members
newCharacter.SetHandle(argPacket->handle);
newCharacter.SetAvatar(argPacket->avatar);
newCharacter.SetHandle(argPacket->GetHandle());
newCharacter.SetAvatar(argPacket->GetAvatar());
newCharacter.GetSprite()->LoadSurface(ConfigUtility::GetSingleton()["dir.sprites"] + newCharacter.GetAvatar(), 4, 4);
newCharacter.SetOrigin(argPacket->origin);
newCharacter.SetMotion(argPacket->motion);
newCharacter.SetBounds({0, 16, 32, 32}); //TODO: magic numbers, fix this
newCharacter.SetOrigin(argPacket->GetOrigin());
newCharacter.SetMotion(argPacket->GetMotion());
newCharacter.SetBounds({
CHARACTER_BOUNDS_X,
CHARACTER_BOUNDS_Y,
CHARACTER_BOUNDS_WIDTH,
CHARACTER_BOUNDS_HEIGHT
});
(*newCharacter.GetStats()) = argPacket->stats;
*newCharacter.GetStats() = *argPacket->GetStatistics();
//bookkeeping code
newCharacter.CorrectSprite();
//catch this client's player object
if (argPacket->accountIndex == accountIndex && !localCharacter) {
characterIndex = argPacket->characterIndex;
if (argPacket->GetAccountIndex() == accountIndex && !localCharacter) {
characterIndex = argPacket->GetCharacterIndex();
localCharacter = &newCharacter;
//setup the camera
@@ -334,39 +344,39 @@ void InWorld::HandleCharacterDelete(CharacterPacket* const argPacket) {
//TODO: authenticate when own character is being deleted (linked to a TODO in the server)
//catch this client's player object
if (argPacket->characterIndex == characterIndex) {
if (argPacket->GetCharacterIndex() == characterIndex) {
characterIndex = -1;
localCharacter = nullptr;
}
characterMap.erase(argPacket->characterIndex);
characterMap.erase(argPacket->GetCharacterIndex());
}
void InWorld::HandleCharacterUpdate(CharacterPacket* const argPacket) {
if (characterMap.find(argPacket->characterIndex) == characterMap.end()) {
if (characterMap.find(argPacket->GetCharacterIndex()) == characterMap.end()) {
std::cout << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl;
HandleCharacterNew(argPacket);
return;
}
Character& character = characterMap[argPacket->characterIndex];
Character& character = characterMap[argPacket->GetCharacterIndex()];
//other characters moving
if (argPacket->characterIndex != characterIndex) {
character.SetOrigin(argPacket->origin);
character.SetMotion(argPacket->motion);
if (argPacket->GetCharacterIndex() != characterIndex) {
character.SetOrigin(argPacket->GetOrigin());
character.SetMotion(argPacket->GetMotion());
character.CorrectSprite();
}
}
void InWorld::HandleRegionContent(RegionPacket* const argPacket) {
//replace existing regions
regionPager.UnloadRegion(argPacket->x, argPacket->y);
regionPager.PushRegion(argPacket->region);
regionPager.UnloadRegion(argPacket->GetX(), argPacket->GetY());
regionPager.PushRegion(argPacket->GetRegion());
//clean up after the serial code
delete argPacket->region;
argPacket->region = nullptr;
delete argPacket->GetRegion();
argPacket->SetRegion(nullptr);
}
//-------------------------
@@ -377,9 +387,9 @@ void InWorld::RequestSynchronize() {
ClientPacket newPacket;
//request a sync
newPacket.type = SerialPacketType::SYNCHRONIZE;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
newPacket.SetType(SerialPacketType::SYNCHRONIZE);
newPacket.SetClientIndex(clientIndex);
newPacket.SetAccountIndex(accountIndex);
//TODO: location, range for sync request
@@ -390,15 +400,15 @@ void InWorld::SendPlayerUpdate() {
CharacterPacket newPacket;
//pack the packet
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
newPacket.SetType(SerialPacketType::CHARACTER_UPDATE);
newPacket.characterIndex = characterIndex;
newPacket.SetCharacterIndex(characterIndex);
//NOTE: omitting the handle and avatar here
newPacket.accountIndex = accountIndex;
newPacket.roomIndex = 0; //TODO: room index
newPacket.origin = localCharacter->GetOrigin();
newPacket.motion = localCharacter->GetMotion();
newPacket.stats = *localCharacter->GetStats();
newPacket.SetAccountIndex(accountIndex);
newPacket.SetRoomIndex(0); //TODO: room index
newPacket.SetOrigin(localCharacter->GetOrigin());
newPacket.SetMotion(localCharacter->GetMotion());
*newPacket.GetStatistics() = *localCharacter->GetStats();
//TODO: gameplay components: equipment, items, buffs, debuffs
@@ -409,9 +419,9 @@ void InWorld::RequestDisconnect() {
ClientPacket newPacket;
//send a disconnect request
newPacket.type = SerialPacketType::DISCONNECT;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
newPacket.SetType(SerialPacketType::DISCONNECT);
newPacket.SetClientIndex(clientIndex);
newPacket.SetAccountIndex(accountIndex);
network.SendTo(Channels::SERVER, &newPacket);
}
@@ -420,9 +430,9 @@ void InWorld::RequestShutDown() {
ClientPacket newPacket;
//send a shutdown request
newPacket.type = SerialPacketType::SHUTDOWN;
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
newPacket.SetType(SerialPacketType::SHUTDOWN);
newPacket.SetClientIndex(clientIndex);
newPacket.SetAccountIndex(accountIndex);
network.SendTo(Channels::SERVER, &newPacket);
}
@@ -431,10 +441,10 @@ void InWorld::RequestRegion(int roomIndex, int x, int y) {
RegionPacket packet;
//pack the region's data
packet.type = SerialPacketType::REGION_REQUEST;
packet.roomIndex = roomIndex;
packet.x = x;
packet.y = y;
packet.SetType(SerialPacketType::REGION_REQUEST);
packet.SetRoomIndex(roomIndex);
packet.SetX(x);
packet.SetY(y);
network.SendTo(Channels::SERVER, &packet);
}
+2 -3
View File
@@ -49,7 +49,6 @@ class InWorld : public BaseScene {
public:
//Public access members
InWorld(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex,
int* const argCharacterIndex,
@@ -60,7 +59,7 @@ public:
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void RenderFrame();
void Render(SDL_Surface* const);
@@ -92,7 +91,7 @@ protected:
void UpdateMap();
//shared parameters
UDPNetworkUtility& network;
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
int& clientIndex;
int& accountIndex;
int& characterIndex;
+62 -51
View File
@@ -30,12 +30,7 @@
//Public access members
//-------------------------
LobbyMenu::LobbyMenu(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex
):
network(*argNetwork),
LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex)
{
@@ -70,6 +65,9 @@ LobbyMenu::LobbyMenu(
//BUGFIX: Eat incoming packets
while(network.Receive());
//Initial broadcast
SendBroadcastRequest();
}
LobbyMenu::~LobbyMenu() {
@@ -84,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() {
@@ -109,7 +107,10 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
for (int i = 0; i < serverInfo.size(); i++) {
//draw the selected server's highlight
if (selection == &serverInfo[i]) {
SDL_Rect r = listBox;
SDL_Rect r = {
(Sint16)listBox.x, (Sint16)listBox.y,
(Uint16)listBox.w, (Uint16)listBox.h
};
r.y += i * listBox.h;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
}
@@ -147,39 +148,19 @@ void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (search.MouseButtonUp(button) == Button::State::HOVER) {
//broadcast to the network, or a specific server
SerialPacket packet;
packet.type = SerialPacketType::BROADCAST_REQUEST;
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
//reset the server list
serverInfo.clear();
selection = nullptr;
SendBroadcastRequest();
}
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
//pack the packet
ClientPacket packet;
packet.type = SerialPacketType::JOIN_REQUEST;
strncpy(packet.username, config["client.username"].c_str(), PACKET_STRING_SIZE);
//join the selected server
network.SendTo(&selection->address, &packet);
selection = nullptr;
SendJoinRequest();
}
else if (back.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU);
}
else if (
//has the user selected a server on the list?
//TODO: replace with regular collision checker
button.x > listBox.x &&
button.x < listBox.x + listBox.w &&
button.y > listBox.y &&
button.y < listBox.y + listBox.h * serverInfo.size()
) {
//has the user selected a server on the list?
BoundingBox tmpBox = listBox;
tmpBox.h *= serverInfo.size();
if (tmpBox.CheckOverlap({button.x, button.y})) {
selection = &serverInfo[(button.y - listBox.y)/listBox.h];
}
else {
@@ -188,7 +169,11 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
}
void LobbyMenu::KeyDown(SDL_KeyboardEvent const& key) {
//
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
}
}
void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
@@ -200,7 +185,7 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
//-------------------------
void LobbyMenu::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
switch(argPacket->GetType()) {
case SerialPacketType::BROADCAST_RESPONSE:
HandleBroadcastResponse(static_cast<ServerPacket*>(argPacket));
break;
@@ -209,7 +194,7 @@ void LobbyMenu::HandlePacket(SerialPacket* const argPacket) {
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in LobbyMenu: " + to_string_custom(static_cast<int>(argPacket->type)) ));
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in LobbyMenu: " + to_string_custom(static_cast<int>(argPacket->GetType())) ));
break;
}
}
@@ -217,10 +202,10 @@ void LobbyMenu::HandlePacket(SerialPacket* const argPacket) {
void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) {
//extract the data
ServerInformation server;
server.address = argPacket->srcAddress;
server.name = argPacket->name;
server.playerCount = argPacket->playerCount;
server.version = argPacket->version;
server.address = argPacket->GetAddress();
server.name = argPacket->GetName();
server.playerCount = argPacket->GetPlayerCount();
server.version = argPacket->GetVersion();
//Checking compatibility
server.compatible = server.version == NETWORK_VERSION;
@@ -230,16 +215,42 @@ void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) {
}
void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
clientIndex = argPacket->clientIndex;
accountIndex = argPacket->accountIndex;
network.Bind(&argPacket->srcAddress, Channels::SERVER);
clientIndex = argPacket->GetClientIndex();
accountIndex = argPacket->GetAccountIndex();
network.Bind(argPacket->GetAddressPtr(), Channels::SERVER);
SetNextScene(SceneList::INWORLD);
//send this player's character info
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_NEW;
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
newPacket.accountIndex = accountIndex;
newPacket.SetType(SerialPacketType::CHARACTER_NEW);
newPacket.SetHandle(config["client.handle"].c_str());
newPacket.SetAvatar(config["client.avatar"].c_str());
newPacket.SetAccountIndex(accountIndex);
network.SendTo(Channels::SERVER, &newPacket);
}
}
//-------------------------
//server control
//-------------------------
void LobbyMenu::SendBroadcastRequest() {
//broadcast to the network, or a specific server
ServerPacket packet;
packet.SetType(SerialPacketType::BROADCAST_REQUEST);
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
//reset the server list
serverInfo.clear();
selection = nullptr;
}
void LobbyMenu::SendJoinRequest() {
//pack the packet
ClientPacket packet;
packet.SetType(SerialPacketType::JOIN_REQUEST);
packet.SetUsername(config["client.username"].c_str());
//join the selected server
network.SendTo(&selection->address, &packet);
selection = nullptr;
}
+10 -9
View File
@@ -26,6 +26,7 @@
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include "bounding_box.hpp"
//utilities
#include "config_utility.hpp"
@@ -40,17 +41,13 @@
class LobbyMenu : public BaseScene {
public:
//Public access members
LobbyMenu(
UDPNetworkUtility* const argNetwork,
int* const argClientIndex,
int* const argAccountIndex
);
LobbyMenu(int* const argClientIndex, int* const argAccountIndex);
~LobbyMenu();
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void Update();
void FrameEnd();
void Render(SDL_Surface* const);
@@ -66,9 +63,13 @@ protected:
void HandleBroadcastResponse(ServerPacket* const);
void HandleJoinResponse(ClientPacket* const);
//server control
void SendBroadcastRequest();
void SendJoinRequest();
//shared parameters
ConfigUtility& config = ConfigUtility::GetSingleton();
UDPNetworkUtility& network;
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
int& clientIndex;
int& accountIndex;
@@ -90,9 +91,9 @@ protected:
std::vector<ServerInformation> serverInfo;
//a terrible hack, forgive me
//NOTE: a terrible hack
//I'd love a proper gui system for this
SDL_Rect listBox;
BoundingBox listBox;
ServerInformation* selection = nullptr;
};
+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
@@ -1,5 +1,5 @@
#config
INCLUDES+=. .. ../../common/gameplay ../../common/graphics ../../common/map ../../common/network ../../common/network/packet ../../common/network/serial ../../common/ui ../../common/utilities
INCLUDES+=. .. ../../common/gameplay ../../common/graphics ../../common/map ../../common/network ../../common/network/packet_types ../../common/ui ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+6 -2
View File
@@ -59,7 +59,7 @@ void OptionsMenu::FrameStart() {
//
}
void OptionsMenu::Update(double delta) {
void OptionsMenu::Update() {
//
}
@@ -92,7 +92,11 @@ void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
}
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
//
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
}
}
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
+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
+5 -2
View File
@@ -21,11 +21,14 @@
*/
#include "region.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <cmath>
#include <cstring>
int snapToBase(int base, int x) {
return floor((double)x / base) * base;
}
Region::Region(int argX, int argY): x(argX), y(argY) {
if (x != snapToBase(REGION_WIDTH, x) || y != snapToBase(REGION_HEIGHT, y)) {
throw(std::invalid_argument("Region location is off grid"));
+2 -6
View File
@@ -23,15 +23,14 @@
#define REGION_HPP_
#include <bitset>
#include <cmath>
//the region's storage format
constexpr int REGION_WIDTH = 20;
constexpr int REGION_HEIGHT = 20;
constexpr int REGION_DEPTH = 3;
//the size of the solid map
constexpr int REGION_SOLID_FOOTPRINT = ceil(REGION_WIDTH * REGION_HEIGHT / 8.0);
//utility function
int snapToBase(int base, int x);
class Region {
public:
@@ -61,7 +60,4 @@ private:
std::bitset<REGION_WIDTH*REGION_HEIGHT> solid;
};
//the memory footprint of the tile and solid data; not including any metadata
constexpr int REGION_FOOTPRINT = REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + REGION_SOLID_FOOTPRINT;
#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 -2
View File
@@ -24,8 +24,6 @@
#include "region_pager_lua.hpp"
#include "region.hpp"
#include <string>
//DOCS: These glue functions simply wrap RegionPagerLua's methods
static int setTile(lua_State* L) {
@@ -90,16 +88,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}
};
+5 -6
View File
@@ -21,8 +21,6 @@
*/
#include "region_pager_base.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <algorithm>
@@ -73,12 +71,12 @@ Region* RegionPagerBase::PushRegion(Region* const ptr) {
}
Region* RegionPagerBase::LoadRegion(int x, int y) {
//TODO: load the region if possible
//EMPTY, intended for override
return nullptr;
}
Region* RegionPagerBase::SaveRegion(int x, int y) {
//TODO: find & save the region
//EMPTY, intended for override
return nullptr;
}
@@ -91,8 +89,9 @@ Region* RegionPagerBase::CreateRegion(int x, int y) {
}
void RegionPagerBase::UnloadRegion(int x, int y) {
//custom loop, not FindRegion()
regionList.remove_if([x, y](Region& region) -> bool { return region.GetX() == x && region.GetY() == y; });
regionList.remove_if([x, y](Region& region) -> bool {
return region.GetX() == x && region.GetY() == y;
});
}
void RegionPagerBase::UnloadAll() {
+92 -36
View File
@@ -21,47 +21,71 @@
*/
#include "region_pager_lua.hpp"
#include "utility.hpp"
#include <stdexcept>
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 +93,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
+2 -3
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=. packet serial ../gameplay ../map ../utilities
INCLUDES+=. packet_types ../gameplay ../map ../utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
@@ -17,8 +17,7 @@ OUT=$(addprefix $(OUTDIR)/,libcommon.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(MAKE) -C packet
$(MAKE) -C serial
$(MAKE) -C packet_types
$(OBJ): | $(OBJDIR)
-46
View File
@@ -1,46 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 COMBATPACKET_HPP_
#define COMBATPACKET_HPP_
#include "serial_packet_base.hpp"
#include "combat_defines.hpp"
struct CombatPacket : SerialPacketBase {
//identify the combat instance
int combatIndex;
int difficulty;
TerrainType terrainType;
//combatants
int characterArray[COMBAT_MAX_CHARACTERS];
int enemyArray[COMBAT_MAX_ENEMIES];
//location
int mapIndex;
Vector2 origin;
//TODO: gameplay components: rewards
};
#endif
-39
View File
@@ -1,39 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 ENEMYPACKET_HPP_
#define ENEMYPACKET_HPP_
#include "serial_packet_base.hpp"
struct EnemyPacket : SerialPacketBase {
//identify the enemy
int enemyIndex;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
//gameplay
Statistics stats;
//TODO: gameplay components: equipment, items, buffs, debuffs, rewards
};
#endif
-28
View File
@@ -1,28 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 "serial_packet.hpp"
/* DOCS: Sanity check, read more
* Since most/all of the files in this directory are header files, I've created
* this source file as a "sanity check", to ensure that the above header files
* are written correctly via make.
*/
@@ -1,113 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 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 SERIALPACKETTYPE_HPP_
#define SERIALPACKETTYPE_HPP_
/* Key for the comments:
* request => response
*/
enum class SerialPacketType {
//default: there is something wrong
NONE = 0,
//keep alive
//ping => pong
PING = 1,
PONG = 2,
//search for the server list
//none => server name, player count, version info (and source address)
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
//try to join the server
//username, and password => client index, account index
JOIN_REQUEST = 5,
JOIN_RESPONSE = 6,
JOIN_REJECTION = 7,
//mass update of all surrounding content
//character.x, character.y => packet barrage
SYNCHRONIZE = 8,
//disconnect from the server
//autentication, account index => disconnect that account
DISCONNECT = 9,
//shut down the server
//autentication => disconnect, shutdown
SHUTDOWN = 10,
//map data
//room index, region.x, region.y => room index, region.x, region.y, region content
REGION_REQUEST = 11,
REGION_CONTENT = 12,
//combat data
//TODO: system incomplete
COMBAT_NEW = 13,
COMBAT_DELETE = 14,
COMBAT_UPDATE = 15,
COMBAT_ENTER_REQUEST = 16,
COMBAT_ENTER_RESPONSE = 17,
COMBAT_EXIT_REQUEST = 18,
COMBAT_EXIT_RESPONSE = 19,
//TODO: COMBAT info
COMBAT_REJECTION = 20,
//character data
//character data => etc.
CHARACTER_NEW = 21,
CHARACTER_DELETE = 22,
CHARACTER_UPDATE = 23,
//authentication, character index => character stats
CHARACTER_STATS_REQUEST= 24,
CHARACTER_STATS_RESPONSE = 25,
//character new => character rejection, disconnect?
CHARACTER_REJECTION = 26,
//enemy data
//enemy data => etc.
ENEMY_NEW = 27,
ENEMY_DELETE = 28,
ENEMY_UPDATE = 29,
ENEMY_STATS_REQUEST = 30,
ENEMY_STATS_RESPONSE = 31,
//enemy index => enemy doens't exist
ENEMY_REJECTION= 32,
//NOTE: more packet types go here
//not used
LAST
};
#endif
@@ -0,0 +1,72 @@
/* 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 "character_packet.hpp"
#include "serial_utility.hpp"
void CharacterPacket::Serialize(void* buffer) {
serializeCopy(&buffer, &type, sizeof(SerialPacketType));
//identify the character
serializeCopy(&buffer, &characterIndex, sizeof(int));
serializeCopy(&buffer, handle, PACKET_STRING_SIZE);
serializeCopy(&buffer, avatar, PACKET_STRING_SIZE);
//the owner
serializeCopy(&buffer, &accountIndex, sizeof(int));
//location
serializeCopy(&buffer, &roomIndex, sizeof(int));
serializeCopy(&buffer, &origin.x, sizeof(double));
serializeCopy(&buffer, &origin.y, sizeof(double));
serializeCopy(&buffer, &motion.x, sizeof(double));
serializeCopy(&buffer, &motion.y, sizeof(double));
//stats structure
serializeCopyStatistics(&buffer, &stats);
//TODO: gameplay components: equipment, items, buffs, debuffs
}
void CharacterPacket::Deserialize(void* buffer) {
deserializeCopy(&buffer, &type, sizeof(SerialPacketType));
//identify the character
deserializeCopy(&buffer, &characterIndex, sizeof(int));
deserializeCopy(&buffer, handle, PACKET_STRING_SIZE);
deserializeCopy(&buffer, avatar, PACKET_STRING_SIZE);
//the owner
deserializeCopy(&buffer, &accountIndex, sizeof(int));
//location
deserializeCopy(&buffer, &roomIndex, sizeof(int));
deserializeCopy(&buffer, &origin.x, sizeof(double));
deserializeCopy(&buffer, &origin.y, sizeof(double));
deserializeCopy(&buffer, &motion.x, sizeof(double));
deserializeCopy(&buffer, &motion.y, sizeof(double));
//stats structure
deserializeCopyStatistics(&buffer, &stats);
//TODO: gameplay components: equipment, items, buffs, debuffs
}
@@ -0,0 +1,87 @@
/* Copyright: (c) Kayne Ruse 2013, 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 CHARACTERPACKET_HPP_
#define CHARACTERPACKET_HPP_
#include "serial_packet_base.hpp"
#include "vector2.hpp"
#include "statistics.hpp"
#include <cstring>
class CharacterPacket : public SerialPacketBase {
public:
CharacterPacket() {}
~CharacterPacket() {}
//indentity
int SetCharacterIndex(int i) { return characterIndex = i; }
const char* SetHandle(const char* s)
{ return strncpy(handle, s, PACKET_STRING_SIZE); }
const char* SetAvatar(const char* s)
{ return strncpy(handle, s, PACKET_STRING_SIZE); }
int SetAccountIndex(int i) { return accountIndex = i; }
int GetCharacterIndex() { return characterIndex; }
const char* GetHandle() { return handle; }
const char* GetAvatar() { return avatar; }
int GetAccountIndex() { return accountIndex; }
//location
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; }
//gameplay
Statistics* GetStatistics() { return &stats; }
virtual void Serialize(void* buffer) override;
virtual void Deserialize(void* buffer) override;
private:
//identify the character
int characterIndex;
char handle[PACKET_STRING_SIZE+1];
char avatar[PACKET_STRING_SIZE+1];
//the owner
int accountIndex;
//location
int roomIndex;
Vector2 origin;
Vector2 motion;
//gameplay
Statistics stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
};
#endif
@@ -19,36 +19,22 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "enemy_manager.hpp"
#include "client_packet.hpp"
//-------------------------
//public access methods
//-------------------------
#include "serial_utility.hpp"
//TODO
void ClientPacket::Serialize(void* buffer) {
serializeCopy(&buffer, &type, sizeof(SerialPacketType));
//-------------------------
//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;
serializeCopy(&buffer, &clientIndex, sizeof(int));
serializeCopy(&buffer, &accountIndex, sizeof(int));
serializeCopy(&buffer, username, PACKET_STRING_SIZE);
}
std::map<int, EnemyData>* EnemyManager::GetContainer() {
return &enemyMap;
}
void ClientPacket::Deserialize(void* buffer) {
deserializeCopy(&buffer, &type, sizeof(SerialPacketType));
lua_State* EnemyManager::SetLuaState(lua_State* L) {
return luaState = L;
}
lua_State* EnemyManager::GetLuaState() {
return luaState;
deserializeCopy(&buffer, &clientIndex, sizeof(int));
deserializeCopy(&buffer, &accountIndex, sizeof(int));
deserializeCopy(&buffer, username, PACKET_STRING_SIZE);
}
@@ -24,10 +24,30 @@
#include "serial_packet_base.hpp"
struct ClientPacket : SerialPacketBase {
#include <cstring>
class ClientPacket : public SerialPacketBase {
public:
ClientPacket() {}
~ClientPacket() {}
//accessors & mutators
int SetClientIndex(int i) { return clientIndex = i; }
int SetAccountIndex(int i) { return accountIndex = i; }
const char* SetUsername(const char* s)
{ return strncpy(username, s, PACKET_STRING_SIZE); }
int GetClientIndex() { return clientIndex; }
int GetAccountIndex() { return accountIndex; }
const char* GetUsername() { return username; }
virtual void Serialize(void* buffer) override;
virtual void Deserialize(void* buffer) override;
private:
int clientIndex;
int accountIndex;
char username[PACKET_STRING_SIZE];
char username[PACKET_STRING_SIZE+1];
// char password[PACKET_STRING_SIZE]; //hashed, not currently used
};
@@ -1,5 +1,5 @@
#config
INCLUDES+=. ../../gameplay ../../map ../../utilities
INCLUDES+=. .. ../../gameplay ../../map ../../utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
@@ -0,0 +1,79 @@
/* 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 "region_packet.hpp"
#include "serial_utility.hpp"
void RegionPacket::Serialize(void* buffer) {
serializeCopy(&buffer, &type, sizeof(SerialPacketType));
//format
serializeCopy(&buffer, &roomIndex, sizeof(int));
serializeCopy(&buffer, &x, sizeof(int));
serializeCopy(&buffer, &y, sizeof(int));
if (type != SerialPacketType::REGION_CONTENT) {
return;
}
//tiles
for (int i = 0; i < REGION_WIDTH; i++) {
for (int j = 0; j < REGION_HEIGHT; j++) {
for (int k = 0; k < REGION_DEPTH; k++) {
*reinterpret_cast<Region::type_t*>(buffer) = region->GetTile(i, j, k);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Region::type_t);
}
}
}
//solids
serializeCopy(&buffer, region->GetSolidBitset(), REGION_SOLID_FOOTPRINT);
}
void RegionPacket::Deserialize(void* buffer) {
deserializeCopy(&buffer, &type, sizeof(SerialPacketType));
//format
deserializeCopy(&buffer, &roomIndex, sizeof(int));
deserializeCopy(&buffer, &x, sizeof(int));
deserializeCopy(&buffer, &y, sizeof(int));
if (type != SerialPacketType::REGION_CONTENT) {
return;
}
//an object to work on
region = new Region(x, y);
//tiles
for (int i = 0; i < REGION_WIDTH; i++) {
for (int j = 0; j < REGION_HEIGHT; j++) {
for (int k = 0; k < REGION_DEPTH; k++) {
region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
buffer = reinterpret_cast<char*>(buffer) + sizeof(Region::type_t);
}
}
}
//solids
deserializeCopy(&buffer, region->GetSolidBitset(), REGION_SOLID_FOOTPRINT);
}
@@ -26,7 +26,36 @@
#include "region.hpp"
struct RegionPacket : SerialPacketBase {
#include <cmath>
#include <cstring>
//define the memory footprint for the region's members
constexpr int REGION_TILE_FOOTPRINT = sizeof(Region::type_t) * REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH;
constexpr int REGION_SOLID_FOOTPRINT = ceil(REGION_WIDTH * REGION_HEIGHT / 8.0);
constexpr int REGION_METADATA_FOOTPRINT = sizeof(int) * 3;
class RegionPacket : public SerialPacketBase {
public:
RegionPacket() {}
~RegionPacket() {}
//location
int SetRoomIndex(int i) { return roomIndex = i; }
int SetX(int i) { return x = i; }
int SetY(int i) { return y = i; }
int GetRoomIndex() { return roomIndex; }
int GetX() { return x; }
int GetY() { return y; }
//the region itself
Region* SetRegion(Region* r) { return region = r; }
Region* GetRegion() { return region; }
virtual void Serialize(void* buffer) override;
virtual void Deserialize(void* buffer) override;
private:
//location/identify the region
int roomIndex;
int x, y;
@@ -19,16 +19,6 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef SERVERPACKET_HPP_
#define SERVERPACKET_HPP_
#include "serial_packet_base.hpp"
struct ServerPacket : SerialPacketBase {
//identify the server
char name[PACKET_STRING_SIZE];
int playerCount;
int version;
};
#endif
//NOTE: This is a sanity check
@@ -22,25 +22,32 @@
#ifndef SERIALPACKETBASE_HPP_
#define SERIALPACKETBASE_HPP_
#ifndef SERIALPACKET_HPP_
#error Cannot include this file without 'serial_packet.hpp'
#endif
#include "serial_packet_type.hpp"
#include "SDL/SDL_net.h"
constexpr int NETWORK_VERSION = 20140701;
//The packets use a char array for string storage
constexpr int PACKET_STRING_SIZE = 100;
struct SerialPacketBase {
//members
class SerialPacketBase {
public:
SerialPacketType SetType(SerialPacketType t) { return type = t; }
SerialPacketType GetType() { return type; }
IPaddress GetAddress() { return srcAddress; }
IPaddress* GetAddressPtr() { return &srcAddress; }
SerialPacketBase() {};
virtual ~SerialPacketBase() {};
virtual void Serialize(void* buffer) = 0;
virtual void Deserialize(void* buffer) = 0;
protected:
friend class UDPNetworkUtility;
SerialPacketType type;
IPaddress srcAddress;
virtual ~SerialPacketBase() {};
};
typedef SerialPacketBase SerialPacket;
#endif
@@ -19,24 +19,24 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "serial.hpp"
#include "server_packet.hpp"
#include "serial_util.hpp"
#include "serial_utility.hpp"
void serializeServer(ServerPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
void ServerPacket::Serialize(void* buffer) {
serializeCopy(&buffer, &type, sizeof(SerialPacketType));
//identify the server
SERIALIZE(buffer, &packet->name, PACKET_STRING_SIZE);
SERIALIZE(buffer, &packet->playerCount, sizeof(int));
SERIALIZE(buffer, &packet->version, sizeof(int));
serializeCopy(&buffer, name, PACKET_STRING_SIZE);
serializeCopy(&buffer, &playerCount, sizeof(int));
serializeCopy(&buffer, &version, sizeof(int));
}
void deserializeServer(ServerPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
void ServerPacket::Deserialize(void* buffer) {
deserializeCopy(&buffer, &type, sizeof(SerialPacketType));
//identify the server
DESERIALIZE(buffer, &packet->name, PACKET_STRING_SIZE);
DESERIALIZE(buffer, &packet->playerCount, sizeof(int));
DESERIALIZE(buffer, &packet->version, sizeof(int));
deserializeCopy(&buffer, name, PACKET_STRING_SIZE);
deserializeCopy(&buffer, &playerCount, sizeof(int));
deserializeCopy(&buffer, &version, sizeof(int));
}
@@ -19,32 +19,35 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef CHARACTERPACKET_HPP_
#define CHARACTERPACKET_HPP_
#ifndef SERVERPACKET_HPP_
#define SERVERPACKET_HPP_
#include "serial_packet_base.hpp"
#include "vector2.hpp"
#include "statistics.hpp"
#include <cstring>
struct CharacterPacket : SerialPacketBase {
//identify the character
int characterIndex;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
class ServerPacket : public SerialPacketBase {
public:
ServerPacket() {}
~ServerPacket() {}
//the owner
int accountIndex;
const char* SetName(const char* s)
{ return strncpy(name, s, PACKET_STRING_SIZE); }
int SetPlayerCount(int i) { return playerCount = i; }
int SetVersion(int i) { return version = i; }
//location
int roomIndex;
Vector2 origin;
Vector2 motion;
const char* GetName() { return name; }
int GetPlayerCount() { return playerCount; }
int GetVersion() { return version; }
//gameplay
Statistics stats;
virtual void Serialize(void* buffer) override;
virtual void Deserialize(void* buffer) override;
//TODO: gameplay components: equipment, items, buffs, debuffs
private:
//identify the server
char name[PACKET_STRING_SIZE+1];
int playerCount;
int version;
};
#endif
-37
View File
@@ -1,37 +0,0 @@
#config
INCLUDES+=. ../packet ../../gameplay ../../map ../../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)/,libcommon.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
-182
View File
@@ -1,182 +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 "serial.hpp"
#include "serial_util.hpp"
//simple type functions
void serializeType(SerialPacketBase* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
}
void deserializeType(SerialPacketBase* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
}
//main switch functions
void serializePacket(SerialPacketBase* packet, void* buffer) {
switch(packet->type) {
//no extra data
case SerialPacketType::NONE:
case SerialPacketType::PING:
case SerialPacketType::PONG:
case SerialPacketType::BROADCAST_REQUEST:
//all rejections
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
case SerialPacketType::ENEMY_REJECTION:
case SerialPacketType::COMBAT_REJECTION:
serializeType(packet, buffer);
break;
//character info
case SerialPacketType::CHARACTER_NEW:
case SerialPacketType::CHARACTER_DELETE:
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
serializeCharacter(static_cast<CharacterPacket*>(packet), buffer);
break;
//client info
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
serializeClient(static_cast<ClientPacket*>(packet), buffer);
break;
//combat info
case SerialPacketType::COMBAT_NEW:
case SerialPacketType::COMBAT_DELETE:
case SerialPacketType::COMBAT_UPDATE:
case SerialPacketType::COMBAT_ENTER_REQUEST:
case SerialPacketType::COMBAT_ENTER_RESPONSE:
case SerialPacketType::COMBAT_EXIT_REQUEST:
case SerialPacketType::COMBAT_EXIT_RESPONSE:
serializeCombat(static_cast<CombatPacket*>(packet), buffer);
break;
//enemy info
case SerialPacketType::ENEMY_NEW:
case SerialPacketType::ENEMY_DELETE:
case SerialPacketType::ENEMY_UPDATE:
case SerialPacketType::ENEMY_STATS_REQUEST:
case SerialPacketType::ENEMY_STATS_RESPONSE:
serializeEnemy(static_cast<EnemyPacket*>(packet), buffer);
break;
//region info
case SerialPacketType::REGION_REQUEST:
serializeRegionFormat(static_cast<RegionPacket*>(packet), buffer);
break;
case SerialPacketType::REGION_CONTENT:
serializeRegionContent(static_cast<RegionPacket*>(packet), buffer);
break;
//server info
case SerialPacketType::BROADCAST_RESPONSE:
serializeServer(static_cast<ServerPacket*>(packet), buffer);
break;
}
}
void deserializePacket(SerialPacketBase* packet, void* buffer) {
//find the type, so that you can actually deserialize the packet!
deserializeType(packet, buffer);
switch(packet->type) {
//no extra data
case SerialPacketType::NONE:
case SerialPacketType::PING:
case SerialPacketType::PONG:
case SerialPacketType::BROADCAST_REQUEST:
//all rejections
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
case SerialPacketType::ENEMY_REJECTION:
case SerialPacketType::COMBAT_REJECTION:
//NOTHING
break;
//character info
case SerialPacketType::CHARACTER_NEW:
case SerialPacketType::CHARACTER_DELETE:
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
deserializeCharacter(static_cast<CharacterPacket*>(packet), buffer);
break;
//client info
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
deserializeClient(static_cast<ClientPacket*>(packet), buffer);
break;
//combat info
case SerialPacketType::COMBAT_NEW:
case SerialPacketType::COMBAT_DELETE:
case SerialPacketType::COMBAT_UPDATE:
case SerialPacketType::COMBAT_ENTER_REQUEST:
case SerialPacketType::COMBAT_ENTER_RESPONSE:
case SerialPacketType::COMBAT_EXIT_REQUEST:
case SerialPacketType::COMBAT_EXIT_RESPONSE:
serializeCombat(static_cast<CombatPacket*>(packet), buffer);
break;
//enemy info
case SerialPacketType::ENEMY_NEW:
case SerialPacketType::ENEMY_DELETE:
case SerialPacketType::ENEMY_UPDATE:
case SerialPacketType::ENEMY_STATS_REQUEST:
case SerialPacketType::ENEMY_STATS_RESPONSE:
serializeEnemy(static_cast<EnemyPacket*>(packet), buffer);
break;
//region info
case SerialPacketType::REGION_REQUEST:
deserializeRegionFormat(static_cast<RegionPacket*>(packet), buffer);
break;
case SerialPacketType::REGION_CONTENT:
deserializeRegionContent(static_cast<RegionPacket*>(packet), buffer);
break;
//server info
case SerialPacketType::BROADCAST_RESPONSE:
deserializeServer(static_cast<ServerPacket*>(packet), buffer);
break;
}
}
-67
View File
@@ -1,67 +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 SERIALIZE_HPP_
#define SERIALIZE_HPP_
#include "serial_packet.hpp"
#include "region.hpp"
#include "statistics.hpp"
//Primary interface functions
void serializePacket(SerialPacketBase*, void* dest);
void deserializePacket(SerialPacketBase*, void* src);
void serializeType(SerialPacketBase*, void*);
void deserializeType(SerialPacketBase*, void*);
//utility functions, exposed
void serializeCharacter(CharacterPacket*, void*);
void serializeClient(ClientPacket*, void*);
void serializeCombat(CombatPacket*, void*);
void serializeEnemy(EnemyPacket*, void*);
void serializeRegionFormat(RegionPacket*, void*);
void serializeRegionContent(RegionPacket*, void*);
void serializeServer(ServerPacket*, void*);
void serializeStatistics(Statistics*, void*);
void deserializeCharacter(CharacterPacket*, void*);
void deserializeClient(ClientPacket*, void*);
void deserializeCombat(CombatPacket*, void*);
void deserializeEnemy(EnemyPacket*, void*);
void deserializeRegionFormat(RegionPacket*, void*);
void deserializeRegionContent(RegionPacket*, void*);
void deserializeServer(ServerPacket*, void*);
void deserializeStatistics(Statistics*, void*);
/* DOCS: Keep PACKET_BUFFER_SIZE up to date
* DOCS: SerialPacketType::REGION_CONTENT is currently the largest type of packet, read more
* The metadata used are:
* SerialPacketType
* room index
* X & Y positon
* The rest is taken up by the Regions's content.
*/
constexpr int PACKET_BUFFER_SIZE = sizeof(SerialPacketType) + sizeof(int) * 3 + REGION_FOOTPRINT;
#endif
@@ -1,74 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeCharacter(CharacterPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the character
SERIALIZE(buffer, &packet->characterIndex, sizeof(int));
SERIALIZE(buffer, &packet->handle, PACKET_STRING_SIZE);
SERIALIZE(buffer, &packet->avatar, PACKET_STRING_SIZE);
//the owner
SERIALIZE(buffer, &packet->accountIndex, sizeof(int));
//location
SERIALIZE(buffer, &packet->roomIndex, sizeof(int));
SERIALIZE(buffer, &packet->origin.x, sizeof(double));
SERIALIZE(buffer, &packet->origin.y, sizeof(double));
SERIALIZE(buffer, &packet->motion.x, sizeof(double));
SERIALIZE(buffer, &packet->motion.y, sizeof(double));
//stats structure
serializeStatistics(&packet->stats, buffer);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Statistics);
//TODO: gameplay components: equipment, items, buffs, debuffs
}
void deserializeCharacter(CharacterPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the character
DESERIALIZE(buffer, &packet->characterIndex, sizeof(int));
DESERIALIZE(buffer, &packet->handle, PACKET_STRING_SIZE);
DESERIALIZE(buffer, &packet->avatar, PACKET_STRING_SIZE);
//the owner
DESERIALIZE(buffer, &packet->accountIndex, sizeof(int));
//location
DESERIALIZE(buffer, &packet->roomIndex, sizeof(int));
DESERIALIZE(buffer, &packet->origin.x, sizeof(double));
DESERIALIZE(buffer, &packet->origin.y, sizeof(double));
DESERIALIZE(buffer, &packet->motion.x, sizeof(double));
DESERIALIZE(buffer, &packet->motion.y, sizeof(double));
//stats structure
deserializeStatistics(&packet->stats, buffer);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Statistics);
//TODO: gameplay components: equipment, items, buffs, debuffs
}
-42
View File
@@ -1,42 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeClient(ClientPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
SERIALIZE(buffer, &packet->clientIndex, sizeof(int));
SERIALIZE(buffer, &packet->accountIndex, sizeof(int));
SERIALIZE(buffer, &packet->username, PACKET_STRING_SIZE);
// SERIALIZE(buffer, &packet->password, PACKET_STRING_SIZE);
}
void deserializeClient(ClientPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
DESERIALIZE(buffer, &packet->clientIndex, sizeof(int));
DESERIALIZE(buffer, &packet->accountIndex, sizeof(int));
DESERIALIZE(buffer, &packet->username, PACKET_STRING_SIZE);
// DESERIALIZE(buffer, &packet->password, PACKET_STRING_SIZE);
}
-64
View File
@@ -1,64 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeCombat(CombatPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the combat instance
SERIALIZE(buffer, &packet->combatIndex, sizeof(int));
SERIALIZE(buffer, &packet->difficulty, sizeof(int));
SERIALIZE(buffer, &packet->terrainType, sizeof(TerrainType));
//combatants
SERIALIZE(buffer, &packet->characterArray, sizeof(int) * COMBAT_MAX_CHARACTERS);
SERIALIZE(buffer, &packet->enemyArray, sizeof(int) * COMBAT_MAX_ENEMIES);
//location
SERIALIZE(buffer, &packet->mapIndex, sizeof(int));
SERIALIZE(buffer, &packet->origin.x, sizeof(double));
SERIALIZE(buffer, &packet->origin.y, sizeof(double));
//TODO: gameplay components: rewards
}
void deserializeCombat(CombatPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the combat instance
DESERIALIZE(buffer, &packet->combatIndex, sizeof(int));
DESERIALIZE(buffer, &packet->difficulty, sizeof(int));
DESERIALIZE(buffer, &packet->terrainType, sizeof(TerrainType));
//combatants
DESERIALIZE(buffer, &packet->characterArray, sizeof(int) * COMBAT_MAX_CHARACTERS);
DESERIALIZE(buffer, &packet->enemyArray, sizeof(int) * COMBAT_MAX_ENEMIES);
//location
DESERIALIZE(buffer, &packet->mapIndex, sizeof(int));
DESERIALIZE(buffer, &packet->origin.x, sizeof(double));
DESERIALIZE(buffer, &packet->origin.y, sizeof(double));
//TODO: gameplay components: rewards
}
-56
View File
@@ -1,56 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeEnemy(EnemyPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the enemy
SERIALIZE(buffer, &packet->enemyIndex, sizeof(int));
SERIALIZE(buffer, &packet->handle, PACKET_STRING_SIZE);
SERIALIZE(buffer, &packet->avatar, PACKET_STRING_SIZE);
//gameplay
//stats structure
serializeStatistics(&packet->stats, buffer);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Statistics);
//TODO: gameplay components: equipment, items, buffs, debuffs, rewards
}
void deserializeEnemy(EnemyPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//identify the enemy
DESERIALIZE(buffer, &packet->enemyIndex, sizeof(int));
DESERIALIZE(buffer, &packet->handle, PACKET_STRING_SIZE);
DESERIALIZE(buffer, &packet->avatar, PACKET_STRING_SIZE);
//stats structure
deserializeStatistics(&packet->stats, buffer);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Statistics);
//TODO: gameplay components: equipment, items, buffs, debuffs, rewards
}
-89
View File
@@ -1,89 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeRegionFormat(RegionPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//format
SERIALIZE(buffer, &packet->roomIndex, sizeof(int));
SERIALIZE(buffer, &packet->x, sizeof(int));
SERIALIZE(buffer, &packet->y, sizeof(int));
}
void serializeRegionContent(RegionPacket* packet, void* buffer) {
SERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//format
SERIALIZE(buffer, &packet->roomIndex, sizeof(int));
SERIALIZE(buffer, &packet->x, sizeof(int));
SERIALIZE(buffer, &packet->y, sizeof(int));
//tiles
for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < REGION_DEPTH; k++) {
*reinterpret_cast<Region::type_t*>(buffer) = packet->region->GetTile(i, j, k);
buffer = reinterpret_cast<char*>(buffer) + sizeof(Region::type_t);
}
}
}
//solids
SERIALIZE(buffer, packet->region->GetSolidBitset(), REGION_SOLID_FOOTPRINT);
}
void deserializeRegionFormat(RegionPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//format
DESERIALIZE(buffer, &packet->roomIndex, sizeof(int));
DESERIALIZE(buffer, &packet->x, sizeof(int));
DESERIALIZE(buffer, &packet->y, sizeof(int));
}
void deserializeRegionContent(RegionPacket* packet, void* buffer) {
DESERIALIZE(buffer, &packet->type, sizeof(SerialPacketType));
//format
DESERIALIZE(buffer, &packet->roomIndex, sizeof(int));
DESERIALIZE(buffer, &packet->x, sizeof(int));
DESERIALIZE(buffer, &packet->y, sizeof(int));
//an object to work on
packet->region = new Region(packet->x, packet->y);
//tiles
for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < REGION_DEPTH; k++) {
packet->region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
buffer = reinterpret_cast<char*>(buffer) + sizeof(Region::type_t);
}
}
}
//solids
DESERIALIZE(buffer, packet->region->GetSolidBitset(), REGION_SOLID_FOOTPRINT);
}
@@ -1,65 +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 "serial.hpp"
#include "serial_util.hpp"
void serializeStatistics(Statistics* stats, void* buffer) {
//integers
SERIALIZE(buffer, &stats->level, sizeof(int));
SERIALIZE(buffer, &stats->exp, sizeof(int));
SERIALIZE(buffer, &stats->maxHP, sizeof(int));
SERIALIZE(buffer, &stats->health, sizeof(int));
SERIALIZE(buffer, &stats->maxMP, sizeof(int));
SERIALIZE(buffer, &stats->mana, sizeof(int));
SERIALIZE(buffer, &stats->attack, sizeof(int));
SERIALIZE(buffer, &stats->defence, sizeof(int));
SERIALIZE(buffer, &stats->intelligence, sizeof(int));
SERIALIZE(buffer, &stats->resistance, sizeof(int));
SERIALIZE(buffer, &stats->speed, sizeof(int));
//floats
SERIALIZE(buffer, &stats->accuracy, sizeof(float));
SERIALIZE(buffer, &stats->evasion, sizeof(float));
SERIALIZE(buffer, &stats->luck, sizeof(float));
}
void deserializeStatistics(Statistics* stats, void* buffer) {
//integers
DESERIALIZE(buffer, &stats->level, sizeof(int));
DESERIALIZE(buffer, &stats->exp, sizeof(int));
DESERIALIZE(buffer, &stats->maxHP, sizeof(int));
DESERIALIZE(buffer, &stats->health, sizeof(int));
DESERIALIZE(buffer, &stats->maxMP, sizeof(int));
DESERIALIZE(buffer, &stats->mana, sizeof(int));
DESERIALIZE(buffer, &stats->attack, sizeof(int));
DESERIALIZE(buffer, &stats->defence, sizeof(int));
DESERIALIZE(buffer, &stats->intelligence, sizeof(int));
DESERIALIZE(buffer, &stats->resistance, sizeof(int));
DESERIALIZE(buffer, &stats->speed, sizeof(int));
//floats
DESERIALIZE(buffer, &stats->accuracy, sizeof(float));
DESERIALIZE(buffer, &stats->evasion, sizeof(float));
DESERIALIZE(buffer, &stats->luck, sizeof(float));
}
-31
View File
@@ -1,31 +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 SERIALIZEUTIL_HPP_
#define SERIALIZEUTIL_HPP_
#include <cstring>
//NOTE: The strange assignments here used in order to move the void* parameter
#define SERIALIZE(buffer, data, size) memcpy(buffer, data, size); buffer = reinterpret_cast<char*>(buffer) + size;
#define DESERIALIZE(buffer, data, size) memcpy(data, buffer, size); buffer = reinterpret_cast<char*>(buffer) + size;
#endif
@@ -22,23 +22,46 @@
#ifndef SERIALPACKET_HPP_
#define SERIALPACKET_HPP_
/* DOCS: serial_packet.hpp is used to define a number of required constants.
* These are used extensively by the server and client
*/
#include "serial_packet_base.hpp"
#include "character_packet.hpp"
#include "client_packet.hpp"
#include "combat_packet.hpp"
#include "enemy_packet.hpp"
#include "region_packet.hpp"
#include "server_packet.hpp"
//NOTE: SerialPacket is defined in serial_packet_base.hpp
//SerialPacketBase is defined in serial_packet_base.hpp
typedef SerialPacketBase SerialPacket;
union MaxPacket {
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20140831;
//_MaxPacket Should not be used
union _MaxPacket {
CharacterPacket a;
ClientPacket b;
CombatPacket c;
EnemyPacket d;
RegionPacket e;
ServerPacket f;
RegionPacket c;
ServerPacket d;
};
constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket);
constexpr int MAX_PACKET_SIZE = sizeof(_MaxPacket);
/* DOCS: PACKET_BUFFER_SIZE is the memory required to store serialized data
* DOCS: SerialPacketType::REGION_CONTENT is currently the largest packet type
* Serialized RegionPacket structure:
* SerialPacketType
* room index (int)
* X & Y position (int)
* tile data (3 layers)
* solid data (bitset)
*/
constexpr int PACKET_BUFFER_SIZE =
sizeof(SerialPacketType) +
REGION_METADATA_FOOTPRINT +
REGION_TILE_FOOTPRINT +
REGION_SOLID_FOOTPRINT;
#endif
+98
View File
@@ -0,0 +1,98 @@
/* Copyright: (c) Kayne Ruse 2013, 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 SERIALPACKETTYPE_HPP_
#define SERIALPACKETTYPE_HPP_
/* DOCS: The headers indicate what packet type is used for each message
* different messages under the same header will carry different amounts of
* valid data, but it will still be carried in that packet's format.
*/
enum class SerialPacketType {
//default: there is something wrong
NONE = 0,
//-------------------------
//ServerPacket
// name, player count, version
//-------------------------
//heartbeat
PING,
PONG,
//Used for finding available servers
BROADCAST_REQUEST,
BROADCAST_RESPONSE,
//-------------------------
//ClientPacket
// client index, account index, character index
//-------------------------
//Connecting to a server as a client
JOIN_REQUEST,
JOIN_RESPONSE,
JOIN_REJECTION,
//client requests all information from the server
SYNCHRONIZE,
//disconnect from the server
DISCONNECT,
//shut down the server
SHUTDOWN,
//-------------------------
//RegionPacket
// room index, x, y, raw data
//-------------------------
//map data
REGION_REQUEST,
REGION_CONTENT,
//-------------------------
//CharacterPacket
// handle, avatar, character index, account index,
// room index, origin, motion
// statistics
//-------------------------
//controlling characters
CHARACTER_NEW,
CHARACTER_DELETE,
CHARACTER_UPDATE,
//authentication, character index => character stats
CHARACTER_STATS_REQUEST,
CHARACTER_STATS_RESPONSE,
//reject a character request
CHARACTER_REJECTION,
//not used
LAST
};
#endif
+147
View File
@@ -0,0 +1,147 @@
/* 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 "serial_utility.hpp"
#include "serial_packet_type.hpp"
#include "server_packet.hpp"
#include "client_packet.hpp"
#include "region_packet.hpp"
#include "character_packet.hpp"
#include <cstring>
void serializePacket(SerialPacketBase* packet, void* data) {
switch(packet->GetType()) {
case SerialPacketType::PING:
case SerialPacketType::PONG:
case SerialPacketType::BROADCAST_REQUEST:
case SerialPacketType::BROADCAST_RESPONSE:
static_cast<ServerPacket*>(packet)->Serialize(data);
break;
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
static_cast<ClientPacket*>(packet)->Serialize(data);
break;
case SerialPacketType::REGION_REQUEST:
case SerialPacketType::REGION_CONTENT:
static_cast<RegionPacket*>(packet)->Serialize(data);
break;
case SerialPacketType::CHARACTER_NEW:
case SerialPacketType::CHARACTER_DELETE:
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
case SerialPacketType::CHARACTER_REJECTION:
static_cast<CharacterPacket*>(packet)->Serialize(data);
break;
}
}
void deserializePacket(SerialPacketBase* packet, void* data) {
//get the type
SerialPacketType type;
memcpy(&type, data, sizeof(SerialPacketType));
switch(type) {
case SerialPacketType::PING:
case SerialPacketType::PONG:
case SerialPacketType::BROADCAST_REQUEST:
case SerialPacketType::BROADCAST_RESPONSE:
static_cast<ServerPacket*>(packet)->Deserialize(data);
break;
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
static_cast<ClientPacket*>(packet)->Deserialize(data);
break;
case SerialPacketType::REGION_REQUEST:
case SerialPacketType::REGION_CONTENT:
static_cast<RegionPacket*>(packet)->Deserialize(data);
break;
case SerialPacketType::CHARACTER_NEW:
case SerialPacketType::CHARACTER_DELETE:
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
case SerialPacketType::CHARACTER_REJECTION:
static_cast<CharacterPacket*>(packet)->Deserialize(data);
break;
}
}
void serializeCopy(void** bufferHead, void* data, int size) {
memcpy(*bufferHead, data, size);
(*bufferHead) = static_cast<void*>(static_cast<char*>(*bufferHead) + size);
}
void deserializeCopy(void** bufferHead, void* data, int size) {
memcpy(data, *bufferHead, size);
(*bufferHead) = static_cast<void*>(static_cast<char*>(*bufferHead) + size);
}
void serializeCopyStatistics(void** bufferHead, Statistics* stats) {
//integers
serializeCopy(bufferHead, &stats->level, sizeof(int));
serializeCopy(bufferHead, &stats->exp, sizeof(int));
serializeCopy(bufferHead, &stats->maxHP, sizeof(int));
serializeCopy(bufferHead, &stats->health, sizeof(int));
serializeCopy(bufferHead, &stats->maxMP, sizeof(int));
serializeCopy(bufferHead, &stats->mana, sizeof(int));
serializeCopy(bufferHead, &stats->attack, sizeof(int));
serializeCopy(bufferHead, &stats->defence, sizeof(int));
serializeCopy(bufferHead, &stats->intelligence, sizeof(int));
serializeCopy(bufferHead, &stats->resistance, sizeof(int));
serializeCopy(bufferHead, &stats->speed, sizeof(int));
//floats
serializeCopy(bufferHead, &stats->accuracy, sizeof(float));
serializeCopy(bufferHead, &stats->evasion, sizeof(float));
serializeCopy(bufferHead, &stats->luck, sizeof(float));
}
void deserializeCopyStatistics(void** bufferHead, Statistics* stats) {
//integers
deserializeCopy(bufferHead, &stats->level, sizeof(int));
deserializeCopy(bufferHead, &stats->exp, sizeof(int));
deserializeCopy(bufferHead, &stats->maxHP, sizeof(int));
deserializeCopy(bufferHead, &stats->health, sizeof(int));
deserializeCopy(bufferHead, &stats->maxMP, sizeof(int));
deserializeCopy(bufferHead, &stats->mana, sizeof(int));
deserializeCopy(bufferHead, &stats->attack, sizeof(int));
deserializeCopy(bufferHead, &stats->defence, sizeof(int));
deserializeCopy(bufferHead, &stats->intelligence, sizeof(int));
deserializeCopy(bufferHead, &stats->resistance, sizeof(int));
deserializeCopy(bufferHead, &stats->speed, sizeof(int));
//floats
deserializeCopy(bufferHead, &stats->accuracy, sizeof(float));
deserializeCopy(bufferHead, &stats->evasion, sizeof(float));
deserializeCopy(bufferHead, &stats->luck, sizeof(float));
}
@@ -19,29 +19,24 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef ENEMYDATA_HPP_
#define ENEMYDATA_HPP_
#ifndef SERIALIZEUTILITY_HPP_
#define SERIALIZEUTILITY_HPP_
#include "serial_packet_base.hpp"
#include "vector2.hpp"
#include "statistics.hpp"
//std namespace
#include <string>
//NOTE: The naming conventions here are fucking terrible
struct EnemyData {
//metadata
std::string handle;
std::string avatar;
//BUGFIX: There's really no way to escape this :(
void serializePacket(SerialPacketBase* packet, void* data);
void deserializePacket(SerialPacketBase* packet, void* data);
//gameplay
Statistics stats;
//raw memcpy
void serializeCopy(void** bufferHead, void* data, int size);
void deserializeCopy(void** bufferHead, void* data, int size);
//TODO: gameplay components: equipment, items, buffs, debuffs, rewards
//active gameplay members
//NOTE: these are lost when unloaded
int tableIndex;
int atbGauge = 0;
};
void serializeCopyStatistics(void** bufferHead, Statistics* stats);
void deserializeCopyStatistics(void** bufferHead, Statistics* stats);
#endif
+6 -3
View File
@@ -21,7 +21,7 @@
*/
#include "udp_network_utility.hpp"
#include "serial.hpp"
#include "serial_utility.hpp"
#include <stdexcept>
@@ -213,8 +213,11 @@ int UDPNetworkUtility::SendToAllChannels(SerialPacket* serialPacket) {
int UDPNetworkUtility::Receive(SerialPacket* serialPacket) {
memset(packet->data, 0, packet->maxlen);
int ret = SDLNet_UDP_Recv(socket, packet);
deserializePacket(serialPacket, packet->data);
serialPacket->srcAddress = packet->address;
if (ret > 0) {
//BUG: This simply fails
deserializePacket(serialPacket, packet->data);
serialPacket->srcAddress = packet->address;
}
if (ret < 0) {
throw(std::runtime_error("Unknown network error occured"));
+11 -6
View File
@@ -22,15 +22,15 @@
#ifndef UDPNETWORKUTILITY_HPP_
#define UDPNETWORKUTILITY_HPP_
//common
#include "serial_packet.hpp"
#include "singleton.hpp"
//APIs
#include "SDL/SDL_net.h"
#include "serial_packet.hpp"
class UDPNetworkUtility {
class UDPNetworkUtility : public Singleton<UDPNetworkUtility> {
public:
UDPNetworkUtility() = default;
~UDPNetworkUtility() = default;
void Open(int port);
void Close();
@@ -65,6 +65,11 @@ public:
return socket;
}
private:
friend Singleton<UDPNetworkUtility>;
UDPNetworkUtility() = default;
~UDPNetworkUtility() = default;
UDPsocket socket = nullptr;
UDPpacket* packet = nullptr;
};
+2 -1
View File
@@ -32,6 +32,7 @@ public:
int w, h;
BoundingBox() = default;
BoundingBox(int i, int j): x(i), y(j), w(0), h(0) {};
BoundingBox(int i, int j, int k, int l): x(i), y(j), w(k), h(l) {};
~BoundingBox() = default;
BoundingBox& operator=(BoundingBox const&) = default;
@@ -62,7 +63,7 @@ public:
};
//This is explicitly a POD
static_assert(std::is_pod<Vector2>::value, "BoundingBox is not a POD");
static_assert(std::is_pod<BoundingBox>::value, "BoundingBox is not a POD");
#include "vector2.hpp"
-40
View File
@@ -1,40 +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 "check_bounds.hpp"
bool checkPoint(Vector2 const& origin, Vector2 const& bound, Vector2 const& point) {
return !(
point.x < origin.x ||
point.y < origin.y ||
point.x >= origin.x + bound.x ||
point.y >= origin.y + bound.y
);
}
bool checkOverlap(Vector2 const& originOne, Vector2 const& boundOne, Vector2 const& originTwo, Vector2 const& boundTwo) {
return !(
originOne.x >= originTwo.x + boundTwo.x ||
originOne.x + boundOne.x >= originTwo.x ||
originOne.y >= originTwo.y + boundTwo.y ||
originOne.y + boundOne.y >= originTwo.y
);
}
-30
View File
@@ -1,30 +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 CHECKBOUNDS_HPP_
#define CHECKBOUNDS_HPP_
#include "vector2.hpp"
bool checkPoint(Vector2 const& origin, Vector2 const& bound, Vector2 const& point);
bool checkOverlap(Vector2 const& originOne, Vector2 const& boundOne, Vector2 const& originTwo, Vector2 const& boundTwo);
#endif
-13
View File
@@ -23,19 +23,6 @@
#include <algorithm>
int snapToBase(int base, int x) {
//snap to a grid
if (x < 0) {
++x;
return x / base * base - base;
}
return x / base * base;
}
double snapToBase(double base, double x) {
return floor(x / base) * base;
}
std::string truncatePath(std::string pathname) {
return std::string(
std::find_if(
-3
View File
@@ -24,9 +24,6 @@
#include <string>
int snapToBase(int base, int x);
double snapToBase(double base, double x);
std::string truncatePath(std::string pathname);
//fixing known bugs in g++
+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 -6
View File
@@ -3,11 +3,6 @@
#MKDIR=mkdir
#RM=del /y
#CXXFLAGS+=-static-libgcc -static-libstdc++ -g -fno-inline-functions -Wall
#CXXFLAGS+=-static-libgcc -static-libstdc++
#export
OUTDIR=out
all: $(OUTDIR)
@@ -19,7 +14,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 $(OUTDIR)/*.exe $(OUTDIR)/*.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
-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}
};
+14 -3
View File
@@ -23,6 +23,7 @@
//singletons
#include "config_utility.hpp"
#include "udp_network_utility.hpp"
#include <stdexcept>
#include <iostream>
@@ -32,18 +33,28 @@ using namespace std;
int main(int argc, char** argv) {
try {
//create the singletons
AccountManager::Create();
CharacterManager::Create();
ConfigUtility::Create();
ServerApplication::Create();
RoomManager::Create();
UDPNetworkUtility::Create();
//call the server's routines
ServerApplication::Create();
ServerApplication& app = ServerApplication::GetSingleton();
app.Init(argc, argv);
app.Proc();
app.Quit();
//delete the singletons
ConfigUtility::Delete();
ServerApplication::Delete();
//delete the singletons
AccountManager::Delete();
CharacterManager::Delete();
ConfigUtility::Delete();
RoomManager::Delete();
UDPNetworkUtility::Delete();
}
catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl;
+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_types ../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
-495
View File
@@ -1,495 +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 "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
//-------------------------
void ServerApplication::HandleBroadcastRequest(SerialPacket* const argPacket) {
//send the server's data
ServerPacket newPacket;
newPacket.type = SerialPacketType::BROADCAST_RESPONSE;
strncpy(newPacket.name, config["server.name"].c_str(), PACKET_STRING_SIZE);
newPacket.playerCount = characterMgr.GetContainer()->size();
newPacket.version = NETWORK_VERSION;
network.SendTo(&argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
}
void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//create the new client
ClientData newClient;
newClient.address = argPacket->srcAddress;
//load the user account
//TODO: handle passwords
int accountIndex = accountMgr.LoadAccount(argPacket->username, clientUID);
if (accountIndex < 0) {
//TODO: send rejection packet
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
return;
}
//send the client their info
ClientPacket newPacket;
newPacket.type = SerialPacketType::JOIN_RESPONSE;
newPacket.clientIndex = clientUID;
newPacket.accountIndex = accountIndex;
network.SendTo(&newClient.address, static_cast<SerialPacket*>(&newPacket));
//finished this routine
clientMap[clientUID++] = newClient;
std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) {
//TODO: authenticate who is disconnecting/kicking
/*Pseudocode:
if sender's account index -> client index -> address == sender's address then
continue
end
if sender's account index -> admin == true OR sender's account index -> mod == true then
continue
end
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,
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) {
PumpCharacterUnload(it->first);
return true;
}
return false;
});
//erase the in-memory stuff
clientMap.erase(accountMgr.GetAccount(argPacket->accountIndex)->clientIndex);
accountMgr.UnloadAccount(argPacket->accountIndex);
//finished this routine
std::cout << "Disconnection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
void ServerApplication::HandleShutdown(SerialPacket* const argPacket) {
//TODO: authenticate who is shutting the server down
/*Pseudocode:
if sender's account -> admin is not true then
print a warning
return
end
*/
//end the server
running = false;
//disconnect all clients
SerialPacket newPacket;
newPacket.type = SerialPacketType::DISCONNECT;
PumpPacket(&newPacket);
//finished this routine
std::cout << "Shutdown signal accepted" << std::endl;
}
//-------------------------
//map management
//-------------------------
void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) {
RegionPacket newPacket;
newPacket.type = SerialPacketType::REGION_CONTENT;
newPacket.roomIndex = argPacket->roomIndex;
newPacket.x = argPacket->x;
newPacket.y = argPacket->y;
newPacket.region = roomMgr.GetRoom(argPacket->roomIndex)->pager.GetRegion(argPacket->x, argPacket->y);
//send the content
network.SendTo(&argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
}
//-------------------------
//Character Management
//-------------------------
void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) {
//BUG: #27 Characters can be created with an invalid account index
//NOTE: misnomer, try to load the character first
int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex == -1) {
//TODO: rejection packet
std::cerr << "Warning: Character already loaded" << std::endl;
return;
}
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character already exists" << std::endl;
return;
}
//send this new character to all clients
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_NEW;
CopyCharacterToPacket(&newPacket, characterIndex);
PumpPacket(&newPacket);
}
void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) {
//NOTE: Disconnecting only unloads a character, this explicitly deletes it
//Authenticate the owner is doing this
int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
//if this is not your character
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character cannot be deleted" << std::endl;
//unload an unneeded character
if (characterIndex != -1) {
characterMgr.UnloadCharacter(characterIndex);
}
return;
}
//delete it
characterMgr.DeleteCharacter(characterIndex);
//TODO: success packet
//Unload this character from all clients
PumpCharacterUnload(characterIndex);
}
void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) {
CharacterData* character = characterMgr.GetCharacter(argPacket->characterIndex);
//make a new character if this one doesn't exist
if (!character) {
//this isn't normal
std::cerr << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl;
HandleCharacterNew(argPacket);
return;
}
//accept client-side logic
character->roomIndex = argPacket->roomIndex;
character->origin = argPacket->origin;
character->motion = argPacket->motion;
character->stats = argPacket->stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
PumpPacket(argPacket);
}
//-------------------------
//mismanagement
//-------------------------
void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) {
//TODO: compensate for large distances
//NOTE: I quite dislike this function
//send all of the server's data to this client
ClientData& client = clientMap[argPacket->clientIndex];
//send all characters
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
for (auto& it : *characterMgr.GetContainer()) {
newPacket.characterIndex = it.first;
CopyCharacterToPacket(&newPacket, it.first);
network.SendTo(&client.address, static_cast<SerialPacket*>(&newPacket));
}
//TODO: more in HandleSynchronize()
}
//-------------------------
//utility methods
//-------------------------
//TODO: a function that only sends to characters in a certain proximity
void ServerApplication::PumpPacket(SerialPacket* const argPacket) {
for (auto& it : clientMap) {
network.SendTo(&it.second.address, argPacket);
}
}
void ServerApplication::PumpCharacterUnload(int uid) {
//delete the client-side character(s)
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_DELETE;
newPacket.characterIndex = uid;
PumpPacket(static_cast<SerialPacket*>(&newPacket));
}
void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
CharacterData* character = characterMgr.GetCharacter(characterIndex);
if (!character) {
throw(std::runtime_error("Failed to copy a character to a packet"));
}
//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;
}
+5 -5
View File
@@ -85,20 +85,20 @@ private:
//APIs and utilities
sqlite3* database = nullptr;
lua_State* luaState = nullptr;
UDPNetworkUtility network;
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
ConfigUtility& config = ConfigUtility::GetSingleton();
//simple tables
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
+232
View File
@@ -0,0 +1,232 @@
/* 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"
#include "serial_packet.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_TILE_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_SOLID_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->GetType()) {
//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->GetType()));
throw(std::runtime_error(msg));
}
break;
}
}
+281
View File
@@ -0,0 +1,281 @@
/* 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"
#include <iostream>
//-------------------------
//basic connections
//-------------------------
void ServerApplication::HandleBroadcastRequest(SerialPacket* const argPacket) {
//send the server's data
ServerPacket newPacket;
newPacket.SetType(SerialPacketType::BROADCAST_RESPONSE);
newPacket.SetName(config["server.name"].c_str());
newPacket.SetPlayerCount(characterMgr.GetContainer()->size());
newPacket.SetVersion(NETWORK_VERSION);
network.SendTo(argPacket->GetAddressPtr(), static_cast<SerialPacket*>(&newPacket));
}
void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//create the new client
ClientData newClient;
newClient.address = argPacket->GetAddress();
//load the user account
//TODO: handle passwords
int accountIndex = accountMgr.LoadAccount(argPacket->GetUsername(), clientIndex);
if (accountIndex < 0) {
//TODO: send rejection packet
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
return;
}
//send the client their info
ClientPacket newPacket;
newPacket.SetType(SerialPacketType::JOIN_RESPONSE);
newPacket.SetClientIndex(clientIndex);
newPacket.SetAccountIndex(accountIndex);
network.SendTo(&newClient.address, static_cast<SerialPacket*>(&newPacket));
//finished this routine
clientMap[clientIndex++] = newClient;
std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) {
//TODO: authenticate who is disconnecting/kicking
/*Pseudocode:
if sender's account index -> client index -> address == sender's address then
continue
end
if sender's account index -> admin == true OR sender's account index -> mod == true then
continue
end
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->GetAccountIndex())->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->GetAccountIndex() == it->second.GetOwner()) {
PumpCharacterUnload(it->first);
return true;
}
return false;
});
//erase the in-memory stuff
clientMap.erase(accountMgr.GetAccount(argPacket->GetAccountIndex())->GetClientIndex());
accountMgr.UnloadAccount(argPacket->GetAccountIndex());
//finished this routine
std::cout << "Disconnection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
void ServerApplication::HandleShutdown(SerialPacket* const argPacket) {
//TODO: authenticate who is shutting the server down
/*Pseudocode:
if sender's account -> admin is not true then
print a warning
return
end
*/
//end the server
running = false;
//disconnect all clients
ServerPacket newPacket;
newPacket.SetType(SerialPacketType::DISCONNECT);
PumpPacket(&newPacket);
//finished this routine
std::cout << "Shutdown signal accepted" << std::endl;
}
//-------------------------
//map management
//-------------------------
void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) {
RegionPacket newPacket;
newPacket.SetType(SerialPacketType::REGION_CONTENT);
newPacket.SetRoomIndex(argPacket->GetRoomIndex());
newPacket.SetX(argPacket->GetX());
newPacket.SetY(argPacket->GetY());
newPacket.SetRegion(roomMgr.GetRoom(argPacket->GetRoomIndex())->GetPager()->GetRegion(argPacket->GetX(), argPacket->GetY() ));
//send the content
network.SendTo(argPacket->GetAddressPtr(), static_cast<SerialPacket*>(&newPacket));
}
//-------------------------
//Character Management
//-------------------------
void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) {
//BUG: #27 Characters can be created with an invalid account index
//NOTE: misnomer, try to load the character first
int characterIndex = characterMgr.LoadCharacter(argPacket->GetAccountIndex(), argPacket->GetHandle(), argPacket->GetAvatar());
if (characterIndex == -1) {
//TODO: rejection packet
std::cerr << "Warning: Character already loaded" << std::endl;
return;
}
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character already exists" << std::endl;
return;
}
//send this new character to all clients
CharacterPacket newPacket;
newPacket.SetType(SerialPacketType::CHARACTER_NEW);
CopyCharacterToPacket(&newPacket, characterIndex);
PumpPacket(&newPacket);
}
void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) {
//NOTE: Disconnecting only unloads a character, this explicitly deletes it
//Authenticate the owner is doing this
int characterIndex = characterMgr.LoadCharacter(argPacket->GetAccountIndex(), argPacket->GetHandle(), argPacket->GetAvatar());
//if this is not your character
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character cannot be deleted" << std::endl;
//unload an unneeded character
if (characterIndex != -1) {
characterMgr.UnloadCharacter(characterIndex);
}
return;
}
//delete it
characterMgr.DeleteCharacter(characterIndex);
//TODO: success packet
//Unload this character from all clients
PumpCharacterUnload(characterIndex);
}
void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket) {
CharacterData* character = characterMgr.GetCharacter(argPacket->GetCharacterIndex());
//make a new character if this one doesn't exist
if (!character) {
//this isn't normal
std::cerr << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl;
HandleCharacterNew(argPacket);
return;
}
//accept client-side logic
character->SetRoomIndex(argPacket->GetRoomIndex());
character->SetOrigin(argPacket->GetOrigin());
character->SetMotion(argPacket->GetMotion());
*character->GetBaseStats() = *argPacket->GetStatistics();
//TODO: gameplay components: equipment, items, buffs, debuffs
PumpPacket(argPacket);
}
//-------------------------
//mismanagement
//-------------------------
void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) {
//TODO: compensate for large distances
//NOTE: I quite dislike this function
//send all of the server's data to this client
ClientData& client = clientMap[argPacket->GetClientIndex()];
//send all characters
CharacterPacket newPacket;
newPacket.SetType(SerialPacketType::CHARACTER_UPDATE);
for (auto& it : *characterMgr.GetContainer()) {
newPacket.SetCharacterIndex(it.first);
CopyCharacterToPacket(&newPacket, it.first);
network.SendTo(&client.address, static_cast<SerialPacket*>(&newPacket));
}
//TODO: more in HandleSynchronize()
}
//-------------------------
//utility methods
//-------------------------
//TODO: a function that only sends to characters in a certain proximity
void ServerApplication::PumpPacket(SerialPacket* const argPacket) {
for (auto& it : clientMap) {
network.SendTo(&it.second.address, argPacket);
}
}
void ServerApplication::PumpCharacterUnload(int uid) {
//delete the client-side character(s)
CharacterPacket newPacket;
newPacket.SetType(SerialPacketType::CHARACTER_DELETE);
newPacket.SetCharacterIndex(uid);
PumpPacket(static_cast<SerialPacket*>(&newPacket));
}
void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
CharacterData* character = characterMgr.GetCharacter(characterIndex);
if (!character) {
throw(std::runtime_error("Failed to copy a character to a packet"));
}
//TODO: keep this up to date when the character changes
packet->SetCharacterIndex(characterIndex);
packet->SetHandle(character->GetHandle().c_str());
packet->SetAvatar(character->GetAvatar().c_str());
packet->SetAccountIndex(character->GetOwner());
packet->SetRoomIndex(character->GetRoomIndex());
packet->SetOrigin(character->GetOrigin());
packet->SetMotion(character->GetMotion());
*packet->GetStatistics() = *character->GetBaseStats();
}
+9 -37
View File
@@ -1,45 +1,17 @@
TODO: Reduce the verbosity of the network packets
TODO: encapsulate the data structures
TODO: Get the rooms working
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: Move the map system into it's own namespace
TODO: The TileSheet class should implement the surface itself
TODO: Fix shoddy movement
TODO: make the whole thing more fault tolerant
TODO: Authentication
TODO: server is slaved to the client
TODO: I completely forgot about status ailments
TODO: Time delay for requesting region packets
TODO: command line parameters overriding config.cfg settings
--Battle System--
TODO
--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) --
TODO: A proper logging system