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
+2 -2
View File
@@ -7,7 +7,7 @@ This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), a
## 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-linux.tar).
* The most recent stable build for Linux can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar).
## Documentation
@@ -52,4 +52,4 @@ Permission is granted to anyone to use this software for any purpose, including
### Items not made by me
* [Coolvetica Font](http://typodermicfonts.com/coolvetica/)
* Creative Commons Artwork from [Artsader](http://www.moosader.com/artsader/)
* Creative Commons Artwork from [Artsader](http://www.moosader.com/artsader/)
+1
View File
@@ -23,6 +23,7 @@
#include "base_barrier.hpp"
#include <functional>
#include <list>
#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 <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//-------------------------
//Public access members
//-------------------------
@@ -49,14 +51,16 @@ DisconnectedScreen::DisconnectedScreen() {
//setup the button
backButton.SetBackgroundTexture(GetRenderer(), image.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE);
backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions
backButton.SetX(50);
backButton.SetY(50);
//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
UDPNetworkUtility::GetSingleton().Unbind(Channels::SERVER);
@@ -92,7 +96,7 @@ void DisconnectedScreen::FrameEnd() {
void DisconnectedScreen::RenderFrame(SDL_Renderer* renderer) {
backButton.DrawTo(renderer);
textLine.DrawTo(renderer, 50, 30);
textLine.DrawTo(renderer);
}
//-------------------------
+15 -7
View File
@@ -27,6 +27,8 @@
#include <stdexcept>
#include <sstream>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//-------------------------
//Public access members
//-------------------------
@@ -52,11 +54,11 @@ LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
//setup the buttons
searchButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
searchButton.SetText(GetRenderer(), font, "Search", COLOR_WHITE);
searchButton.SetText(GetRenderer(), font, WHITE, "Search");
joinButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
joinButton.SetText(GetRenderer(), font, "Join", COLOR_WHITE);
joinButton.SetText(GetRenderer(), font, WHITE, "Join");
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE);
backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions (assumed)
searchButton.SetX(50);
@@ -67,6 +69,7 @@ LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
backButton.SetY(90);
//pseudo-list selection
//TODO: move this into the UI library?
boundingBox = {300, 50, 200, 12};
//hacked together a highlight box
@@ -121,8 +124,13 @@ void LobbyMenu::RenderFrame(SDL_Renderer* renderer) {
}
//draw the server's info
serverVector[i].nameImage.DrawTo(renderer, boundingBox.x, boundingBox.y + boundingBox.h * i);
serverVector[i].playerCountImage.DrawTo(renderer, boundingBox.x+276, boundingBox.y + boundingBox.h * i);
serverVector[i].nameImage.SetX(boundingBox.x);
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
serverVector.back().nameImage.SetText(GetRenderer(), font, newServer.name, color);
serverVector.back().playerCountImage.SetText(GetRenderer(), font, itoa_base10(newServer.playerCount), color);
serverVector.back().nameImage.SetText(GetRenderer(), font, color, newServer.name);
serverVector.back().playerCountImage.SetText(GetRenderer(), font, color, itoa_base10(newServer.playerCount));
}
void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
+15 -11
View File
@@ -26,6 +26,8 @@
#include <sstream>
#include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//-------------------------
//Public access members
//-------------------------
@@ -46,11 +48,11 @@ MainMenu::MainMenu() {
//setup the buttons
startButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
startButton.SetText(GetRenderer(), font, "Start", COLOR_WHITE);
startButton.SetText(GetRenderer(), font, WHITE, "Start");
optionsButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
optionsButton.SetText(GetRenderer(), font, "Options", COLOR_WHITE);
optionsButton.SetText(GetRenderer(), font, WHITE, "Options");
quitButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
quitButton.SetText(GetRenderer(), font, "Quit", COLOR_WHITE);
quitButton.SetText(GetRenderer(), font, WHITE, "Quit");
//set the button positions
startButton.SetX(50);
@@ -61,9 +63,15 @@ MainMenu::MainMenu() {
quitButton.SetY(50 + 20 * 2);
//text box
textBox.PushLine(GetRenderer(), font, "Thanks for playing!", {255, 255, 255, 255});
textBox.PushLine(GetRenderer(), font, "You can get the latest version at: ", {255, 255, 255, 255});
textBox.PushLine(GetRenderer(), font, "krgamestudios.com", {255, 255, 255, 255}); //TODO: (9) click to open the website/update
int h = -1;
SDL_RenderGetLogicalSize(GetRenderer(), nullptr, &h);
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
//
@@ -93,11 +101,7 @@ void MainMenu::RenderFrame(SDL_Renderer* renderer) {
startButton.DrawTo(renderer);
optionsButton.DrawTo(renderer);
quitButton.DrawTo(renderer);
int h = -1;
SDL_RenderGetLogicalSize(GetRenderer(), nullptr, &h);
textBox.DrawTo(renderer, 50, h-50, -12);
textBox.DrawTo(renderer);
}
//-------------------------
+7 -3
View File
@@ -26,6 +26,8 @@
#include <sstream>
#include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//-------------------------
//Public access members
//-------------------------
@@ -46,14 +48,16 @@ OptionsMenu::OptionsMenu() {
//setup the button
backButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
backButton.SetText(GetRenderer(), font, "Back", COLOR_WHITE);
backButton.SetText(GetRenderer(), font, WHITE, "Back");
//set the button positions
backButton.SetX(50);
backButton.SetY(50);
//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() {
@@ -78,7 +82,7 @@ void OptionsMenu::FrameEnd() {
void OptionsMenu::RenderFrame(SDL_Renderer* renderer) {
backButton.DrawTo(renderer);
textLine.DrawTo(renderer, 50, 30);
textLine.DrawTo(renderer);
}
//-------------------------
+14 -45
View File
@@ -34,6 +34,8 @@
#include <sstream>
#include <stdexcept>
constexpr SDL_Color WHITE = {255, 255, 255, 255};
//-------------------------
//static functions
//-------------------------
@@ -72,9 +74,9 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
//setup the buttons
disconnectButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
disconnectButton.SetText(GetRenderer(), font, "Disconnect", COLOR_WHITE);
disconnectButton.SetText(GetRenderer(), font, WHITE, "Disconnect");
shutdownButton.SetBackgroundTexture(GetRenderer(), buttonImage.GetTexture());
shutdownButton.SetText(GetRenderer(), font, "Shutdown", COLOR_WHITE);
shutdownButton.SetText(GetRenderer(), font, WHITE, "Shutdown");
//set the button positions
disconnectButton.SetX(50);
@@ -159,7 +161,12 @@ void World::Update() {
delete reinterpret_cast<char*>(packetBuffer);
//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
for (auto& it : characterMap) {
@@ -261,12 +268,12 @@ void World::RenderFrame(SDL_Renderer* renderer) {
shutdownButton.DrawTo(renderer);
//FPS
fpsTextLine.DrawTo(renderer, 0, 0);
fpsTextLine.DrawTo(renderer);
int fpsRet = fps.Calculate();
if (fpsRet != -1) {
std::ostringstream msg;
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) {
//heartbeat system
case SerialPacketType::PING:
hPing(static_cast<ServerPacket*>(argPacket));
heartbeatUtility.hPing(static_cast<ServerPacket*>(argPacket));
break;
case SerialPacketType::PONG:
hPong(static_cast<ServerPacket*>(argPacket));
heartbeatUtility.hPong(static_cast<ServerPacket*>(argPacket));
break;
//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
//-------------------------
+2 -9
View File
@@ -43,6 +43,7 @@
#include "base_scene.hpp"
#include "base_barrier.hpp"
#include "base_creature.hpp"
#include "heartbeat_utility.hpp"
#include "local_character.hpp"
#include "SDL2/SDL.h"
@@ -80,12 +81,6 @@ private:
//handle incoming traffic
void HandlePacket(SerialPacket* const);
//heartbeat system
void hPing(ServerPacket* const);
void hPong(ServerPacket* const);
void CheckHeartBeat();
//basic connections
void SendLogoutRequest();
void SendDisconnectRequest();
@@ -165,11 +160,9 @@ private:
LocalCharacter* localCharacter = nullptr;
//heartbeat
//TODO: (2) Heartbeat needs it's own utility
HeartbeatUtility heartbeatUtility;
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
int attemptedBeats = 0;
//ugly references; I hate this
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 "render_text_texture.hpp"
#include <stdexcept>
void Button::DrawTo(SDL_Renderer* renderer) {
@@ -51,19 +53,9 @@ void Button::SetBackgroundTexture(SDL_Renderer* renderer, SDL_Texture* texture)
image.SetClipH(image.GetClipH() / 3);
}
void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, std::string s, SDL_Color color) {
//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"));
}
void Button::SetText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string s) {
//convert to texture
SDL_Texture* text = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf);
if (!text) {
throw(std::runtime_error("Failed to create a TTF texture"));
}
SDL_Texture* text = renderTextTexture(renderer, font, color, s);
//get the dimensions & rects
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);
}
void Button::SetX(int x) {
posX = x;
}
void Button::SetY(int y) {
posY = y;
}
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& event) {
//if out of bounds, exit
if (!CheckBounds(event.x, event.y)) {
@@ -156,6 +140,22 @@ Button::State Button::GetState() {
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) {
//return if true (x, y) is within bounds, otherwise return false
return !(
+8 -9
View File
@@ -27,11 +27,6 @@
#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 {
public:
enum State {
@@ -46,9 +41,7 @@ public:
//setup
void SetBackgroundTexture(SDL_Renderer*, SDL_Texture*);
void SetText(SDL_Renderer*, TTF_Font*, std::string, SDL_Color);
void SetX(int x);
void SetY(int y);
void SetText(SDL_Renderer*, TTF_Font*, SDL_Color, std::string);
//capture input
State MouseMotion(SDL_MouseMotionEvent const&);
@@ -59,10 +52,16 @@ public:
void SetState(State); //TODO: idle, busy or disabled
State GetState();
//accessors & mutators
int SetX(int x);
int SetY(int y);
int GetX() const;
int GetY() const;
protected:
bool CheckBounds(int x, int y);
Image image;
int posX = 0, posY = 0;
State state = State::IDLE;
int posX = 0, posY = 0;
};
+1 -1
View File
@@ -1,5 +1,5 @@
#config
INCLUDES+=.
INCLUDES+=. ../utilities
LIBS+=
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++) {
it->DrawTo(renderer, posX, posY);
posY += pointSize;
it->SetX(posX);
it->SetY(renderY);
it->DrawTo(renderer);
renderY += it->GetPointHeight();
}
}
void TextBox::PushLine(SDL_Renderer* renderer, TTF_Font* font, std::string str, SDL_Color color) {
lineList.emplace_front(renderer, font, str, color);
void TextBox::PushLine(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color, std::string str) {
lineList.emplace_back(renderer, font, color, str, 0, 0);
}
void TextBox::PopLine(int num) {
@@ -47,10 +50,26 @@ void TextBox::PopLine(int num) {
num < lineList.size() ? num : lineList.size();
for (int i = 0; i < num; ++i) {
lineList.pop_back();
lineList.pop_front();
}
}
void TextBox::ClearLines() {
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();
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 ClearLines();
int SetX(int i);
int SetY(int i);
int GetX() const;
int GetY() const;
private:
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 "render_text_texture.hpp"
#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(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() {
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_QueryTexture(texture, nullptr, nullptr, &dclip.w, &dclip.h);
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
SDL_DestroyTexture(texture);
texture = renderTextTexture(renderer, font, str, color);
texture = renderTextTexture(renderer, font, color, str);
pointHeight = TTF_FontHeight(font);
}
void TextLine::ClearText() {
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>
SDL_Texture* renderTextTexture(SDL_Renderer*, TTF_Font*, std::string, SDL_Color color);
class TextLine {
public:
TextLine();
TextLine(SDL_Renderer* r, TTF_Font* f, std::string s, SDL_Color c)
{ SetText(r, f, s, c); }
TextLine(SDL_Renderer*, TTF_Font*, SDL_Color, std::string, int x, int y);
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();
//accessors & mutators
int SetX(int i);
int SetY(int i);
int GetX() const;
int GetY() const;
//utility
int GetPointHeight();
protected:
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;
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20160404;
constexpr int NETWORK_VERSION = 20160825;
union MaxPacket {
CharacterPacket a;
ClientPacket b;
CreaturePacket c;
RegionPacket d;
ServerPacket e;
TextPacket f;
BarrierPacket a;
CharacterPacket b;
ClientPacket c;
CreaturePacket d;
RegionPacket e;
ServerPacket f;
TextPacket g;
};
constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket);
+22 -19
View File
@@ -142,25 +142,6 @@ enum class SerialPacketType {
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
// name, text
@@ -184,6 +165,28 @@ enum class SerialPacketType {
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
//-------------------------
+8 -8
View File
@@ -70,13 +70,13 @@ void serializePacket(void* buffer, SerialPacketBase* 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)) {
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) {
@@ -104,11 +104,11 @@ void deserializePacket(void* buffer, SerialPacketBase* 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)) {
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.
*/
-------------------------
--defines
-------------------------
PRAGMA foreign_keys = ON;
-------------------------
--table definitions
-------------------------
CREATE TABLE IF NOT EXISTS UserAccounts (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(100) UNIQUE, --TODO: (3) Swap username for email address
--server-client security
-- passhash varchar(100),
-- passsalt varchar(100),
passhash varchar(100),
passsalt varchar(100),
--server controls
blacklisted BIT DEFAULT 0,
@@ -39,8 +49,8 @@ CREATE TABLE IF NOT EXISTS LiveCharacters (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
--metadata
owner INTEGER REFERENCES Accounts(uid),
handle varchar(100) UNIQUE,
owner INTEGER REFERENCES UserAccounts(uid),
handle varchar(100),
avatar varchar(100),
birth timestamp NOT NULL DEFAULT (datetime()),
@@ -48,59 +58,8 @@ CREATE TABLE IF NOT EXISTS LiveCharacters (
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 DeadCharacters (
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
--combat stats
level INTEGER DEFAULT 0,
exp INTEGER DEFAULT 0,
maxHP INTEGER DEFAULT 0,
@@ -111,48 +70,53 @@ CREATE TABLE IF NOT EXISTS StatisticSets (
defence INTEGER DEFAULT 0,
intelligence INTEGER DEFAULT 0,
resistance INTEGER DEFAULT 0,
accuracy INTEGER DEFAULT 0,
evasion INTEGER DEFAULT 0,
speed INTEGER DEFAULT 0,
accuracy REAL DEFAULT 0.0,
evasion REAL DEFAULT 0.0,
luck REAL DEFAULT 0.0
luck INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS InWorldItems (
CREATE TABLE IF NOT EXISTS DeadCharacters (
uid INTEGER PRIMARY KEY,
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
itemType INTEGER,
owner INTEGER REFERENCES UserAccounts(uid),
handle varchar(100),
avatar varchar(100),
birth timestamp NOT NULL,
death timestamp NOT NULL DEFAULT (datetime()),
--position in the world
roomIndex INTEGER DEFAULT 0,
originX INTEGER DEFAULT 0,
originY INTEGER DEFAULT 0,
--unique information
stackSize INTEGER DEFAULT 0,
durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid)
--combat stats
level INTEGER DEFAULT 0,
exp INTEGER DEFAULT 0,
maxHP INTEGER DEFAULT 0,
maxMP INTEGER DEFAULT 0,
attack INTEGER DEFAULT 0,
defence INTEGER DEFAULT 0,
intelligence INTEGER DEFAULT 0,
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 (
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
owner INTEGER REFERENCES Characters(uid),
itemType INTEGER,
uid INTEGER PRIMARY KEY AUTOINCREMENT,
name varchar(100) UNIQUE,
type varchar(100), --tmp type
--unique information
stackSize INTEGER DEFAULT 0,
durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid)
durability INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS WornEquipment (
--metadata
uid INTEGER PRIMARY KEY AUTOINCREMENT,
owner INTEGER REFERENCES Characters(uid),
itemType INTEGER,
-------------------------
--member tables
-------------------------
--unique information
durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid)
--attached script?
);
--TODO
+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
* 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
void CombatInstance::PushCharacter(CharacterData* const characterData) {
//
}
void CombatInstance::PopCharacter(CharacterData* const characterData) {
//
}
void CombatInstance::PushCreature(CreatureData* const creatureData) {
//
}
void CombatInstance::PopCreature(CreatureData* const creatureData) {
//
int ItemData::GetQuantity() {
return quantity;
}
+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
INCLUDES+=. .. ../characters ../creatures ../entities ../../common/gameplay ../../common/utilities
INCLUDES+=. ../../common/gameplay
LIBS+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
@@ -52,15 +52,17 @@ static int getTag(lua_State* L) {
return 1;
}
static int setInstance(lua_State* L) {
/*
static int setBattleIndex(lua_State* L) {
BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1));
barrier->SetInstanceIndex(lua_tointeger(L, 2));
barrier->SetBattleIndex(lua_tointeger(L, 2));
return 0;
}
*/
static int getInstance(lua_State* L) {
static int getBattleIndex(lua_State* L) {
BarrierData* barrier = static_cast<BarrierData*>(lua_touserdata(L, 1));
lua_pushinteger(L, barrier->GetInstanceIndex());
lua_pushinteger(L, barrier->GetBattleIndex());
return 1;
}
@@ -81,8 +83,8 @@ static const luaL_Reg barrierLib[] = {
{"GetScript", getScript},
{"SetTag", setTag},
{"GetTag", getTag},
{"SetInstance", setInstance},
{"GetInstance", getInstance},
// {"SetBattleIndex", setBattleIndex},
{"GetBattleIndex", getBattleIndex},
{"SetStatus", setStatus},
{"GetStatus", getStatus},
{nullptr, nullptr}
@@ -28,8 +28,15 @@
BarrierData::BarrierData(int i):
Entity::Entity("barrier")
{
instanceIndex = i;
battleIndex = i;
memset(status, 0, sizeof(int) * 8);
SetBounds({
BARRIER_BOUNDS_X,
BARRIER_BOUNDS_Y,
BARRIER_BOUNDS_WIDTH,
BARRIER_BOUNDS_HEIGHT
});
}
BarrierData::~BarrierData() {
@@ -39,6 +46,7 @@ BarrierData::~BarrierData() {
int BarrierData::Update(lua_State* L) {
int ret = 0;
//NOTE: this is here mostly for the "barrier tick" effect
if (scriptRef != LUA_NOREF) {
//Call the script reference
lua_pushinteger(L, scriptRef);
@@ -77,12 +85,12 @@ std::string BarrierData::GetTag(std::string key) {
return tags[key];
}
int BarrierData::SetInstanceIndex(int i) {
return instanceIndex = i;
int BarrierData::SetBattleIndex(int i) {
return battleIndex = i;
}
int BarrierData::GetInstanceIndex() const {
return instanceIndex;
int BarrierData::GetBattleIndex() const {
return battleIndex;
}
int BarrierData::SetStatus(int k, int v) {
@@ -21,6 +21,7 @@
*/
#pragma once
#include "barrier_defines.hpp"
#include "entity.hpp"
#include "lua.hpp"
@@ -30,7 +31,7 @@
class BarrierData: public Entity {
public:
BarrierData(int instanceIndex);
BarrierData(int battleIndex);
~BarrierData();
int Update(lua_State*);
@@ -38,11 +39,12 @@ public:
int SetScriptReference(int);
int GetScriptReference();
//NOTE: Why does this have tags? Are the tags used?
std::string SetTag(std::string key, std::string value);
std::string GetTag(std::string key);
int SetInstanceIndex(int i);
int GetInstanceIndex() const;
int SetBattleIndex(int i);
int GetBattleIndex() const;
int SetStatus(int k, int v);
int GetStatus(int k);
@@ -53,7 +55,7 @@ private:
int scriptRef = LUA_NOREF;
std::map<std::string, std::string> tags;
int instanceIndex;
int battleIndex;
int status[8];
};
@@ -27,6 +27,7 @@
#include "sqlite3.h"
#include <algorithm>
#include <functional>
#include <list>
#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 "creature_data.hpp"
class CombatInstance {
#include <functional>
class BattleData {
public:
CombatInstance();
~CombatInstance();
constexpr static int BATTLE_SIZE = 8;
BattleData();
~BattleData();
void Update();
//accessors and mutators
void PushCharacter(CharacterData* const characterData);
void PopCharacter(CharacterData* const characterData);
int PushCharacter(CharacterData* const characterData);
int PopCharacter(CharacterData const * const characterData);
void PushCreature(CreatureData* const creatureData);
void PopCreature(CreatureData* const creatureData);
int PushCreature(CreatureData* const creatureData);
int PopCreature(CreatureData const * const creatureData);
private:
std::array<CharacterData*, 8> characterArray;
std::array<CreatureData*, 8> creatureArray;
std::array<CharacterData*, BATTLE_SIZE> characterArray;
std::array<CreatureData*, BATTLE_SIZE> creatureArray;
};
@@ -19,26 +19,26 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "combat_instance_manager.hpp"
#include "battle_manager.hpp"
CombatInstanceManager::CombatInstanceManager() {
BattleManager::BattleManager() {
//EMPTY
}
CombatInstanceManager::~CombatInstanceManager() {
BattleManager::~BattleManager() {
UnloadAll();
}
//arg: a list of combats to be updated in the clients
void CombatInstanceManager::Update() {
void BattleManager::Update() {
for (auto& it : elementMap) {
it.second.Update();
}
}
int CombatInstanceManager::Create() {
int BattleManager::Create() {
//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
return counter++;
@@ -46,16 +46,16 @@ int CombatInstanceManager::Create() {
//TODO: (1) combat load, save
void CombatInstanceManager::Unload(int uid) {
void BattleManager::Unload(int uid) {
elementMap.erase(uid);
}
void CombatInstanceManager::UnloadAll() {
void BattleManager::UnloadAll() {
elementMap.clear();
}
void CombatInstanceManager::UnloadIf(std::function<bool(std::pair<const int, CombatInstance const&>)> fn) {
std::map<int, CombatInstance>::iterator it = elementMap.begin();
void BattleManager::UnloadIf(std::function<bool(std::pair<const int, BattleData const&>)> fn) {
std::map<int, BattleData>::iterator it = elementMap.begin();
while (it != elementMap.end()) {
if (fn(*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) {
std::map<int, CombatInstance>::iterator it = elementMap.find(uid);
BattleData* BattleManager::Find(int uid) {
std::map<int, BattleData>::iterator it = elementMap.find(uid);
if (it == elementMap.end()) {
return nullptr;
@@ -76,26 +76,26 @@ CombatInstance* CombatInstanceManager::Find(int uid) {
return &it->second;
}
int CombatInstanceManager::GetLoadedCount() {
int BattleManager::GetLoadedCount() {
return elementMap.size();
}
std::map<int, CombatInstance>* CombatInstanceManager::GetContainer() {
std::map<int, BattleData>* BattleManager::GetContainer() {
return &elementMap;
}
lua_State* CombatInstanceManager::SetLuaState(lua_State* L) {
lua_State* BattleManager::SetLuaState(lua_State* L) {
return lua = L;
}
lua_State* CombatInstanceManager::GetLuaState() {
lua_State* BattleManager::GetLuaState() {
return lua;
}
sqlite3* CombatInstanceManager::SetDatabase(sqlite3* db) {
sqlite3* BattleManager::SetDatabase(sqlite3* db) {
return database = db;
}
sqlite3* CombatInstanceManager::GetDatabase() {
sqlite3* BattleManager::GetDatabase() {
return database;
}
@@ -21,7 +21,7 @@
*/
#pragma once
#include "combat_instance.hpp"
#include "battle_data.hpp"
#include "lua.hpp"
#include "sqlite3.h"
@@ -29,10 +29,10 @@
#include <algorithm>
#include <map>
class CombatInstanceManager {
class BattleManager {
public:
CombatInstanceManager();
~CombatInstanceManager();
BattleManager();
~BattleManager();
//common public methods
void Update();
@@ -41,12 +41,12 @@ public:
void Unload(int uid);
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
CombatInstance* Find(int uid);
BattleData* Find(int uid);
int GetLoadedCount();
std::map<int, CombatInstance>* GetContainer();
std::map<int, BattleData>* GetContainer();
//hooks
lua_State* SetLuaState(lua_State* L);
@@ -56,7 +56,7 @@ public:
private:
//members
std::map<int, CombatInstance> elementMap;
std::map<int, BattleData> elementMap;
int counter = 0;
lua_State* lua = 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 <stdexcept>
#include <iostream>
static int setRoom(lua_State* L) {
//reverse engineer the character index
int characterIndex = -1;
//variables
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
CharacterManager& characterMgr = CharacterManager::GetSingleton();
for (auto& it : *characterMgr.GetContainer()) {
if (character == &it.second) {
characterIndex = it.first;
break;
}
}
//error checking
if (characterIndex == -1) {
throw(std::runtime_error("Lua Error: Failed to find character index by reference"));
if (characterMgr.Find(character->GetIndex()) != character) {
throw(std::runtime_error("Lua Error: Failed to verify character index by reference"));
}
//get the room index, depending on the parameter type
int roomIndex = -1;
RoomManager& roomMgr = RoomManager::GetSingleton();
switch(lua_type(L, 2)) {
case LUA_TNUMBER:
//simple integer
roomIndex = lua_tointeger(L, 2);
break;
case LUA_TLIGHTUSERDATA:
//reverse engineer the room index
for (auto& it : *roomMgr.GetContainer()) {
if (lua_touserdata(L, 2) == &it.second) {
roomIndex = it.first;
break;
}
}
break;
}
case LUA_TLIGHTUSERDATA: {
//check that this is a room first
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 2));
RoomManager& roomMgr = RoomManager::GetSingleton();
//error checking
if (roomIndex == -1) {
throw(std::runtime_error("Lua Error: Failed to find room index by reference"));
if (roomMgr.Find(room->GetRoomIndex()) != room) {
std::cout << room->GetRoomIndex() << std::endl;
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
pumpAndChangeRooms(character, roomIndex, characterIndex);
pumpAndChangeRooms(character, roomIndex, character->GetIndex());
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) {
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
lua_pushinteger(L, character->GetOwner());
@@ -95,6 +93,7 @@ static int getAvatar(lua_State* L) {
static const luaL_Reg characterLib[] = {
{"SetRoom", setRoom},
{"GetIndex", getIndex},
// {"GetOwner", getOwner}, //unusable without account API
{"GetHandle", getHandle},
{"GetAvatar", getAvatar},
+12
View File
@@ -30,6 +30,14 @@ CharacterData::CharacterData(): Entity("character") {
});
}
//-------------------------
//database stuff
//-------------------------
int CharacterData::GetIndex() {
return index;
}
int CharacterData::GetOwner() {
return owner;
}
@@ -40,4 +48,8 @@ std::string CharacterData::GetHandle() {
std::string CharacterData::GetAvatar() {
return avatar;
}
Inventory* CharacterData::GetInventory() {
return &inventory;
}
+6
View File
@@ -24,6 +24,7 @@
//components
#include "character_defines.hpp"
#include "entity.hpp"
#include "inventory.hpp"
//std namespace
#include <string>
@@ -35,14 +36,19 @@ public:
~CharacterData() = default;
//database stuff
int GetIndex();
int GetOwner();
std::string GetHandle();
std::string GetAvatar();
Inventory* GetInventory();
private:
friend class CharacterManager;
//database stuff
int index = -1;
int owner = -1;
std::string handle;
std::string avatar;
Inventory inventory;
};
+10 -29
View File
@@ -39,12 +39,8 @@
static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters ("
"owner, "
"handle, "
"avatar, "
"boundsX, "
"boundsY, "
"boundsW, "
"boundsH"
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
"avatar "
") VALUES (?1, ?2, ?3);";
static const char* LOAD_CHARACTER = "SELECT "
"uid, "
@@ -53,21 +49,13 @@ static const char* LOAD_CHARACTER = "SELECT "
"avatar, "
"roomIndex, "
"originX, "
"originY, "
"boundsX, "
"boundsY, "
"boundsW, "
"boundsH "
"originY "
"FROM LiveCharacters WHERE handle = ?;";
static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET "
"roomIndex = ?2, "
"originX = ?3, "
"originY = ?4, "
"boundsX = ?5, "
"boundsY = ?6, "
"boundsW = ?7, "
"boundsH = ?8 "
"originY = ?4 "
"WHERE uid = ?1;";
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_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_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
if (ret) {
@@ -157,6 +141,7 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) {
CharacterData& newChar = elementMap[uid];
//metadata
newChar.index = uid;
newChar.owner = owner;
newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2));
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
@@ -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.y = (double)sqlite3_column_int(statement, 6);
//bounds
newChar.bounds.x = (int)sqlite3_column_int(statement, 7);
newChar.bounds.y = (int)sqlite3_column_int(statement, 8);
newChar.bounds.w = (int)sqlite3_column_int(statement, 9);
newChar.bounds.h = (int)sqlite3_column_int(statement, 10);
newChar.bounds.x = CHARACTER_BOUNDS_X;
newChar.bounds.y = CHARACTER_BOUNDS_Y;
newChar.bounds.w = CHARACTER_BOUNDS_WIDTH;
newChar.bounds.h = CHARACTER_BOUNDS_HEIGHT;
//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, 3, (int)character.origin.x) != 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
if (ret) {
+1 -1
View File
@@ -1,5 +1,5 @@
#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+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+4 -2
View File
@@ -1,5 +1,5 @@
#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
#the order of the $(LIBS) is important, at least for MinGW
@@ -30,11 +30,13 @@ OUT=$(addprefix $(OUTDIR)/,server)
#targets
all: $(OBJ) $(OUT)
$(MAKE) -C accounts
$(MAKE) -C barriers
$(MAKE) -C battles
$(MAKE) -C characters
$(MAKE) -C clients
$(MAKE) -C combat
$(MAKE) -C creatures
$(MAKE) -C entities
$(MAKE) -C inventory
$(MAKE) -C rooms
$(MAKE) -C triggers
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
+1 -1
View File
@@ -1,5 +1,5 @@
#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+=
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
+162 -19
View File
@@ -31,8 +31,48 @@
#include <stack>
#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() {
RunFrameUpdates(RunFrameLuaOnTick());
RunFrameTriggers();
RunFrameCharacterCreatureCollisions();
RunFrameCharacterBarrierCollisions();
}
//-------------------------
//hi-cohesion methods for one-time use
//-------------------------
bool RoomData::RunFrameLuaOnTick() {
//get the hook
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
@@ -46,7 +86,7 @@ void RoomData::RunFrame() {
}
//pump creatures & barriers
if (lua_tonumber(lua, -1)) {
if (lua_tonumber(lua, -1) > 0) {
updateAll = true;
}
@@ -56,6 +96,10 @@ void RoomData::RunFrame() {
lua_pop(lua, 1);
}
return updateAll;
}
void RoomData::RunFrameUpdates(bool updateAll) {
//lists of non-character entities that need updating client-side
std::list<std::pair<const int, CreatureData*>> creatureList;
std::list<std::pair<const int, BarrierData*>> barrierList;
@@ -67,7 +111,34 @@ void RoomData::RunFrame() {
creatureMgr.Update(&creatureList, 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
//currently, this only uses characters
std::stack<Entity*> entityStack;
for (auto& it : characterList) {
entityStack.push(it);
@@ -75,8 +146,10 @@ void RoomData::RunFrame() {
//Compare the triggers to the entities, using their real hitboxes
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) {
BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin();
@@ -86,7 +159,9 @@ void RoomData::RunFrame() {
BoundingBox creatureBox = creatureIt.second.GetBounds() + creatureIt.second.GetOrigin();
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->SetRoomIndex(roomIndex);
barrierData->SetOrigin({
@@ -118,26 +193,56 @@ void RoomData::RunFrame() {
creatureMgr.Unload(it);
}
}
}
//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);
}
void RoomData::RunFrameCharacterBarrierCollisions() {
//TODO: check for character collisions with barriers, O(m*n)
for (auto characterIt : characterList) {
//character bounds
BoundingBox characterBox = characterIt->GetBounds() + characterIt->GetOrigin();
//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);
for (auto barrierIt : *barrierMgr.GetContainer()) {
//barrier bounds
BoundingBox barrierBox = barrierIt.second.GetBounds() + barrierIt.second.GetOrigin();
//move the character to the battle screen
if (characterBox.CheckOverlap(barrierBox)) {
//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) {
return roomName = s;
}
@@ -162,6 +267,44 @@ int RoomData::GetRoomIndex() {
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() {
return &barrierMgr;
}
+12 -2
View File
@@ -23,7 +23,7 @@
#include "barrier_manager.hpp"
#include "character_data.hpp"
#include "combat_instance_manager.hpp"
#include "battle_manager.hpp"
#include "creature_manager.hpp"
#include "region_pager_lua.hpp"
#include "trigger_manager.hpp"
@@ -53,6 +53,9 @@ public:
int SetRoomIndex(int i);
int GetRoomIndex();
void PushCharacter(CharacterData* const character);
void PopCharacter(CharacterData const * const character);
BarrierManager* GetBarrierMgr();
std::list<CharacterData*>* GetCharacterList();
CreatureManager* GetCreatureMgr();
@@ -74,6 +77,13 @@ public:
std::string GetTag(std::string key);
private:
//hi-cohesion methods for one-time use
bool RunFrameLuaOnTick();
void RunFrameUpdates(bool updateAll);
void RunFrameTriggers();
void RunFrameCharacterCreatureCollisions();
void RunFrameCharacterBarrierCollisions();
//metadata
std::string roomName;
std::string tilesetName;
@@ -82,7 +92,7 @@ private:
int roomIndex = 0;
BarrierManager barrierMgr;
std::list<CharacterData*> characterList;
CombatInstanceManager CombatInstanceMgr;
BattleManager battleMgr;
CreatureManager creatureMgr;
RegionPagerLua pager;
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);
}
void RoomManager::PushCharacter(CharacterData* character) {
void RoomManager::PushCharacter(CharacterData* const character) {
if (!character) {
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());
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
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());
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) {
return character == ptr;
});
room->PopCharacter(character);
}
//TODO: rename these functions from Get to Find
+2 -2
View File
@@ -39,8 +39,8 @@ public:
void UnloadAll();
void UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn);
void PushCharacter(CharacterData* character);
void PopCharacter(CharacterData const* character);
void PushCharacter(CharacterData* const character);
void PopCharacter(CharacterData const * const character);
//accessors and mutators
RoomData* Find(int uid);
+29 -4
View File
@@ -596,11 +596,36 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
//respond with all character data
CharacterPacket newPacket;
for (auto& it : *characterMgr.GetContainer()) {
if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) {
continue;
//retrieve all character data
if (argPacket->roomIndex == -1) {
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;
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);
}
//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) {
//delete the character from the old room
CharacterPacket newPacket;
+19 -20
View File
@@ -1,26 +1,25 @@
TODO: Resource manager
TODO: Add the TextureLoader
TODO: Consistency for bounds names
TODO: Cross compiler (to replace dead linux PC ;_;)
TODO: New button graphics
TODO: New button graphics?
TODO: New typeface
TODO: Account passwords (list)
* backbone account server OR
* social network login OR
* ...
* salts & hashes
* login screen prompting for username & password
TODO: backbone account server OR
TODO: social network login OR
TODO: salts & hashes
TODO: login screen prompting for username & password
TODO: Features
* Make sure login errors are sent to the client
* 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)
* Fix shoddy movement
* Remove the big "Shut Down" button (currently broken...)
* Make a way for the server owner to control the server directly
* The TileSheet class should implement the surface itself
* Time delay for requesting region packets
* A proper logging system
* Fix the const-ness of accessors
* Add a screenshot of the game to README.md
* joystick/gamepad support
* add the tilesheet to the map system
TODO: Make sure login errors are sent to the client
TODO: Add the "home" parameter to the server's config file
TODO: Fix shoddy movement
TODO: Better UI system
TODO: Make a way for the server owner to control the server directly
TODO: The TileSheet class should implement the surface itself
TODO: Time delay for requesting region packets
TODO: A proper logging system
TODO: Fix the const-ness of accessors
TODO: Add a screenshot of the game to README.md
TODO: joystick/gamepad support
TODO: add the tilesheet to the map system
TODO: Better collision logic