Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93c41bb19c | |||
| bf922ec598 | |||
| de902d2d3d | |||
| 7b3bf24e5d | |||
| de7da81102 | |||
| 6428b02d85 | |||
| 519b8a1e36 | |||
| 967f0653a1 | |||
| b86d393571 | |||
| 6b38501c27 | |||
| 5893342ad8 | |||
| ac4a264f12 | |||
| 43895a462a | |||
| 1bde0ed3f7 | |||
| d903c0df30 | |||
| 9620826d65 | |||
| 0a71f43ef3 | |||
| a47e76845f | |||
| c2eb08bd5e | |||
| 7b76e07231 | |||
| 1dd8042d3d | |||
| c575ee9ce1 | |||
| 1befc76b70 | |||
| 6a6e7f7125 | |||
| bb6e248583 | |||
| f7df4fba6c | |||
| e7403be508 | |||
| 873715b28c | |||
| b1d6e5a314 | |||
| f0453375c4 | |||
| e5a98efd7d | |||
| 14b330009b | |||
| 288b62d3f8 | |||
| c5e8f1b3af | |||
| 980717f9fd | |||
| 68475eee0f | |||
| eeb2400e79 | |||
| 01244005e9 | |||
| c5005b9b07 | |||
| 80a26341b1 | |||
| b7877962f1 | |||
| 688d064085 | |||
| 1c4d53e3ef | |||
| a53a134163 | |||
| 4d12788c53 | |||
| 1beb7cbd5d | |||
| 8358d72a98 | |||
| 4ebff4a25a | |||
| 0ff787abda | |||
| 9b5b48a8ab | |||
| 5dd0fb9e23 | |||
| 7c210e04a5 | |||
| 9236e02101 | |||
| 8f4ebf20da | |||
| 910e51f637 | |||
| 92fc9b4e25 | |||
| 2b8e7241c9 | |||
| 124cb3ad13 | |||
| 6d3400d948 | |||
| 5031352fe3 | |||
| 624369f147 | |||
| 9a7f7b8684 | |||
| fa9487c2f2 | |||
| 9ec1ddab99 | |||
| 6f1c2d0555 | |||
| 01b50d5590 | |||
| 9c673928e6 | |||
| d55dfb90e4 | |||
| 235a05d006 | |||
| dabb7b3b2e | |||
| e756289c2b | |||
| c534158c2e | |||
| b47191a0c1 | |||
| 6c6a025f2a | |||
| 60edc97ea5 | |||
| a5b209d9e0 | |||
| fd673a415f | |||
| 4270765146 | |||
| f56cb58dfb | |||
| f315f4bf35 | |||
| 69765de433 | |||
| 35d463d4ba | |||
| 894b46c5db | |||
| eb0b18af6f | |||
| fba183fa27 | |||
| c5a627004a | |||
| ac27fb0ca7 | |||
| be4a8311d5 | |||
| 6d32d44fa3 | |||
| 9bacfb1424 | |||
| c3464be589 | |||
| 7fe71c60d0 | |||
| 0c6537fb36 |
@@ -1,23 +1,25 @@
|
||||
The most recent stable windows build can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
||||
The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
||||
|
||||
Tortuga is an open source 2D multiplayer role playing game featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, competition, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
||||
Tortuga is a 2D multiplayer JRPG featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
||||
|
||||
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
|
||||
|
||||
## Documentation
|
||||
|
||||
Tortuga's full documentation can be found in a separate branch, see [Tortuga/docs](https://github.com/Ratstail91/Tortuga/tree/docs).
|
||||
For Tortuga's primary documentation, please read the [Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/Tortuga%20Game%20Design%20Document.docx?raw=true).
|
||||
|
||||
## External Dependencies
|
||||
|
||||
* [SDL 1.6](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||
* [SDL 1.2](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||
* [SDL_net 1.2](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
||||
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
||||
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
||||
|
||||
## Documentation
|
||||
|
||||
[Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/design%20doc.docx?raw=true)
|
||||
[Tortuga Technical Document](https://github.com/Ratstail91/Tortuga/blob/docs/technical%20doc.docx?raw=true)
|
||||
|
||||
## Copyright
|
||||
|
||||
(Future versions (to be determined) may be released under a modified version of the [Uplink Developer's License](http://www.introversion.co.uk/uplink/developer/license.html).)
|
||||
|
||||
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
||||
|
||||
Copyright (c) 2013, 2014 Kayne Ruse
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,3 +1,24 @@
|
||||
/* 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 CHANNELS_HPP_
|
||||
#define CHANNELS_HPP_
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -21,15 +21,11 @@
|
||||
*/
|
||||
#include "client_application.hpp"
|
||||
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
//-------------------------
|
||||
//Static declarations
|
||||
//-------------------------
|
||||
|
||||
ClientApplication ClientApplication::instance;
|
||||
|
||||
//-------------------------
|
||||
//Scene headers
|
||||
//-------------------------
|
||||
@@ -46,15 +42,7 @@ ClientApplication ClientApplication::instance;
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
ClientApplication::ClientApplication() {
|
||||
//
|
||||
}
|
||||
|
||||
ClientApplication::~ClientApplication() {
|
||||
//
|
||||
}
|
||||
|
||||
void ClientApplication::Init() {
|
||||
void ClientApplication::Init(int argc, char** argv) {
|
||||
//load the prerequisites
|
||||
config.Load("rsc\\config.cfg");
|
||||
|
||||
@@ -68,7 +56,7 @@ void ClientApplication::Init() {
|
||||
if (SDLNet_Init()) {
|
||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
network.Open(0, PACKET_BUFFER_SIZE);
|
||||
network.Open(0);
|
||||
}
|
||||
|
||||
void ClientApplication::Proc() {
|
||||
@@ -131,13 +119,13 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||
activeScene = new OptionsMenu(&config);
|
||||
break;
|
||||
case SceneList::LOBBYMENU:
|
||||
activeScene = new LobbyMenu(&config, &network, &clientIndex);
|
||||
activeScene = new LobbyMenu(&config, &network, &clientIndex, &accountIndex, &characterIndex);
|
||||
break;
|
||||
case SceneList::INWORLD:
|
||||
activeScene = new InWorld(&config, &network, &clientIndex);
|
||||
activeScene = new InWorld(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap);
|
||||
break;
|
||||
case SceneList::INCOMBAT:
|
||||
activeScene = new InCombat();
|
||||
activeScene = new InCombat(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap, &enemyMap);
|
||||
break;
|
||||
default:
|
||||
throw(std::logic_error("Failed to recognize the scene index"));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -26,19 +26,19 @@
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "network_packet.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
class ClientApplication {
|
||||
private:
|
||||
ClientApplication();
|
||||
~ClientApplication();
|
||||
static ClientApplication instance;
|
||||
|
||||
public:
|
||||
static ClientApplication* GetInstance() { return &instance; }
|
||||
ClientApplication() = default;
|
||||
~ClientApplication() = default;
|
||||
|
||||
void Init();
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
@@ -49,9 +49,16 @@ private:
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility config;
|
||||
UDPNetworkUtility network;
|
||||
int clientIndex = -1; //replace with a struct?
|
||||
int clientIndex = -1;
|
||||
int accountIndex = -1;
|
||||
int characterIndex = -1;
|
||||
|
||||
std::map<int, CombatData> combatMap;
|
||||
std::map<int, CharacterData> characterMap;
|
||||
std::map<int, EnemyData> enemyMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -25,7 +25,25 @@
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InCombat::InCombat() {
|
||||
InCombat::InCombat(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap,
|
||||
std::map<int, EnemyData>* argEnemyMap
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex),
|
||||
combatMap(*argCombatMap),
|
||||
characterMap(*argCharacterMap),
|
||||
enemyMap(*argEnemyMap)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@@ -49,6 +67,13 @@ 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) {
|
||||
//
|
||||
}
|
||||
@@ -57,6 +82,12 @@ void InCombat::Render(SDL_Surface* const screen) {
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InCombat::QuitEvent() {
|
||||
//exit the game AND the server
|
||||
// RequestDisconnect();
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InCombat::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
@@ -80,3 +111,15 @@ void InCombat::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
void InCombat::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
//TODO: network handlers
|
||||
|
||||
//-------------------------
|
||||
//Server control
|
||||
//-------------------------
|
||||
|
||||
//TODO: server control
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,62 +19,86 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef EDITORSCENE_HPP_
|
||||
#define EDITORSCENE_HPP_
|
||||
#ifndef INCOMBAT_HPP_
|
||||
#define INCOMBAT_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
//network
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
//graphics
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "menu_bar.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "region_pager.hpp"
|
||||
#include "map_generator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "tile_sheet.hpp"
|
||||
//common
|
||||
#include "config_utility.hpp"
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
class EditorScene : public BaseScene {
|
||||
#include "combat_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
class InCombat : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
EditorScene(ConfigUtility* const);
|
||||
~EditorScene();
|
||||
InCombat(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap,
|
||||
std::map<int, EnemyData>* argEnemyMap
|
||||
);
|
||||
~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&);
|
||||
|
||||
//members
|
||||
void HandleMenuOption(int entry, int drop);
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
//TODO: more
|
||||
|
||||
//globals
|
||||
//Server control
|
||||
void SendPlayerUpdate();
|
||||
void RequestDisconnect();
|
||||
void RequestShutdown();
|
||||
//TODO: more
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
std::map<int, CombatData>& combatMap;
|
||||
std::map<int, CharacterData>& characterMap;
|
||||
std::map<int, EnemyData>& enemyMap;
|
||||
|
||||
//debugging tools
|
||||
void DrawToDebugInfo(std::string, int line);
|
||||
Image debugInfo;
|
||||
bool debugOpen = true;
|
||||
//graphics
|
||||
//TODO: graphics
|
||||
|
||||
RasterFont font;
|
||||
Image buttonImage;
|
||||
MenuBar menuBar;
|
||||
|
||||
struct {
|
||||
int x = 0, y = 0;
|
||||
} camera;
|
||||
|
||||
RegionPager<BlankGenerator, DummyFormat> pager;
|
||||
TileSheet tsheet;
|
||||
//UI
|
||||
//TODO: UI
|
||||
FrameRate fps;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,452 @@
|
||||
/* 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_world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InWorld::InWorld(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex),
|
||||
combatMap(*argCombatMap),
|
||||
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
|
||||
disconnectButton.SetImage(&buttonImage);
|
||||
disconnectButton.SetFont(&font);
|
||||
shutDownButton.SetImage(&buttonImage);
|
||||
shutDownButton.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
disconnectButton.SetX(50);
|
||||
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||
shutDownButton.SetX(50);
|
||||
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
|
||||
|
||||
//set the button texts
|
||||
disconnectButton.SetText("Disconnect");
|
||||
shutDownButton.SetText("Shut Down");
|
||||
|
||||
//load the tilesheet
|
||||
//TODO: add the tilesheet to the map system?
|
||||
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||
|
||||
//request a sync
|
||||
RequestSynchronize();
|
||||
|
||||
//debug
|
||||
// RequestRegion(0, 0);
|
||||
}
|
||||
|
||||
InWorld::~InWorld() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InWorld::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::Update(double delta) {
|
||||
SerialPacket packet;
|
||||
|
||||
//suck in all waiting packets
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
|
||||
//update the characters
|
||||
for (auto& it : characterMap) {
|
||||
it.second.Update(delta);
|
||||
}
|
||||
|
||||
//update the camera
|
||||
if(localCharacter) {
|
||||
camera.x = localCharacter->position.x - camera.marginX;
|
||||
camera.y = localCharacter->position.y - camera.marginY;
|
||||
}
|
||||
|
||||
//check the map
|
||||
UpdateMap();
|
||||
}
|
||||
|
||||
void InWorld::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::RenderFrame() {
|
||||
// SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
void InWorld::Render(SDL_Surface* const screen) {
|
||||
//draw the map
|
||||
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw characters
|
||||
for (auto& it : characterMap) {
|
||||
//TODO: drawing order according to Y position
|
||||
it.second.DrawTo(screen, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw UI
|
||||
disconnectButton.DrawTo(screen);
|
||||
shutDownButton.DrawTo(screen);
|
||||
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::QuitEvent() {
|
||||
//exit the game AND the server
|
||||
RequestDisconnect();
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
disconnectButton.MouseMotion(motion);
|
||||
shutDownButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
disconnectButton.MouseButtonDown(button);
|
||||
shutDownButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestDisconnect();
|
||||
}
|
||||
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE: {
|
||||
QuitEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
HandleRegionContent(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
HandleCharacterUpdate(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
HandleCharacterNew(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
HandleCharacterDelete(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in InWorld: " + to_string_custom(int(packet.meta.type))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandleDisconnect(SerialPacket packet) {
|
||||
network.Unbind(Channels::SERVER);
|
||||
clientIndex = -1;
|
||||
accountIndex = -1;
|
||||
characterIndex = -1;
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InWorld::HandleRegionContent(SerialPacket packet) {
|
||||
//replace existing regions
|
||||
regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
regionPager.PushRegion(packet.regionInfo.region);
|
||||
packet.regionInfo.region = nullptr;
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterUpdate(SerialPacket packet) {
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) {
|
||||
HandleCharacterNew(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
//update only if the message didn't originate from here
|
||||
if (packet.characterInfo.clientIndex != clientIndex) {
|
||||
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
|
||||
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
|
||||
}
|
||||
characterMap[packet.characterInfo.characterIndex].CorrectSprite();
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterNew(SerialPacket packet) {
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) != characterMap.end()) {
|
||||
throw(std::runtime_error("Cannot create duplicate characters"));
|
||||
}
|
||||
|
||||
//create the character object
|
||||
CharacterData& character = characterMap[packet.characterInfo.characterIndex];
|
||||
|
||||
//set the members
|
||||
character.handle = packet.characterInfo.handle;
|
||||
character.avatar = packet.characterInfo.avatar;
|
||||
character.sprite.LoadSurface(config["dir.sprites"] + character.avatar, 4, 4);
|
||||
character.mapIndex = packet.characterInfo.mapIndex;
|
||||
character.position = packet.characterInfo.position;
|
||||
character.motion = packet.characterInfo.motion;
|
||||
character.stats = packet.characterInfo.stats;
|
||||
|
||||
character.CorrectSprite();
|
||||
|
||||
//catch this client's player object
|
||||
if (packet.characterInfo.characterIndex == characterIndex && !localCharacter) {
|
||||
localCharacter = &character;
|
||||
|
||||
//setup the camera
|
||||
//TODO: can't change the screen size?
|
||||
camera.width = GetScreen()->w;
|
||||
camera.height = GetScreen()->h;
|
||||
|
||||
//center on the player's character
|
||||
camera.marginX = (GetScreen()->w / 2 - localCharacter->sprite.GetImage()->GetClipW() / 2);
|
||||
camera.marginY = (GetScreen()->h / 2 - localCharacter->sprite.GetImage()->GetClipH() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterDelete(SerialPacket packet) {
|
||||
//TODO: authenticate when own character is being deleted (linked to a TODO in the server)
|
||||
//catch this client's player object
|
||||
if (packet.characterInfo.characterIndex == characterIndex) {
|
||||
characterIndex = -1;
|
||||
localCharacter = nullptr;
|
||||
}
|
||||
|
||||
characterMap.erase(packet.characterInfo.characterIndex);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Server control
|
||||
//-------------------------
|
||||
|
||||
void InWorld::RequestSynchronize() {
|
||||
SerialPacket packet;
|
||||
|
||||
//request a sync
|
||||
packet.meta.type = SerialPacket::Type::SYNCHRONIZE;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::SendPlayerUpdate() {
|
||||
SerialPacket packet;
|
||||
|
||||
//pack the packet
|
||||
packet.meta.type = SerialPacket::Type::CHARACTER_UPDATE;
|
||||
packet.characterInfo.clientIndex = clientIndex;
|
||||
packet.characterInfo.accountIndex = accountIndex;
|
||||
packet.characterInfo.characterIndex = characterIndex;
|
||||
packet.characterInfo.position = localCharacter->position;
|
||||
packet.characterInfo.motion = localCharacter->motion;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestDisconnect() {
|
||||
SerialPacket packet;
|
||||
|
||||
//send a disconnect request
|
||||
packet.meta.type = SerialPacket::Type::DISCONNECT;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestShutDown() {
|
||||
SerialPacket packet;
|
||||
|
||||
//send a shutdown request
|
||||
packet.meta.type = SerialPacket::Type::SHUTDOWN;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestRegion(int mapIndex, int x, int y) {
|
||||
SerialPacket packet;
|
||||
|
||||
//pack the region's data
|
||||
packet.meta.type = SerialPacket::Type::REGION_REQUEST;
|
||||
packet.regionInfo.mapIndex = mapIndex;
|
||||
packet.regionInfo.x = x;
|
||||
packet.regionInfo.y = y;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Utilities
|
||||
//-------------------------
|
||||
|
||||
//TODO: convert this into a more generic function?; using parameters for the bounds
|
||||
void InWorld::UpdateMap() {
|
||||
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
|
||||
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
|
||||
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
|
||||
|
||||
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
|
||||
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
|
||||
|
||||
//prune distant regions
|
||||
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) {
|
||||
//check if the region is outside off this area
|
||||
if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) {
|
||||
|
||||
//clunky, but the alternative was time consuming
|
||||
int tmpX = (*it)->GetX();
|
||||
int tmpY = (*it)->GetY();
|
||||
++it;
|
||||
|
||||
regionPager.UnloadRegion(tmpX, tmpY);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
//request empty regions within this zone
|
||||
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
||||
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
||||
if (!regionPager.FindRegion(i, j)) {
|
||||
RequestRegion(0, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -23,14 +23,12 @@
|
||||
#define INWORLD_HPP_
|
||||
|
||||
//maps
|
||||
#include "map_generator.hpp"
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//networking
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "network_packet.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
//graphics
|
||||
#include "image.hpp"
|
||||
@@ -42,9 +40,11 @@
|
||||
#include "config_utility.hpp"
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
#include "combat_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
#include "player_character.hpp"
|
||||
|
||||
//STL
|
||||
#include <map>
|
||||
@@ -52,7 +52,15 @@
|
||||
class InWorld : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const);
|
||||
InWorld(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap
|
||||
);
|
||||
~InWorld();
|
||||
|
||||
protected:
|
||||
@@ -72,28 +80,31 @@ protected:
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//Network handlers
|
||||
void HandlePacket(NetworkPacket);
|
||||
void HandleDisconnect(NetworkPacket);
|
||||
void HandlePlayerNew(NetworkPacket);
|
||||
void HandlePlayerDelete(NetworkPacket);
|
||||
void HandlePlayerUpdate(NetworkPacket);
|
||||
void HandleRegionContent(NetworkPacket);
|
||||
void HandlePacket(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
void HandleCharacterNew(SerialPacket);
|
||||
void HandleCharacterDelete(SerialPacket);
|
||||
void HandleCharacterUpdate(SerialPacket);
|
||||
void HandleRegionContent(SerialPacket);
|
||||
|
||||
//Server control
|
||||
void SendState();
|
||||
void RequestSynchronize();
|
||||
void SendPlayerUpdate();
|
||||
void RequestDisconnect();
|
||||
void RequestShutDown();
|
||||
void RequestRegion(int x, int y);
|
||||
void RequestRegion(int mapIndex, int x, int y);
|
||||
|
||||
//utilities
|
||||
int CheckBufferDistance(Region* const);
|
||||
void UpdateMap();
|
||||
|
||||
//globals
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
FrameRate fps;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
std::map<int, CombatData>& combatMap;
|
||||
std::map<int, CharacterData>& characterMap;
|
||||
|
||||
//graphics
|
||||
Image buttonImage;
|
||||
@@ -101,21 +112,21 @@ protected:
|
||||
TileSheet tileSheet;
|
||||
|
||||
//map
|
||||
RegionPager<BlankGenerator, DummyFormat> mapPager;
|
||||
RegionPager<BlankAllocator, DummyFormat> regionPager;
|
||||
|
||||
//UI
|
||||
Button disconnectButton;
|
||||
Button shutDownButton;
|
||||
//TODO: Review the camera
|
||||
struct {
|
||||
int x = 0, y = 0;
|
||||
int width = 0, height = 0;
|
||||
int marginX = 0, marginY = 0;
|
||||
} camera;
|
||||
FrameRate fps;
|
||||
|
||||
//game
|
||||
std::map<int, PlayerCharacter> playerCharacters;
|
||||
PlayerCharacter* localCharacter = nullptr;
|
||||
int playerIndex = -1;
|
||||
CharacterData* localCharacter = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "lobby_menu.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -29,10 +30,18 @@
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
LobbyMenu::LobbyMenu(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex):
|
||||
LobbyMenu::LobbyMenu(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex)
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex)
|
||||
{
|
||||
//setup the utility objects
|
||||
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
@@ -77,11 +86,9 @@ void LobbyMenu::FrameStart() {
|
||||
}
|
||||
|
||||
void LobbyMenu::Update(double delta) {
|
||||
//suck in all waiting packets
|
||||
NetworkPacket packet;
|
||||
while(network.Receive()) {
|
||||
deserialize(&packet, network.GetInData());
|
||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||
//suck in and process all waiting packets
|
||||
SerialPacket packet;
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
}
|
||||
@@ -91,9 +98,14 @@ void LobbyMenu::FrameEnd() {
|
||||
}
|
||||
|
||||
void LobbyMenu::Render(SDL_Surface* const screen) {
|
||||
//TODO: I need a proper UI system for the entire client and the editor
|
||||
|
||||
//UI
|
||||
search.DrawTo(screen);
|
||||
join.DrawTo(screen);
|
||||
back.DrawTo(screen);
|
||||
|
||||
//TODO: draw headers for the server list
|
||||
for (int i = 0; i < serverInfo.size(); i++) {
|
||||
//draw the selected server's highlight
|
||||
if (selection == &serverInfo[i]) {
|
||||
@@ -104,6 +116,16 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
|
||||
|
||||
//draw the server name
|
||||
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h);
|
||||
|
||||
//draw the player count
|
||||
font.DrawStringTo(to_string_custom(serverInfo[i].playerCount), screen, listBox.x + listBox.w, listBox.y + i*listBox.h);
|
||||
|
||||
//compatible?
|
||||
if (!serverInfo[i].compatible) {
|
||||
font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h);
|
||||
}
|
||||
|
||||
//TODO: ping/delay?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,29 +147,26 @@ void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
|
||||
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (search.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
//the vars
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//broadcast to the network, or a specific server
|
||||
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(config["server.host"].c_str(), config.Int("server.port"), buffer, PACKET_BUFFER_SIZE);
|
||||
SerialPacket packet;
|
||||
packet.meta.type = SerialPacket::Type::BROADCAST_REQUEST;
|
||||
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
|
||||
|
||||
//reset the server list
|
||||
serverInfo.clear();
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) {
|
||||
//the vars
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
|
||||
//pack the packet
|
||||
SerialPacket packet;
|
||||
packet.meta.type = SerialPacket::Type::JOIN_REQUEST;
|
||||
strncpy(packet.clientInfo.username, config["client.username"].c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.clientInfo.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.clientInfo.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
|
||||
|
||||
//join the selected server
|
||||
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE);
|
||||
network.SendTo(&selection->address, &packet);
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
@@ -181,24 +200,38 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::HandlePacket(NetworkPacket packet) {
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case NetworkPacket::Type::BROADCAST_RESPONSE: {
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE: {
|
||||
//extract the data
|
||||
ServerInformation server;
|
||||
server.name = packet.serverInfo.name;
|
||||
server.address = packet.meta.srcAddress;
|
||||
server.networkVersion = packet.serverInfo.networkVersion;
|
||||
server.name = packet.serverInfo.name;
|
||||
server.playerCount = packet.serverInfo.playerCount;
|
||||
|
||||
//NOTE: Check compatibility here
|
||||
server.compatible = server.networkVersion == NETWORK_VERSION;
|
||||
|
||||
//push
|
||||
serverInfo.push_back(server);
|
||||
}
|
||||
break;
|
||||
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||
clientIndex = packet.clientInfo.index;
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
clientIndex = packet.clientInfo.clientIndex;
|
||||
accountIndex = packet.clientInfo.accountIndex;
|
||||
characterIndex = packet.clientInfo.characterIndex;
|
||||
network.Bind(&packet.meta.srcAddress, Channels::SERVER);
|
||||
SetNextScene(SceneList::INWORLD);
|
||||
break;
|
||||
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in LobbyMenu: " + to_string_custom(int(packet.meta.type))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -22,23 +22,31 @@
|
||||
#ifndef LOBBYMENU_HPP_
|
||||
#define LOBBYMENU_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//graphics & utilities
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "network_packet.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
//network
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//STL
|
||||
#include <vector>
|
||||
|
||||
class LobbyMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const);
|
||||
LobbyMenu(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex
|
||||
);
|
||||
~LobbyMenu();
|
||||
|
||||
protected:
|
||||
@@ -55,12 +63,15 @@ protected:
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
void HandlePacket(NetworkPacket);
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket);
|
||||
|
||||
//global
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
@@ -71,8 +82,11 @@ protected:
|
||||
|
||||
//server list
|
||||
struct ServerInformation {
|
||||
std::string name;
|
||||
IPaddress address;
|
||||
int networkVersion;
|
||||
std::string name;
|
||||
int playerCount;
|
||||
bool compatible;
|
||||
};
|
||||
|
||||
std::vector<ServerInformation> serverInfo;
|
||||
+6
-5
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -26,12 +26,13 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char**) {
|
||||
int main(int argc, char** argv) {
|
||||
cout << "Beginning client" << endl;
|
||||
try {
|
||||
ClientApplication::GetInstance()->Init();
|
||||
ClientApplication::GetInstance()->Proc();
|
||||
ClientApplication::GetInstance()->Quit();
|
||||
ClientApplication app;
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//globals
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
+3
-10
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. scenes ../common ../common/graphics ../common/map ../common/network ../common/ui
|
||||
LIBS+=libclient.a ../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
INCLUDES+=. ../common/gameplay ../common/graphics ../common/map ../common/network ../common/ui ../common/utilities
|
||||
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
@@ -19,7 +16,6 @@ OUT=$(addprefix $(OUTDIR)/,client)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(MAKE) -C scenes
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
@@ -35,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//globals
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
@@ -1,117 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 "player_character.hpp"
|
||||
|
||||
#define WALKING_SPEED 140
|
||||
|
||||
void PlayerCharacter::Update(double delta) {
|
||||
if (diagonal) {
|
||||
constexpr double d = 1.0/sqrt(2);
|
||||
position += motion * delta * d;
|
||||
}
|
||||
else {
|
||||
position += motion * delta;
|
||||
}
|
||||
sprite.Update(delta);
|
||||
}
|
||||
|
||||
void PlayerCharacter::AdjustDirection(Direction direction) {
|
||||
//shift the movement in this direction
|
||||
switch(direction) {
|
||||
case Direction::NORTH:
|
||||
if (motion.y >= 0) {
|
||||
motion.y -= WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::SOUTH:
|
||||
if (motion.y <= 0) {
|
||||
motion.y += WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::WEST:
|
||||
if (motion.x >= 0) {
|
||||
motion.x -= WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::EAST:
|
||||
if (motion.x <= 0) {
|
||||
motion.x += WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//face the correct direction
|
||||
ResetDirection();
|
||||
}
|
||||
|
||||
void PlayerCharacter::FaceDirection(Direction direction) {
|
||||
//this function depends on the format of the sprite sheets
|
||||
switch(direction) {
|
||||
case Direction::NORTH:
|
||||
sprite.SetYIndex(1);
|
||||
break;
|
||||
case Direction::SOUTH:
|
||||
sprite.SetYIndex(0);
|
||||
break;
|
||||
case Direction::WEST:
|
||||
sprite.SetYIndex(2);
|
||||
break;
|
||||
case Direction::EAST:
|
||||
sprite.SetYIndex(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerCharacter::ResetDirection() {
|
||||
//base the direction on the character's movement
|
||||
if (motion.y > 0) {
|
||||
FaceDirection(Direction::SOUTH);
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
FaceDirection(Direction::NORTH);
|
||||
}
|
||||
else if (motion.x > 0) {
|
||||
FaceDirection(Direction::EAST);
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
FaceDirection(Direction::WEST);
|
||||
}
|
||||
ResetSpeed();
|
||||
}
|
||||
|
||||
void PlayerCharacter::ResetSpeed() {
|
||||
//diagonal
|
||||
if (motion.x != 0 && motion.y != 0) {
|
||||
sprite.SetDelay(0.1);
|
||||
diagonal = true;
|
||||
}
|
||||
//cardinal
|
||||
else if (motion != 0) {
|
||||
sprite.SetDelay(0.1);
|
||||
diagonal = false;
|
||||
}
|
||||
//not moving
|
||||
else {
|
||||
sprite.SetDelay(0);
|
||||
sprite.SetXIndex(0);
|
||||
diagonal = false;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 PLAYERCHARACTER_HPP_
|
||||
#define PLAYERCHARACTER_HPP_
|
||||
|
||||
#include "vector2.hpp"
|
||||
#include "sprite_sheet.hpp"
|
||||
|
||||
class PlayerCharacter {
|
||||
public:
|
||||
enum class Direction {
|
||||
NORTH, SOUTH, EAST, WEST
|
||||
};
|
||||
|
||||
PlayerCharacter() = default;
|
||||
~PlayerCharacter() = default;
|
||||
|
||||
void Update(double delta);
|
||||
|
||||
void DrawTo(SDL_Surface* const dest, int camX, int camY) { sprite.DrawTo(dest, position.x - camX, position.y - camY); }
|
||||
|
||||
//clunky code results in smooth movement and controls
|
||||
void AdjustDirection(Direction);
|
||||
void FaceDirection(Direction);
|
||||
void ResetDirection();
|
||||
void ResetSpeed();
|
||||
|
||||
//accessors and mutators
|
||||
Vector2 SetPosition(Vector2 v) { return position = v; }
|
||||
Vector2 ShiftPosition(Vector2 v) { return position += v; }
|
||||
Vector2 GetPosition() { return position; }
|
||||
|
||||
Vector2 SetMotion(Vector2 v) { return motion = v; }
|
||||
Vector2 ShiftMotion(Vector2 v) { return motion += v; }
|
||||
Vector2 GetMotion() { return motion; }
|
||||
|
||||
SpriteSheet* GetSprite() { return &sprite; }
|
||||
private:
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
SpriteSheet sprite;
|
||||
|
||||
//for moving diagonally
|
||||
bool diagonal = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 "base_scene.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Static declarations
|
||||
//-------------------------
|
||||
|
||||
SDL_Surface* BaseScene::screen = nullptr;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
BaseScene::BaseScene() {
|
||||
//
|
||||
}
|
||||
|
||||
BaseScene::~BaseScene() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Program control
|
||||
//-------------------------
|
||||
|
||||
SDL_Surface* BaseScene::SetScreen(int w, int h, int bpp, Uint32 flags) {
|
||||
if (!bpp) {
|
||||
bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
|
||||
}
|
||||
|
||||
screen = SDL_SetVideoMode(w, h, bpp, flags);
|
||||
|
||||
if (!screen) {
|
||||
throw(std::runtime_error("Failed to create the screen surface"));
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
SDL_Surface* BaseScene::GetScreen() {
|
||||
return screen;
|
||||
}
|
||||
|
||||
SceneList BaseScene::SetNextScene(SceneList sceneIndex) {
|
||||
return nextScene = sceneIndex;
|
||||
}
|
||||
|
||||
SceneList BaseScene::GetNextScene() const {
|
||||
return nextScene;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void BaseScene::RunFrame(double delta) {
|
||||
FrameStart();
|
||||
HandleEvents();
|
||||
Update(delta);
|
||||
FrameEnd();
|
||||
}
|
||||
|
||||
void BaseScene::RenderFrame() {
|
||||
SDL_FillRect(screen, 0, 0);
|
||||
Render(screen);
|
||||
SDL_Flip(screen);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void BaseScene::HandleEvents() {
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_QUIT:
|
||||
QuitEvent();
|
||||
break;
|
||||
|
||||
case SDL_VIDEORESIZE:
|
||||
SetScreen(event.resize.w, event.resize.h, 0, screen->flags);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
MouseMotion(event.motion);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
MouseButtonDown(event.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
MouseButtonUp(event.button);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
KeyDown(event.key);
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
KeyUp(event.key);
|
||||
break;
|
||||
|
||||
#ifdef USE_EVENT_JOYSTICK
|
||||
//TODO: joystick/gamepad support
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT_UNKNOWN
|
||||
default:
|
||||
UnknownEvent(event);
|
||||
break;
|
||||
#endif
|
||||
}//switch
|
||||
}//while
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 BASESCENE_HPP_
|
||||
#define BASESCENE_HPP_
|
||||
|
||||
#include "scene_list.hpp"
|
||||
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
class BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
BaseScene();
|
||||
virtual ~BaseScene();
|
||||
|
||||
//Program control
|
||||
static SDL_Surface* SetScreen(int w, int h, int bpp = 0, Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||
static SDL_Surface* GetScreen();
|
||||
|
||||
SceneList SetNextScene(SceneList sceneIndex);
|
||||
SceneList GetNextScene() const;
|
||||
|
||||
//Frame loop
|
||||
virtual void RunFrame(double delta);
|
||||
virtual void RenderFrame();
|
||||
|
||||
protected:
|
||||
virtual void FrameStart() {}
|
||||
virtual void HandleEvents();
|
||||
virtual void Update(double delta) {}
|
||||
virtual void FrameEnd() {}
|
||||
virtual void Render(SDL_Surface* const screen) {}
|
||||
|
||||
//Event handlers
|
||||
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
|
||||
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
|
||||
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
|
||||
virtual void MouseButtonUp(SDL_MouseButtonEvent const&) {}
|
||||
virtual void KeyDown(SDL_KeyboardEvent const&) {}
|
||||
virtual void KeyUp(SDL_KeyboardEvent const&) {}
|
||||
|
||||
#ifdef USE_EVENT_JOYSTICK
|
||||
//TODO: joystick/gamepad support
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT_UNKNOWN
|
||||
virtual void UnknownEvent(SDL_Event const&) {}
|
||||
#endif
|
||||
|
||||
private:
|
||||
static SDL_Surface* screen;
|
||||
SceneList nextScene = SceneList::CONTINUE;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,499 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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_world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
//debugging
|
||||
#include <iostream>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex)
|
||||
{
|
||||
//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
|
||||
disconnectButton.SetImage(&buttonImage);
|
||||
disconnectButton.SetFont(&font);
|
||||
shutDownButton.SetImage(&buttonImage);
|
||||
shutDownButton.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
disconnectButton.SetX(50);
|
||||
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||
shutDownButton.SetX(50);
|
||||
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
|
||||
|
||||
//set the button texts
|
||||
disconnectButton.SetText("Disconnect");
|
||||
shutDownButton.SetText("Shut Down");
|
||||
|
||||
//load the tilesheet
|
||||
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||
|
||||
//setup the map object
|
||||
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||
|
||||
//create the server-side player object
|
||||
NetworkPacket packet;
|
||||
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
||||
packet.playerInfo.clientIndex = clientIndex;
|
||||
snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str());
|
||||
snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str());
|
||||
packet.playerInfo.position = {0,0};
|
||||
packet.playerInfo.motion = {0,0};
|
||||
|
||||
//send it
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
|
||||
//request a sync
|
||||
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
|
||||
//debug
|
||||
// RequestRegion(0, 0);
|
||||
}
|
||||
|
||||
InWorld::~InWorld() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InWorld::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::Update(double delta) {
|
||||
NetworkPacket packet;
|
||||
|
||||
//suck in all waiting packets
|
||||
while(network.Receive()) {
|
||||
deserialize(&packet, network.GetInData());
|
||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||
HandlePacket(packet);
|
||||
}
|
||||
|
||||
//update the characters
|
||||
for (auto& it : playerCharacters) {
|
||||
it.second.Update(delta);
|
||||
}
|
||||
//TODO: sort the players and entities by Y position
|
||||
|
||||
//update the camera
|
||||
if(localCharacter) {
|
||||
camera.x = localCharacter->GetPosition().x - camera.marginX;
|
||||
camera.y = localCharacter->GetPosition().y - camera.marginY;
|
||||
}
|
||||
|
||||
//check the map
|
||||
UpdateMap();
|
||||
}
|
||||
|
||||
void InWorld::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::RenderFrame() {
|
||||
// SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
}
|
||||
|
||||
void InWorld::Render(SDL_Surface* const screen) {
|
||||
//draw the map
|
||||
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw characters
|
||||
for (auto& it : playerCharacters) {
|
||||
it.second.DrawTo(screen, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw UI
|
||||
disconnectButton.DrawTo(screen);
|
||||
shutDownButton.DrawTo(screen);
|
||||
|
||||
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::QuitEvent() {
|
||||
//exit the game AND the server
|
||||
RequestDisconnect();
|
||||
}
|
||||
|
||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
disconnectButton.MouseMotion(motion);
|
||||
shutDownButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
disconnectButton.MouseButtonDown(button);
|
||||
shutDownButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestDisconnect();
|
||||
}
|
||||
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE: {
|
||||
QuitEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH);
|
||||
SendState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::HandlePacket(NetworkPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case NetworkPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_NEW:
|
||||
HandlePlayerNew(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_DELETE:
|
||||
HandlePlayerDelete(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||
HandlePlayerUpdate(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::REGION_CONTENT:
|
||||
HandleRegionContent(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandleDisconnect(NetworkPacket packet) {
|
||||
network.Unbind(Channels::SERVER);
|
||||
clientIndex = -1;
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InWorld::HandlePlayerNew(NetworkPacket packet) {
|
||||
if (playerCharacters.find(packet.playerInfo.playerIndex) != playerCharacters.end()) {
|
||||
throw(std::runtime_error("Cannot create duplicate players"));
|
||||
}
|
||||
|
||||
playerCharacters[packet.playerInfo.playerIndex].GetSprite()->LoadSurface(config["dir.sprites"] + packet.playerInfo.avatar, 4, 4);
|
||||
playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position);
|
||||
playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion);
|
||||
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
||||
|
||||
//catch this client's player object
|
||||
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
||||
playerIndex = packet.playerInfo.playerIndex;
|
||||
localCharacter = &playerCharacters[playerIndex];
|
||||
//setup the camera
|
||||
camera.width = GetScreen()->w;
|
||||
camera.height = GetScreen()->h;
|
||||
//center on the player's character
|
||||
camera.marginX = (GetScreen()->w / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
||||
camera.marginY = (GetScreen()->h / 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandlePlayerDelete(NetworkPacket packet) {
|
||||
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
|
||||
throw(std::runtime_error("Cannot delete non-existant players"));
|
||||
}
|
||||
|
||||
playerCharacters.erase(packet.playerInfo.playerIndex);
|
||||
|
||||
//catch this client's player object
|
||||
if (packet.playerInfo.clientIndex == clientIndex) {
|
||||
playerIndex = -1;
|
||||
localCharacter = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandlePlayerUpdate(NetworkPacket packet) {
|
||||
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
|
||||
HandlePlayerNew(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
//update only if the message didn't originate from here
|
||||
if (packet.playerInfo.clientIndex != clientIndex) {
|
||||
playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position);
|
||||
playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion);
|
||||
}
|
||||
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
||||
}
|
||||
|
||||
void InWorld::HandleRegionContent(NetworkPacket packet) {
|
||||
//replace existing regions
|
||||
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||
mapPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
}
|
||||
mapPager.PushRegion(packet.regionInfo.region);
|
||||
packet.regionInfo.region = nullptr;
|
||||
|
||||
//debugging
|
||||
cout << "Received region: " << packet.regionInfo.x << ", " << packet.regionInfo.y << endl;
|
||||
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||
cout << "Success" << endl;
|
||||
}
|
||||
else {
|
||||
cout << "Failure" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Server control
|
||||
//-------------------------
|
||||
|
||||
void InWorld::SendState() {
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//pack the packet
|
||||
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||
packet.playerInfo.clientIndex = clientIndex;
|
||||
packet.playerInfo.playerIndex = playerIndex;
|
||||
packet.playerInfo.position = localCharacter->GetPosition();
|
||||
packet.playerInfo.motion = localCharacter->GetMotion();
|
||||
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void InWorld::RequestDisconnect() {
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//send a disconnect request
|
||||
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||
packet.clientInfo.index = clientIndex;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void InWorld::RequestShutDown() {
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//send a shutdown request
|
||||
packet.meta.type = NetworkPacket::Type::SHUTDOWN;
|
||||
packet.clientInfo.index = clientIndex;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void InWorld::RequestRegion(int x, int y) {
|
||||
NetworkPacket packet;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//pack the region's data
|
||||
packet.meta.type = NetworkPacket::Type::REGION_REQUEST;
|
||||
packet.regionInfo.x = x;
|
||||
packet.regionInfo.y = y;
|
||||
serialize(&packet, buffer);
|
||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Utilities
|
||||
//-------------------------
|
||||
|
||||
int InWorld::CheckBufferDistance(Region* const region) {
|
||||
/* DOCUMENTATION
|
||||
* This algorithm is extremely complex and involed, but initial tests show
|
||||
* that it gives the right answers. The purpose is to determine how far off screen
|
||||
* a certain region is, so that it can be unloaded when necessary.
|
||||
*
|
||||
* If the region is actually onscreen, then there's no reason to run the rest, so
|
||||
* the algorithm corrects for the camera's location, before checking the bounds of
|
||||
* the screen.
|
||||
*
|
||||
* The next part is tricky. If X or Y is negative, then it is divided by the
|
||||
* graphical size of the regions, resulting in a usable integer, representing how
|
||||
* far from the screen it is in "region units". If, however, X or Y is larger than
|
||||
* 0, than first, the size of the screen is subtracted from that variable, before
|
||||
* it is then divided by the graphical size of a region. Finally, to compensate for
|
||||
* the off by one error, 1 is added at the end.
|
||||
*
|
||||
* Since only the magnitude of the distance in either direction is needed, this
|
||||
* method returns the largest absolute value of X or Y.
|
||||
*
|
||||
* The final result of this algorithm is an integer representing how far, rounded
|
||||
* up, a certain region is from the screen's edges in any direction, measured in
|
||||
* "region units". This algorithm may be flawed, in which case, I recommend simply
|
||||
* replacing it with a boolean check, to see if the region's distance from the player
|
||||
* is larger than a certain value. This algorithm lacks the advantages I initially
|
||||
* expected, so that may be beneficial at some point.
|
||||
*/
|
||||
|
||||
//locations relative to the camera
|
||||
int x = region->GetX() - camera.x;
|
||||
int y = region->GetY() - camera.y;
|
||||
|
||||
//if the region is visible, return -1
|
||||
if (x >= -mapPager.GetRegionWidth() * tileSheet.GetTileW() && x < camera.width &&
|
||||
y >= -mapPager.GetRegionHeight() * tileSheet.GetTileH() && y < camera.height) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//prune the screen's area from the algorithm; get the pseudo-indexes
|
||||
if (x < 0) x /= (mapPager.GetRegionWidth() * tileSheet.GetTileW());
|
||||
if (y < 0) y /= (mapPager.GetRegionHeight() * tileSheet.GetTileH());
|
||||
if (x > 0) x = (x - camera.width) / (mapPager.GetRegionWidth() * tileSheet.GetTileW()) + 1;
|
||||
if (y > 0) y = (y - camera.height) / (mapPager.GetRegionHeight() * tileSheet.GetTileH()) + 1;
|
||||
|
||||
//return the pseudo-index with the greatest magnitude
|
||||
return std::max(abs(x), abs(y));
|
||||
}
|
||||
|
||||
void InWorld::UpdateMap() {
|
||||
//prune distant regions
|
||||
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); /* EMPTY */) {
|
||||
if (CheckBufferDistance(*it) > 2) {
|
||||
//debugging
|
||||
cout << "unloading: " << (*it)->GetX() << ", " << (*it)->GetY() << endl;
|
||||
|
||||
mapPager.UnloadRegion((*it)->GetX(), (*it)->GetY());
|
||||
|
||||
//reset
|
||||
it = mapPager.GetContainer()->begin();
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
//TODO: make the region units official
|
||||
int regionUnitX = mapPager.GetRegionWidth() * tileSheet.GetTileW();
|
||||
int regionUnitY = mapPager.GetRegionHeight() * tileSheet.GetTileH();
|
||||
|
||||
//request empty regions, including buffers (-1 & +1 region unit)
|
||||
for (int i = snapToBase(regionUnitX, camera.x - regionUnitX); i <= snapToBase(regionUnitX, camera.x + camera.width + regionUnitX); i += regionUnitX) {
|
||||
for (int j = snapToBase(regionUnitY, camera.y - regionUnitY); j <= snapToBase(regionUnitY, camera.y + camera.height + regionUnitY); j += regionUnitY) {
|
||||
if (!mapPager.FindRegion(i, j)) {
|
||||
RequestRegion(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -40,7 +40,7 @@ protected:
|
||||
void Update(double delta);
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//globals
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,30 +19,18 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef INCOMBAT_HPP_
|
||||
#define INCOMBAT_HPP_
|
||||
#ifndef ACCOUNTDATA_HPP_
|
||||
#define ACCOUNTDATA_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
#include <string>
|
||||
|
||||
class InCombat : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InCombat();
|
||||
~InCombat();
|
||||
struct AccountData {
|
||||
std::string username;
|
||||
//TODO: password
|
||||
bool blackListed = false;
|
||||
bool whiteListed = true;
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
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&);
|
||||
int clientIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/* 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_data.hpp"
|
||||
|
||||
void CharacterData::Update(double delta) {
|
||||
if (motion.x && motion.y) {
|
||||
position += motion * delta * CHARACTER_WALKING_MOD;
|
||||
}
|
||||
else if (motion != 0) {
|
||||
position += motion * delta;
|
||||
}
|
||||
#ifdef GRAPHICS
|
||||
sprite.Update(delta);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GRAPHICS
|
||||
|
||||
void CharacterData::DrawTo(SDL_Surface* const dest, int camX, int camY) {
|
||||
sprite.DrawTo(dest, position.x - camX, position.y - camY);
|
||||
}
|
||||
|
||||
void CharacterData::CorrectSprite() {
|
||||
//NOTE: These must correspond to the sprite sheet in use
|
||||
if (motion.y > 0) {
|
||||
sprite.SetYIndex(0);
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
sprite.SetYIndex(1);
|
||||
}
|
||||
else if (motion.x > 0) {
|
||||
sprite.SetYIndex(3);
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
sprite.SetYIndex(2);
|
||||
}
|
||||
|
||||
//animation
|
||||
if (motion != 0) {
|
||||
sprite.SetDelay(0.1);
|
||||
}
|
||||
else {
|
||||
sprite.SetDelay(0);
|
||||
sprite.SetXIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/* 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 CHARACTERDATA_HPP_
|
||||
#define CHARACTERDATA_HPP_
|
||||
|
||||
//POD members
|
||||
#include "bbox.hpp"
|
||||
#include "vector2.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
//the speeds that the characters move
|
||||
constexpr double CHARACTER_WALKING_SPEED = 140.0;
|
||||
constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0);
|
||||
|
||||
struct CharacterData {
|
||||
//metadata
|
||||
int owner;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
|
||||
//world position
|
||||
int mapIndex = 0;
|
||||
Vector2 position = {0.0,0.0};
|
||||
Vector2 motion = {0.0,0.0};
|
||||
|
||||
//base statistics
|
||||
Statistics stats;
|
||||
|
||||
//TODO: equipment
|
||||
//TODO: items
|
||||
//TODO: buffs
|
||||
//TODO: debuffs
|
||||
|
||||
//methods
|
||||
void Update(double delta);
|
||||
#ifdef GRAPHICS
|
||||
void DrawTo(SDL_Surface* const, int camX, int camY);
|
||||
void CorrectSprite();
|
||||
#endif
|
||||
|
||||
//active gameplay members
|
||||
//NOTE: these are lost when unloaded
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
#endif
|
||||
BBox bbox = {0,0,0,0};
|
||||
bool inCombat = false;
|
||||
int atbGauge = 0;
|
||||
//TODO: stored command
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,18 +19,13 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SCENELIST_HPP_
|
||||
#define SCENELIST_HPP_
|
||||
#ifndef CLIENTDATA_HPP_
|
||||
#define CLIENTDATA_HPP_
|
||||
|
||||
enum class SceneList {
|
||||
//these are reserved
|
||||
QUIT,
|
||||
CONTINUE,
|
||||
FIRST,
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
//custom indexes
|
||||
TESTIFICATESCENE,
|
||||
EDITORSCENE,
|
||||
struct ClientData {
|
||||
IPaddress address = {0,0};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/* 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_
|
||||
|
||||
//POD members
|
||||
#include "vector2.hpp"
|
||||
#include "bbox.hpp"
|
||||
|
||||
//gameplay members
|
||||
#include "character_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
struct CombatData {
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
|
||||
//combatants, point to the std::map's internal pairs
|
||||
std::list<std::pair<const int, CharacterData>*> characterList;
|
||||
std::list<std::pair<const int, EnemyData>*> enemyList;
|
||||
|
||||
//world interaction
|
||||
int mapIndex = 0;
|
||||
Vector2 position = {0.0,0.0};
|
||||
BBox bbox = {0,0,0,0};
|
||||
|
||||
//time interval
|
||||
Clock::time_point lastTick = Clock::now();
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef ENEMYDATA_HPP_
|
||||
#define ENEMYDATA_HPP_
|
||||
|
||||
//gameplay
|
||||
#include "statistics.hpp"
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <string>
|
||||
|
||||
struct EnemyData {
|
||||
//metadata
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
|
||||
//gameplay
|
||||
Statistics stats;
|
||||
|
||||
//TODO: equipment
|
||||
//TODO: items
|
||||
//TODO: buffs
|
||||
//TODO: debuffs
|
||||
|
||||
//active gameplay members
|
||||
//NOTE: these are lost when unloaded
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
#endif
|
||||
int tableIndex;
|
||||
int atbGauge = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,21 +1,18 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../../common ../../common/graphics ../../common/map ../../common/network ../../common/ui
|
||||
INCLUDES+=. ../utilities ../graphics
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libclient.a)
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* 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 "account_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "client_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
#include "statistics.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.
|
||||
*
|
||||
* Oddly enough, I'm pretty sure this is the first directory compiled in a
|
||||
* clean build.
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/* 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 STATISTICS_HPP_
|
||||
#define STATISTICS_HPP_
|
||||
|
||||
struct Statistics {
|
||||
int level = 0;
|
||||
int exp = 0;
|
||||
int maxHP = 0;
|
||||
int health = 0;
|
||||
int maxMP = 0;
|
||||
int mana = 0;
|
||||
int attack = 0;
|
||||
int defence = 0;
|
||||
int intelligence = 0;
|
||||
int resistance = 0;
|
||||
int speed = 0;
|
||||
float accuracy = 0.0;
|
||||
float evasion = 0.0;
|
||||
float luck = 0.0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../map
|
||||
INCLUDES+=. ../map
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -44,17 +44,17 @@ void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t til
|
||||
|
||||
void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) {
|
||||
Region::type_t tile = 0;
|
||||
for (register int i = 0; i < region->GetWidth(); ++i) {
|
||||
for (register int j = 0; j < region->GetHeight(); ++j) {
|
||||
for (register int k = 0; k < region->GetDepth(); ++k) {
|
||||
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) {
|
||||
tile = region->GetTile(i, j, k);
|
||||
//0 is invisible
|
||||
if (tile == 0) continue;
|
||||
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||
image.DrawTo(dest,
|
||||
region->GetX() + i * image.GetClipW() - camX,
|
||||
region->GetY() + j * image.GetClipH() - camY);
|
||||
(region->GetX() + i) * image.GetClipW() - camX,
|
||||
(region->GetY() + j) * image.GetClipH() - camY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-39
@@ -1,46 +1,11 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
ar -crs $(OUT) $(OBJ)
|
||||
all:
|
||||
$(MAKE) -C gameplay
|
||||
$(MAKE) -C graphics
|
||||
$(MAKE) -C map
|
||||
$(MAKE) -C script
|
||||
$(MAKE) -C network
|
||||
$(MAKE) -C script
|
||||
$(MAKE) -C ui
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
$(MAKE) -C utilities
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
+2
-8
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../graphics
|
||||
INCLUDES+=. ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -19,33 +19,25 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "map_generator.hpp"
|
||||
#include "map_allocator.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void BlankGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||
(*ptr) = new Region(width, height, depth, x, y);
|
||||
void BlankAllocator::Create(Region** const ptr, int x, int y) {
|
||||
(*ptr) = new Region(x, y);
|
||||
}
|
||||
|
||||
void BlankGenerator::Unload(Region* const ptr) {
|
||||
void BlankAllocator::Unload(Region* const ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
/*
|
||||
void PerlinGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||
(*ptr) = new Region(width, height, depth, x, y);
|
||||
}
|
||||
|
||||
void PerlinGenerator::Unload(Region* const ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
*/
|
||||
void LuaGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||
void LuaAllocator::Create(Region** const ptr, int x, int y) {
|
||||
//something to work on
|
||||
(*ptr) = new Region(width, height, depth, x, y);
|
||||
(*ptr) = new Region(x, y);
|
||||
|
||||
//API hook
|
||||
lua_getglobal(state, "Region");
|
||||
lua_getfield(state, -1, "Create");
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "create");
|
||||
lua_pushlightuserdata(state, *ptr);
|
||||
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
@@ -53,10 +45,10 @@ void LuaGenerator::Create(Region** const ptr, int width, int height, int depth,
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
void LuaGenerator::Unload(Region* const ptr) {
|
||||
void LuaAllocator::Unload(Region* const ptr) {
|
||||
//API hook
|
||||
lua_getglobal(state, "Region");
|
||||
lua_getfield(state, -1, "Unload");
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "unload");
|
||||
lua_pushlightuserdata(state, ptr);
|
||||
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
@@ -19,32 +19,24 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MAPGENERATOR_HPP_
|
||||
#define MAPGENERATOR_HPP_
|
||||
#ifndef MAPALLOCATOR_HPP_
|
||||
#define MAPALLOCATOR_HPP_
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class BlankGenerator {
|
||||
class BlankAllocator {
|
||||
public:
|
||||
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Create(Region** const, int x, int y);
|
||||
void Unload(Region* const);
|
||||
private:
|
||||
//
|
||||
};
|
||||
/*
|
||||
class PerlinGenerator {
|
||||
|
||||
class LuaAllocator {
|
||||
public:
|
||||
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Unload(Region* const);
|
||||
private:
|
||||
//
|
||||
};
|
||||
*/
|
||||
class LuaGenerator {
|
||||
public:
|
||||
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Create(Region** const, int x, int y);
|
||||
void Unload(Region* const);
|
||||
|
||||
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||
@@ -23,37 +23,24 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||
void DummyFormat::Load(Region** const ptr, int x, int y) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void DummyFormat::Save(Region* const ptr) {
|
||||
//EMPTY
|
||||
}
|
||||
/*
|
||||
void VerboseFormat::Load(Region** const ptr, int x, int y) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void VerboseFormat::Save(Region* const ptr) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void CompactFormat::Load(Region** const ptr, int x, int y) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void CompactFormat::Save(Region* const ptr) {
|
||||
//TODO
|
||||
}
|
||||
*/
|
||||
void LuaFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||
void LuaFormat::Load(Region** const ptr, int x, int y) {
|
||||
//something to load into
|
||||
(*ptr) = new Region(width, height, depth, x, y);
|
||||
|
||||
if (!(*ptr)) {
|
||||
(*ptr) = new Region(x, y);
|
||||
}
|
||||
|
||||
//API hook
|
||||
lua_getglobal(state, "Region");
|
||||
lua_getfield(state, -1, "Load");
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "load");
|
||||
lua_pushlightuserdata(state, *ptr);
|
||||
lua_pushstring(state, saveDir.c_str());
|
||||
if (lua_pcall(state, 2, 1, 0) != LUA_OK) {
|
||||
@@ -68,8 +55,8 @@ void LuaFormat::Load(Region** const ptr, int width, int height, int depth, int x
|
||||
|
||||
void LuaFormat::Save(Region* const ptr) {
|
||||
//API hook
|
||||
lua_getglobal(state, "Region");
|
||||
lua_getfield(state, -1, "Save");
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "save");
|
||||
lua_pushlightuserdata(state, ptr);
|
||||
lua_pushstring(state, saveDir.c_str());
|
||||
if (lua_pcall(state, 2, 0, 0) != LUA_OK) {
|
||||
|
||||
@@ -30,18 +30,7 @@
|
||||
|
||||
class DummyFormat {
|
||||
public:
|
||||
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Save(Region* const);
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
std::string GetSaveDir() { return saveDir; }
|
||||
private:
|
||||
std::string saveDir;
|
||||
};
|
||||
/*
|
||||
class VerboseFormat {
|
||||
public:
|
||||
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Load(Region** const, int x, int y);
|
||||
void Save(Region* const);
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
@@ -50,20 +39,12 @@ private:
|
||||
std::string saveDir;
|
||||
};
|
||||
|
||||
class CompactFormat {
|
||||
public:
|
||||
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Save(Region* const);
|
||||
//TODO: verbose save file format
|
||||
//TODO: compact save file format
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
std::string GetSaveDir() { return saveDir; }
|
||||
private:
|
||||
std::string saveDir;
|
||||
};
|
||||
*/
|
||||
class LuaFormat {
|
||||
public:
|
||||
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||
void Load(Region** const, int x, int y);
|
||||
void Save(Region* const);
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
|
||||
+3
-23
@@ -21,35 +21,15 @@
|
||||
*/
|
||||
#include "region.hpp"
|
||||
|
||||
Region::Region(int argWidth, int argHeight, int argDepth, int argX, int argY):
|
||||
width(argWidth),
|
||||
height(argHeight),
|
||||
depth(argDepth),
|
||||
Region::Region(int argX, int argY):
|
||||
x(argX),
|
||||
y(argY)
|
||||
{
|
||||
tiles = new type_t**[width];
|
||||
for (register int i = 0; i < width; ++i) {
|
||||
tiles[i] = new type_t*[height];
|
||||
for (register int j = 0; j < height; ++j) {
|
||||
tiles[i][j] = new type_t[depth];
|
||||
for (register int k = 0; k < depth; ++k) {
|
||||
tiles[i][j][k] = 0;
|
||||
}
|
||||
}
|
||||
for (register int i = 0; i < REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH; ++i) {
|
||||
*(reinterpret_cast<type_t*>(tiles) + i) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Region::~Region() {
|
||||
for (register int i = 0; i < width; ++i) {
|
||||
for (register int j = 0; j < height; j++) {
|
||||
delete tiles[i][j];
|
||||
}
|
||||
delete tiles[i];
|
||||
}
|
||||
delete tiles;
|
||||
}
|
||||
|
||||
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||
return tiles[x][y][z] = v;
|
||||
}
|
||||
|
||||
+3
-10
@@ -22,7 +22,6 @@
|
||||
#ifndef REGION_HPP_
|
||||
#define REGION_HPP_
|
||||
|
||||
//temporary?
|
||||
#define REGION_WIDTH 20
|
||||
#define REGION_HEIGHT 20
|
||||
#define REGION_DEPTH 3
|
||||
@@ -32,26 +31,20 @@ public:
|
||||
typedef unsigned short type_t;
|
||||
|
||||
Region() = delete;
|
||||
Region(int width, int height, int depth, int x, int y);
|
||||
~Region();
|
||||
Region(int x, int y);
|
||||
~Region() = default;
|
||||
|
||||
type_t SetTile(int x, int y, int z, type_t v);
|
||||
type_t GetTile(int x, int y, int z);
|
||||
|
||||
//accessors
|
||||
int GetWidth() const { return width; }
|
||||
int GetHeight() const { return height; }
|
||||
int GetDepth() const { return depth; }
|
||||
int GetX() const { return x; }
|
||||
int GetY() const { return y; }
|
||||
private:
|
||||
const int width;
|
||||
const int height;
|
||||
const int depth;
|
||||
const int x;
|
||||
const int y;
|
||||
|
||||
type_t*** tiles = nullptr;
|
||||
type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,18 +23,6 @@
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
RegionPagerBase::RegionPagerBase(int argWidth, int argHeight, int argDepth):
|
||||
regionWidth(argWidth),
|
||||
regionHeight(argHeight),
|
||||
regionDepth(argDepth)
|
||||
{
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
RegionPagerBase::~RegionPagerBase() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
|
||||
Region* ptr = GetRegion(x, y);
|
||||
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
|
||||
@@ -47,12 +35,10 @@ Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
|
||||
|
||||
Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(regionWidth, x);
|
||||
y = snapToBase(regionHeight, y);
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//get the region by various means
|
||||
|
||||
//TODO: revert this try/catch point
|
||||
Region* ptr = nullptr;
|
||||
ptr = FindRegion(x, y);
|
||||
if (ptr) return ptr;
|
||||
@@ -62,6 +48,10 @@ Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::FindRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//find the region
|
||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||
|
||||
+29
-53
@@ -29,9 +29,8 @@
|
||||
|
||||
class RegionPagerBase {
|
||||
public:
|
||||
RegionPagerBase() = default;
|
||||
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth);
|
||||
virtual ~RegionPagerBase();
|
||||
RegionPagerBase() {};
|
||||
virtual ~RegionPagerBase() {};
|
||||
|
||||
//tile manipulation
|
||||
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
|
||||
@@ -47,93 +46,70 @@ public:
|
||||
virtual Region* SaveRegion(int x, int y) = 0;
|
||||
virtual Region* CreateRegion(int x, int y) = 0;
|
||||
virtual void UnloadRegion(int x, int y) = 0;
|
||||
//TODO: delete?
|
||||
//TODO: delete existing regions
|
||||
|
||||
//accessors & mutators
|
||||
//NOTE: don't change the sizes mid-program, it will cause issues
|
||||
int SetRegionWidth(int i) { return regionWidth = i; }
|
||||
int SetRegionHeight(int i) { return regionHeight = i; }
|
||||
int SetRegionDepth(int i) { return regionDepth = i; }
|
||||
|
||||
int GetRegionWidth() const { return regionWidth; }
|
||||
int GetRegionHeight() const { return regionHeight; }
|
||||
int GetRegionDepth() const { return regionDepth; }
|
||||
|
||||
std::list<Region*>* GetContainer() { return ®ionList; }
|
||||
protected:
|
||||
int regionWidth;
|
||||
int regionHeight;
|
||||
int regionDepth;
|
||||
std::list<Region*> regionList;
|
||||
};
|
||||
|
||||
template<typename MapGenerator, typename MapFileFormat>
|
||||
template<typename Allocator, typename FileFormat>
|
||||
class RegionPager : public RegionPagerBase {
|
||||
public:
|
||||
RegionPager() = default;
|
||||
RegionPager(int w, int h, int d):
|
||||
RegionPagerBase(w, h, d)
|
||||
{
|
||||
//EMPTY
|
||||
}
|
||||
RegionPager() {};
|
||||
~RegionPager() {
|
||||
UnloadAll();
|
||||
}
|
||||
|
||||
Region* LoadRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(regionWidth, x);
|
||||
y = snapToBase(regionHeight, y);
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//load the region if possible
|
||||
Region* ptr = nullptr;
|
||||
format.Load(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||
format.Load(&ptr, x, y);
|
||||
if (ptr) {
|
||||
regionList.push_back(ptr);
|
||||
return ptr;
|
||||
return PushRegion(ptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Region* SaveRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(regionWidth, x);
|
||||
y = snapToBase(regionHeight, y);
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//find & save the region
|
||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||
format.Save(*it);
|
||||
return *it;
|
||||
}
|
||||
Region* ptr = FindRegion(x, y);
|
||||
if (ptr) {
|
||||
format.Save(ptr);
|
||||
}
|
||||
return nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Region* CreateRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(regionWidth, x);
|
||||
y = snapToBase(regionHeight, y);
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//create and push the object
|
||||
Region* ptr = nullptr;
|
||||
generator.Create(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||
regionList.push_back(ptr);
|
||||
return ptr;
|
||||
allocator.Create(&ptr, x, y);
|
||||
return PushRegion(ptr);
|
||||
}
|
||||
|
||||
void UnloadRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(regionWidth, x);
|
||||
y = snapToBase(regionHeight, y);
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//custom loop
|
||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
|
||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||
generator.Unload(*it);
|
||||
regionList.erase(it);
|
||||
|
||||
//reset the loop, because of reasons
|
||||
it = regionList.begin();
|
||||
allocator.Unload(*it);
|
||||
it = regionList.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
@@ -141,17 +117,17 @@ public:
|
||||
}
|
||||
void UnloadAll() {
|
||||
for (auto& it : regionList) {
|
||||
generator.Unload(it);
|
||||
allocator.Unload(it);
|
||||
}
|
||||
regionList.clear();
|
||||
}
|
||||
|
||||
//accessors
|
||||
MapGenerator* GetGenerator() { return &generator; }
|
||||
MapFileFormat* GetFormat() { return &format; }
|
||||
Allocator* GetAllocator() { return &allocator; }
|
||||
FileFormat* GetFormat() { return &format; }
|
||||
protected:
|
||||
MapGenerator generator;
|
||||
MapFileFormat format;
|
||||
Allocator allocator;
|
||||
FileFormat format;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../map
|
||||
INCLUDES+=. ../gameplay ../map ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
+310
-176
@@ -21,97 +21,71 @@
|
||||
*/
|
||||
#include "serial.hpp"
|
||||
|
||||
#include "map_generator.hpp"
|
||||
#include "map_allocator.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
//-------------------------
|
||||
//Convenience Macros
|
||||
//-------------------------
|
||||
|
||||
#define SERIALIZE(buffer, data, size) memcpy(buffer, data, size); buffer += size;
|
||||
#define DESERIALIZE(buffer, data, size) memcpy(data, buffer, size); buffer += size;
|
||||
|
||||
//-------------------------
|
||||
//internal serialization functions
|
||||
//-------------------------
|
||||
|
||||
void serializeType(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
void serializeType(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
}
|
||||
|
||||
void serializeServer(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||
void serializeServer(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//server info
|
||||
SERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
|
||||
SERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
|
||||
}
|
||||
|
||||
void serializeClient(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
memcpy(buffer, &packet->clientInfo.index, sizeof(int));
|
||||
}
|
||||
|
||||
void serializePlayer(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
void serializeClient(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(buffer, &packet->playerInfo.playerIndex, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
SERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
|
||||
|
||||
//text
|
||||
memcpy(buffer, packet->playerInfo.handle, PACKET_STRING_SIZE);
|
||||
buffer += PACKET_STRING_SIZE;
|
||||
memcpy(buffer, packet->playerInfo.avatar, PACKET_STRING_SIZE);
|
||||
buffer += PACKET_STRING_SIZE;
|
||||
|
||||
//vectors
|
||||
memcpy(buffer, &packet->playerInfo.position.x, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(buffer, &packet->playerInfo.position.y, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(buffer, &packet->playerInfo.motion.x, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double));
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
|
||||
//TODO: password
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
}
|
||||
|
||||
void serializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
void serializeRegionFormat(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//size
|
||||
memcpy(buffer, &packet->regionInfo.width, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(buffer, &packet->regionInfo.height, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(buffer, &packet->regionInfo.depth, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
|
||||
//x & y
|
||||
memcpy(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
}
|
||||
|
||||
void serializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||
//format
|
||||
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
}
|
||||
|
||||
//size
|
||||
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetWidth();
|
||||
buffer += sizeof(int);
|
||||
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetHeight();
|
||||
buffer += sizeof(int);
|
||||
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetDepth();
|
||||
buffer += sizeof(int);
|
||||
void serializeRegionContent(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//x & y
|
||||
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetX();
|
||||
buffer += sizeof(int);
|
||||
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetY();
|
||||
buffer += sizeof(int);
|
||||
//format
|
||||
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
|
||||
//content
|
||||
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||
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->regionInfo.region->GetTile(i, j, k);
|
||||
buffer += sizeof(Region::type_t);
|
||||
}
|
||||
@@ -119,88 +93,130 @@ void serializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void serializeCombat(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//integers
|
||||
SERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
|
||||
//TODO: more comabat info
|
||||
}
|
||||
|
||||
void serializeStatistics(Statistics* stats, char* 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 serializeCharacter(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
SERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//vectors
|
||||
SERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
|
||||
|
||||
//stats structure
|
||||
serializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
void serializeEnemy(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//stats structure
|
||||
serializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//internal deserialization functions
|
||||
//-------------------------
|
||||
|
||||
void deserializeType(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||
void deserializeType(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
}
|
||||
|
||||
void deserializeServer(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE);
|
||||
void deserializeServer(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//server info
|
||||
DESERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
|
||||
DESERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
|
||||
}
|
||||
|
||||
void deserializeClient(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
memcpy(&packet->clientInfo.index, buffer, sizeof(int));
|
||||
}
|
||||
|
||||
void deserializePlayer(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
void deserializeClient(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(&packet->playerInfo.playerIndex, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
DESERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
|
||||
|
||||
//text
|
||||
memcpy(packet->playerInfo.handle, buffer, PACKET_STRING_SIZE);
|
||||
buffer += PACKET_STRING_SIZE;
|
||||
memcpy(packet->playerInfo.avatar, buffer, PACKET_STRING_SIZE);
|
||||
buffer += PACKET_STRING_SIZE;
|
||||
|
||||
//vectors
|
||||
memcpy(&packet->playerInfo.position.x, buffer, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(&packet->playerInfo.position.y, buffer, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(&packet->playerInfo.motion.x, buffer, sizeof(double));
|
||||
buffer += sizeof(double);
|
||||
memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double));
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
|
||||
//TODO: password
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
}
|
||||
|
||||
void deserializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||
buffer += sizeof(NetworkPacket::Type);
|
||||
void deserializeRegionFormat(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//size
|
||||
memcpy(&packet->regionInfo.width, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(&packet->regionInfo.height, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(&packet->regionInfo.depth, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
|
||||
//x & y
|
||||
memcpy(&packet->regionInfo.x, buffer, sizeof(int));
|
||||
buffer += sizeof(int);
|
||||
memcpy(&packet->regionInfo.y, buffer, sizeof(int));
|
||||
}
|
||||
|
||||
void deserializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||
//format
|
||||
deserializeRegionFormat(packet, buffer);
|
||||
buffer += sizeof(int) * 5 + sizeof(NetworkPacket::Type);
|
||||
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
}
|
||||
|
||||
//content
|
||||
BlankGenerator().Create(
|
||||
void deserializeRegionContent(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//format
|
||||
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
|
||||
//an object to work on
|
||||
BlankAllocator().Create(
|
||||
&packet->regionInfo.region,
|
||||
packet->regionInfo.width,
|
||||
packet->regionInfo.height,
|
||||
packet->regionInfo.depth,
|
||||
packet->regionInfo.x,
|
||||
packet->regionInfo.y
|
||||
);
|
||||
|
||||
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||
//content
|
||||
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->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
|
||||
buffer += sizeof(Region::type_t);
|
||||
}
|
||||
@@ -208,92 +224,210 @@ void deserializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void deserializeCombat(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//integers
|
||||
DESERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
|
||||
//TODO: more comabat info
|
||||
}
|
||||
|
||||
|
||||
void deserializeStatistics(Statistics* stats, char* 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));
|
||||
}
|
||||
|
||||
void deserializeCharacter(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
DESERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//vectors
|
||||
DESERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
|
||||
|
||||
//stats structure
|
||||
deserializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
void deserializeEnemy(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//stats structure
|
||||
deserializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//the interface functions
|
||||
//-------------------------
|
||||
|
||||
void serialize(NetworkPacket* packet, void* buffer) {
|
||||
void serialize(SerialPacket* packet, void* buffer) {
|
||||
switch(packet->meta.type) {
|
||||
//No extra data
|
||||
case NetworkPacket::Type::NONE:
|
||||
case NetworkPacket::Type::PING:
|
||||
case NetworkPacket::Type::PONG:
|
||||
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||
case NetworkPacket::Type::JOIN_REQUEST:
|
||||
case NetworkPacket::Type::SYNCHRONIZE:
|
||||
//no extra data
|
||||
case SerialPacket::Type::NONE:
|
||||
case SerialPacket::Type::PING:
|
||||
case SerialPacket::Type::PONG:
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
|
||||
//all rejections
|
||||
case SerialPacket::Type::BROADCAST_REJECTION:
|
||||
case SerialPacket::Type::JOIN_REJECTION:
|
||||
case SerialPacket::Type::REGION_REJECTION:
|
||||
case SerialPacket::Type::CHARACTER_REJECTION:
|
||||
case SerialPacket::Type::ENEMY_REJECTION:
|
||||
case SerialPacket::Type::COMBAT_REJECTION:
|
||||
|
||||
serializeType(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//Server info
|
||||
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||
//server info
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE:
|
||||
serializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//Client info
|
||||
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||
case NetworkPacket::Type::DISCONNECT:
|
||||
case NetworkPacket::Type::SHUTDOWN:
|
||||
//client info
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
serializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//Player info
|
||||
case NetworkPacket::Type::PLAYER_NEW:
|
||||
case NetworkPacket::Type::PLAYER_DELETE:
|
||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||
serializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//region info
|
||||
case NetworkPacket::Type::REGION_REQUEST:
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
case NetworkPacket::Type::REGION_CONTENT:
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//combat info
|
||||
case SerialPacket::Type::COMBAT_ENTER:
|
||||
case SerialPacket::Type::COMBAT_EXIT:
|
||||
serializeCombat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//character info
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
|
||||
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
|
||||
serializeCharacter(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//enemy info
|
||||
case SerialPacket::Type::ENEMY_NEW:
|
||||
case SerialPacket::Type::ENEMY_DELETE:
|
||||
case SerialPacket::Type::ENEMY_UPDATE:
|
||||
case SerialPacket::Type::ENEMY_STATS_REQUEST:
|
||||
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
|
||||
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void deserialize(NetworkPacket* packet, void* buffer) {
|
||||
void deserialize(SerialPacket* packet, void* buffer) {
|
||||
//find the type, so that you can actually deserialize the packet!
|
||||
deserializeType(packet, reinterpret_cast<char*>(buffer));
|
||||
switch(packet->meta.type) {
|
||||
//No extra data
|
||||
case NetworkPacket::Type::NONE:
|
||||
case NetworkPacket::Type::PING:
|
||||
case NetworkPacket::Type::PONG:
|
||||
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||
case NetworkPacket::Type::JOIN_REQUEST:
|
||||
case NetworkPacket::Type::SYNCHRONIZE:
|
||||
//no extra data
|
||||
case SerialPacket::Type::NONE:
|
||||
case SerialPacket::Type::PING:
|
||||
case SerialPacket::Type::PONG:
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
|
||||
//all rejections
|
||||
case SerialPacket::Type::BROADCAST_REJECTION:
|
||||
case SerialPacket::Type::JOIN_REJECTION:
|
||||
case SerialPacket::Type::REGION_REJECTION:
|
||||
case SerialPacket::Type::CHARACTER_REJECTION:
|
||||
case SerialPacket::Type::ENEMY_REJECTION:
|
||||
case SerialPacket::Type::COMBAT_REJECTION:
|
||||
|
||||
//NOTHING
|
||||
break;
|
||||
|
||||
//Server info
|
||||
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||
//server info
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE:
|
||||
deserializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//Client info
|
||||
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||
case NetworkPacket::Type::DISCONNECT:
|
||||
case NetworkPacket::Type::SHUTDOWN:
|
||||
//client info
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
deserializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//Player info
|
||||
case NetworkPacket::Type::PLAYER_NEW:
|
||||
case NetworkPacket::Type::PLAYER_DELETE:
|
||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||
deserializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//region info
|
||||
case NetworkPacket::Type::REGION_REQUEST:
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
case NetworkPacket::Type::REGION_CONTENT:
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//combat info
|
||||
case SerialPacket::Type::COMBAT_ENTER:
|
||||
case SerialPacket::Type::COMBAT_EXIT:
|
||||
serializeCombat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//character info
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
|
||||
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
|
||||
deserializeCharacter(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//enemy info
|
||||
case SerialPacket::Type::ENEMY_NEW:
|
||||
case SerialPacket::Type::ENEMY_DELETE:
|
||||
case SerialPacket::Type::ENEMY_UPDATE:
|
||||
case SerialPacket::Type::ENEMY_STATS_REQUEST:
|
||||
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
|
||||
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -22,16 +22,17 @@
|
||||
#ifndef SERIAL_HPP_
|
||||
#define SERIAL_HPP_
|
||||
|
||||
#include "network_packet.hpp"
|
||||
#include "serial_packet.hpp"
|
||||
|
||||
/* Sending regions are the largest type of packet
|
||||
* content: width * height * depth * sizoeof(type)
|
||||
* map format: sizeof(int) * 5
|
||||
* metadata: sizeof(metadata)
|
||||
/* NOTE: Keep the PACKET_BUFFER_SIZE up to date
|
||||
* NOTE: REGION_CONTENT is currently the largest type of packet
|
||||
* map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t)
|
||||
* map format: sizeof(int) * 3
|
||||
* metadata: sizeof(SerialPacket::Type)
|
||||
*/
|
||||
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 5 + sizeof(NetworkPacket::Metadata)
|
||||
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 3 + sizeof(SerialPacket::Type)
|
||||
|
||||
void serialize(NetworkPacket* const, void*);
|
||||
void deserialize(NetworkPacket* const, void*);
|
||||
void serialize(SerialPacket* const, void* dest);
|
||||
void deserialize(SerialPacket* const, void* src);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,53 +19,84 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef NETWORKPACKET_HPP_
|
||||
#define NETWORKPACKET_HPP_
|
||||
#ifndef SERIALPACKET_HPP_
|
||||
#define SERIALPACKET_HPP_
|
||||
|
||||
#include "vector2.hpp"
|
||||
#include "region.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
#define NETWORK_VERSION 20140528
|
||||
#define PACKET_STRING_SIZE 100
|
||||
|
||||
#pragma pack(push, 0)
|
||||
|
||||
union NetworkPacket {
|
||||
union SerialPacket {
|
||||
//types of packets
|
||||
enum class Type {
|
||||
//default: there is something wrong
|
||||
NONE = 0,
|
||||
|
||||
//not used
|
||||
//keep alive
|
||||
PING = 1,
|
||||
PONG = 2,
|
||||
|
||||
//Searching for a server to join
|
||||
//searching for a server to join
|
||||
BROADCAST_REQUEST = 3,
|
||||
BROADCAST_RESPONSE = 4,
|
||||
BROADCAST_REJECTION = 5,
|
||||
|
||||
//try to join the server
|
||||
JOIN_REQUEST = 5,
|
||||
JOIN_RESPONSE = 6,
|
||||
|
||||
//disconnect from the server
|
||||
DISCONNECT = 7,
|
||||
JOIN_REQUEST = 6,
|
||||
JOIN_RESPONSE = 7,
|
||||
JOIN_REJECTION = 8,
|
||||
|
||||
//mass update
|
||||
SYNCHRONIZE = 8,
|
||||
SYNCHRONIZE = 9,
|
||||
|
||||
//disconnect from the server
|
||||
DISCONNECT = 10,
|
||||
|
||||
//shut down the server
|
||||
SHUTDOWN = 9,
|
||||
|
||||
//Player movement, etc.
|
||||
PLAYER_NEW = 10,
|
||||
PLAYER_DELETE = 11,
|
||||
PLAYER_UPDATE = 12,
|
||||
SHUTDOWN = 11,
|
||||
|
||||
//map data
|
||||
REGION_REQUEST = 13,
|
||||
REGION_CONTENT = 14,
|
||||
REGION_REQUEST = 12,
|
||||
REGION_CONTENT = 13,
|
||||
REGION_REJECTION = 14,
|
||||
|
||||
//combat data
|
||||
COMBAT_ENTER = 15,
|
||||
COMBAT_EXIT = 16,
|
||||
|
||||
COMBAT_UPDATE = 17,
|
||||
|
||||
COMBAT_REJECTION = 18,
|
||||
|
||||
//character data
|
||||
CHARACTER_NEW = 19,
|
||||
CHARACTER_DELETE = 20,
|
||||
CHARACTER_UPDATE = 21,
|
||||
|
||||
CHARACTER_STATS_REQUEST = 22,
|
||||
CHARACTER_STATS_RESPONSE = 23,
|
||||
|
||||
CHARACTER_REJECTION = 24,
|
||||
|
||||
//enemy data
|
||||
ENEMY_NEW = 25,
|
||||
ENEMY_DELETE = 26,
|
||||
ENEMY_UPDATE = 27,
|
||||
|
||||
ENEMY_STATS_REQUEST = 28,
|
||||
ENEMY_STATS_RESPONSE = 29,
|
||||
|
||||
ENEMY_REJECTION = 30,
|
||||
|
||||
//more packet types go here
|
||||
|
||||
//not used
|
||||
LAST,
|
||||
};
|
||||
|
||||
//metadata on the packet itself
|
||||
@@ -74,46 +105,71 @@ union NetworkPacket {
|
||||
IPaddress srcAddress;
|
||||
}meta;
|
||||
|
||||
//information about the server
|
||||
//info about the server
|
||||
struct ServerInformation {
|
||||
Metadata meta;
|
||||
//TODO: version info
|
||||
int networkVersion;
|
||||
char name[PACKET_STRING_SIZE];
|
||||
//TODO: player count
|
||||
//TODO: map format
|
||||
int playerCount;
|
||||
}serverInfo;
|
||||
|
||||
//information about the client
|
||||
//info about the client
|
||||
struct ClientInformation {
|
||||
Metadata meta;
|
||||
int index;
|
||||
}clientInfo;
|
||||
|
||||
//information about a player
|
||||
struct PlayerInformation {
|
||||
Metadata meta;
|
||||
int clientIndex;
|
||||
int playerIndex;
|
||||
int accountIndex;
|
||||
int characterIndex;
|
||||
char username[PACKET_STRING_SIZE];
|
||||
//TODO: password
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
}playerInfo;
|
||||
}clientInfo;
|
||||
|
||||
//map data
|
||||
//info about a region
|
||||
struct RegionInformation {
|
||||
Metadata meta;
|
||||
int width, height, depth, x, y;
|
||||
int mapIndex;
|
||||
int x, y;
|
||||
Region* region;
|
||||
}regionInfo;
|
||||
|
||||
//info about a combat scenario
|
||||
struct CombatInformation {
|
||||
Metadata meta;
|
||||
int combatIndex;
|
||||
int difficulty;
|
||||
//TODO: background image, based on terrain type
|
||||
//TODO: array of combatants
|
||||
//TODO: rewards
|
||||
}combatInfo;
|
||||
|
||||
//info about a character
|
||||
struct CharacterInformation {
|
||||
Metadata meta;
|
||||
int clientIndex;
|
||||
int accountIndex;
|
||||
int characterIndex;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
int mapIndex;
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
Statistics stats;
|
||||
}characterInfo;
|
||||
|
||||
//info about an enemy
|
||||
struct EnemyInformation {
|
||||
Metadata meta;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
Statistics stats;
|
||||
}enemyInfo;
|
||||
|
||||
//defaults
|
||||
NetworkPacket() {
|
||||
SerialPacket() {
|
||||
meta.type = Type::NONE;
|
||||
meta.srcAddress = {0,0};
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -21,34 +21,33 @@
|
||||
*/
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void UDPNetworkUtility::Open(int port, int packSize) {
|
||||
if (!(socket = SDLNet_UDP_Open(port))) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to open a UDP socket"));
|
||||
}
|
||||
//DOCS: memset() is used before sending a packet to remove old data; you don't want to send sensitive data over the network
|
||||
//NOTE: don't confuse SerialPacket with UDPpacket
|
||||
|
||||
if (!(packOut = SDLNet_AllocPacket(packSize))) {
|
||||
void UDPNetworkUtility::Open(int port) {
|
||||
socket = SDLNet_UDP_Open(port);
|
||||
packet = SDLNet_AllocPacket(PACKET_BUFFER_SIZE);
|
||||
if (!socket || !packet) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to allocate the out packet"));
|
||||
}
|
||||
|
||||
if (!(packIn = SDLNet_AllocPacket(packSize))) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to allocate the in packet"));
|
||||
throw(std::runtime_error("Failed to open UDPNetworkUtility"));
|
||||
}
|
||||
}
|
||||
|
||||
void UDPNetworkUtility::Close() {
|
||||
SDLNet_UDP_Close(socket);
|
||||
SDLNet_FreePacket(packOut);
|
||||
SDLNet_FreePacket(packIn);
|
||||
SDLNet_FreePacket(packet);
|
||||
socket = nullptr;
|
||||
packOut = nullptr;
|
||||
packIn = nullptr;
|
||||
packet = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//bind to a channel
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
@@ -61,7 +60,7 @@ int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
|
||||
int UDPNetworkUtility::Bind(IPaddress* add, int channel) {
|
||||
int ret = SDLNet_UDP_Bind(socket, channel, add);
|
||||
|
||||
if (ret == -1) {
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Failed to bind to a channel"));
|
||||
}
|
||||
|
||||
@@ -72,25 +71,29 @@ void UDPNetworkUtility::Unbind(int channel) {
|
||||
SDLNet_UDP_Unbind(socket, channel);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(const char* ip, int port, void* data, int len) {
|
||||
//-------------------------
|
||||
//send a buffer
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::SendTo(const char* ip, int port, void* data, int len) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
Send(&add, data, len);
|
||||
SendTo(&add, data, len);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(IPaddress* add, void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
int UDPNetworkUtility::SendTo(IPaddress* add, void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
packOut->address = *add;
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
packet->address = *add;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packOut);
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
@@ -99,15 +102,15 @@ int UDPNetworkUtility::Send(IPaddress* add, void* data, int len) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(int channel, void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
int UDPNetworkUtility::SendTo(int channel, void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packOut);
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
@@ -116,29 +119,30 @@ int UDPNetworkUtility::Send(int channel, void* data, int len) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendAll(void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
int UDPNetworkUtility::SendToAllChannels(void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
|
||||
int sent = 0;
|
||||
|
||||
//send to all bound channels
|
||||
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
|
||||
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
|
||||
sent += SDLNet_UDP_Send(socket, i, packOut);
|
||||
sent += SDLNet_UDP_Send(socket, i, packet);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
//TODO: put a void* and int* parameter list here
|
||||
int UDPNetworkUtility::Receive() {
|
||||
memset(packIn->data, 0, packIn->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packIn);
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packet);
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Unknown network error occured"));
|
||||
@@ -146,3 +150,75 @@ int UDPNetworkUtility::Receive() {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//send a SerialPacket
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::SendTo(const char* ip, int port, SerialPacket* serialPacket) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
SendTo(&add, serialPacket);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(IPaddress* add, SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
packet->address = *add;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(int channel, SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendToAllChannels(SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
|
||||
int sent = 0;
|
||||
|
||||
//send to all bound channels
|
||||
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
|
||||
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
|
||||
sent += SDLNet_UDP_Send(socket, i, packet);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Receive(SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packet);
|
||||
deserialize(serialPacket, packet->data);
|
||||
serialPacket->meta.srcAddress = packet->address;
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Unknown network error occured"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -24,12 +24,14 @@
|
||||
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
#include "serial_packet.hpp"
|
||||
|
||||
class UDPNetworkUtility {
|
||||
public:
|
||||
UDPNetworkUtility() = default;
|
||||
~UDPNetworkUtility() = default;
|
||||
|
||||
void Open(int port, int packSize);
|
||||
void Open(int port);
|
||||
void Close();
|
||||
|
||||
//bind to a channel
|
||||
@@ -41,31 +43,30 @@ public:
|
||||
return SDLNet_UDP_GetPeerAddress(socket, channel);
|
||||
}
|
||||
|
||||
int Send(const char* ip, int port, void* data, int len);
|
||||
int Send(IPaddress* add, void* data, int len);
|
||||
int Send(int channel, void* data, int len);
|
||||
int SendAll(void* data, int len);
|
||||
//send a buffer
|
||||
int SendTo(const char* ip, int port, void* data, int len);
|
||||
int SendTo(IPaddress* add, void* data, int len);
|
||||
int SendTo(int channel, void* data, int len);
|
||||
int SendToAllChannels(void* data, int len);
|
||||
int Receive();
|
||||
|
||||
void* GetOutData() const {
|
||||
return reinterpret_cast<void*>(packOut->data);
|
||||
};
|
||||
void* GetInData() const {
|
||||
return reinterpret_cast<void*>(packIn->data);
|
||||
};
|
||||
UDPpacket* GetOutPacket() const {
|
||||
return packOut;
|
||||
}
|
||||
UDPpacket* GetInPacket() const {
|
||||
return packIn;
|
||||
//send a SerialPacket
|
||||
int SendTo(const char* ip, int port, SerialPacket* serialPacket);
|
||||
int SendTo(IPaddress* add, SerialPacket* serialPacket);
|
||||
int SendTo(int channel, SerialPacket* serialPacket);
|
||||
int SendToAllChannels(SerialPacket* serialPacket);
|
||||
int Receive(SerialPacket* serialPacket);
|
||||
|
||||
//accessors
|
||||
UDPpacket* GetPacket() const {
|
||||
return packet;
|
||||
}
|
||||
UDPsocket GetSocket() const {
|
||||
return socket;
|
||||
}
|
||||
private:
|
||||
UDPsocket socket = nullptr;
|
||||
UDPpacket* packOut = nullptr;
|
||||
UDPpacket* packIn = nullptr;
|
||||
UDPpacket* packet = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include "region_api.hpp"
|
||||
#include "map_api.hpp"
|
||||
|
||||
|
||||
/*
|
||||
@@ -41,7 +41,7 @@ static const luaL_Reg loadedlibs[] = {
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
|
||||
/* custom libs */
|
||||
{LUA_REGIONLIBNAME, luaopen_regionapi},
|
||||
{LUA_MAPLIBNAME, luaopen_mapapi},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../map
|
||||
INCLUDES+=. ../map ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/* 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 "map_api.hpp"
|
||||
|
||||
//map headers
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//NOTE: When operating on a region, setTile() & getTile() *are not* zero indexed, but when operating on the entire map they *are* zero indexed.
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
if (lua_gettop(L) == 5) {
|
||||
//operating on a region
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||
}
|
||||
else {
|
||||
//operating on the whole map
|
||||
lua_pushstring(L, "pager");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//assume the pager is using lua
|
||||
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
|
||||
|
||||
//balance the stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
pager->SetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
if (lua_gettop(L) == 4) {
|
||||
//operating on a region
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
else {
|
||||
//operating on the whole map
|
||||
lua_pushstring(L, "pager");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//assume the pager is using lua
|
||||
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
|
||||
|
||||
//balance the stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
int ret = pager->GetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getX(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetX());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getY(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetY());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionWidth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_WIDTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionHeight(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_HEIGHT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionDepth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_DEPTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dummy(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionlib[] = {
|
||||
{"create", dummy},
|
||||
{"unload", dummy},
|
||||
{"load", dummy},
|
||||
{"save", dummy},
|
||||
{"settile",setTile},
|
||||
{"gettile",getTile},
|
||||
{"getx",getX},
|
||||
{"gety",getY},
|
||||
{"getregionwidth",getRegionWidth},
|
||||
{"getregionheight",getRegionHeight},
|
||||
{"getregiondepth",getRegionDepth},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int luaopen_mapapi(lua_State* L) {
|
||||
luaL_newlib(L, regionlib);
|
||||
return 1;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONAPI_HPP_
|
||||
#define REGIONAPI_HPP_
|
||||
#ifndef MAPAPI_HPP_
|
||||
#define MAPAPI_HPP_
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#define LUA_REGIONLIBNAME "Region"
|
||||
LUAMOD_API int luaopen_regionapi(lua_State* L);
|
||||
#define LUA_MAPLIBNAME "map"
|
||||
LUAMOD_API int luaopen_mapapi(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -1,91 +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 "region_api.hpp"
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||
lua_pushnumber(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getWidth(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetWidth());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getHeight(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetHeight());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getDepth(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetDepth());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getX(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetX());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getY(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetY());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dummy(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionlib[] = {
|
||||
{"SetTile",setTile},
|
||||
{"GetTile",getTile},
|
||||
{"GetWidth",getWidth},
|
||||
{"GetHeight",getHeight},
|
||||
{"GetDepth",getDepth},
|
||||
{"GetX",getX},
|
||||
{"GetY",getY},
|
||||
{"Create", dummy},
|
||||
{"Unload", dummy},
|
||||
{"Load", dummy},
|
||||
{"Save", dummy},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int luaopen_regionapi(lua_State* L) {
|
||||
luaL_newlib(L, regionlib);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
+2
-8
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. .. ../graphics
|
||||
INCLUDES+=. ../graphics
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/* 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 BBOX_HPP_
|
||||
#define BBOX_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
//TODO: This is supposed to interact with the vector
|
||||
class BBox {
|
||||
public:
|
||||
double x, y;
|
||||
double w, h;
|
||||
|
||||
BBox() = default;
|
||||
BBox(double i, double j, double k, double l): x(i), y(j), w(k), h(l) {};
|
||||
~BBox() = default;
|
||||
BBox& operator=(BBox const&) = default;
|
||||
|
||||
double Size() {
|
||||
return std::max(w*h,0.0);
|
||||
}
|
||||
|
||||
bool IsCollision(BBox rhs) {
|
||||
return not (
|
||||
x >= rhs.x + rhs.w ||
|
||||
y >= rhs.y + rhs.h ||
|
||||
rhs.x >= x + w ||
|
||||
rhs.y >= y + h
|
||||
);
|
||||
}
|
||||
|
||||
BBox Intersection(BBox rhs) {
|
||||
if (!IsCollision(rhs)) {
|
||||
return {0, 0, 0, 0};
|
||||
}
|
||||
BBox ret;
|
||||
ret.x = std::max(x, rhs.x);
|
||||
ret.y = std::max(y, rhs.y);
|
||||
ret.w = std::min(x+w, rhs.x+rhs.w) - ret.x;
|
||||
ret.h = std::min(y+h, rhs.y+rhs.h) - ret.y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
double operator[](size_t i) {
|
||||
if (i >= 4)
|
||||
throw(std::domain_error("Out of range"));
|
||||
return *(&x+i);
|
||||
}
|
||||
};
|
||||
|
||||
//This is explicitly a POD
|
||||
static_assert(std::is_pod<BBox>::value, "BBox is not a POD");
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -0,0 +1,37 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
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
|
||||
@@ -0,0 +1,50 @@
|
||||
/* 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 "sql_utility.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
|
||||
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**), void* argPtr) {
|
||||
//load the file into a string
|
||||
std::ifstream is(fname);
|
||||
if (!is.is_open()) {
|
||||
return -1;
|
||||
}
|
||||
std::string script;
|
||||
getline(is, script, '\0');
|
||||
is.close();
|
||||
|
||||
//run the SQL loaded from the file
|
||||
char* errmsg = nullptr;
|
||||
int ret = sqlite3_exec(db, script.c_str(), callback, argPtr, &errmsg);
|
||||
if (ret != SQLITE_OK) {
|
||||
//handle any errors received from the SQL
|
||||
std::runtime_error e(std::string() + "SQL Script Error " + to_string_custom(ret) + ": " + errmsg);
|
||||
free(errmsg);
|
||||
throw(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/* 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 SERVERUTILITY_HPP_
|
||||
#define SERVERUTILITY_HPP_
|
||||
|
||||
#include "sqlite3/sqlite3.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**) = nullptr, void* argPtr = nullptr);
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -22,6 +22,7 @@
|
||||
#ifndef VECTOR2_HPP_
|
||||
#define VECTOR2_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
@@ -29,7 +30,6 @@ class Vector2 {
|
||||
public:
|
||||
double x, y;
|
||||
|
||||
//This is explicitly a POD
|
||||
Vector2() = default;
|
||||
Vector2(double i, double j): x(i), y(j) {};
|
||||
~Vector2() = default;
|
||||
@@ -112,4 +112,7 @@ template<typename T> Vector2 operator/(T t, Vector2 v) { return v / t; }
|
||||
template<typename T> bool operator==(T t, Vector2 v) { return v == t; }
|
||||
template<typename T> bool operator!=(T t, Vector2 v) { return v != t; }
|
||||
|
||||
//This is explicitly a POD
|
||||
static_assert(std::is_pod<Vector2>::value, "Vector2 is not a POD");
|
||||
|
||||
#endif
|
||||
@@ -1,130 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 EditorApplications, 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 "editor_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
//-------------------------
|
||||
//Static declarations
|
||||
//-------------------------
|
||||
|
||||
EditorApplication EditorApplication::instance;
|
||||
|
||||
//-------------------------
|
||||
//Scene headers
|
||||
//-------------------------
|
||||
|
||||
//Add the custom scene headers here
|
||||
#include "editor_scene.hpp"
|
||||
#include "testificate_scene.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
EditorApplication::EditorApplication() {
|
||||
//
|
||||
}
|
||||
|
||||
EditorApplication::~EditorApplication() {
|
||||
//
|
||||
}
|
||||
|
||||
void EditorApplication::Init() {
|
||||
config.Load("rsc\\config.cfg");
|
||||
if (SDL_Init(SDL_INIT_VIDEO))
|
||||
throw(std::runtime_error("Failed to initialize SDL"));
|
||||
|
||||
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"));
|
||||
}
|
||||
|
||||
void EditorApplication::Proc() {
|
||||
LoadScene(SceneList::FIRST);
|
||||
|
||||
//prepare the time system
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
|
||||
Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
|
||||
Clock::time_point simTime = Clock::now();
|
||||
Clock::time_point realTime;
|
||||
|
||||
//The main loop
|
||||
while(activeScene->GetNextScene() != SceneList::QUIT) {
|
||||
//switch scenes when necessary
|
||||
if (activeScene->GetNextScene() != SceneList::CONTINUE) {
|
||||
LoadScene(activeScene->GetNextScene());
|
||||
continue;
|
||||
}
|
||||
|
||||
//update the current time
|
||||
realTime = Clock::now();
|
||||
|
||||
//simulate game time
|
||||
while (simTime < realTime) {
|
||||
//call each user defined function
|
||||
activeScene->RunFrame(double(delta.count()) / Clock::duration::period::den);
|
||||
simTime += delta;
|
||||
}
|
||||
|
||||
//draw the game to the screen
|
||||
activeScene->RenderFrame();
|
||||
|
||||
//give the computer a break
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
UnloadScene();
|
||||
}
|
||||
|
||||
void EditorApplication::Quit() {
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Private access members
|
||||
//-------------------------
|
||||
|
||||
void EditorApplication::LoadScene(SceneList sceneIndex) {
|
||||
UnloadScene();
|
||||
|
||||
switch(sceneIndex) {
|
||||
//add scene creation calls here
|
||||
case SceneList::FIRST:
|
||||
case SceneList::EDITORSCENE:
|
||||
activeScene = new EditorScene(&config);
|
||||
break;
|
||||
|
||||
case SceneList::TESTIFICATESCENE:
|
||||
activeScene = new TestificateScene(&config);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw(std::logic_error("Failed to recognize the scene index"));
|
||||
}
|
||||
}
|
||||
|
||||
void EditorApplication::UnloadScene() {
|
||||
delete activeScene;
|
||||
activeScene = nullptr;
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 "editor_scene.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
EditorScene::EditorScene(ConfigUtility* const arg1):
|
||||
config(*arg1)
|
||||
{
|
||||
//create the debugging "window"
|
||||
debugInfo.CreateSurface(256, 256);
|
||||
|
||||
//setup the utility objects
|
||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||
|
||||
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||
|
||||
//setup the menu bar
|
||||
menuBar.SetFont(&font);
|
||||
menuBar.SetImage(&buttonImage);
|
||||
|
||||
menuBar.SetEntries({
|
||||
{"File", "New", "Open", "Save", "Close"},
|
||||
{"Edit", "Set Tile", "Set Brush", "Script"},
|
||||
{"Debug", "Debug On", "Debug Off", "Toggle", "Testificate"}
|
||||
});
|
||||
|
||||
//setup the map
|
||||
pager.SetRegionWidth(REGION_WIDTH);
|
||||
pager.SetRegionHeight(REGION_HEIGHT);
|
||||
pager.SetRegionDepth(REGION_DEPTH);
|
||||
|
||||
//debug
|
||||
tsheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||
for (int i = 0; i < REGION_WIDTH; i++) {
|
||||
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||
pager.SetTile(i, j, 0, 14);
|
||||
}
|
||||
}
|
||||
pager.SetTile(5, 10, 1, 48);
|
||||
}
|
||||
|
||||
EditorScene::~EditorScene() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void EditorScene::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void EditorScene::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void EditorScene::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void EditorScene::Render(SDL_Surface* const screen) {
|
||||
tsheet.DrawRegionTo(screen, pager.GetRegion(0, 0), camera.x, camera.y);
|
||||
/* //debug
|
||||
for (int i = 0; i < pager.GetRegionWidth()*2; i++) {
|
||||
for (int j = 0; j < pager.GetRegionHeight()*2; j++) {
|
||||
for (int k = 0; k < pager.GetRegionDepth(); k++) {
|
||||
//TODO: skip the out-of-bounds regions
|
||||
tsheet.DrawTo(
|
||||
screen,
|
||||
i*tsheet.GetTileW()-camera.x,
|
||||
j*tsheet.GetTileH()-camera.y,
|
||||
pager.GetTile(i,j,k)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//draw a big bar across the top (hackish)
|
||||
buttonImage.SetClipY(0);
|
||||
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
||||
buttonImage.DrawTo(screen, i, 0);
|
||||
}
|
||||
|
||||
//draw the menu bar
|
||||
menuBar.DrawTo(screen);
|
||||
|
||||
//draw some debugging info
|
||||
if (debugOpen) {
|
||||
SDL_FillRect(debugInfo.GetSurface(), 0, 0);
|
||||
DrawToDebugInfo(string("camera.x: ") + to_string_custom(camera.x), 0);
|
||||
DrawToDebugInfo(string("camera.y: ") + to_string_custom(camera.y), 1);
|
||||
debugInfo.DrawTo(screen, screen->w - debugInfo.GetClipW(), buttonImage.GetClipH());
|
||||
}
|
||||
}
|
||||
|
||||
void EditorScene::DrawToDebugInfo(std::string str, int line) {
|
||||
//draw the debug info on the right, with a grey background
|
||||
SDL_Rect clip = {
|
||||
Sint16(debugInfo.GetClipW() - str.size() * font.GetCharW()),
|
||||
Sint16(font.GetCharH() * line),
|
||||
Uint16(str.size() * font.GetCharW()),
|
||||
Uint16(font.GetCharH())
|
||||
};
|
||||
SDL_FillRect(debugInfo.GetSurface(), &clip, SDL_MapRGB(debugInfo.GetSurface()->format, 64, 64, 64));
|
||||
font.DrawStringTo(str, debugInfo.GetSurface(), clip.x, clip.y);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
menuBar.MouseMotion(motion);
|
||||
|
||||
if (motion.state & SDL_BUTTON_RMASK) {
|
||||
camera.x -= motion.xrel;
|
||||
camera.y -= motion.yrel;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
menuBar.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void EditorScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
int entry, drop;
|
||||
menuBar.MouseButtonUp(button, &entry, &drop);
|
||||
HandleMenuOption(entry, drop);
|
||||
}
|
||||
|
||||
void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
case SDLK_SPACE:
|
||||
camera.x = 0;
|
||||
camera.y = 0;
|
||||
break;
|
||||
case SDLK_TAB:
|
||||
debugOpen = !debugOpen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorScene::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Members
|
||||
//-------------------------
|
||||
|
||||
void EditorScene::HandleMenuOption(int entry, int drop) {
|
||||
//manage input from the menu bar
|
||||
switch(entry) {
|
||||
case 0: //File
|
||||
switch(drop) {
|
||||
case 0:
|
||||
//TODO: NEW
|
||||
break;
|
||||
case 1:
|
||||
//TODO: OPEN
|
||||
break;
|
||||
case 2:
|
||||
//TODO: SAVE
|
||||
break;
|
||||
case 3:
|
||||
//TODO: CLOSE
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: //Edit
|
||||
switch(drop) {
|
||||
case 0:
|
||||
//TODO: SET TILE
|
||||
break;
|
||||
case 1:
|
||||
//TODO: SET BRUSH
|
||||
break;
|
||||
case 2:
|
||||
//TODO: SCRIPT
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: //Debug
|
||||
switch(drop) {
|
||||
case 0:
|
||||
debugOpen = true;
|
||||
break;
|
||||
case 1:
|
||||
debugOpen = false;
|
||||
break;
|
||||
case 2:
|
||||
debugOpen = !debugOpen;
|
||||
break;
|
||||
case 3:
|
||||
SetNextScene(SceneList::TESTIFICATESCENE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#config
|
||||
INCLUDES+=../common ../common/graphics ../common/map ../common/ui
|
||||
LIBS+=../libcommon.a -lmingw32 -lSDLmain -lSDL -llua
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
OUT=$(addprefix $(OUTDIR)/,editor)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,91 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 "testificate_scene.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
TestificateScene::TestificateScene(ConfigUtility* const arg1):
|
||||
config(*arg1)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
TestificateScene::~TestificateScene() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void TestificateScene::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void TestificateScene::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestificateScene::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void TestificateScene::Render(SDL_Surface* const screen) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void TestificateScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
void TestificateScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestificateScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestificateScene::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
// QuitEvent();
|
||||
SetNextScene(SceneList::EDITORSCENE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TestificateScene::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
@@ -14,7 +14,6 @@ all: $(OUTDIR)
|
||||
$(MAKE) -C common
|
||||
$(MAKE) -C server
|
||||
$(MAKE) -C client
|
||||
$(MAKE) -C editor
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
+3
-2
@@ -23,7 +23,8 @@ map.pager.height = 20
|
||||
map.pager.depth = 3
|
||||
|
||||
#player options
|
||||
player.handle = username
|
||||
player.avatar = elliot2.bmp
|
||||
client.username = Kayne Ruse
|
||||
client.handle = Ratstail91
|
||||
client.avatar = elliot2.bmp
|
||||
|
||||
#debugging
|
||||
|
||||
@@ -1,29 +1,36 @@
|
||||
print("Lua script check OK (./rsc)")
|
||||
print("Lua script check (./rsc)")
|
||||
|
||||
function Region.Create(r)
|
||||
print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")")
|
||||
for i = 1, Region.GetWidth(r) do
|
||||
for j = 1, Region.GetHeight(r) do
|
||||
if math.abs(i) == math.abs(j) then
|
||||
Region.SetTile(r, i, j, 1, 50)
|
||||
-------------------------
|
||||
--Map API overrides
|
||||
-------------------------
|
||||
|
||||
function map.create(region)
|
||||
for i = 1, map.getregionwidth() do
|
||||
for j = 1, map.getregionheight() do
|
||||
if math.abs(map.getx(region) + i -1) == math.abs(map.gety(region) + j -1) then
|
||||
map.settile(region, i, j, 1, 50)
|
||||
else
|
||||
Region.SetTile(r, i, j, 1, 14)
|
||||
map.settile(region, i, j, 1, 14)
|
||||
end
|
||||
end
|
||||
end
|
||||
print("done")
|
||||
end
|
||||
|
||||
function Region.Unload(r)
|
||||
print("Region:Unload(r", Region.GetX(r), Region.GetY(r), ")")
|
||||
function map.unload(region)
|
||||
--
|
||||
end
|
||||
|
||||
--return true if file loaded, otherwise return false
|
||||
function Region.Load(r, saveDir)
|
||||
print("Region:Load(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||
function map.load(region, dir)
|
||||
--return true if file loaded, otherwise return false
|
||||
return false
|
||||
end
|
||||
|
||||
function Region.Save(r, saveDir)
|
||||
print("Region:Save(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||
function map.save(region, dir)
|
||||
--
|
||||
end
|
||||
|
||||
-------------------------
|
||||
--Enemy API
|
||||
-------------------------
|
||||
|
||||
--TODO
|
||||
@@ -1,73 +1,63 @@
|
||||
-------------------------
|
||||
--Server
|
||||
-------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS UserAccounts (
|
||||
userAccountID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username varchar(30) UNIQUE,
|
||||
password varchar(30),
|
||||
CREATE TABLE IF NOT EXISTS Accounts (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username varchar(100) UNIQUE,
|
||||
--TODO: server-client security
|
||||
-- password varchar(100),
|
||||
blacklisted BIT DEFAULT 0,
|
||||
whitelisted BIT DEFAULT 1
|
||||
whitelisted BIT DEFAULT 1,
|
||||
administrator BIT DEFAULT 0
|
||||
);
|
||||
|
||||
-------------------------
|
||||
--Items
|
||||
-------------------------
|
||||
CREATE TABLE IF NOT EXISTS Characters (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
CREATE TABLE IF NOT EXISTS GlobalItemList (
|
||||
globalItemListID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemName varchar(30) UNIQUE,
|
||||
itemImage varchar(30),
|
||||
type varchar(15), --{'mundane', 'consumable', 'equipment'}
|
||||
maxStackSize INTEGER, --{1-max; 0 for non-stackable}
|
||||
maxUniqueCopies INTEGER --{1-max; 0 for unlimited}
|
||||
);
|
||||
--metadata
|
||||
owner INTEGER REFERENCES Accounts(uid),
|
||||
handle varchar(100) UNIQUE,
|
||||
avatar varchar(100),
|
||||
birth timestamp NOT NULL DEFAULT (datetime()),
|
||||
|
||||
CREATE TABLE IF NOT EXISTS MundaneItems (
|
||||
mundaneItemID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||
--holds whatever
|
||||
);
|
||||
--position
|
||||
mapIndex INTEGER DEFAULT 0,
|
||||
positionX INTEGER DEFAULT 0,
|
||||
positionY INTEGER DEFAULT 0,
|
||||
|
||||
CREATE TABLE IF NOT EXISTS Consumables (
|
||||
consumableID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||
--holds all consumable items info (food, potions, etc.)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS Equipment (
|
||||
equipmentID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||
--hold all equipment info
|
||||
);
|
||||
|
||||
-------------------------
|
||||
--Players
|
||||
-------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS PlayerCharacters (
|
||||
playerCharacterID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name varchar(30) UNIQUE,
|
||||
|
||||
--stats
|
||||
currentLevel INTEGER DEFAULT 0,
|
||||
currentExperience INTEGER DEFAULT 0,
|
||||
maxHealth INTEGER DEFAULT 0,
|
||||
maxMana INTEGER DEFAULT 0,
|
||||
currentHealth INTEGER DEFAULT 0,
|
||||
currentMana INTEGER DEFAULT 0,
|
||||
attack INTEGER DEFAULT 0,
|
||||
defence INTEGER DEFAULT 0,
|
||||
--etc.
|
||||
--statistics
|
||||
level INTEGER DEFAULT 0,
|
||||
exp INTEGER DEFAULT 0,
|
||||
maxHP INTEGER DEFAULT 0,
|
||||
health INTEGER DEFAULT 0,
|
||||
maxMP INTEGER DEFAULT 0,
|
||||
mana INTEGER DEFAULT 0,
|
||||
attack INTEGER DEFAULT 0,
|
||||
defence INTEGER DEFAULT 0,
|
||||
intelligence INTEGER DEFAULT 0,
|
||||
resistance INTEGER DEFAULT 0,
|
||||
speed INTEGER DEFAULT 0,
|
||||
accuracy REAL DEFAULT 0.0,
|
||||
evasion REAL DEFAULT 0.0,
|
||||
luck REAL DEFAULT 0.0,
|
||||
|
||||
--equipment
|
||||
weapon INTEGER REFERENCES Equipment(equipmentID),
|
||||
helmet INTEGER REFERENCES Equipment(equipmentID),
|
||||
armour INTEGER REFERENCES Equipment(equipmentID)
|
||||
weapon INTEGER REFERENCES WornEquipment(uid),
|
||||
helmet INTEGER REFERENCES WornEquipment(uid),
|
||||
armour INTEGER REFERENCES WornEquipment(uid)
|
||||
--etc.
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS PlayerInventoryItems (
|
||||
characterID INTEGER REFERENCES PlayerCharacters(characterID),
|
||||
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||
CREATE TABLE IF NOT EXISTS InventoryItems (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemID INTEGER, --type
|
||||
stackSize INTEGER DEFAULT 0,
|
||||
owner INTEGER REFERENCES Characters(uid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS WornEquipment (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemID INTEGER, --type
|
||||
owner INTEGER REFERENCES Characters(uid)
|
||||
--hold all equipment info
|
||||
--stat mods, special effects, etc.
|
||||
);
|
||||
@@ -0,0 +1,191 @@
|
||||
/* 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 "sqlite3/sqlite3.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES (?);";
|
||||
static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;";
|
||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3 WHERE uid = ?1;";
|
||||
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
|
||||
|
||||
//-------------------------
|
||||
//Define the methods
|
||||
//-------------------------
|
||||
|
||||
int ServerApplication::CreateUserAccount(std::string username, int clientIndex) {
|
||||
//create this user account, failing if it exists, leave this account in memory
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, CREATE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than this account exists
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//load this account into memory
|
||||
return LoadUserAccount(username, clientIndex);
|
||||
}
|
||||
|
||||
int ServerApplication::LoadUserAccount(std::string username, int clientIndex) {
|
||||
//load this user account, failing if it is in memory, creating it if it doesn't exist
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, LOAD_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
int ret = sqlite3_step(statement);
|
||||
|
||||
//process the result
|
||||
if (ret == SQLITE_ROW) {
|
||||
//get the index
|
||||
int uid = sqlite3_column_int(statement, 0);
|
||||
|
||||
//check to see if this account is already loaded
|
||||
if (accountMap.find(uid) != accountMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
AccountData& newAccount = accountMap[uid];
|
||||
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
|
||||
newAccount.blackListed = sqlite3_column_int(statement, 2);
|
||||
newAccount.whiteListed = sqlite3_column_int(statement, 3);
|
||||
newAccount.clientIndex = clientIndex;
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return uid;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
if (ret == SQLITE_DONE) {
|
||||
//create the non-existant account instead
|
||||
return CreateUserAccount(username, clientIndex);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int ServerApplication::SaveUserAccount(int uid) {
|
||||
//save this user account from memory, replacing it if it exists in the database
|
||||
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
|
||||
|
||||
//this method fails if this account is not loaded
|
||||
if (accountMap.find(uid) == accountMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AccountData& account = accountMap[uid];
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, SAVE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 2, account.blackListed) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, account.whiteListed) != SQLITE_OK;
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//successful execution
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerApplication::UnloadUserAccount(int uid) {
|
||||
//save this user account, and then unload it
|
||||
//NOTE: the associated characters are unloaded externally
|
||||
SaveUserAccount(uid);
|
||||
accountMap.erase(uid);
|
||||
}
|
||||
|
||||
void ServerApplication::DeleteUserAccount(int uid) {
|
||||
//delete a user account from the database, and remove it from memory
|
||||
//NOTE: the associated characters are unloaded externally
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, DELETE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
accountMap.erase(uid);
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/* 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 "sqlite3/sqlite3.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
//TODO: save and load the statistics
|
||||
static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, avatar) VALUES (?, ?, ?);";
|
||||
static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;";
|
||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET mapIndex = ?2, positionX = ?3, positionY = ?4 WHERE uid = ?1;";
|
||||
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
|
||||
|
||||
//-------------------------
|
||||
//Define the methods
|
||||
//-------------------------
|
||||
|
||||
//TODO: default stats as a parameter
|
||||
int ServerApplication::CreateCharacter(int owner, std::string handle, std::string avatar) {
|
||||
//Create the character, failing if it exists
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, CREATE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, owner);
|
||||
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
|
||||
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than this character exists
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//load this character into memory
|
||||
return LoadCharacter(owner, handle, avatar);
|
||||
}
|
||||
|
||||
int ServerApplication::LoadCharacter(int owner, std::string handle, std::string avatar) {
|
||||
//load the specified character, creating it if it doesn't exist
|
||||
//fail if it is already loaded, or does not belong to this account
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, LOAD_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, handle.c_str(), handle.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
int ret = sqlite3_step(statement);
|
||||
|
||||
//process the result
|
||||
if (ret == SQLITE_ROW) {
|
||||
//get the index
|
||||
int uid = sqlite3_column_int(statement, 0);
|
||||
|
||||
//check to see if this character is already loaded
|
||||
if (characterMap.find(uid) != characterMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check the owner
|
||||
if (owner != sqlite3_column_int(statement, 1)) {
|
||||
sqlite3_finalize(statement);
|
||||
return -2;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
CharacterData& newChar = characterMap[uid];
|
||||
|
||||
//metadata
|
||||
newChar.owner = owner;
|
||||
newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2));
|
||||
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
|
||||
//Don't cache the birth
|
||||
|
||||
//world position
|
||||
newChar.mapIndex = sqlite3_column_int(statement, 5);
|
||||
newChar.position.x = (double)sqlite3_column_int(statement, 6);
|
||||
newChar.position.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);
|
||||
|
||||
//TODO: equipment
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return uid;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
if (ret == SQLITE_DONE) {
|
||||
//create the non-existant character instead
|
||||
return CreateCharacter(owner, handle, avatar);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int ServerApplication::SaveCharacter(int uid) {
|
||||
//save this character from memory, replacing it if it exists in the database
|
||||
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
|
||||
|
||||
//this method fails if this character is not loaded
|
||||
if (characterMap.find(uid) == characterMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CharacterData& character = characterMap[uid];
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, SAVE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 2, character.mapIndex) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, (int)character.position.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 4, (int)character.position.y) != SQLITE_OK;
|
||||
//TODO: stats, etc.
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//successful execution
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerApplication::UnloadCharacter(int uid) {
|
||||
//save this character, then unload it
|
||||
SaveCharacter(uid);
|
||||
characterMap.erase(uid);
|
||||
}
|
||||
|
||||
void ServerApplication::DeleteCharacter(int uid) {
|
||||
//delete this character from the database, then remove it from memory
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, DELETE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
characterMap.erase(uid);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,24 +19,16 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "editor_application.hpp"
|
||||
#include "enemy_factory_generic.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
EnemyFactoryGeneric::EnemyFactoryGeneric() : EnemyFactoryInterface() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
EnemyFactoryGeneric::~EnemyFactoryGeneric() noexcept {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
cout << "Beginning editor" << endl;
|
||||
try {
|
||||
EditorApplication::GetInstance()->Init();
|
||||
EditorApplication::GetInstance()->Proc();
|
||||
EditorApplication::GetInstance()->Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
cout << "Clean exit" << endl;
|
||||
return 0;
|
||||
void EnemyFactoryGeneric::Generate(std::list<EnemyData>* container) {
|
||||
//TODO: fill this out
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,35 +19,24 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef EDITORAPPLICATION_HPP_
|
||||
#define EDITORAPPLICATION_HPP_
|
||||
#ifndef ENEMYFACTORYGENERIC_HPP_
|
||||
#define ENEMYFACTORYGENERIC_HPP_
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
#include "config_utility.hpp"
|
||||
#include "enemy_factory_interface.hpp"
|
||||
|
||||
class EditorApplication {
|
||||
private:
|
||||
EditorApplication();
|
||||
~EditorApplication();
|
||||
static EditorApplication instance;
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include <list>
|
||||
|
||||
//DOCS: Not really intended for use, but rather for copying and tweaking
|
||||
class EnemyFactoryGeneric : public EnemyFactoryInterface {
|
||||
public:
|
||||
static EditorApplication* GetInstance() { return &instance; }
|
||||
|
||||
void Init();
|
||||
void Proc();
|
||||
void Quit();
|
||||
EnemyFactoryGeneric();
|
||||
~EnemyFactoryGeneric() noexcept override;
|
||||
|
||||
void Generate(std::list<EnemyData>* container) override;
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
|
||||
//globals
|
||||
ConfigUtility config;
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
//TODO: hold the parameters specified by the room
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -19,35 +19,38 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef TESTIFICATESCENE_HPP_
|
||||
#define TESTIFICATESCENE_HPP_
|
||||
#ifndef ENEMYFACTORYINTERFACE_HPP_
|
||||
#define ENEMYFACTORYINTERFACE_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include <list>
|
||||
|
||||
class TestificateScene : public BaseScene {
|
||||
//TODO: move this elsewhere
|
||||
enum RoomType {
|
||||
OVERWORLD,
|
||||
RUINS,
|
||||
TOWERS,
|
||||
FORESTS,
|
||||
CAVES,
|
||||
};
|
||||
|
||||
//NOTE: Based on biome, world difficulty, etc.
|
||||
class EnemyFactoryInterface {
|
||||
public:
|
||||
//Public access members
|
||||
TestificateScene(ConfigUtility* const);
|
||||
~TestificateScene();
|
||||
EnemyFactoryInterface() = default;
|
||||
virtual ~EnemyFactoryInterface() = default;
|
||||
|
||||
virtual void Generate(std::list<EnemyData>* container) = 0;
|
||||
|
||||
//control the difficulty of the room
|
||||
RoomType SetType(RoomType t) { return type = t; }
|
||||
int SetDifficulty(int d) { return difficulty = d; }
|
||||
RoomType GetType() { return type; }
|
||||
int GetDifficulty() { return difficulty; }
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
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&);
|
||||
|
||||
//globals
|
||||
ConfigUtility& config;
|
||||
RoomType type;
|
||||
int difficulty;
|
||||
};
|
||||
|
||||
#endif
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -33,7 +33,7 @@ int main(int argc, char** argv) {
|
||||
try {
|
||||
ServerApplication app;
|
||||
app.Init(argc, argv);
|
||||
app.Loop();
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
|
||||
+2
-8
@@ -1,17 +1,14 @@
|
||||
#config
|
||||
INCLUDES+=. ../common ../common/map ../common/script ../common/network
|
||||
INCLUDES+=. ../common/gameplay ../common/map ../common/network ../common/script ../common/utilities
|
||||
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
CSRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
@@ -34,9 +31,6 @@ $(OUTDIR):
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
|
||||
@@ -1,361 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
*
|
||||
* 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 "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int runSQLScript(sqlite3* db, std::string fname) {
|
||||
ifstream is(fname);
|
||||
if (!is.is_open()) {
|
||||
return -1;
|
||||
}
|
||||
string script;
|
||||
getline(is, script, '\0');
|
||||
is.close();
|
||||
//TODO: flesh out this error if needed
|
||||
if (sqlite3_exec(db, script.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK) {
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the public members
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::Init(int argc, char** argv) {
|
||||
cout << "Beginning startup" << endl;
|
||||
int ret = 0;
|
||||
|
||||
//load config
|
||||
config.Load("rsc\\config.cfg");
|
||||
|
||||
//Init SDL
|
||||
if (SDL_Init(0)) {
|
||||
throw(runtime_error("Failed to initialize SDL"));
|
||||
}
|
||||
cout << "Initialized SDL" << endl;
|
||||
|
||||
//Init SDL_net
|
||||
if (SDLNet_Init()) {
|
||||
throw(runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE);
|
||||
cout << "Initialized SDL_net" << endl;
|
||||
|
||||
//Init SQL
|
||||
ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
|
||||
if (ret != SQLITE_OK || !database) {
|
||||
throw(runtime_error(string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
cout << "Initialized SQL" << endl;
|
||||
|
||||
//setup the database
|
||||
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
|
||||
throw(runtime_error("Failed to initialize SQL's setup script"));
|
||||
}
|
||||
cout << "Initialized SQL's setup script" << endl;
|
||||
|
||||
//lua
|
||||
luaState = luaL_newstate();
|
||||
if (!luaState) {
|
||||
throw(runtime_error("Failed to initialize lua"));
|
||||
}
|
||||
luaL_openlibs(luaState);
|
||||
cout << "Initialized lua" << endl;
|
||||
|
||||
//run the startup script
|
||||
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
|
||||
throw(runtime_error(string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
|
||||
}
|
||||
cout << "Initialized lua's setup script" << endl;
|
||||
|
||||
//setup the map object
|
||||
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||
mapPager.GetGenerator()->SetLuaState(luaState);
|
||||
mapPager.GetFormat()->SetLuaState(luaState);
|
||||
mapPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||
//TODO: pass args to the generator & format as needed
|
||||
//NOTE: I might need to rearrange the init process so that lua & SQL can interact
|
||||
// with the map system as needed.
|
||||
cout << "Initialized the map system" << endl;
|
||||
cout << "\tsizeof(NetworkPacket): " << sizeof(NetworkPacket) << endl;
|
||||
cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << endl;
|
||||
|
||||
//finalize the startup
|
||||
cout << "Startup completed successfully" << endl;
|
||||
|
||||
//debugging
|
||||
//
|
||||
}
|
||||
|
||||
void ServerApplication::Loop() {
|
||||
NetworkPacket packet;
|
||||
while(running) {
|
||||
//suck in the waiting packets & process them
|
||||
while(network.Receive()) {
|
||||
//get the packet
|
||||
deserialize(&packet, network.GetInData());
|
||||
//cache the source address
|
||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||
//we need to go deeper
|
||||
HandlePacket(packet);
|
||||
}
|
||||
//give the computer a break
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::Quit() {
|
||||
cout << "Shutting down" << endl;
|
||||
//empty the members
|
||||
mapPager.UnloadAll();
|
||||
//TODO: player manager
|
||||
//TODO: client manager
|
||||
|
||||
//APIs
|
||||
lua_close(luaState);
|
||||
sqlite3_close_v2(database);
|
||||
network.Close();
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
cout << "Shutdown finished" << endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the uber switch
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandlePacket(NetworkPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||
HandleBroadcastRequest(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::JOIN_REQUEST:
|
||||
HandleJoinRequest(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::SYNCHRONIZE:
|
||||
HandleSynchronize(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::SHUTDOWN:
|
||||
HandleShutdown(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_NEW:
|
||||
HandlePlayerNew(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_DELETE:
|
||||
HandlePlayerDelete(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||
HandlePlayerUpdate(packet);
|
||||
break;
|
||||
case NetworkPacket::Type::REGION_REQUEST:
|
||||
HandleRegionRequest(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Handle various network input
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
|
||||
//send back the server's metadata
|
||||
packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE;
|
||||
//TODO: version info
|
||||
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
||||
//TODO: player count
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
serialize(&packet, buffer);
|
||||
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
||||
//register the new client
|
||||
ClientEntry c;
|
||||
c.address = packet.meta.srcAddress;
|
||||
clientMap[clientCounter] = c;
|
||||
|
||||
//send the client their info
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
||||
packet.clientInfo.index = clientCounter;
|
||||
serialize(&packet, buffer);
|
||||
|
||||
network.Send(&clientMap[clientCounter].address, buffer, PACKET_BUFFER_SIZE);
|
||||
|
||||
//finished this routine
|
||||
clientCounter++;
|
||||
cout << "Connect, total: " << clientMap.size() << endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
||||
//disconnect the specified client
|
||||
//TODO: authenticate who is disconnecting/kicking
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
serialize(&packet, buffer);
|
||||
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||
clientMap.erase(packet.clientInfo.index);
|
||||
|
||||
//delete players from all clients
|
||||
NetworkPacket delPacket;
|
||||
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||
|
||||
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
|
||||
//find the internal players to delete
|
||||
if (it.second.clientIndex == packet.clientInfo.index) {
|
||||
delPacket.playerInfo.playerIndex = it.first;
|
||||
//send the delete player command to all clients
|
||||
PumpPacket(delPacket);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
//finished this routine
|
||||
cout << "Disconnect, total: " << clientMap.size() << endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
||||
//send all the server's data to this client
|
||||
//TODO: compensate for large distances
|
||||
NetworkPacket newPacket;
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
|
||||
//players
|
||||
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||
for (auto& it : playerMap) {
|
||||
newPacket.playerInfo.playerIndex = it.first;
|
||||
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
||||
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
||||
newPacket.playerInfo.position = it.second.position;
|
||||
newPacket.playerInfo.motion = it.second.motion;
|
||||
serialize(&newPacket, buffer);
|
||||
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::HandleShutdown(NetworkPacket packet) {
|
||||
//end the server
|
||||
running = false;
|
||||
|
||||
//disconnect all clients
|
||||
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||
PumpPacket(packet);
|
||||
|
||||
//finished this routine
|
||||
cout << "Shutdown signal accepted" << endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
||||
//create the new player object
|
||||
PlayerEntry newPlayer;
|
||||
newPlayer.clientIndex = packet.playerInfo.clientIndex;
|
||||
newPlayer.mapIndex = 0;
|
||||
newPlayer.handle = packet.playerInfo.handle;
|
||||
newPlayer.avatar = packet.playerInfo.avatar;
|
||||
newPlayer.position = {0,0};
|
||||
newPlayer.motion = {0,0};
|
||||
|
||||
//push this player
|
||||
playerMap[playerCounter] = newPlayer;
|
||||
|
||||
//send the client their info
|
||||
packet.playerInfo.playerIndex = playerCounter;
|
||||
packet.playerInfo.position = playerMap[playerCounter].position;
|
||||
packet.playerInfo.motion = playerMap[playerCounter].motion;
|
||||
|
||||
//actually send to everyone
|
||||
PumpPacket(packet);
|
||||
|
||||
//finish this routine
|
||||
playerCounter++;
|
||||
}
|
||||
|
||||
void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
||||
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
||||
throw(std::runtime_error("Cannot delete a non-existant player"));
|
||||
}
|
||||
|
||||
//delete players
|
||||
erase_if(playerMap, [&](pair<int, PlayerEntry> it) -> bool {
|
||||
if (it.first == packet.playerInfo.playerIndex) {
|
||||
NetworkPacket delPacket;
|
||||
|
||||
//data to delete one specific player
|
||||
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||
delPacket.playerInfo.playerIndex = it.first;
|
||||
|
||||
//send to all
|
||||
PumpPacket(delPacket);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
||||
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
||||
throw(std::runtime_error("Cannot update a non-existant player"));
|
||||
}
|
||||
|
||||
//server is the slave to the clients, but only for now
|
||||
playerMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position;
|
||||
playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
|
||||
|
||||
PumpPacket(packet);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
packet.meta.type = NetworkPacket::Type::REGION_CONTENT;
|
||||
packet.regionInfo.region = mapPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
serialize(&packet, buffer);
|
||||
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void ServerApplication::PumpPacket(NetworkPacket packet) {
|
||||
//I don't really like this, but it'll do for now
|
||||
char buffer[PACKET_BUFFER_SIZE];
|
||||
serialize(&packet, buffer);
|
||||
for (auto& it : clientMap) {
|
||||
network.Send(&it.second.address, buffer, PACKET_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013
|
||||
/* 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
|
||||
@@ -22,15 +22,20 @@
|
||||
#ifndef SERVERAPPLICATION_HPP_
|
||||
#define SERVERAPPLICATION_HPP_
|
||||
|
||||
//server specific stuff
|
||||
#include "client_data.hpp"
|
||||
#include "account_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_factory_generic.hpp"
|
||||
|
||||
//maps
|
||||
#include "map_generator.hpp"
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//networking
|
||||
#include "network_packet.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
//common
|
||||
#include "config_utility.hpp"
|
||||
@@ -45,20 +50,8 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
struct ClientEntry {
|
||||
IPaddress address;
|
||||
};
|
||||
|
||||
struct PlayerEntry {
|
||||
int clientIndex;
|
||||
int mapIndex;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
};
|
||||
|
||||
//The main application class
|
||||
//TODO: modulate this god class
|
||||
class ServerApplication {
|
||||
public:
|
||||
//standard functions
|
||||
@@ -66,46 +59,65 @@ public:
|
||||
~ServerApplication() = default;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Loop();
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
void HandlePacket(NetworkPacket);
|
||||
void HandlePacket(SerialPacket);
|
||||
|
||||
//high cohesion utility functions
|
||||
void HandleBroadcastRequest(NetworkPacket);
|
||||
void HandleJoinRequest(NetworkPacket);
|
||||
void HandleDisconnect(NetworkPacket);
|
||||
void HandleSynchronize(NetworkPacket);
|
||||
void HandleShutdown(NetworkPacket);
|
||||
void HandlePlayerNew(NetworkPacket);
|
||||
void HandlePlayerDelete(NetworkPacket);
|
||||
void HandlePlayerUpdate(NetworkPacket);
|
||||
void HandleRegionRequest(NetworkPacket);
|
||||
//handle incoming traffic
|
||||
void HandleBroadcastRequest(SerialPacket);
|
||||
void HandleJoinRequest(SerialPacket);
|
||||
void HandleSynchronize(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
void HandleShutdown(SerialPacket);
|
||||
void HandleCharacterUpdate(SerialPacket);
|
||||
void HandleRegionRequest(SerialPacket);
|
||||
|
||||
void PumpPacket(NetworkPacket);
|
||||
//TODO: a function that only sends to characters in a certain proximity
|
||||
void PumpPacket(SerialPacket);
|
||||
void PumpCharacterUnload(int uid);
|
||||
|
||||
//Account management
|
||||
int CreateUserAccount(std::string username, int clientIndex);
|
||||
int LoadUserAccount(std::string username, int clientIndex);
|
||||
int SaveUserAccount(int uid);
|
||||
void UnloadUserAccount(int uid);
|
||||
void DeleteUserAccount(int uid);
|
||||
|
||||
//character management
|
||||
int CreateCharacter(int owner, std::string handle, std::string avatar);
|
||||
int LoadCharacter(int owner, std::string handle, std::string avatar);
|
||||
int SaveCharacter(int uid);
|
||||
void UnloadCharacter(int uid);
|
||||
void DeleteCharacter(int uid);
|
||||
|
||||
//TODO: combat management
|
||||
|
||||
//APIs
|
||||
UDPNetworkUtility network;
|
||||
sqlite3* database = nullptr;
|
||||
lua_State* luaState = nullptr;
|
||||
|
||||
//server tables
|
||||
std::map<int, ClientData> clientMap;
|
||||
std::map<int, AccountData> accountMap;
|
||||
std::map<int, CharacterData> characterMap;
|
||||
std::map<int, CombatData> combatMap;
|
||||
std::map<int, EnemyData> enemyMap;
|
||||
|
||||
//maps
|
||||
RegionPager<LuaGenerator, LuaFormat> mapPager;
|
||||
|
||||
//networking
|
||||
UDPNetworkUtility network;
|
||||
|
||||
//database
|
||||
sqlite3* database = nullptr;
|
||||
|
||||
//lua
|
||||
lua_State* luaState = nullptr;
|
||||
//TODO: I need to handle multiple map objects
|
||||
//TODO: Unload regions that are distant from any characters
|
||||
RegionPager<LuaAllocator, LuaFormat> regionPager;
|
||||
EnemyFactoryGeneric enemyFactory;
|
||||
|
||||
//misc
|
||||
bool running = true;
|
||||
ConfigUtility config;
|
||||
|
||||
std::map<int, ClientEntry> clientMap;
|
||||
std::map<int, PlayerEntry> playerMap;
|
||||
|
||||
int clientCounter = 0;
|
||||
int playerCounter = 0;
|
||||
int clientUID = 0;
|
||||
int combatUID = 0;
|
||||
int enemyUID = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/* 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 "server_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Handle various network input
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandleBroadcastRequest(SerialPacket packet) {
|
||||
//pack the server's data
|
||||
packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
|
||||
packet.serverInfo.networkVersion = NETWORK_VERSION;
|
||||
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
||||
packet.serverInfo.playerCount = characterMap.size();
|
||||
|
||||
//bounce this packet
|
||||
network.SendTo(&packet.meta.srcAddress, &packet);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleJoinRequest(SerialPacket packet) {
|
||||
//create the new client
|
||||
ClientData newClient;
|
||||
newClient.address = packet.meta.srcAddress;
|
||||
|
||||
//load the user account
|
||||
int accountIndex = LoadUserAccount(packet.clientInfo.username, clientUID);
|
||||
if (accountIndex < 0) {
|
||||
//TODO: send rejection packet
|
||||
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//load the new character
|
||||
int characterIndex = LoadCharacter(accountIndex, packet.clientInfo.handle, packet.clientInfo.avatar);
|
||||
if (characterIndex < 0) {
|
||||
//TODO: send rejection packet
|
||||
std::cerr << "Error: Character already loaded: " << characterIndex << std::endl;
|
||||
UnloadUserAccount(accountIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
//send the client their info
|
||||
packet.meta.type = SerialPacket::Type::JOIN_RESPONSE;
|
||||
packet.clientInfo.clientIndex = clientUID;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
//bounce this packet
|
||||
network.SendTo(&newClient.address, &packet);
|
||||
|
||||
//send the new character to all clients
|
||||
packet.meta.type = SerialPacket::Type::CHARACTER_NEW;
|
||||
packet.characterInfo.characterIndex = characterIndex;
|
||||
strncpy(packet.characterInfo.handle, characterMap[characterIndex].handle.c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.characterInfo.avatar, characterMap[characterIndex].avatar.c_str(), PACKET_STRING_SIZE);
|
||||
packet.characterInfo.position = characterMap[characterIndex].position;
|
||||
packet.characterInfo.motion = characterMap[characterIndex].motion;
|
||||
PumpPacket(packet);
|
||||
|
||||
//TODO: don't send anything to a certain client until they send the OK (the sync packet? or ignore client side?)
|
||||
//finished this routine
|
||||
clientMap[clientUID++] = newClient;
|
||||
std::cout << "Connect, total: " << clientMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleSynchronize(SerialPacket packet) {
|
||||
//TODO: compensate for large distances
|
||||
|
||||
//send all the server's data to this client
|
||||
SerialPacket newPacket;
|
||||
|
||||
//characters
|
||||
newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE;
|
||||
for (auto& it : characterMap) {
|
||||
//TODO: update this for the expanded CharacterData structure
|
||||
newPacket.characterInfo.characterIndex = it.first;
|
||||
snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
||||
snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
||||
newPacket.characterInfo.mapIndex = it.second.mapIndex;
|
||||
newPacket.characterInfo.position = it.second.position;
|
||||
newPacket.characterInfo.motion = it.second.motion;
|
||||
newPacket.characterInfo.stats = it.second.stats;
|
||||
|
||||
network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::HandleDisconnect(SerialPacket packet) {
|
||||
//TODO: authenticate who is disconnecting/kicking
|
||||
|
||||
//forward to the specified client
|
||||
network.SendTo(&clientMap[accountMap[packet.clientInfo.accountIndex].clientIndex].address, &packet);
|
||||
|
||||
//unload client and server-side characters
|
||||
for (std::map<int, CharacterData>::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) {
|
||||
if (it->second.owner == packet.clientInfo.accountIndex) {
|
||||
PumpCharacterUnload(it->first);
|
||||
SaveCharacter(it->first);
|
||||
it = characterMap.erase(it); //efficient
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//erase the in-memory stuff
|
||||
clientMap.erase(accountMap[packet.clientInfo.accountIndex].clientIndex);
|
||||
UnloadUserAccount(packet.clientInfo.accountIndex);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "Disconnect, total: " << clientMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleShutdown(SerialPacket packet) {
|
||||
//TODO: authenticate who is shutting the server down
|
||||
|
||||
//end the server
|
||||
running = false;
|
||||
|
||||
//disconnect all clients
|
||||
packet.meta.type = SerialPacket::Type::DISCONNECT;
|
||||
PumpPacket(packet);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "Shutdown signal accepted" << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleCharacterUpdate(SerialPacket packet) {
|
||||
//TODO: this should be moved elsewhere
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) {
|
||||
throw(std::runtime_error("Cannot update a non-existant character"));
|
||||
}
|
||||
|
||||
//TODO: the server needs it's own movement system too
|
||||
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
|
||||
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
|
||||
|
||||
PumpPacket(packet);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleRegionRequest(SerialPacket packet) {
|
||||
//TODO: this should be moved elsewhere
|
||||
packet.meta.type = SerialPacket::Type::REGION_CONTENT;
|
||||
packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
|
||||
//send the content
|
||||
network.SendTo(&packet.meta.srcAddress, &packet);
|
||||
}
|
||||
|
||||
void ServerApplication::PumpPacket(SerialPacket packet) {
|
||||
//NOTE: I don't really like this, but it'll do for now
|
||||
for (auto& it : clientMap) {
|
||||
network.SendTo(&it.second.address, &packet);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::PumpCharacterUnload(int uid) {
|
||||
//delete the client-side character(s)
|
||||
SerialPacket delPacket;
|
||||
delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE;
|
||||
delPacket.characterInfo.characterIndex = uid;
|
||||
PumpPacket(delPacket);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/* 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 "sql_utility.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//-------------------------
|
||||
//Define the public members
|
||||
//-------------------------
|
||||
|
||||
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 startup" << std::endl;
|
||||
|
||||
//initial setup
|
||||
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
|
||||
//-------------------------
|
||||
|
||||
//setup the map object
|
||||
regionPager.GetAllocator()->SetLuaState(luaState);
|
||||
regionPager.GetFormat()->SetLuaState(luaState);
|
||||
//TODO: config parameter
|
||||
regionPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||
std::cout << "Prepared the map system" << std::endl;
|
||||
|
||||
//push the pager onto the lua registry
|
||||
lua_pushstring(luaState, "pager");
|
||||
lua_pushlightuserdata(luaState, reinterpret_cast<void*>(®ionPager));
|
||||
lua_settable(luaState, LUA_REGISTRYINDEX);
|
||||
std::cout << "Registered the map system in 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
|
||||
std::cout << "Internal sizes:" << std::endl;
|
||||
std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl;
|
||||
std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl;
|
||||
|
||||
//finalize the startup
|
||||
std::cout << "Startup completed successfully" << std::endl;
|
||||
|
||||
//debugging
|
||||
//
|
||||
}
|
||||
|
||||
void ServerApplication::Proc() {
|
||||
SerialPacket packet;
|
||||
while(running) {
|
||||
//suck in the waiting packets & process them
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
//update the internals
|
||||
//TODO: update the internals i.e. player positions
|
||||
//give the computer a break
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::Quit() {
|
||||
std::cout << "Shutting down" << std::endl;
|
||||
|
||||
//save the server state
|
||||
for (auto& it : accountMap) {
|
||||
SaveUserAccount(it.first);
|
||||
}
|
||||
for (auto& it : characterMap) {
|
||||
SaveCharacter(it.first);
|
||||
}
|
||||
|
||||
//empty the members
|
||||
accountMap.clear();
|
||||
characterMap.clear();
|
||||
regionPager.UnloadAll();
|
||||
|
||||
//APIs
|
||||
lua_close(luaState);
|
||||
sqlite3_close_v2(database);
|
||||
network.Close();
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
std::cout << "Shutdown finished" << std::endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the uber switch
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
HandleBroadcastRequest(packet);
|
||||
break;
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
HandleJoinRequest(packet);
|
||||
break;
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
HandleSynchronize(packet);
|
||||
break;
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
HandleShutdown(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
HandleCharacterUpdate(packet);
|
||||
break;
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
HandleRegionRequest(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error("Unknown SerialPacket::Type encountered"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user