Merge branch 'develop'

This commit is contained in:
Kayne Ruse
2014-06-02 22:42:36 +10:00
30 changed files with 689 additions and 202 deletions
+9 -1
View File
@@ -37,6 +37,7 @@
#include "lobby_menu.hpp"
#include "in_world.hpp"
#include "in_combat.hpp"
#include "restart.hpp"
//-------------------------
//Public access members
@@ -50,7 +51,11 @@ void ClientApplication::Init(int argc, char** argv) {
if (SDL_Init(SDL_INIT_VIDEO)) {
throw(std::runtime_error("Failed to initialize SDL"));
}
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
int w = config.Int("client.screen.w");
int h = config.Int("client.screen.h");
int f = config.Bool("client.screen.f") ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF;
BaseScene::SetScreen(w ? w : 800, h ? h : 600, 0, f);
//initialize SDL_net
if (SDLNet_Init()) {
@@ -127,6 +132,9 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
case SceneList::INCOMBAT:
activeScene = new InCombat(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap, &enemyMap);
break;
case SceneList::RESTART:
activeScene = new Restart(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap, &enemyMap);
break;
default:
throw(std::logic_error("Failed to recognize the scene index"));
}
+108 -5
View File
@@ -21,6 +21,11 @@
*/
#include "in_combat.hpp"
#include "channels.hpp"
#include "utility.hpp"
#include <stdexcept>
//-------------------------
//Public access members
//-------------------------
@@ -44,6 +49,26 @@ InCombat::InCombat(
characterMap(*argCharacterMap),
enemyMap(*argEnemyMap)
{
/* //setup the utility objects
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
buttonImage.SetClipH(buttonImage.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
backButton.SetImage(&buttonImage);
backButton.SetFont(&font);
//set the button positions
backButton.SetX(50);
backButton.SetY(50 + buttonImage.GetClipH() * 0);
//set the button texts
backButton.SetText("Back");
//request a sync
RequestSynchronize();
*/
//debug
//
}
@@ -60,7 +85,14 @@ void InCombat::FrameStart() {
}
void InCombat::Update(double delta) {
//
SerialPacket packet;
//suck in all waiting packets
while(network.Receive(&packet)) {
HandlePacket(packet);
}
//TODO: more
}
void InCombat::FrameEnd() {
@@ -75,7 +107,13 @@ void InCombat::RenderFrame() {
}
void InCombat::Render(SDL_Surface* const screen) {
//
//TODO: draw the background
//TODO: draw the characters
//TODO: draw the enemies
//TODO: draw the UI
}
//-------------------------
@@ -84,7 +122,7 @@ void InCombat::Render(SDL_Surface* const screen) {
void InCombat::QuitEvent() {
//exit the game AND the server
// RequestDisconnect();
RequestDisconnect();
SetNextScene(SceneList::MAINMENU);
}
@@ -116,10 +154,75 @@ void InCombat::KeyUp(SDL_KeyboardEvent const& key) {
//Network handlers
//-------------------------
//TODO: network handlers
void InCombat::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) {
case SerialPacket::Type::DISCONNECT:
HandleDisconnect(packet);
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in InCombat: " + to_string_custom(int(packet.meta.type))));
break;
}
}
void InCombat::HandleDisconnect(SerialPacket) {
SetNextScene(SceneList::RESTART);
}
//TODO: more network handlers
//-------------------------
//Server control
//-------------------------
//TODO: server control
void InCombat::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 InCombat::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;
//TODO: stats
network.SendTo(Channels::SERVER, &packet);
}
void InCombat::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 InCombat::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);
}
+2 -1
View File
@@ -75,9 +75,10 @@ protected:
//Network handlers
void HandlePacket(SerialPacket);
void HandleDisconnect(SerialPacket);
//TODO: more
//TODO: more network handlers
//Server control
void RequestSynchronize();
void SendPlayerUpdate();
void RequestDisconnect();
void RequestShutdown();
+8 -12
View File
@@ -77,7 +77,7 @@ InWorld::InWorld(
RequestSynchronize();
//debug
// RequestRegion(0, 0);
//
}
InWorld::~InWorld() {
@@ -107,8 +107,8 @@ void InWorld::Update(double delta) {
//update the camera
if(localCharacter) {
camera.x = localCharacter->position.x - camera.marginX;
camera.y = localCharacter->position.y - camera.marginY;
camera.x = localCharacter->origin.x - camera.marginX;
camera.y = localCharacter->origin.y - camera.marginY;
}
//check the map
@@ -134,7 +134,7 @@ void InWorld::Render(SDL_Surface* const screen) {
//draw characters
for (auto& it : characterMap) {
//TODO: drawing order according to Y position
//TODO: drawing order according to Y origin
it.second.DrawTo(screen, camera.x, camera.y);
}
@@ -273,11 +273,7 @@ void InWorld::HandlePacket(SerialPacket packet) {
}
void InWorld::HandleDisconnect(SerialPacket packet) {
network.Unbind(Channels::SERVER);
clientIndex = -1;
accountIndex = -1;
characterIndex = -1;
SetNextScene(SceneList::MAINMENU);
SetNextScene(SceneList::RESTART);
}
void InWorld::HandleRegionContent(SerialPacket packet) {
@@ -295,7 +291,7 @@ void InWorld::HandleCharacterUpdate(SerialPacket packet) {
//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].origin = packet.characterInfo.origin;
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
}
characterMap[packet.characterInfo.characterIndex].CorrectSprite();
@@ -314,7 +310,7 @@ void InWorld::HandleCharacterNew(SerialPacket packet) {
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.origin = packet.characterInfo.origin;
character.motion = packet.characterInfo.motion;
character.stats = packet.characterInfo.stats;
@@ -370,7 +366,7 @@ void InWorld::SendPlayerUpdate() {
packet.characterInfo.clientIndex = clientIndex;
packet.characterInfo.accountIndex = accountIndex;
packet.characterInfo.characterIndex = characterIndex;
packet.characterInfo.position = localCharacter->position;
packet.characterInfo.origin = localCharacter->origin;
packet.characterInfo.motion = localCharacter->motion;
network.SendTo(Channels::SERVER, &packet);
+1
View File
@@ -29,6 +29,7 @@
#include "raster_font.hpp"
#include "button.hpp"
//TODO: The options screen needs to be USED
class OptionsMenu : public BaseScene {
public:
//Public access members
+142
View File
@@ -0,0 +1,142 @@
/* 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 "restart.hpp"
#include "channels.hpp"
#include <stdexcept>
//-------------------------
//Public access members
//-------------------------
Restart::Restart(
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)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
backButton.SetImage(&image);
backButton.SetFont(&font);
//set the button positions
backButton.SetX(50);
backButton.SetY(50 + image.GetClipH() * 0);
//set the button texts
backButton.SetText("Back");
//full reset
network.Unbind(Channels::SERVER);
clientIndex = -1;
accountIndex = -1;
characterIndex = -1;
combatMap.clear();
characterMap.clear();
enemyMap.clear();
//auto return
startTick = std::chrono::steady_clock::now();
}
Restart::~Restart() {
//
}
//-------------------------
//Frame loop
//-------------------------
void Restart::Update(double delta) {
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(10)) {
QuitEvent();
}
while(network.Receive()) {
//EAT INCOMING PACKETS
}
}
void Restart::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void Restart::Render(SDL_Surface* const screen) {
backButton.DrawTo(screen);
font.DrawStringTo("You have been disconnected.", screen, 50, 30);
}
//-------------------------
//Event handlers
//-------------------------
void Restart::QuitEvent() {
SetNextScene(SceneList::MAINMENU);
}
void Restart::MouseMotion(SDL_MouseMotionEvent const& motion) {
backButton.MouseMotion(motion);
}
void Restart::MouseButtonDown(SDL_MouseButtonEvent const& button) {
backButton.MouseButtonDown(button);
}
void Restart::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
QuitEvent();
}
}
void Restart::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
QuitEvent();
break;
}
}
void Restart::KeyUp(SDL_KeyboardEvent const& key) {
//
}
+98
View File
@@ -0,0 +1,98 @@
/* 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 RESTART_HPP_
#define RESTART_HPP_
//network
#include "udp_network_utility.hpp"
//graphics
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
//common
#include "config_utility.hpp"
#include "frame_rate.hpp"
#include "combat_data.hpp"
#include "character_data.hpp"
#include "enemy_data.hpp"
//client
#include "base_scene.hpp"
//std namespace
#include <chrono>
class Restart : public BaseScene {
public:
//Public access members
Restart(
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
);
~Restart();
protected:
//Frame loop
void Update(double delta);
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&);
//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;
//graphics
Image image;
RasterFont font;
//UI
Button backButton;
FrameRate fps;
//auto return
std::chrono::steady_clock::time_point startTick;
};
#endif
+1
View File
@@ -35,6 +35,7 @@ enum class SceneList {
LOBBYMENU,
INWORLD,
INCOMBAT,
RESTART,
};
#endif
+2
View File
@@ -29,6 +29,8 @@ struct AccountData {
//TODO: password
bool blackListed = false;
bool whiteListed = true;
bool mod = false;
bool admin = false;
int clientIndex;
};
+3 -3
View File
@@ -23,10 +23,10 @@
void CharacterData::Update(double delta) {
if (motion.x && motion.y) {
position += motion * delta * CHARACTER_WALKING_MOD;
origin += motion * delta * CHARACTER_WALKING_MOD;
}
else if (motion != 0) {
position += motion * delta;
origin += motion * delta;
}
#ifdef GRAPHICS
sprite.Update(delta);
@@ -36,7 +36,7 @@ void CharacterData::Update(double delta) {
#ifdef GRAPHICS
void CharacterData::DrawTo(SDL_Surface* const dest, int camX, int camY) {
sprite.DrawTo(dest, position.x - camX, position.y - camY);
sprite.DrawTo(dest, origin.x - camX, origin.y - camY);
}
void CharacterData::CorrectSprite() {
+2 -4
View File
@@ -22,8 +22,6 @@
#ifndef CHARACTERDATA_HPP_
#define CHARACTERDATA_HPP_
//POD members
#include "bbox.hpp"
#include "vector2.hpp"
#include "statistics.hpp"
@@ -48,8 +46,9 @@ struct CharacterData {
//world position
int mapIndex = 0;
Vector2 position = {0.0,0.0};
Vector2 origin = {0.0,0.0};
Vector2 motion = {0.0,0.0};
Vector2 bounds = {0.0,0.0};
//base statistics
Statistics stats;
@@ -71,7 +70,6 @@ struct CharacterData {
#ifdef GRAPHICS
SpriteSheet sprite;
#endif
BBox bbox = {0,0,0,0};
bool inCombat = false;
int atbGauge = 0;
//TODO: stored command
+11 -4
View File
@@ -22,9 +22,7 @@
#ifndef COMBATDATA_HPP_
#define COMBATDATA_HPP_
//POD members
#include "vector2.hpp"
#include "bbox.hpp"
//gameplay members
#include "character_data.hpp"
@@ -40,7 +38,16 @@
#include <list>
#include <utility>
#define COMBAT_MAX_CHARACTER_COUNT 12
#define COMBAT_MAX_ENEMY_COUNT 12
struct CombatData {
enum class Terrain {
//TODO: types of terrains
NONE = 0,
GRASSLANDS,
};
typedef std::chrono::steady_clock Clock;
//combatants, point to the std::map's internal pairs
@@ -49,8 +56,8 @@ struct CombatData {
//world interaction
int mapIndex = 0;
Vector2 position = {0.0,0.0};
BBox bbox = {0,0,0,0};
Vector2 origin = {0.0,0.0};
Vector2 bounds = {0.0,0.0};
//time interval
Clock::time_point lastTick = Clock::now();
+3 -1
View File
@@ -22,7 +22,7 @@
#ifndef ENEMYDATA_HPP_
#define ENEMYDATA_HPP_
//gameplay
#include "vector2.hpp"
#include "statistics.hpp"
//graphics
@@ -50,6 +50,8 @@ struct EnemyData {
//NOTE: these are lost when unloaded
#ifdef GRAPHICS
SpriteSheet sprite;
Vector2 origin = {0.0,0.0};
Vector2 bounds = {0.0,0.0};
#endif
int tableIndex;
int atbGauge = 0;
+35
View File
@@ -0,0 +1,35 @@
/* 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 ROOMDATA_HPP_
#define ROOMDATA_HPP_
struct RoomData {
enum class RoomType {
OVERWORLD,
RUINS,
TOWERS,
FORESTS,
CAVES,
};
};
#endif
+1
View File
@@ -24,6 +24,7 @@
#include "client_data.hpp"
#include "combat_data.hpp"
#include "enemy_data.hpp"
#include "room_data.hpp"
#include "statistics.hpp"
/* DOCS: Sanity check, read more
+1 -1
View File
@@ -28,7 +28,7 @@
class Region {
public:
typedef unsigned short type_t;
typedef unsigned char type_t;
Region() = delete;
Region(int x, int y);
+50 -10
View File
@@ -99,7 +99,19 @@ void serializeCombat(SerialPacket* packet, char* buffer) {
//integers
SERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
SERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
//TODO: more comabat info
SERIALIZE(buffer, &packet->combatInfo.terrainType, sizeof(CombatData::Terrain));
//arrays
SERIALIZE(buffer, &packet->combatInfo.characterArray, COMBAT_MAX_CHARACTER_COUNT);
SERIALIZE(buffer, &packet->combatInfo.enemyArray, COMBAT_MAX_ENEMY_COUNT);
//position
SERIALIZE(buffer, &packet->combatInfo.mapIndex, sizeof(int));
SERIALIZE(buffer, &packet->combatInfo.origin.x, sizeof(double));
SERIALIZE(buffer, &packet->combatInfo.origin.y, sizeof(double));
//TODO: rewards
}
void serializeStatistics(Statistics* stats, char* buffer) {
@@ -135,8 +147,8 @@ void serializeCharacter(SerialPacket* packet, char* buffer) {
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.origin.x, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.origin.y, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
SERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
@@ -231,7 +243,19 @@ void deserializeCombat(SerialPacket* packet, char* buffer) {
//integers
DESERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
DESERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
//TODO: more comabat info
DESERIALIZE(buffer, &packet->combatInfo.terrainType, sizeof(CombatData::Terrain));
//arrays
DESERIALIZE(buffer, &packet->combatInfo.characterArray, COMBAT_MAX_CHARACTER_COUNT);
DESERIALIZE(buffer, &packet->combatInfo.enemyArray, COMBAT_MAX_ENEMY_COUNT);
//position
DESERIALIZE(buffer, &packet->combatInfo.mapIndex, sizeof(int));
DESERIALIZE(buffer, &packet->combatInfo.origin.x, sizeof(double));
DESERIALIZE(buffer, &packet->combatInfo.origin.y, sizeof(double));
//TODO: rewards
}
@@ -268,8 +292,8 @@ void deserializeCharacter(SerialPacket* packet, char* buffer) {
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.origin.x, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.origin.y, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
DESERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
@@ -337,8 +361,16 @@ void serialize(SerialPacket* packet, void* buffer) {
break;
//combat info
case SerialPacket::Type::COMBAT_ENTER:
case SerialPacket::Type::COMBAT_EXIT:
case SerialPacket::Type::COMBAT_NEW:
case SerialPacket::Type::COMBAT_DELETE:
case SerialPacket::Type::COMBAT_UPDATE:
//TODO: is this the best fit?
case SerialPacket::Type::COMBAT_ENTER_REQUEST:
case SerialPacket::Type::COMBAT_ENTER_RESPONSE:
case SerialPacket::Type::COMBAT_EXIT_REQUEST:
case SerialPacket::Type::COMBAT_EXIT_RESPONSE:
serializeCombat(packet, reinterpret_cast<char*>(buffer));
break;
@@ -407,8 +439,16 @@ void deserialize(SerialPacket* packet, void* buffer) {
break;
//combat info
case SerialPacket::Type::COMBAT_ENTER:
case SerialPacket::Type::COMBAT_EXIT:
case SerialPacket::Type::COMBAT_NEW:
case SerialPacket::Type::COMBAT_DELETE:
case SerialPacket::Type::COMBAT_UPDATE:
//TODO: is this the best fit?
case SerialPacket::Type::COMBAT_ENTER_REQUEST:
case SerialPacket::Type::COMBAT_ENTER_RESPONSE:
case SerialPacket::Type::COMBAT_EXIT_REQUEST:
case SerialPacket::Type::COMBAT_EXIT_RESPONSE:
serializeCombat(packet, reinterpret_cast<char*>(buffer));
break;
+47 -34
View File
@@ -25,12 +25,14 @@
#include "vector2.hpp"
#include "region.hpp"
#include "statistics.hpp"
#include "combat_data.hpp"
#include "SDL/SDL_net.h"
#define NETWORK_VERSION 20140528
#define NETWORK_VERSION 20140601
#define PACKET_STRING_SIZE 100
//TODO: would it be possible to serialize structures directly?
union SerialPacket {
//types of packets
enum class Type {
@@ -38,60 +40,67 @@ union SerialPacket {
NONE = 0,
//keep alive
PING = 1,
PONG = 2,
PING,
PONG,
//searching for a server to join
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
BROADCAST_REJECTION = 5,
BROADCAST_REQUEST,
BROADCAST_RESPONSE,
BROADCAST_REJECTION,
//try to join the server
JOIN_REQUEST = 6,
JOIN_RESPONSE = 7,
JOIN_REJECTION = 8,
JOIN_REQUEST,
JOIN_RESPONSE,
JOIN_REJECTION,
//mass update
SYNCHRONIZE = 9,
SYNCHRONIZE,
//disconnect from the server
DISCONNECT = 10,
DISCONNECT,
//shut down the server
SHUTDOWN = 11,
SHUTDOWN,
//map data
REGION_REQUEST = 12,
REGION_CONTENT = 13,
REGION_REJECTION = 14,
REGION_REQUEST,
REGION_CONTENT,
REGION_REJECTION,
//combat data
COMBAT_ENTER = 15,
COMBAT_EXIT = 16,
COMBAT_NEW,
COMBAT_DELETE,
COMBAT_UPDATE,
COMBAT_UPDATE = 17,
COMBAT_ENTER_REQUEST,
COMBAT_ENTER_RESPONSE,
COMBAT_REJECTION = 18,
COMBAT_EXIT_REQUEST,
COMBAT_EXIT_RESPONSE,
//TODO: COMBAT info
COMBAT_REJECTION,
//character data
CHARACTER_NEW = 19,
CHARACTER_DELETE = 20,
CHARACTER_UPDATE = 21,
CHARACTER_NEW,
CHARACTER_DELETE,
CHARACTER_UPDATE,
CHARACTER_STATS_REQUEST = 22,
CHARACTER_STATS_RESPONSE = 23,
CHARACTER_STATS_REQUEST,
CHARACTER_STATS_RESPONSE,
CHARACTER_REJECTION = 24,
CHARACTER_REJECTION,
//enemy data
ENEMY_NEW = 25,
ENEMY_DELETE = 26,
ENEMY_UPDATE = 27,
ENEMY_NEW,
ENEMY_DELETE,
ENEMY_UPDATE,
ENEMY_STATS_REQUEST = 28,
ENEMY_STATS_RESPONSE = 29,
ENEMY_STATS_REQUEST,
ENEMY_STATS_RESPONSE,
ENEMY_REJECTION = 30,
ENEMY_REJECTION,
//more packet types go here
@@ -138,8 +147,11 @@ union SerialPacket {
Metadata meta;
int combatIndex;
int difficulty;
//TODO: background image, based on terrain type
//TODO: array of combatants
CombatData::Terrain terrainType;
int characterArray[COMBAT_MAX_CHARACTER_COUNT];
int enemyArray[COMBAT_MAX_ENEMY_COUNT];
int mapIndex;
Vector2 origin;
//TODO: rewards
}combatInfo;
@@ -152,7 +164,7 @@ union SerialPacket {
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
int mapIndex;
Vector2 position;
Vector2 origin;
Vector2 motion;
Statistics stats;
}characterInfo;
@@ -163,6 +175,7 @@ union SerialPacket {
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
Statistics stats;
//TODO: rewards
}enemyInfo;
//defaults
-75
View File
@@ -1,75 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef 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
+40
View File
@@ -0,0 +1,40 @@
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "check_bounds.hpp"
bool checkPoint(Vector2 const& origin, Vector2 const& bound, Vector2 const& point) {
return !(
point.x < origin.x ||
point.y < origin.y ||
point.x >= origin.x + bound.x ||
point.y >= origin.y + bound.y
);
}
bool checkOverlap(Vector2 const& originOne, Vector2 const& boundOne, Vector2 const& originTwo, Vector2 const& boundTwo) {
return !(
originOne.x >= originTwo.x + boundTwo.x ||
originOne.x + boundOne.x >= originTwo.x ||
originOne.y >= originTwo.y + boundTwo.y ||
originOne.y + boundOne.y >= originTwo.y
);
}
+30
View File
@@ -0,0 +1,30 @@
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef CHECKBOUNDS_HPP_
#define CHECKBOUNDS_HPP_
#include "vector2.hpp"
bool checkPoint(Vector2 const& origin, Vector2 const& bound, Vector2 const& point);
bool checkOverlap(Vector2 const& originOne, Vector2 const& boundOne, Vector2 const& originTwo, Vector2 const& boundTwo);
#endif
-6
View File
@@ -42,12 +42,6 @@ public:
return x*x+y*y;
}
double operator[](size_t i) {
if (i >= 2)
throw(std::domain_error("Out of range"));
return *(&x+i);
}
//Arithmetic operators
Vector2 operator+(Vector2 v) const {
Vector2 ret;
+10 -11
View File
@@ -1,13 +1,18 @@
#configuration of the programs
#server specific settings
server.host = 255.255.255.255
server.port = 21795
server.name = local
server.dbname = database.db
screen.w = 800
screen.h = 600
screen.f = false
#client specific settings
client.screen.f = false
client.username = Kayne Ruse
client.handle = Ratstail91
client.avatar = elliot2.bmp
#directories
dir.fonts = rsc/graphics/fonts/
@@ -16,15 +21,9 @@ dir.sprites = rsc/graphics/sprites/
dir.tilesets = rsc/graphics/tilesets/
dir.interface = rsc/graphics/interface/
dir.scripts = rsc/scripts/
dir.maps = rsc/maps/
#map system
map.pager.width = 20
map.pager.height = 20
map.pager.depth = 3
#player options
client.username = Kayne Ruse
client.handle = Ratstail91
client.avatar = elliot2.bmp
map.savename = servermap
#debugging
Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

+8 -3
View File
@@ -1,3 +1,7 @@
--TODO: why is the database setup script scripted, while accessing, etc. hardcoded?
--there should be a way to control the database more directly
--TODO: move this script into a hardocded Init() method?
CREATE TABLE IF NOT EXISTS Accounts (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(100) UNIQUE,
@@ -5,7 +9,8 @@ CREATE TABLE IF NOT EXISTS Accounts (
-- password varchar(100),
blacklisted BIT DEFAULT 0,
whitelisted BIT DEFAULT 1,
administrator BIT DEFAULT 0
mod BIT DEFAULT 0,
admin BIT DEFAULT 0
);
CREATE TABLE IF NOT EXISTS Characters (
@@ -19,8 +24,8 @@ CREATE TABLE IF NOT EXISTS Characters (
--position
mapIndex INTEGER DEFAULT 0,
positionX INTEGER DEFAULT 0,
positionY INTEGER DEFAULT 0,
originX INTEGER DEFAULT 0,
originY INTEGER DEFAULT 0,
--statistics
level INTEGER DEFAULT 0,
+6 -2
View File
@@ -31,7 +31,7 @@
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* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3, mod = ?4, admin = ?5 WHERE uid = ?1;";
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
//-------------------------
@@ -98,6 +98,8 @@ int ServerApplication::LoadUserAccount(std::string username, int clientIndex) {
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
newAccount.blackListed = sqlite3_column_int(statement, 2);
newAccount.whiteListed = sqlite3_column_int(statement, 3);
newAccount.mod = sqlite3_column_int(statement, 4);
newAccount.admin = sqlite3_column_int(statement, 5);
newAccount.clientIndex = clientIndex;
//finish the routine
@@ -137,6 +139,8 @@ int ServerApplication::SaveUserAccount(int uid) {
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;
ret |= sqlite3_bind_int(statement, 4, account.mod) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 5, account.admin) != SQLITE_OK;
//check for binding errors
if (ret) {
@@ -165,7 +169,7 @@ void ServerApplication::UnloadUserAccount(int 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
//NOTE: the associated characters should be deleted externally
sqlite3_stmt* statement = nullptr;
//prep
+52 -9
View File
@@ -29,17 +29,37 @@
//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* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET "
"mapIndex = ?2,"
"originX = ?3,"
"originY = ?4,"
"level = ?5,"
"exp = ?6,"
"maxHP = ?7,"
"health = ?8,"
"maxMP = ?9,"
"mana = ?10,"
"attack = ?11,"
"defence = ?12,"
"intelligence = ?13,"
"resistance = ?14,"
"speed = ?15,"
"accuracy = ?16,"
"evasion = ?17,"
"luck = ?18"
" WHERE uid = ?1;";
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
//-------------------------
//Define the methods
//-------------------------
//TODO: default stats as a parameter
//TODO: should statistics be stored separately?
//TODO: default stats as a parameter? This would be good for differing beggining states or multiple classes
int ServerApplication::CreateCharacter(int owner, std::string handle, std::string avatar) {
//Create the character, failing if it exists
sqlite3_stmt* statement = nullptr;
@@ -117,10 +137,10 @@ int ServerApplication::LoadCharacter(int owner, std::string handle, std::string
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
//Don't cache the birth
//world position
//world origin
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);
newChar.origin.x = (double)sqlite3_column_int(statement, 6);
newChar.origin.y = (double)sqlite3_column_int(statement, 7);
//statistics
newChar.stats.level = sqlite3_column_int(statement, 8);
@@ -139,6 +159,9 @@ int ServerApplication::LoadCharacter(int owner, std::string handle, std::string
newChar.stats.luck = sqlite3_column_double(statement, 21);
//TODO: equipment
//TODO: items
//TODO: buffs
//TODO: debuffs
//finish the routine
sqlite3_finalize(statement);
@@ -176,9 +199,29 @@ int ServerApplication::SaveCharacter(int uid) {
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.
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
//statistics
ret |= sqlite3_bind_int(statement, 5, character.stats.level) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 6, character.stats.exp) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 7, character.stats.maxHP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 8, character.stats.health) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 9, character.stats.maxMP) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 10, character.stats.mana) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 11, character.stats.attack) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 12, character.stats.defence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 13, character.stats.intelligence) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 14, character.stats.resistance) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 15, character.stats.speed) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 16, character.stats.accuracy) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 17, character.stats.evasion) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 18, character.stats.luck) != SQLITE_OK;
//TODO: equipment
//TODO: items
//TODO: buffs
//TODO: debuffs
//check for binding errors
if (ret) {
+4 -12
View File
@@ -23,18 +23,10 @@
#define ENEMYFACTORYINTERFACE_HPP_
#include "enemy_data.hpp"
#include "room_data.hpp"
#include <list>
//TODO: move this elsewhere
enum RoomType {
OVERWORLD,
RUINS,
TOWERS,
FORESTS,
CAVES,
};
//NOTE: Based on biome, world difficulty, etc.
class EnemyFactoryInterface {
public:
@@ -44,12 +36,12 @@ public:
virtual void Generate(std::list<EnemyData>* container) = 0;
//control the difficulty of the room
RoomType SetType(RoomType t) { return type = t; }
RoomData::RoomType SetType(RoomData::RoomType t) { return type = t; }
int SetDifficulty(int d) { return difficulty = d; }
RoomType GetType() { return type; }
RoomData::RoomType GetType() { return type; }
int GetDifficulty() { return difficulty; }
protected:
RoomType type;
RoomData::RoomType type;
int difficulty;
};
+14 -6
View File
@@ -70,13 +70,21 @@ void ServerApplication::HandleJoinRequest(SerialPacket packet) {
//bounce this packet
network.SendTo(&newClient.address, &packet);
//reference to prevent multiple lookups
//TODO: I need a way to pack structures unto packets more easily
//NOTE: this chunk of code is similar to HandleSynchronize
CharacterData& character = characterMap[characterIndex];
//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;
strncpy(packet.characterInfo.handle, character.handle.c_str(), PACKET_STRING_SIZE);
strncpy(packet.characterInfo.avatar, character.avatar.c_str(), PACKET_STRING_SIZE);
packet.characterInfo.mapIndex = character.mapIndex;
packet.characterInfo.origin = character.origin;
packet.characterInfo.motion = character.motion;
packet.characterInfo.stats = character.stats;
PumpPacket(packet);
//TODO: don't send anything to a certain client until they send the OK (the sync packet? or ignore client side?)
@@ -99,7 +107,7 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) {
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.origin = it.second.origin;
newPacket.characterInfo.motion = it.second.motion;
newPacket.characterInfo.stats = it.second.stats;
@@ -155,7 +163,7 @@ void ServerApplication::HandleCharacterUpdate(SerialPacket packet) {
}
//TODO: the server needs it's own movement system too
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
characterMap[packet.characterInfo.characterIndex].origin = packet.characterInfo.origin;
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
PumpPacket(packet);
+1 -2
View File
@@ -78,8 +78,7 @@ void ServerApplication::Init(int argc, char** argv) {
//setup the map object
regionPager.GetAllocator()->SetLuaState(luaState);
regionPager.GetFormat()->SetLuaState(luaState);
//TODO: config parameter
regionPager.GetFormat()->SetSaveDir("save/mapname/");
regionPager.GetFormat()->SetSaveDir(config["dir.maps"] + config["map.savename"]);
std::cout << "Prepared the map system" << std::endl;
//push the pager onto the lua registry