Compare commits

...

22 Commits

Author SHA1 Message Date
Kayne Ruse 4cce98dba4 BattleData can hold a limited number of characters 2016-08-29 19:05:41 +10:00
Kayne Ruse b2aecc933a I need to do some refactoring 2016-08-26 00:11:54 +10:00
Kayne Ruse 64833f86da Added index to CharacterData, removed some expensive lookups 2016-08-25 23:23:57 +10:00
Kayne Ruse 518ea93adc Added RoomData::[Pop/Push]Character() 2016-08-25 20:47:08 +10:00
Kayne Ruse 07218418a2 Discovered I need to do something 2016-08-25 20:01:17 +10:00
Kayne Ruse 6d8d7963a1 Renamed CombatInstance to Battle, for clarity 2016-07-11 10:14:07 +10:00
Kayne Ruse 69a13c5ed6 Broke RoomData::RunFrame() into several parts for readability 2016-07-09 20:14:07 +10:00
Kayne Ruse 011f71ea61 Wrote out the pseudocode for RoomData::RunFrame
This method is too overloaded. The pseudocode itself takes up a whole
page.
2016-07-09 17:25:13 +10:00
Kayne Ruse 4894daa273 Moved barrier system into it's own subdirectory 2016-07-09 16:56:35 +10:00
Kayne Ruse 9a1dcc2f53 Set barrier bounds 2016-05-29 02:24:10 +10:00
Kayne Ruse 8d2fc45d7d Combat instances are created alongside the barriers 2016-05-29 02:15:41 +10:00
Kayne Ruse 867a86fd79 Fixed Missing #include<functional> 2016-05-28 13:01:19 +10:00
Kayne Ruse 7ccea0d1c0 I quit 2016-04-25 22:22:04 +10:00
Kayne Ruse 7c6468c1dd Multiple changes, read more
* Implemented HeartbeatUtility
* simplified the SQL files
* Added a dummy inventory button
2016-04-25 22:10:11 +10:00
Kayne Ruse 5285397101 I really hate SQL 2016-04-22 20:00:31 +10:00
Kayne Ruse ba295099f3 Experimenting with SQL 2016-04-22 18:14:07 +10:00
Kayne Ruse 754fb71850 Updated SQL script 2016-04-22 08:26:19 +10:00
Kayne Ruse dd25f068af Merge remote-tracking branch 'refs/remotes/origin/master' 2016-04-19 10:14:08 +10:00
Kayne Ruse bf273db9c2 Fixed Typo in README.md 2016-04-18 09:20:03 +10:00
Kayne Ruse 5d3d82bf3f Added a new button graphic 2016-04-17 02:15:23 +10:00
Kayne Ruse 36ba3fa132 Updated GUI library 2016-04-17 02:10:08 +10:00
Kayne Ruse 3002afa1e9 Moved a file 2016-04-17 01:35:34 +10:00
69 changed files with 1435 additions and 460 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), a
## Releases ## Releases
* The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-win.rar). * The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-win.rar).
* The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar). * The most recent stable build for Linux can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar).
## Documentation ## Documentation
+1
View File
@@ -23,6 +23,7 @@
#include "base_barrier.hpp" #include "base_barrier.hpp"
#include <functional>
#include <list> #include <list>
#include <string> #include <string>
+58
View File
@@ -0,0 +1,58 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "heartbeat_utility.hpp"
#include "channels.hpp"
#include "ip_operators.hpp"
//heartbeat system
void HeartbeatUtility::hPing(ServerPacket* const argPacket) {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PONG;
network.SendTo(argPacket->srcAddress, &newPacket);
}
void HeartbeatUtility::hPong(ServerPacket* const argPacket) {
if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) {
throw(std::runtime_error("Heartbeat message received from an unknown source"));
}
attemptedBeats = 0;
lastBeat = Clock::now();
}
int HeartbeatUtility::CheckHeartBeat() {
//check the connection (heartbeat)
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
if (attemptedBeats > 2) {
return 1;
}
else {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PING;
network.SendTo(Channels::SERVER, &newPacket);
attemptedBeats++;
lastBeat = Clock::now();
}
}
return 0;
}
+42
View File
@@ -0,0 +1,42 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "server_packet.hpp"
#include "udp_network_utility.hpp"
#include <chrono>
class HeartbeatUtility {
public:
//heartbeat system
void hPing(ServerPacket* const);
void hPong(ServerPacket* const);
int CheckHeartBeat();
private:
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
typedef std::chrono::steady_clock Clock;
Clock::time_point lastBeat = Clock::now();
int attemptedBeats = 0;
};
+7 -3
View File
@@ -28,6 +28,8 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
@@ -49,14 +51,16 @@ DisconnectedScreen::DisconnectedScreen() {
//setup the button //setup the button
backButton.SetBackgroundTexture(GetRenderer(), image.GetTexture()); backButton.SetBackgroundTexture(GetRenderer(), image.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE); backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions //set the button positions
backButton.SetX(50); backButton.SetX(50);
backButton.SetY(50); backButton.SetY(50);
//set the disconnection message text //set the disconnection message text
textLine.SetText(GetRenderer(), font, config["client.disconnectMessage"], {255, 255, 255, 255}); textLine.SetX(50);
textLine.SetY(30);
textLine.SetText(GetRenderer(), font, WHITE, config["client.disconnectMessage"]);
//full reset //full reset
UDPNetworkUtility::GetSingleton().Unbind(Channels::SERVER); UDPNetworkUtility::GetSingleton().Unbind(Channels::SERVER);
@@ -92,7 +96,7 @@ void DisconnectedScreen::FrameEnd() {
void DisconnectedScreen::RenderFrame(SDL_Renderer* renderer) { void DisconnectedScreen::RenderFrame(SDL_Renderer* renderer) {
backButton.DrawTo(renderer); backButton.DrawTo(renderer);
textLine.DrawTo(renderer, 50, 30); textLine.DrawTo(renderer);
} }
//------------------------- //-------------------------
+15 -7
View File
@@ -27,6 +27,8 @@
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
@@ -52,11 +54,11 @@ LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
//setup the buttons //setup the buttons
searchButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); searchButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
searchButton.SetText(GetRenderer(), font, "Search", COLOR_WHITE); searchButton.SetText(GetRenderer(), font, WHITE, "Search");
joinButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); joinButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
joinButton.SetText(GetRenderer(), font, "Join", COLOR_WHITE); joinButton.SetText(GetRenderer(), font, WHITE, "Join");
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE); backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions (assumed) //set the button positions (assumed)
searchButton.SetX(50); searchButton.SetX(50);
@@ -67,6 +69,7 @@ LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
backButton.SetY(90); backButton.SetY(90);
//pseudo-list selection //pseudo-list selection
//TODO: move this into the UI library?
boundingBox = {300, 50, 200, 12}; boundingBox = {300, 50, 200, 12};
//hacked together a highlight box //hacked together a highlight box
@@ -121,8 +124,13 @@ void LobbyMenu::RenderFrame(SDL_Renderer* renderer) {
} }
//draw the server's info //draw the server's info
serverVector[i].nameImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i); serverVector[i].nameImage.SetX(boundingBox.x);
serverVector[i].playerCountImage.DrawTo(renderer, boundingBox.x+276, boundingBox.y + boundingBox.h * i); serverVector[i].nameImage.SetY(boundingBox.y + boundingBox.h * i);
serverVector[i].nameImage.DrawTo(renderer);
serverVector[i].playerCountImage.SetX(boundingBox.x+276);
serverVector[i].playerCountImage.SetY(boundingBox.y + boundingBox.h * i);
serverVector[i].playerCountImage.DrawTo(renderer);
} }
} }
@@ -248,8 +256,8 @@ void LobbyMenu::HandleBroadcastResponse(ServerPacket* const argPacket) {
}; };
//text graphics //text graphics
serverVector.back().nameImage.SetText(GetRenderer(), font, newServer.name, color); serverVector.back().nameImage.SetText(GetRenderer(), font, color, newServer.name);
serverVector.back().playerCountImage.SetText(GetRenderer(), font, itoa_base10(newServer.playerCount), color); serverVector.back().playerCountImage.SetText(GetRenderer(), font, color, itoa_base10(newServer.playerCount));
} }
void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) { void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
+15 -11
View File
@@ -26,6 +26,8 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
@@ -46,11 +48,11 @@ MainMenu::MainMenu() {
//setup the buttons //setup the buttons
startButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); startButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
startButton.SetText(GetRenderer(), font, "Start", COLOR_WHITE); startButton.SetText(GetRenderer(), font, WHITE, "Start");
optionsButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); optionsButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
optionsButton.SetText(GetRenderer(), font, "Options", COLOR_WHITE); optionsButton.SetText(GetRenderer(), font, WHITE, "Options");
quitButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); quitButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
quitButton.SetText(GetRenderer(), font, "Quit", COLOR_WHITE); quitButton.SetText(GetRenderer(), font, WHITE, "Quit");
//set the button positions //set the button positions
startButton.SetX(50); startButton.SetX(50);
@@ -61,9 +63,15 @@ MainMenu::MainMenu() {
quitButton.SetY(50 + 20 * 2); quitButton.SetY(50 + 20 * 2);
//text box //text box
textBox.PushLine(GetRenderer(), font, "Thanks for playing!", {255, 255, 255, 255}); int h = -1;
textBox.PushLine(GetRenderer(), font, "You can get the latest version at: ", {255, 255, 255, 255}); SDL_RenderGetLogicalSize(GetRenderer(), nullptr, &h);
textBox.PushLine(GetRenderer(), font, "krgamestudios.com", {255, 255, 255, 255}); //TODO: (9) click to open the website/update
textBox.SetX(50);
textBox.SetY(h-100);
textBox.PushLine(GetRenderer(), font, WHITE, "Thanks for playing!");
textBox.PushLine(GetRenderer(), font, WHITE, "You can get the latest version at: ");
textBox.PushLine(GetRenderer(), font, WHITE, "krgamestudios.com"); //TODO: (9) click to open the website/update
//debug //debug
// //
@@ -93,11 +101,7 @@ void MainMenu::RenderFrame(SDL_Renderer* renderer) {
startButton.DrawTo(renderer); startButton.DrawTo(renderer);
optionsButton.DrawTo(renderer); optionsButton.DrawTo(renderer);
quitButton.DrawTo(renderer); quitButton.DrawTo(renderer);
textBox.DrawTo(renderer);
int h = -1;
SDL_RenderGetLogicalSize(GetRenderer(), nullptr, &h);
textBox.DrawTo(renderer, 50, h-50, -12);
} }
//------------------------- //-------------------------
+7 -3
View File
@@ -26,6 +26,8 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
@@ -46,14 +48,16 @@ OptionsMenu::OptionsMenu() {
//setup the button //setup the button
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE); backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions //set the button positions
backButton.SetX(50); backButton.SetX(50);
backButton.SetY(50); backButton.SetY(50);
//text line //text line
textLine.SetText(GetRenderer(), font, "This code is fucking hard to refactor.", {255, 255, 255, 255}); textLine.SetX(50);
textLine.SetY(30);
textLine.SetText(GetRenderer(), font, WHITE, "Am I making any progress?");
} }
OptionsMenu::~OptionsMenu() { OptionsMenu::~OptionsMenu() {
@@ -78,7 +82,7 @@ void OptionsMenu::FrameEnd() {
void OptionsMenu::RenderFrame(SDL_Renderer* renderer) { void OptionsMenu::RenderFrame(SDL_Renderer* renderer) {
backButton.DrawTo(renderer); backButton.DrawTo(renderer);
textLine.DrawTo(renderer, 50, 30); textLine.DrawTo(renderer);
} }
//------------------------- //-------------------------
+14 -45
View File
@@ -34,6 +34,8 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//------------------------- //-------------------------
//static functions //static functions
//------------------------- //-------------------------
@@ -72,9 +74,9 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
//setup the buttons //setup the buttons
disconnectButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); disconnectButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
disconnectButton.SetText(GetRenderer(), font, "Disconnect", COLOR_WHITE); disconnectButton.SetText(GetRenderer(), font, WHITE, "Disconnect");
shutdownButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture()); shutdownButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
shutdownButton.SetText(GetRenderer(), font, "Shutdown", COLOR_WHITE); shutdownButton.SetText(GetRenderer(), font, WHITE, "Shutdown");
//set the button positions //set the button positions
disconnectButton.SetX(50); disconnectButton.SetX(50);
@@ -159,7 +161,12 @@ void World::Update() {
delete reinterpret_cast<char*>(packetBuffer); delete reinterpret_cast<char*>(packetBuffer);
//heartbeat system //heartbeat system
CheckHeartBeat(); if (heartbeatUtility.CheckHeartBeat()) {
//escape to the disconnect screen
SendDisconnectRequest();
SetSceneSignal(SceneSignal::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
}
//update all entities //update all entities
for (auto& it : characterMap) { for (auto& it : characterMap) {
@@ -261,12 +268,12 @@ void World::RenderFrame(SDL_Renderer* renderer) {
shutdownButton.DrawTo(renderer); shutdownButton.DrawTo(renderer);
//FPS //FPS
fpsTextLine.DrawTo(renderer, 0, 0); fpsTextLine.DrawTo(renderer);
int fpsRet = fps.Calculate(); int fpsRet = fps.Calculate();
if (fpsRet != -1) { if (fpsRet != -1) {
std::ostringstream msg; std::ostringstream msg;
msg << "FPS: " << fpsRet; msg << "FPS: " << fpsRet;
fpsTextLine.SetText(renderer, font, msg.str(), {255, 255, 255, 255}); fpsTextLine.SetText(renderer, font, WHITE, msg.str());
} }
} }
@@ -409,10 +416,10 @@ void World::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) { switch(argPacket->type) {
//heartbeat system //heartbeat system
case SerialPacketType::PING: case SerialPacketType::PING:
hPing(static_cast<ServerPacket*>(argPacket)); heartbeatUtility.hPing(static_cast<ServerPacket*>(argPacket));
break; break;
case SerialPacketType::PONG: case SerialPacketType::PONG:
hPong(static_cast<ServerPacket*>(argPacket)); heartbeatUtility.hPong(static_cast<ServerPacket*>(argPacket));
break; break;
//game server connections //game server connections
@@ -518,44 +525,6 @@ void World::HandlePacket(SerialPacket* const argPacket) {
} }
} }
//-------------------------
//heartbeat system
//-------------------------
void World::hPing(ServerPacket* const argPacket) {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PONG;
network.SendTo(argPacket->srcAddress, &newPacket);
}
void World::hPong(ServerPacket* const argPacket) {
if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) {
throw(std::runtime_error("Heartbeat message received from an unknown source"));
}
attemptedBeats = 0;
lastBeat = Clock::now();
}
void World::CheckHeartBeat() {
//check the connection (heartbeat)
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
if (attemptedBeats > 2) {
//escape to the disconnect screen
SendDisconnectRequest();
SetSceneSignal(SceneSignal::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
}
else {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PING;
network.SendTo(Channels::SERVER, &newPacket);
attemptedBeats++;
lastBeat = Clock::now();
}
}
}
//------------------------- //-------------------------
//Connection control //Connection control
//------------------------- //-------------------------
+2 -9
View File
@@ -43,6 +43,7 @@
#include "base_scene.hpp" #include "base_scene.hpp"
#include "base_barrier.hpp" #include "base_barrier.hpp"
#include "base_creature.hpp" #include "base_creature.hpp"
#include "heartbeat_utility.hpp"
#include "local_character.hpp" #include "local_character.hpp"
#include "SDL2/SDL.h" #include "SDL2/SDL.h"
@@ -80,12 +81,6 @@ private:
//handle incoming traffic //handle incoming traffic
void HandlePacket(SerialPacket* const); void HandlePacket(SerialPacket* const);
//heartbeat system
void hPing(ServerPacket* const);
void hPong(ServerPacket* const);
void CheckHeartBeat();
//basic connections //basic connections
void SendLogoutRequest(); void SendLogoutRequest();
void SendDisconnectRequest(); void SendDisconnectRequest();
@@ -165,11 +160,9 @@ private:
LocalCharacter* localCharacter = nullptr; LocalCharacter* localCharacter = nullptr;
//heartbeat //heartbeat
//TODO: (2) Heartbeat needs it's own utility HeartbeatUtility heartbeatUtility;
typedef std::chrono::steady_clock Clock; typedef std::chrono::steady_clock Clock;
Clock::time_point lastBeat = Clock::now();
Clock::time_point queryTime = Clock::now() - std::chrono::seconds(4); //back 4 seconds to trigger automatically Clock::time_point queryTime = Clock::now() - std::chrono::seconds(4); //back 4 seconds to trigger automatically
int attemptedBeats = 0;
//ugly references; I hate this //ugly references; I hate this
ConfigUtility& config = ConfigUtility::GetSingleton(); ConfigUtility& config = ConfigUtility::GetSingleton();
+32
View File
@@ -0,0 +1,32 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
enum ItemType {
//basics
POTION = 101,
//weapons
SWORD = 201,
DAGGER = 202,
STAFF = 203
};
+20 -20
View File
@@ -21,6 +21,8 @@
*/ */
#include "button.hpp" #include "button.hpp"
#include "render_text_texture.hpp"
#include <stdexcept> #include <stdexcept>
void Button::DrawTo(SDL_Renderer* renderer) { void Button::DrawTo(SDL_Renderer* renderer) {
@@ -51,19 +53,9 @@ void Button::SetBackgroundTexture(SDL_Renderer* renderer, SDL_Texture* texture)
image.SetClipH(image.GetClipH() / 3); image.SetClipH(image.GetClipH() / 3);
} }
void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, std::string s, SDL_Color color) { void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string s) {
//make the surface (from SDL_ttf)
SDL_Surface* surf = TTF_RenderText_Solid(font, s.c_str(), color);
if (!surf) {
throw(std::runtime_error("Failed to create a TTF surface"));
}
//convert to texture //convert to texture
SDL_Texture* text = SDL_CreateTextureFromSurface(renderer, surf); SDL_Texture* text = renderTextTexture(renderer, font, color, s);
SDL_FreeSurface(surf);
if (!text) {
throw(std::runtime_error("Failed to create a TTF texture"));
}
//get the dimensions & rects //get the dimensions & rects
int x, y, w, h; int x, y, w, h;
@@ -87,14 +79,6 @@ void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, std::string s, SDL_
SDL_DestroyTexture(text); SDL_DestroyTexture(text);
} }
void Button::SetX(int x) {
posX = x;
}
void Button::SetY(int y) {
posY = y;
}
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& event) { Button::State Button::MouseMotion(SDL_MouseMotionEvent const& event) {
//if out of bounds, exit //if out of bounds, exit
if (!CheckBounds(event.x, event.y)) { if (!CheckBounds(event.x, event.y)) {
@@ -156,6 +140,22 @@ Button::State Button::GetState() {
return state; return state;
} }
int Button::SetX(int i) {
return posX = i;
}
int Button::SetY(int i) {
return posY = i;
}
int Button::GetX() const {
return posX;
}
int Button::GetY() const {
return posY;
}
bool Button::CheckBounds(int x, int y) { bool Button::CheckBounds(int x, int y) {
//return if true (x, y) is within bounds, otherwise return false //return if true (x, y) is within bounds, otherwise return false
return !( return !(
+8 -9
View File
@@ -27,11 +27,6 @@
#include <string> #include <string>
constexpr SDL_Color COLOR_WHITE = {255, 255, 255, 255};
constexpr SDL_Color COLOR_RED = {255, 0, 0, 255};
constexpr SDL_Color COLOR_ORANGE = {255, 127, 0, 255};
constexpr SDL_Color COLOR_BLUE = {0, 0, 255, 255};
class Button { class Button {
public: public:
enum State { enum State {
@@ -46,9 +41,7 @@ public:
//setup //setup
void SetBackgroundTexture(SDL_Renderer*, SDL_Texture*); void SetBackgroundTexture(SDL_Renderer*, SDL_Texture*);
void SetText(SDL_Renderer*, TTF_Font*, std::string, SDL_Color); void SetText(SDL_Renderer*, TTF_Font*, SDL_Color, std::string);
void SetX(int x);
void SetY(int y);
//capture input //capture input
State MouseMotion(SDL_MouseMotionEvent const&); State MouseMotion(SDL_MouseMotionEvent const&);
@@ -59,10 +52,16 @@ public:
void SetState(State); //TODO: idle, busy or disabled void SetState(State); //TODO: idle, busy or disabled
State GetState(); State GetState();
//accessors & mutators
int SetX(int x);
int SetY(int y);
int GetX() const;
int GetY() const;
protected: protected:
bool CheckBounds(int x, int y); bool CheckBounds(int x, int y);
Image image; Image image;
int posX = 0, posY = 0;
State state = State::IDLE; State state = State::IDLE;
int posX = 0, posY = 0;
}; };
+1 -1
View File
@@ -1,5 +1,5 @@
#config #config
INCLUDES+=. INCLUDES+=. ../utilities
LIBS+= LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+46
View File
@@ -0,0 +1,46 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "render_text_texture.hpp"
#include <stdexcept>
SDL_Texture* renderTextTexture(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string str) {
//make the surface (from SDL_ttf)
SDL_Surface* surface = TTF_RenderText_Solid(font, str.c_str(), color);
if (!surface) {
throw(std::runtime_error("Failed to create a TTF surface"));
}
//convert to texture
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
//cleanup
SDL_FreeSurface(surface);
//check
if (!texture) {
throw(std::runtime_error("Failed to create a TTF texture"));
}
//NOTE: free the texture yourself
return texture;
}
+29
View File
@@ -0,0 +1,29 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"
#include <string>
SDL_Texture* renderTextTexture(SDL_Renderer*, TTF_Font*, SDL_Color color, std::string);
+25 -6
View File
@@ -31,15 +31,18 @@ TextBox::~TextBox() {
// //
} }
void TextBox::DrawTo(SDL_Renderer* renderer, int posX, int posY, int pointSize) { void TextBox::DrawTo(SDL_Renderer* renderer) {
int renderY = posY;
for (std::list<TextLine>::iterator it = lineList.begin(); it != lineList.end(); it++) { for (std::list<TextLine>::iterator it = lineList.begin(); it != lineList.end(); it++) {
it->DrawTo(renderer, posX, posY); it->SetX(posX);
posY += pointSize; it->SetY(renderY);
it->DrawTo(renderer);
renderY += it->GetPointHeight();
} }
} }
void TextBox::PushLine(SDL_Renderer* renderer, TTF_Font* font, std::string str, SDL_Color color) { void TextBox::PushLine(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string str) {
lineList.emplace_front(renderer, font, str, color); lineList.emplace_back(renderer, font, color, str, 0, 0);
} }
void TextBox::PopLine(int num) { void TextBox::PopLine(int num) {
@@ -47,10 +50,26 @@ void TextBox::PopLine(int num) {
num < lineList.size() ? num : lineList.size(); num < lineList.size() ? num : lineList.size();
for (int i = 0; i < num; ++i) { for (int i = 0; i < num; ++i) {
lineList.pop_back(); lineList.pop_front();
} }
} }
void TextBox::ClearLines() { void TextBox::ClearLines() {
lineList.clear(); lineList.clear();
} }
int TextBox::SetX(int i) {
return posX = i;
}
int TextBox::SetY(int i) {
return posY = i;
}
int TextBox::GetX() const {
return posX;
}
int TextBox::GetY() const {
return posY;
}
+8 -2
View File
@@ -34,12 +34,18 @@ public:
TextBox(); TextBox();
~TextBox(); ~TextBox();
void DrawTo(SDL_Renderer*, int posX, int posY, int pointSize); void DrawTo(SDL_Renderer*);
void PushLine(SDL_Renderer*, TTF_Font*, std::string, SDL_Color color); void PushLine(SDL_Renderer*, TTF_Font*, SDL_Color color, std::string);
void PopLine(int num = 1); void PopLine(int num = 1);
void ClearLines(); void ClearLines();
int SetX(int i);
int SetY(int i);
int GetX() const;
int GetY() const;
private: private:
std::list<TextLine> lineList; std::list<TextLine> lineList;
int posX = 0, posY = 0;
}; };
+109
View File
@@ -0,0 +1,109 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "text_field.hpp"
#include "render_text_texture.hpp"
TextField::TextField() {
//
}
TextField::~TextField() {
SDL_DestroyTexture(texture);
}
void TextField::DrawTo(SDL_Renderer* renderer) {
if (!texture) {
return;
}
SDL_Rect dclip = {posX, posY, 0, 0};
SDL_QueryTexture(texture, nullptr, nullptr, &dclip.w, &dclip.h);
SDL_RenderCopy(renderer, texture, nullptr, &dclip);
}
std::string TextField::PushText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string s) {
text += s;
return SetText(renderer, font, color, text);
}
std::string TextField::SetText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string s) {
text = s;
SDL_DestroyTexture(texture);
if (text.size()) {
texture = renderTextTexture(renderer, font, color, text);
}
else {
texture = nullptr;
}
return text;
}
std::string TextField::PopChars(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, int i) {
if (text.size() > 0) {
text.erase(text.size() - i);
}
return SetText(renderer, font, color, text);
}
std::string TextField::GetText() {
return text;
}
bool TextField::MouseButtonDown(SDL_MouseButtonEvent const& event) {
BoundingBox cursorBox = {event.x, event.y, 0, 0};
BoundingBox fieldBox = bounds;
fieldBox.x += posX;
fieldBox.y += posY;
return focus = fieldBox.CheckOverlap(cursorBox);
}
BoundingBox TextField::SetBounds(BoundingBox b) {
return bounds = b;
}
BoundingBox TextField::GetBounds() {
return bounds;
}
bool TextField::SetFocus(bool b) {
return focus = b;
}
bool TextField::GetFocus() {
return focus;
}
int TextField::SetX(int i) {
return posX = i;
}
int TextField::SetY(int i) {
return posY = i;
}
int TextField::GetX() const {
return posX;
}
int TextField::GetY() const {
return posY;
}
+65
View File
@@ -0,0 +1,65 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "bounding_box.hpp"
#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"
#include <string>
class TextField {
public:
TextField();
~TextField();
void DrawTo(SDL_Renderer*);
//input
std::string PushText(SDL_Renderer*, TTF_Font*, SDL_Color color, std::string);
std::string SetText(SDL_Renderer*, TTF_Font*, SDL_Color color, std::string);
std::string PopChars(SDL_Renderer*, TTF_Font*, SDL_Color color, int i);
std::string GetText();
bool MouseButtonDown(SDL_MouseButtonEvent const& event);
BoundingBox SetBounds(BoundingBox b);
BoundingBox GetBounds();
bool SetFocus(bool b);
bool GetFocus();
//accessors & mutators
int SetX(int i);
int SetY(int i);
int GetX() const;
int GetY() const;
private:
SDL_Texture* texture = nullptr;
std::string text;
BoundingBox bounds;
bool focus = false;
int posX = 0, posY = 0;
};
+33 -25
View File
@@ -21,50 +21,58 @@
*/ */
#include "text_line.hpp" #include "text_line.hpp"
#include "render_text_texture.hpp"
#include <stdexcept> #include <stdexcept>
SDL_Texture* renderTextTexture(SDL_Renderer* renderer, TTF_Font* font, std::string str, SDL_Color color) {
//make the surface (from SDL_ttf)
SDL_Surface* surface = TTF_RenderText_Solid(font, str.c_str(), color);
if (!surface) {
throw(std::runtime_error("Failed to create a TTF surface"));
}
//convert to texture
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
//cleanup
SDL_FreeSurface(surface);
//check
if (!texture) {
throw(std::runtime_error("Failed to create a TTF texture"));
}
//NOTE: free the texture yourself
return texture;
}
TextLine::TextLine() { TextLine::TextLine() {
// //
} }
TextLine::TextLine(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string str, int x, int y) {
SetText(renderer, font, color, str);
posX = x;
posY = y;
}
TextLine::~TextLine() { TextLine::~TextLine() {
ClearText(); ClearText();
} }
void TextLine::DrawTo(SDL_Renderer* renderer, int posX, int posY) { void TextLine::DrawTo(SDL_Renderer* renderer) {
SDL_Rect dclip = {posX, posY, 0, 0}; SDL_Rect dclip = {posX, posY, 0, 0};
SDL_QueryTexture(texture, nullptr, nullptr, &dclip.w, &dclip.h); SDL_QueryTexture(texture, nullptr, nullptr, &dclip.w, &dclip.h);
SDL_RenderCopy(renderer, texture, nullptr, &dclip); SDL_RenderCopy(renderer, texture, nullptr, &dclip);
} }
void TextLine::SetText(SDL_Renderer* renderer, TTF_Font* font, std::string str, SDL_Color color) { void TextLine::SetText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string str) {
//just use the above global function //just use the above global function
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
texture = renderTextTexture(renderer, font, str, color); texture = renderTextTexture(renderer, font, color, str);
pointHeight = TTF_FontHeight(font);
} }
void TextLine::ClearText() { void TextLine::ClearText() {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
pointHeight = 0;
}
int TextLine::SetX(int i) {
return posX = i;
}
int TextLine::SetY(int i) {
return posY = i;
}
int TextLine::GetX() const {
return posX;
}
int TextLine::GetY() const {
return posY;
}
int TextLine::GetPointHeight() {
return pointHeight;
} }
+14 -6
View File
@@ -26,20 +26,28 @@
#include <string> #include <string>
SDL_Texture* renderTextTexture(SDL_Renderer*, TTF_Font*, std::string, SDL_Color color);
class TextLine { class TextLine {
public: public:
TextLine(); TextLine();
TextLine(SDL_Renderer* r, TTF_Font* f, std::string s, SDL_Color c) TextLine(SDL_Renderer*, TTF_Font*, SDL_Color, std::string, int x, int y);
{ SetText(r, f, s, c); }
virtual ~TextLine(); virtual ~TextLine();
void DrawTo(SDL_Renderer*, int posX, int posY); void DrawTo(SDL_Renderer*);
void SetText(SDL_Renderer*, TTF_Font*, std::string, SDL_Color color); void SetText(SDL_Renderer*, TTF_Font*, SDL_Color, std::string);
void ClearText(); void ClearText();
//accessors & mutators
int SetX(int i);
int SetY(int i);
int GetX() const;
int GetY() const;
//utility
int GetPointHeight();
protected: protected:
SDL_Texture* texture = nullptr; SDL_Texture* texture = nullptr;
int posX = 0, posY = 0;
int pointHeight = 0; //internal use for TextBox
}; };
+8 -7
View File
@@ -34,15 +34,16 @@
typedef SerialPacketBase SerialPacket; typedef SerialPacketBase SerialPacket;
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients //DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20160404; constexpr int NETWORK_VERSION = 20160825;
union MaxPacket { union MaxPacket {
CharacterPacket a; BarrierPacket a;
ClientPacket b; CharacterPacket b;
CreaturePacket c; ClientPacket c;
RegionPacket d; CreaturePacket d;
ServerPacket e; RegionPacket e;
TextPacket f; ServerPacket f;
TextPacket g;
}; };
constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket); constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket);
+22 -19
View File
@@ -142,25 +142,6 @@ enum class SerialPacketType {
FORMAT_END_CREATURE = 599, FORMAT_END_CREATURE = 599,
//-------------------------
//BarrierPacket
// barrier index,
// bounds,
// roomIndex, origin, motion
// status
//-------------------------
FORMAT_COMBAT = 700,
BARRIER_UPDATE = 701,
BARRIER_CREATE = 702,
BARRIER_UNLOAD = 703,
QUERY_BARRIER_EXISTS = 704,
FORMAT_END_COMBAT = 799,
//------------------------- //-------------------------
//TextPacket //TextPacket
// name, text // name, text
@@ -184,6 +165,28 @@ enum class SerialPacketType {
FORMAT_END_TEXT = 699, FORMAT_END_TEXT = 699,
//-------------------------
//BarrierPacket
// barrier index,
// bounds,
// roomIndex, origin, motion
// status
//-------------------------
FORMAT_BARRIER = 700,
BARRIER_UPDATE = 701,
BARRIER_CREATE = 702,
BARRIER_UNLOAD = 703,
QUERY_BARRIER_EXISTS = 704,
BARRIER_ENTRY = 705,
BARRIER_EXIT = 706,
FORMAT_END_BARRIER = 799,
//------------------------- //-------------------------
//not used //not used
//------------------------- //-------------------------
+8 -8
View File
@@ -70,13 +70,13 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
serializeCreature(buffer, static_cast<CreaturePacket*>(packet)); serializeCreature(buffer, static_cast<CreaturePacket*>(packet));
} }
if (BOUNDS(packet->type, SerialPacketType::FORMAT_COMBAT, SerialPacketType::FORMAT_END_COMBAT)) {
serializeBarrier(buffer, static_cast<BarrierPacket*>(packet));
}
if (BOUNDS(packet->type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) { if (BOUNDS(packet->type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
serializeText(buffer, static_cast<TextPacket*>(packet)); serializeText(buffer, static_cast<TextPacket*>(packet));
} }
if (BOUNDS(packet->type, SerialPacketType::FORMAT_BARRIER, SerialPacketType::FORMAT_END_BARRIER)) {
serializeBarrier(buffer, static_cast<BarrierPacket*>(packet));
}
} }
void deserializePacket(void* buffer, SerialPacketBase* packet) { void deserializePacket(void* buffer, SerialPacketBase* packet) {
@@ -104,11 +104,11 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
deserializeCreature(buffer, static_cast<CreaturePacket*>(packet)); deserializeCreature(buffer, static_cast<CreaturePacket*>(packet));
} }
if (BOUNDS(type, SerialPacketType::FORMAT_COMBAT, SerialPacketType::FORMAT_END_COMBAT)) {
deserializeBarrier(buffer, static_cast<BarrierPacket*>(packet));
}
if (BOUNDS(type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) { if (BOUNDS(type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
deserializeText(buffer, static_cast<TextPacket*>(packet)); deserializeText(buffer, static_cast<TextPacket*>(packet));
} }
if (BOUNDS(type, SerialPacketType::FORMAT_BARRIER, SerialPacketType::FORMAT_END_BARRIER)) {
deserializeBarrier(buffer, static_cast<BarrierPacket*>(packet));
}
} }
+125
View File
@@ -0,0 +1,125 @@
/* Copyright: (c) Kayne Ruse 2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#pragma once
//DOCS: this is a generic CSV reading tool
//DOCS: empty lines and comment lines begining with '#' are ignored
//DOCS: whitespace characters are valid field values
//DOCS: if the file is invalid, then the behavior is undefined
#include <array>
#include <cstring>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
//define the container types
template<int N>
using CSVElement = std::array<std::string, N>;
template<int N>
using CSVObject = std::vector<CSVElement<N>>;
//read a file into an object
template<int N>
CSVObject<N> readCSV(std::string fname, char delim = ',') {
//open the file
std::ifstream is(fname);
if (!is.is_open()) {
std::ostringstream msg;
msg << "Failed to open file: " << fname;
throw(std::runtime_error(msg.str()));
}
//build the scanf format
std::ostringstream format;
format << "%[^\0" << delim << "]";
//read and store each record (one per line)
CSVObject<N> object;
while(!is.eof()) {
//get a line
std::string tmpLine;
getline(is, tmpLine);
//skip blank and comment lines
if (tmpLine.size() == 0 || tmpLine[0] == '#') {
continue;
}
//read and store each field
CSVElement<N> record;
for (int i = 0; i < N; ++i) {
//get a field
char tmpField[256];
memset(tmpField, 0, 256);
sscanf(tmpLine.c_str(), format.str().c_str(), tmpField);
//prune the input
int len = std::min(strlen(tmpField)+1, tmpLine.size());
tmpLine = tmpLine.substr(len);
//store the field
record[i] = tmpField;
}
object.push_back(record);
}
//finally, close the file
is.close();
return object;
}
template<int N>
void writeCSV(std::string fname, CSVObject<N> const& object, char delim = ',') {
//open the file
std::ofstream os(fname);
if (!os.is_open()) {
std::ostringstream msg;
msg << "Failed to open file: " << fname;
throw(std::runtime_error(msg.str()));
}
//write each record, one at a time
for(auto& record : object) {
//write each field, one at a time
for (int i = 0; i < N; i++) {
os << record[i];
//print delimiter
if (i != N -1) {
os << delim;
}
}
os << std::endl;
}
//finish
os.close();
}
+5
View File
@@ -0,0 +1,5 @@
#Format (4 columns): "name", type, "sprite.png", stackable
"Sword",weapon,"sword.png",false
"Staff",weapon,"staff.png",false
"Dagger",weapon,"dagger.png",false
"Potion",consumable,"potion.png",true
Can't render this file because it contains an unexpected character in line 1 and column 22.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.
+51 -87
View File
@@ -20,13 +20,23 @@
* distribution. * distribution.
*/ */
-------------------------
--defines
-------------------------
PRAGMA foreign_keys = ON;
-------------------------
--table definitions
-------------------------
CREATE TABLE IF NOT EXISTS UserAccounts ( CREATE TABLE IF NOT EXISTS UserAccounts (
uid INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(100) UNIQUE, --TODO: (3) Swap username for email address username varchar(100) UNIQUE, --TODO: (3) Swap username for email address
--server-client security --server-client security
-- passhash varchar(100), passhash varchar(100),
-- passsalt varchar(100), passsalt varchar(100),
--server controls --server controls
blacklisted BIT DEFAULT 0, blacklisted BIT DEFAULT 0,
@@ -39,8 +49,8 @@ CREATE TABLE IF NOT EXISTS LiveCharacters (
uid INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
--metadata --metadata
owner INTEGER REFERENCES Accounts(uid), owner INTEGER REFERENCES UserAccounts(uid),
handle varchar(100) UNIQUE, handle varchar(100),
avatar varchar(100), avatar varchar(100),
birth timestamp NOT NULL DEFAULT (datetime()), birth timestamp NOT NULL DEFAULT (datetime()),
@@ -48,59 +58,8 @@ CREATE TABLE IF NOT EXISTS LiveCharacters (
roomIndex INTEGER DEFAULT 0, roomIndex INTEGER DEFAULT 0,
originX INTEGER DEFAULT 0, originX INTEGER DEFAULT 0,
originY INTEGER DEFAULT 0, originY INTEGER DEFAULT 0,
boundsX INTEGER DEFAULT 0,
boundsY INTEGER DEFAULT 0,
boundsW INTEGER DEFAULT 0,
boundsH INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS DeadCharacters ( --combat stats
uid INTEGER PRIMARY KEY,
--metadata
owner INTEGER REFERENCES Accounts(uid),
handle varchar(100),
avatar varchar(100),
birth timestamp NOT NULL
);
CREATE TABLE IF NOT EXISTS LiveMonsters (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
--metadata
handle varchar(100) UNIQUE,
avatar varchar(100),
--actions
-- script
--physically exists in the world
roomIndex INTEGER DEFAULT 0,
originX INTEGER DEFAULT 0,
originY INTEGER DEFAULT 0,
boundsX INTEGER DEFAULT 0,
boundsY INTEGER DEFAULT 0,
boundsW INTEGER DEFAULT 0,
boundsH INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS DeadMonsters (
uid INTEGER PRIMARY KEY,
--metadata
handle varchar(100) UNIQUE,
avatar varchar(100)
);
-------------------------
--Utility tables
-------------------------
CREATE TABLE IF NOT EXISTS StatisticSets (
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
--general use statistics
level INTEGER DEFAULT 0, level INTEGER DEFAULT 0,
exp INTEGER DEFAULT 0, exp INTEGER DEFAULT 0,
maxHP INTEGER DEFAULT 0, maxHP INTEGER DEFAULT 0,
@@ -111,48 +70,53 @@ CREATE TABLE IF NOT EXISTS StatisticSets (
defence INTEGER DEFAULT 0, defence INTEGER DEFAULT 0,
intelligence INTEGER DEFAULT 0, intelligence INTEGER DEFAULT 0,
resistance INTEGER DEFAULT 0, resistance INTEGER DEFAULT 0,
accuracy INTEGER DEFAULT 0,
evasion INTEGER DEFAULT 0,
speed INTEGER DEFAULT 0, speed INTEGER DEFAULT 0,
accuracy REAL DEFAULT 0.0, luck INTEGER DEFAULT 0
evasion REAL DEFAULT 0.0,
luck REAL DEFAULT 0.0
); );
CREATE TABLE IF NOT EXISTS InWorldItems ( CREATE TABLE IF NOT EXISTS DeadCharacters (
uid INTEGER PRIMARY KEY,
--metadata --metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT, owner INTEGER REFERENCES UserAccounts(uid),
itemType INTEGER, handle varchar(100),
avatar varchar(100),
birth timestamp NOT NULL,
death timestamp NOT NULL DEFAULT (datetime()),
--position in the world --combat stats
roomIndex INTEGER DEFAULT 0, level INTEGER DEFAULT 0,
originX INTEGER DEFAULT 0, exp INTEGER DEFAULT 0,
originY INTEGER DEFAULT 0, maxHP INTEGER DEFAULT 0,
maxMP INTEGER DEFAULT 0,
--unique information attack INTEGER DEFAULT 0,
stackSize INTEGER DEFAULT 0, defence INTEGER DEFAULT 0,
durability INTEGER DEFAULT 0, intelligence INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid) resistance INTEGER DEFAULT 0,
accuracy INTEGER DEFAULT 0,
evasion INTEGER DEFAULT 0,
speed INTEGER DEFAULT 0,
luck INTEGER DEFAULT 0
); );
-------------------------
--global tables
-------------------------
CREATE TABLE IF NOT EXISTS InventoryItems ( CREATE TABLE IF NOT EXISTS InventoryItems (
--metadata --metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
owner INTEGER REFERENCES Characters(uid), name varchar(100) UNIQUE,
itemType INTEGER, type varchar(100), --tmp type
--unique information --unique information
stackSize INTEGER DEFAULT 0, durability INTEGER DEFAULT 0
durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid)
); );
CREATE TABLE IF NOT EXISTS WornEquipment ( -------------------------
--metadata --member tables
uid INTEGER PRIMARY KEY AUTOINCREMENT, -------------------------
owner INTEGER REFERENCES Characters(uid),
itemType INTEGER,
--unique information --TODO
durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid)
--attached script?
);
+23
View File
@@ -0,0 +1,23 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "inventory.hpp"
+35
View File
@@ -0,0 +1,35 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "item_data.hpp"
#include <list>
class Inventory {
public:
Inventory() = default;
~Inventory() = default;
private:
std::list<ItemData> itemList;
};
+23
View File
@@ -0,0 +1,23 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "inventory_manager.hpp"
+33
View File
@@ -0,0 +1,33 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "inventory.hpp"
class InventoryManager {
public:
InventoryManager() = default;
~InventoryManager() = default;
private:
//
};
@@ -19,33 +19,20 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#include "combat_instance.hpp" #include "item_data.hpp"
CombatInstance::CombatInstance() { ItemType ItemData::SetItemType(ItemType t) {
// return type = t;
} }
CombatInstance::~CombatInstance() { ItemType ItemData::GetItemType() {
// return type;
} }
void CombatInstance::Update() { int ItemData::SetQuantity(int i) {
// return quantity = i;
} }
//accessors and mutators int ItemData::GetQuantity() {
void CombatInstance::PushCharacter(CharacterData* const characterData) { return quantity;
//
}
void CombatInstance::PopCharacter(CharacterData* const characterData) {
//
}
void CombatInstance::PushCreature(CreatureData* const creatureData) {
//
}
void CombatInstance::PopCreature(CreatureData* const creatureData) {
//
} }
+41
View File
@@ -0,0 +1,41 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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.
*/
#pragma once
#include "item_type.hpp"
class ItemData {
public:
ItemData() = default;
~ItemData() = default;
//accessors and mutators
ItemType SetItemType(ItemType);
ItemType GetItemType();
int SetQuantity(int);
int GetQuantity();
private:
ItemType type;
int quantity = 1;
};
@@ -1,5 +1,5 @@
#config #config
INCLUDES+=. .. ../characters ../creatures ../entities ../../common/gameplay ../../common/utilities INCLUDES+=. ../../common/gameplay
LIBS+= LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
@@ -52,15 +52,17 @@ static int getTag(lua_State* L) {
return 1; return 1;
} }
static int setInstance(lua_State* L) { /*
static int setBattleIndex(lua_State* L) {
BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1));
barrier->SetInstanceIndex(lua_tointeger(L, 2)); barrier->SetBattleIndex(lua_tointeger(L, 2));
return 0; return 0;
} }
*/
static int getInstance(lua_State* L) { static int getBattleIndex(lua_State* L) {
BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1)); BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1));
lua_pushinteger(L, barrier->GetInstanceIndex()); lua_pushinteger(L, barrier->GetBattleIndex());
return 1; return 1;
} }
@@ -81,8 +83,8 @@ static const luaL_Reg barrierLib[] = {
{"GetScript", getScript}, {"GetScript", getScript},
{"SetTag", setTag}, {"SetTag", setTag},
{"GetTag", getTag}, {"GetTag", getTag},
{"SetInstance", setInstance}, // {"SetBattleIndex", setBattleIndex},
{"GetInstance", getInstance}, {"GetBattleIndex", getBattleIndex},
{"SetStatus", setStatus}, {"SetStatus", setStatus},
{"GetStatus", getStatus}, {"GetStatus", getStatus},
{nullptr, nullptr} {nullptr, nullptr}
@@ -28,8 +28,15 @@
BarrierData::BarrierData(int i): BarrierData::BarrierData(int i):
Entity::Entity("barrier") Entity::Entity("barrier")
{ {
instanceIndex = i; battleIndex = i;
memset(status, 0, sizeof(int) * 8); memset(status, 0, sizeof(int) * 8);
SetBounds({
BARRIER_BOUNDS_X,
BARRIER_BOUNDS_Y,
BARRIER_BOUNDS_WIDTH,
BARRIER_BOUNDS_HEIGHT
});
} }
BarrierData::~BarrierData() { BarrierData::~BarrierData() {
@@ -39,6 +46,7 @@ BarrierData::~BarrierData() {
int BarrierData::Update(lua_State* L) { int BarrierData::Update(lua_State* L) {
int ret = 0; int ret = 0;
//NOTE: this is here mostly for the "barrier tick" effect
if (scriptRef != LUA_NOREF) { if (scriptRef != LUA_NOREF) {
//Call the script reference //Call the script reference
lua_pushinteger(L, scriptRef); lua_pushinteger(L, scriptRef);
@@ -77,12 +85,12 @@ std::string BarrierData::GetTag(std::string key) {
return tags[key]; return tags[key];
} }
int BarrierData::SetInstanceIndex(int i) { int BarrierData::SetBattleIndex(int i) {
return instanceIndex = i; return battleIndex = i;
} }
int BarrierData::GetInstanceIndex() const { int BarrierData::GetBattleIndex() const {
return instanceIndex; return battleIndex;
} }
int BarrierData::SetStatus(int k, int v) { int BarrierData::SetStatus(int k, int v) {
@@ -21,6 +21,7 @@
*/ */
#pragma once #pragma once
#include "barrier_defines.hpp"
#include "entity.hpp" #include "entity.hpp"
#include "lua.hpp" #include "lua.hpp"
@@ -30,7 +31,7 @@
class BarrierData: public Entity { class BarrierData: public Entity {
public: public:
BarrierData(int instanceIndex); BarrierData(int battleIndex);
~BarrierData(); ~BarrierData();
int Update(lua_State*); int Update(lua_State*);
@@ -38,11 +39,12 @@ public:
int SetScriptReference(int); int SetScriptReference(int);
int GetScriptReference(); int GetScriptReference();
//NOTE: Why does this have tags? Are the tags used?
std::string SetTag(std::string key, std::string value); std::string SetTag(std::string key, std::string value);
std::string GetTag(std::string key); std::string GetTag(std::string key);
int SetInstanceIndex(int i); int SetBattleIndex(int i);
int GetInstanceIndex() const; int GetBattleIndex() const;
int SetStatus(int k, int v); int SetStatus(int k, int v);
int GetStatus(int k); int GetStatus(int k);
@@ -53,7 +55,7 @@ private:
int scriptRef = LUA_NOREF; int scriptRef = LUA_NOREF;
std::map<std::string, std::string> tags; std::map<std::string, std::string> tags;
int instanceIndex; int battleIndex;
int status[8]; int status[8];
}; };
@@ -27,6 +27,7 @@
#include "sqlite3.h" #include "sqlite3.h"
#include <algorithm> #include <algorithm>
#include <functional>
#include <list> #include <list>
#include <map> #include <map>
+32
View File
@@ -0,0 +1,32 @@
#config
INCLUDES+=. .. ../characters ../creatures ../entities ../inventory ../../common/gameplay ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=..
OUT=$(addprefix $(OUTDIR)/,server.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
+75
View File
@@ -0,0 +1,75 @@
/* Copyright: (c) Kayne Ruse 2013-2016
*
* 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 "battle_data.hpp"
#include <algorithm>
BattleData::BattleData() {
for (int i = 0; i < BATTLE_SIZE; i++) {
characterArray[i] = nullptr;
creatureArray[i] = nullptr;
}
}
BattleData::~BattleData() {
for (int i = 0; i < BATTLE_SIZE; i++) {
if (characterArray[i] != nullptr || creatureArray[i] != nullptr) {
//breaking a cardinal sin
throw(std::runtime_error("BattleData not empty on destruction"));
}
}
}
void BattleData::Update() {
//TODO: (0) EMPTY
}
//accessors and mutators
int BattleData::PushCharacter(CharacterData* const characterData) {
//push the character into the battle object
for (int i = 0; i < BATTLE_SIZE; i++) {
if (characterArray[i] == nullptr) {
characterArray[i] = characterData;
return 1;
}
}
return 0;
}
int BattleData::PopCharacter(CharacterData const * const characterData) {
//pop the character from the battle object
for (int i = 0; i < BATTLE_SIZE; i++) {
if (characterArray[i] == characterData) {
characterArray[i] = nullptr;
return 1;
}
}
return 0;
}
int BattleData::PushCreature(CreatureData* const creatureData) {
//TODO: (0) EMPTY
}
int BattleData::PopCreature(CreatureData const * const creatureData) {
//TODO: (0) EMPTY
}
@@ -24,21 +24,25 @@
#include "character_data.hpp" #include "character_data.hpp"
#include "creature_data.hpp" #include "creature_data.hpp"
class CombatInstance { #include <functional>
class BattleData {
public: public:
CombatInstance(); constexpr static int BATTLE_SIZE = 8;
~CombatInstance();
BattleData();
~BattleData();
void Update(); void Update();
//accessors and mutators //accessors and mutators
void PushCharacter(CharacterData* const characterData); int PushCharacter(CharacterData* const characterData);
void PopCharacter(CharacterData* const characterData); int PopCharacter(CharacterData const * const characterData);
void PushCreature(CreatureData* const creatureData); int PushCreature(CreatureData* const creatureData);
void PopCreature(CreatureData* const creatureData); int PopCreature(CreatureData const * const creatureData);
private: private:
std::array<CharacterData*, 8> characterArray; std::array<CharacterData*, BATTLE_SIZE> characterArray;
std::array<CreatureData*, 8> creatureArray; std::array<CreatureData*, BATTLE_SIZE> creatureArray;
}; };
@@ -19,26 +19,26 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#include "combat_instance_manager.hpp" #include "battle_manager.hpp"
CombatInstanceManager::CombatInstanceManager() { BattleManager::BattleManager() {
//EMPTY //EMPTY
} }
CombatInstanceManager::~CombatInstanceManager() { BattleManager::~BattleManager() {
UnloadAll(); UnloadAll();
} }
//arg: a list of combats to be updated in the clients //arg: a list of combats to be updated in the clients
void CombatInstanceManager::Update() { void BattleManager::Update() {
for (auto& it : elementMap) { for (auto& it : elementMap) {
it.second.Update(); it.second.Update();
} }
} }
int CombatInstanceManager::Create() { int BattleManager::Create() {
//implicitly create the new object //implicitly create the new object
elementMap.emplace( std::pair<int, CombatInstance>(counter, CombatInstance()) ); elementMap.emplace( std::pair<int, BattleData>(counter, BattleData()) );
//TODO: do various things like saving to the database //TODO: do various things like saving to the database
return counter++; return counter++;
@@ -46,16 +46,16 @@ int CombatInstanceManager::Create() {
//TODO: (1) combat load, save //TODO: (1) combat load, save
void CombatInstanceManager::Unload(int uid) { void BattleManager::Unload(int uid) {
elementMap.erase(uid); elementMap.erase(uid);
} }
void CombatInstanceManager::UnloadAll() { void BattleManager::UnloadAll() {
elementMap.clear(); elementMap.clear();
} }
void CombatInstanceManager::UnloadIf(std::function<bool(std::pair<const int, CombatInstance const&>)> fn) { void BattleManager::UnloadIf(std::function<bool(std::pair<const int, BattleData const&>)> fn) {
std::map<int, CombatInstance>::iterator it = elementMap.begin(); std::map<int, BattleData>::iterator it = elementMap.begin();
while (it != elementMap.end()) { while (it != elementMap.end()) {
if (fn(*it)) { if (fn(*it)) {
it = elementMap.erase(it); it = elementMap.erase(it);
@@ -66,8 +66,8 @@ void CombatInstanceManager::UnloadIf(std::function<bool(std::pair<const int, Com
} }
} }
CombatInstance* CombatInstanceManager::Find(int uid) { BattleData* BattleManager::Find(int uid) {
std::map<int, CombatInstance>::iterator it = elementMap.find(uid); std::map<int, BattleData>::iterator it = elementMap.find(uid);
if (it == elementMap.end()) { if (it == elementMap.end()) {
return nullptr; return nullptr;
@@ -76,26 +76,26 @@ CombatInstance* CombatInstanceManager::Find(int uid) {
return &it->second; return &it->second;
} }
int CombatInstanceManager::GetLoadedCount() { int BattleManager::GetLoadedCount() {
return elementMap.size(); return elementMap.size();
} }
std::map<int, CombatInstance>* CombatInstanceManager::GetContainer() { std::map<int, BattleData>* BattleManager::GetContainer() {
return &elementMap; return &elementMap;
} }
lua_State* CombatInstanceManager::SetLuaState(lua_State* L) { lua_State* BattleManager::SetLuaState(lua_State* L) {
return lua = L; return lua = L;
} }
lua_State* CombatInstanceManager::GetLuaState() { lua_State* BattleManager::GetLuaState() {
return lua; return lua;
} }
sqlite3* CombatInstanceManager::SetDatabase(sqlite3* db) { sqlite3* BattleManager::SetDatabase(sqlite3* db) {
return database = db; return database = db;
} }
sqlite3* CombatInstanceManager::GetDatabase() { sqlite3* BattleManager::GetDatabase() {
return database; return database;
} }
@@ -21,7 +21,7 @@
*/ */
#pragma once #pragma once
#include "combat_instance.hpp" #include "battle_data.hpp"
#include "lua.hpp" #include "lua.hpp"
#include "sqlite3.h" #include "sqlite3.h"
@@ -29,10 +29,10 @@
#include <algorithm> #include <algorithm>
#include <map> #include <map>
class CombatInstanceManager { class BattleManager {
public: public:
CombatInstanceManager(); BattleManager();
~CombatInstanceManager(); ~BattleManager();
//common public methods //common public methods
void Update(); void Update();
@@ -41,12 +41,12 @@ public:
void Unload(int uid); void Unload(int uid);
void UnloadAll(); void UnloadAll();
void UnloadIf(std::function<bool(std::pair<const int, CombatInstance const&>)> fn); void UnloadIf(std::function<bool(std::pair<const int, BattleData const&>)> fn);
//accessors & mutators //accessors & mutators
CombatInstance* Find(int uid); BattleData* Find(int uid);
int GetLoadedCount(); int GetLoadedCount();
std::map<int, CombatInstance>* GetContainer(); std::map<int, BattleData>* GetContainer();
//hooks //hooks
lua_State* SetLuaState(lua_State* L); lua_State* SetLuaState(lua_State* L);
@@ -56,7 +56,7 @@ public:
private: private:
//members //members
std::map<int, CombatInstance> elementMap; std::map<int, BattleData> elementMap;
int counter = 0; int counter = 0;
lua_State* lua = nullptr; lua_State* lua = nullptr;
sqlite3* database = nullptr; sqlite3* database = nullptr;
+32
View File
@@ -0,0 +1,32 @@
#config
INCLUDES+=. .. ../characters ../creatures ../entities ../inventory ../../common/gameplay ../../common/utilities
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
#output
OUTDIR=..
OUT=$(addprefix $(OUTDIR)/,server.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
+26 -27
View File
@@ -28,53 +28,51 @@
#include "server_utilities.hpp" #include "server_utilities.hpp"
#include <stdexcept> #include <stdexcept>
#include <iostream>
static int setRoom(lua_State* L) { static int setRoom(lua_State* L) {
//reverse engineer the character index //variables
int characterIndex = -1;
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1)); CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
CharacterManager& characterMgr = CharacterManager::GetSingleton(); CharacterManager& characterMgr = CharacterManager::GetSingleton();
for (auto& it : *characterMgr.GetContainer()) {
if (character == &it.second) {
characterIndex = it.first;
break;
}
}
//error checking //error checking
if (characterIndex == -1) { if (characterMgr.Find(character->GetIndex()) != character) {
throw(std::runtime_error("Lua Error: Failed to find character index by reference")); throw(std::runtime_error("Lua Error: Failed to verify character index by reference"));
} }
//get the room index, depending on the parameter type //get the room index, depending on the parameter type
int roomIndex = -1; int roomIndex = -1;
RoomManager& roomMgr = RoomManager::GetSingleton();
switch(lua_type(L, 2)) { switch(lua_type(L, 2)) {
case LUA_TNUMBER: case LUA_TNUMBER:
//simple integer
roomIndex = lua_tointeger(L, 2); roomIndex = lua_tointeger(L, 2);
break; break;
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA: {
//reverse engineer the room index //check that this is a room first
for (auto& it : *roomMgr.GetContainer()) { RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 2));
if (lua_touserdata(L, 2) == &it.second) { RoomManager& roomMgr = RoomManager::GetSingleton();
roomIndex = it.first;
break;
}
}
break;
}
//error checking if (roomMgr.Find(room->GetRoomIndex()) != room) {
if (roomIndex == -1) { std::cout << room->GetRoomIndex() << std::endl;
throw(std::runtime_error("Lua Error: Failed to find room index by reference")); throw(std::runtime_error("Lua Error: Failed to verify room index by reference"));
}
roomIndex = room->GetRoomIndex();
}
break;
default:
throw(std::runtime_error("Lua Error: Failed to find room index by reference"));
} }
//send the delete & create messages //send the delete & create messages
pumpAndChangeRooms(character, roomIndex, characterIndex); pumpAndChangeRooms(character, roomIndex, character->GetIndex());
return 0; return 0;
} }
static int getIndex(lua_State* L) {
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
lua_pushinteger(L, character->GetIndex());
return 1;
}
static int getOwner(lua_State* L) { static int getOwner(lua_State* L) {
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1)); CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
lua_pushinteger(L, character->GetOwner()); lua_pushinteger(L, character->GetOwner());
@@ -95,6 +93,7 @@ static int getAvatar(lua_State* L) {
static const luaL_Reg characterLib[] = { static const luaL_Reg characterLib[] = {
{"SetRoom", setRoom}, {"SetRoom", setRoom},
{"GetIndex", getIndex},
// {"GetOwner", getOwner}, //unusable without account API // {"GetOwner", getOwner}, //unusable without account API
{"GetHandle", getHandle}, {"GetHandle", getHandle},
{"GetAvatar", getAvatar}, {"GetAvatar", getAvatar},
+12
View File
@@ -30,6 +30,14 @@ CharacterData::CharacterData(): Entity("character") {
}); });
} }
//-------------------------
//database stuff
//-------------------------
int CharacterData::GetIndex() {
return index;
}
int CharacterData::GetOwner() { int CharacterData::GetOwner() {
return owner; return owner;
} }
@@ -41,3 +49,7 @@ std::string CharacterData::GetHandle() {
std::string CharacterData::GetAvatar() { std::string CharacterData::GetAvatar() {
return avatar; return avatar;
} }
Inventory* CharacterData::GetInventory() {
return &inventory;
}
+6
View File
@@ -24,6 +24,7 @@
//components //components
#include "character_defines.hpp" #include "character_defines.hpp"
#include "entity.hpp" #include "entity.hpp"
#include "inventory.hpp"
//std namespace //std namespace
#include <string> #include <string>
@@ -35,14 +36,19 @@ public:
~CharacterData() = default; ~CharacterData() = default;
//database stuff //database stuff
int GetIndex();
int GetOwner(); int GetOwner();
std::string GetHandle(); std::string GetHandle();
std::string GetAvatar(); std::string GetAvatar();
Inventory* GetInventory();
private: private:
friend class CharacterManager; friend class CharacterManager;
//database stuff
int index = -1;
int owner = -1; int owner = -1;
std::string handle; std::string handle;
std::string avatar; std::string avatar;
Inventory inventory;
}; };
+10 -29
View File
@@ -39,12 +39,8 @@
static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters (" static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters ("
"owner, " "owner, "
"handle, " "handle, "
"avatar, " "avatar "
"boundsX, " ") VALUES (?1, ?2, ?3);";
"boundsY, "
"boundsW, "
"boundsH"
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
static const char* LOAD_CHARACTER = "SELECT " static const char* LOAD_CHARACTER = "SELECT "
"uid, " "uid, "
@@ -53,21 +49,13 @@ static const char* LOAD_CHARACTER = "SELECT "
"avatar, " "avatar, "
"roomIndex, " "roomIndex, "
"originX, " "originX, "
"originY, " "originY "
"boundsX, "
"boundsY, "
"boundsW, "
"boundsH "
"FROM LiveCharacters WHERE handle = ?;"; "FROM LiveCharacters WHERE handle = ?;";
static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET " static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET "
"roomIndex = ?2, " "roomIndex = ?2, "
"originX = ?3, " "originX = ?3, "
"originY = ?4, " "originY = ?4 "
"boundsX = ?5, "
"boundsY = ?6, "
"boundsW = ?7, "
"boundsH = ?8 "
"WHERE uid = ?1;"; "WHERE uid = ?1;";
static const char* DELETE_CHARACTER = "DELETE FROM LiveCharacters WHERE uid = ?;"; static const char* DELETE_CHARACTER = "DELETE FROM LiveCharacters WHERE uid = ?;";
@@ -93,10 +81,6 @@ int CharacterManager::Create(int owner, std::string handle, std::string avatar)
ret |= sqlite3_bind_int(statement, 1, owner); 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, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC); ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
ret |= sqlite3_bind_int(statement, 4, CHARACTER_BOUNDS_X);
ret |= sqlite3_bind_int(statement, 5, CHARACTER_BOUNDS_Y);
ret |= sqlite3_bind_int(statement, 6, CHARACTER_BOUNDS_WIDTH);
ret |= sqlite3_bind_int(statement, 7, CHARACTER_BOUNDS_HEIGHT);
//check for binding errors //check for binding errors
if (ret) { if (ret) {
@@ -157,6 +141,7 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) {
CharacterData& newChar = elementMap[uid]; CharacterData& newChar = elementMap[uid];
//metadata //metadata
newChar.index = uid;
newChar.owner = owner; newChar.owner = owner;
newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2)); newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2));
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3)); newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
@@ -167,10 +152,10 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) {
newChar.origin.x = (double)sqlite3_column_int(statement, 5); newChar.origin.x = (double)sqlite3_column_int(statement, 5);
newChar.origin.y = (double)sqlite3_column_int(statement, 6); newChar.origin.y = (double)sqlite3_column_int(statement, 6);
//bounds //bounds
newChar.bounds.x = (int)sqlite3_column_int(statement, 7); newChar.bounds.x = CHARACTER_BOUNDS_X;
newChar.bounds.y = (int)sqlite3_column_int(statement, 8); newChar.bounds.y = CHARACTER_BOUNDS_Y;
newChar.bounds.w = (int)sqlite3_column_int(statement, 9); newChar.bounds.w = CHARACTER_BOUNDS_WIDTH;
newChar.bounds.h = (int)sqlite3_column_int(statement, 10); newChar.bounds.h = CHARACTER_BOUNDS_HEIGHT;
//gameplay components: equipment, items, buffs, debuffs... //gameplay components: equipment, items, buffs, debuffs...
@@ -212,12 +197,8 @@ int CharacterManager::Save(int uid) {
ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK; ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 5, character.bounds.x) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 6, character.bounds.y) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 7, character.bounds.w) != SQLITE_OK;
ret |= sqlite3_bind_int(statement, 8, character.bounds.h) != SQLITE_OK;
//gameplay components: equipment, items, buffs, debuffs... //TODO: gameplay components: equipment, items, buffs, debuffs...
//check for binding errors //check for binding errors
if (ret) { if (ret) {
+1 -1
View File
@@ -1,5 +1,5 @@
#config #config
INCLUDES+=. .. ../combat ../creatures ../entities ../monsters ../rooms ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities INCLUDES+=. .. ../barriers ../battles ../creatures ../entities ../monsters ../inventory ../rooms ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
LIBS+= LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+4 -2
View File
@@ -1,5 +1,5 @@
#include directories #include directories
INCLUDES+=. accounts characters clients combat creatures entities rooms triggers ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities INCLUDES+=. accounts barriers battles characters clients creatures entities inventory rooms triggers ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities
#libraries #libraries
#the order of the $(LIBS) is important, at least for MinGW #the order of the $(LIBS) is important, at least for MinGW
@@ -30,11 +30,13 @@ OUT=$(addprefix $(OUTDIR)/,server)
#targets #targets
all: $(OBJ) $(OUT) all: $(OBJ) $(OUT)
$(MAKE) -C accounts $(MAKE) -C accounts
$(MAKE) -C barriers
$(MAKE) -C battles
$(MAKE) -C characters $(MAKE) -C characters
$(MAKE) -C clients $(MAKE) -C clients
$(MAKE) -C combat
$(MAKE) -C creatures $(MAKE) -C creatures
$(MAKE) -C entities $(MAKE) -C entities
$(MAKE) -C inventory
$(MAKE) -C rooms $(MAKE) -C rooms
$(MAKE) -C triggers $(MAKE) -C triggers
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
+1 -1
View File
@@ -1,5 +1,5 @@
#config #config
INCLUDES+=. .. ../characters ../combat ../creatures ../entities ../monsters ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities INCLUDES+=. .. ../barriers ../battles ../characters ../creatures ../entities ../inventory ../monsters ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
LIBS+= LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+162 -19
View File
@@ -31,8 +31,48 @@
#include <stack> #include <stack>
#include <stdexcept> #include <stdexcept>
//TODO: (9) character collisions should be preformed client-side /* DOCS: this is the process for RoomData::RunFrame(), read more
*
* updateAll = OnTick()
*
* characterList .UpdateAll()
* creatureMgr .Update(updateAll)
* barrierMgr .Update(updateAll)
* battleMgr .Update(updateAll)
*
* creatureMgr .SendUpdates()
* barrierMgr .SendUpdates()
* //battleMgr .SendUpdates() //TODO: incomplete
*
* triggerMgr .Compare(characterList)
*
* if (a character collides with a creature)
* barrierMgr .Create()
* battleMgr .Create()
*
* barrierMgr .Send()
*
* creatureMgr .Delete()
* endif
*
* if (a character collides with a barrier)
* //TODO: incomplete
* endif
*/
//NOTE: character collisions should be preformed client-side
void RoomData::RunFrame() { void RoomData::RunFrame() {
RunFrameUpdates(RunFrameLuaOnTick());
RunFrameTriggers();
RunFrameCharacterCreatureCollisions();
RunFrameCharacterBarrierCollisions();
}
//-------------------------
//hi-cohesion methods for one-time use
//-------------------------
bool RoomData::RunFrameLuaOnTick() {
//get the hook //get the hook
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef); lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
@@ -46,7 +86,7 @@ void RoomData::RunFrame() {
} }
//pump creatures & barriers //pump creatures & barriers
if (lua_tonumber(lua, -1)) { if (lua_tonumber(lua, -1) > 0) {
updateAll = true; updateAll = true;
} }
@@ -56,6 +96,10 @@ void RoomData::RunFrame() {
lua_pop(lua, 1); lua_pop(lua, 1);
} }
return updateAll;
}
void RoomData::RunFrameUpdates(bool updateAll) {
//lists of non-character entities that need updating client-side //lists of non-character entities that need updating client-side
std::list<std::pair<const int, CreatureData*>> creatureList; std::list<std::pair<const int, CreatureData*>> creatureList;
std::list<std::pair<const int, BarrierData*>> barrierList; std::list<std::pair<const int, BarrierData*>> barrierList;
@@ -67,7 +111,34 @@ void RoomData::RunFrame() {
creatureMgr.Update(&creatureList, updateAll); creatureMgr.Update(&creatureList, updateAll);
barrierMgr.Update(&barrierList, updateAll); barrierMgr.Update(&barrierList, updateAll);
//update the battles
battleMgr.Update();
//send the creature updates
for (auto& it : creatureList) {
CreaturePacket packet;
copyCreatureToPacket(&packet, it.second, it.first);
packet.type = SerialPacketType::CREATURE_UPDATE;
packet.roomIndex = roomIndex;
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS);
}
//send the barrier updates
for (auto& it : barrierList) {
BarrierPacket packet;
copyBarrierToPacket(&packet, it.second, it.first);
packet.type = SerialPacketType::BARRIER_UPDATE;
packet.roomIndex = roomIndex;
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS);
}
//TODO: send the battle updates
}
void RoomData::RunFrameTriggers() {
//build a list of entities for use with the triggers //build a list of entities for use with the triggers
//currently, this only uses characters
std::stack<Entity*> entityStack; std::stack<Entity*> entityStack;
for (auto& it : characterList) { for (auto& it : characterList) {
entityStack.push(it); entityStack.push(it);
@@ -75,8 +146,10 @@ void RoomData::RunFrame() {
//Compare the triggers to the entities, using their real hitboxes //Compare the triggers to the entities, using their real hitboxes
triggerMgr.Compare(entityStack); triggerMgr.Compare(entityStack);
}
//Creature/character collisions, O(m*n) void RoomData::RunFrameCharacterCreatureCollisions() {
//Creature/character collisions, O(m*n), making the barriers
for (auto characterIt : characterList) { for (auto characterIt : characterList) {
BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin(); BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin();
@@ -86,7 +159,9 @@ void RoomData::RunFrame() {
BoundingBox creatureBox = creatureIt.second.GetBounds() + creatureIt.second.GetOrigin(); BoundingBox creatureBox = creatureIt.second.GetBounds() + creatureIt.second.GetOrigin();
if (characterBox.CheckOverlap(creatureBox)) { if (characterBox.CheckOverlap(creatureBox)) {
int barrierIndex = barrierMgr.Create(-1); //create the barrier and battle
//TODO: Barrier needs data about the creatures inside it.
int barrierIndex = barrierMgr.Create(battleMgr.Create()); //link the barrier to a battle
BarrierData* barrierData = barrierMgr.Find(barrierIndex); BarrierData* barrierData = barrierMgr.Find(barrierIndex);
barrierData->SetRoomIndex(roomIndex); barrierData->SetRoomIndex(roomIndex);
barrierData->SetOrigin({ barrierData->SetOrigin({
@@ -118,26 +193,56 @@ void RoomData::RunFrame() {
creatureMgr.Unload(it); creatureMgr.Unload(it);
} }
} }
}
//send the creature updates void RoomData::RunFrameCharacterBarrierCollisions() {
for (auto& it : creatureList) { //TODO: check for character collisions with barriers, O(m*n)
CreaturePacket packet; for (auto characterIt : characterList) {
copyCreatureToPacket(&packet, it.second, it.first); //character bounds
packet.type = SerialPacketType::CREATURE_UPDATE; BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin();
packet.roomIndex = roomIndex;
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS);
}
//send the barrier updates for (auto barrierIt : *barrierMgr.GetContainer()) {
for (auto& it : barrierList) { //barrier bounds
BarrierPacket packet; BoundingBox barrierBox = barrierIt.second.GetBounds() + barrierIt.second.GetOrigin();
copyBarrierToPacket(&packet, it.second, it.first);
packet.type = SerialPacketType::BARRIER_UPDATE; //move the character to the battle screen
packet.roomIndex = roomIndex; if (characterBox.CheckOverlap(barrierBox)) {
pumpPacketProximity(reinterpret_cast<SerialPacket*>(&packet), roomIndex, it.second->GetOrigin(), INFLUENCE_RADIUS); //TODO: (0) What if the barrier is full?
//TODO: (0) What if the player logs in on top of a barrier?
//pump character unload
CharacterPacket charPacket;
charPacket.type = SerialPacketType::CHARACTER_UNLOAD;
charPacket.characterIndex = characterIt->GetIndex();
pumpPacketProximity(static_cast<SerialPacket*>(&charPacket), characterIt->GetRoomIndex());
std::cout << "CharacterList size: " << characterList.size() << std::endl;
//Actually move the character to a battle
BattleData* battle = battleMgr.Find(barrierIt.second.GetBattleIndex()); //TODO: barriers should hold the battle's pointer
battle->PushCharacter(characterIt);
PopCharacter(characterIt);
//DEBUG: output barrierIndex, battleIndex
std::cout << "CharacterList size: " << characterList.size() << std::endl;
//Send the entry message to the client
// BarrierPacket newPacket;
// newPacket.type = SerialPacketType::BARRIER_ENTRY;
// newPacket.barrierIndex = barrierIt.first;
// udpNetworkUtility.Send();
//only confirm one barrier/character collison per frame
return;
}
}
} }
} }
//-------------------------
//Utility methods
//-------------------------
std::string RoomData::SetName(std::string s) { std::string RoomData::SetName(std::string s) {
return roomName = s; return roomName = s;
} }
@@ -162,6 +267,44 @@ int RoomData::GetRoomIndex() {
return roomIndex; return roomIndex;
} }
void RoomData::PushCharacter(CharacterData* const character) {
if (!character) {
throw(std::logic_error("Failed to push a null character to RoomData"));
}
//check to see if the character is already here
for (auto& it : characterList) {
if (it == character) {
throw(std::logic_error("double insertion of CharacterData in RoomData"));
}
}
characterList.push_back(character);
}
void RoomData::PopCharacter(CharacterData const * const character) {
if (!character) {
throw(std::logic_error("Failed to pop a null character to RoomData"));
}
//check to see if the character isn't here
for (auto& it : characterList) {
if (it == character) {
characterList.remove(it);
return;
}
}
//check the battles to see if the character isn't there
for (auto& it : *battleMgr.GetContainer()) {
if (it.second.PopCharacter(character)) {
return;
}
}
throw(std::logic_error("cannot remove a non-existant instance of CharacterData in RoomData"));
}
BarrierManager* RoomData::GetBarrierMgr() { BarrierManager* RoomData::GetBarrierMgr() {
return &barrierMgr; return &barrierMgr;
} }
+12 -2
View File
@@ -23,7 +23,7 @@
#include "barrier_manager.hpp" #include "barrier_manager.hpp"
#include "character_data.hpp" #include "character_data.hpp"
#include "combat_instance_manager.hpp" #include "battle_manager.hpp"
#include "creature_manager.hpp" #include "creature_manager.hpp"
#include "region_pager_lua.hpp" #include "region_pager_lua.hpp"
#include "trigger_manager.hpp" #include "trigger_manager.hpp"
@@ -53,6 +53,9 @@ public:
int SetRoomIndex(int i); int SetRoomIndex(int i);
int GetRoomIndex(); int GetRoomIndex();
void PushCharacter(CharacterData* const character);
void PopCharacter(CharacterData const * const character);
BarrierManager* GetBarrierMgr(); BarrierManager* GetBarrierMgr();
std::list<CharacterData*>* GetCharacterList(); std::list<CharacterData*>* GetCharacterList();
CreatureManager* GetCreatureMgr(); CreatureManager* GetCreatureMgr();
@@ -74,6 +77,13 @@ public:
std::string GetTag(std::string key); std::string GetTag(std::string key);
private: private:
//hi-cohesion methods for one-time use
bool RunFrameLuaOnTick();
void RunFrameUpdates(bool updateAll);
void RunFrameTriggers();
void RunFrameCharacterCreatureCollisions();
void RunFrameCharacterBarrierCollisions();
//metadata //metadata
std::string roomName; std::string roomName;
std::string tilesetName; std::string tilesetName;
@@ -82,7 +92,7 @@ private:
int roomIndex = 0; int roomIndex = 0;
BarrierManager barrierMgr; BarrierManager barrierMgr;
std::list<CharacterData*> characterList; std::list<CharacterData*> characterList;
CombatInstanceManager CombatInstanceMgr; BattleManager battleMgr;
CreatureManager creatureMgr; CreatureManager creatureMgr;
RegionPagerLua pager; RegionPagerLua pager;
TriggerManager triggerMgr; TriggerManager triggerMgr;
+7 -9
View File
@@ -111,7 +111,7 @@ void RoomManager::UnloadIf(std::function<bool(std::pair<const int, RoomData cons
lua_pop(lua, 1); lua_pop(lua, 1);
} }
void RoomManager::PushCharacter(CharacterData* character) { void RoomManager::PushCharacter(CharacterData* const character) {
if (!character) { if (!character) {
throw(std::runtime_error("Failed to push a null character to a room")); throw(std::runtime_error("Failed to push a null character to a room"));
} }
@@ -119,27 +119,25 @@ void RoomManager::PushCharacter(CharacterData* character) {
RoomData* room = Find(character->GetRoomIndex()); RoomData* room = Find(character->GetRoomIndex());
if (!room) { if (!room) {
throw(std::runtime_error("Failed to push an character to a non-existant room")); throw(std::runtime_error("Failed to push a character to a non-existant room"));
} }
room->GetCharacterList()->push_back(character); room->PushCharacter(character);
} }
void RoomManager::PopCharacter(CharacterData const* character) { void RoomManager::PopCharacter(CharacterData const * const character) {
//NOTE: to pop an character from a room, the character must first exist //NOTE: to pop an character from a room, the character must first exist
if (!character) { if (!character) {
throw(std::runtime_error("Failed to pop a null character to a room")); throw(std::runtime_error("Failed to pop a null character from a room"));
} }
RoomData* room = Find(character->GetRoomIndex()); RoomData* room = Find(character->GetRoomIndex());
if (!room) { if (!room) {
throw(std::runtime_error("Failed to pop an character to a non-existant room")); throw(std::runtime_error("Failed to pop a character to a non-existant room"));
} }
room->GetCharacterList()->remove_if([character](CharacterData* ptr) { room->PopCharacter(character);
return character == ptr;
});
} }
//TODO: rename these functions from Get to Find //TODO: rename these functions from Get to Find
+2 -2
View File
@@ -39,8 +39,8 @@ public:
void UnloadAll(); void UnloadAll();
void UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn); void UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn);
void PushCharacter(CharacterData* character); void PushCharacter(CharacterData* const character);
void PopCharacter(CharacterData const* character); void PopCharacter(CharacterData const * const character);
//accessors and mutators //accessors and mutators
RoomData* Find(int uid); RoomData* Find(int uid);
+29 -4
View File
@@ -596,11 +596,36 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
//respond with all character data //respond with all character data
CharacterPacket newPacket; CharacterPacket newPacket;
for (auto& it : *characterMgr.GetContainer()) { //retrieve all character data
if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) { if (argPacket->roomIndex == -1) {
continue; for (auto& it : *characterMgr.GetContainer()) {
copyCharacterToPacket(&newPacket, &it.second, it.first);
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
} }
copyCharacterToPacket(&newPacket, it.first); return;
}
//look for the room
RoomData* room = roomMgr.Find(argPacket->roomIndex);
//room not found
if (!room) {
//build the error message
std::ostringstream msg;
msg << "Room not found: " << argPacket->roomIndex;
//build & send the packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
for (auto& it : *room->GetCharacterList()) {
copyCharacterToPacket(&newPacket, it, it->GetIndex());
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS; newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket)); network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
} }
+1 -1
View File
@@ -195,7 +195,7 @@ void pumpAndChangeRooms(int characterIndex, int newRoomIndex) {
pumpAndChangeRooms(character, newRoomIndex, characterIndex); pumpAndChangeRooms(character, newRoomIndex, characterIndex);
} }
//TODO: (0) refactor this //NOTE: This is one of those ugly things that you just need to put up with
void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex) { void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex) {
//delete the character from the old room //delete the character from the old room
CharacterPacket newPacket; CharacterPacket newPacket;
+19 -20
View File
@@ -1,26 +1,25 @@
TODO: Resource manager TODO: Resource manager
TODO: Add the TextureLoader
TODO: Consistency for bounds names TODO: Consistency for bounds names
TODO: Cross compiler (to replace dead linux PC ;_;) TODO: Cross compiler (to replace dead linux PC ;_;)
TODO: New button graphics TODO: New button graphics?
TODO: New typeface TODO: New typeface
TODO: Account passwords (list) TODO: Account passwords (list)
* backbone account server OR TODO: backbone account server OR
* social network login OR TODO: social network login OR
* ... TODO: salts & hashes
* salts & hashes TODO: login screen prompting for username & password
* login screen prompting for username & password
TODO: Features TODO: Features
* Make sure login errors are sent to the client TODO: Make sure login errors are sent to the client
* Add the "home" parameter to the server's config file TODO: Add the "home" parameter to the server's config file
* Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc. (trigger system) TODO: Fix shoddy movement
* Fix shoddy movement TODO: Better UI system
* Remove the big "Shut Down" button (currently broken...) TODO: Make a way for the server owner to control the server directly
* Make a way for the server owner to control the server directly TODO: The TileSheet class should implement the surface itself
* The TileSheet class should implement the surface itself TODO: Time delay for requesting region packets
* Time delay for requesting region packets TODO: A proper logging system
* A proper logging system TODO: Fix the const-ness of accessors
* Fix the const-ness of accessors TODO: Add a screenshot of the game to README.md
* Add a screenshot of the game to README.md TODO: joystick/gamepad support
* joystick/gamepad support TODO: add the tilesheet to the map system
* add the tilesheet to the map system TODO: Better collision logic