Compare commits
224 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93c41bb19c | |||
| bf922ec598 | |||
| de902d2d3d | |||
| 7b3bf24e5d | |||
| de7da81102 | |||
| 6428b02d85 | |||
| 519b8a1e36 | |||
| 967f0653a1 | |||
| b86d393571 | |||
| 6b38501c27 | |||
| 5893342ad8 | |||
| ac4a264f12 | |||
| 43895a462a | |||
| 1bde0ed3f7 | |||
| d903c0df30 | |||
| 9620826d65 | |||
| 0a71f43ef3 | |||
| a47e76845f | |||
| c2eb08bd5e | |||
| 7b76e07231 | |||
| 1dd8042d3d | |||
| c575ee9ce1 | |||
| 1befc76b70 | |||
| 6a6e7f7125 | |||
| bb6e248583 | |||
| f7df4fba6c | |||
| e7403be508 | |||
| 873715b28c | |||
| b1d6e5a314 | |||
| f0453375c4 | |||
| e5a98efd7d | |||
| 14b330009b | |||
| 288b62d3f8 | |||
| c5e8f1b3af | |||
| 980717f9fd | |||
| 68475eee0f | |||
| eeb2400e79 | |||
| 01244005e9 | |||
| c5005b9b07 | |||
| 80a26341b1 | |||
| b7877962f1 | |||
| 688d064085 | |||
| 1c4d53e3ef | |||
| a53a134163 | |||
| 4d12788c53 | |||
| 1beb7cbd5d | |||
| 8358d72a98 | |||
| 4ebff4a25a | |||
| 0ff787abda | |||
| 9b5b48a8ab | |||
| 5dd0fb9e23 | |||
| 7c210e04a5 | |||
| 9236e02101 | |||
| 8f4ebf20da | |||
| 910e51f637 | |||
| 92fc9b4e25 | |||
| 2b8e7241c9 | |||
| 124cb3ad13 | |||
| 6d3400d948 | |||
| 5031352fe3 | |||
| 624369f147 | |||
| 9a7f7b8684 | |||
| fa9487c2f2 | |||
| 9ec1ddab99 | |||
| 6f1c2d0555 | |||
| 01b50d5590 | |||
| 9c673928e6 | |||
| d55dfb90e4 | |||
| 235a05d006 | |||
| dabb7b3b2e | |||
| e756289c2b | |||
| c534158c2e | |||
| b47191a0c1 | |||
| 6c6a025f2a | |||
| 60edc97ea5 | |||
| a5b209d9e0 | |||
| fd673a415f | |||
| 4270765146 | |||
| f56cb58dfb | |||
| f315f4bf35 | |||
| 69765de433 | |||
| 35d463d4ba | |||
| 894b46c5db | |||
| eb0b18af6f | |||
| fba183fa27 | |||
| c5a627004a | |||
| ac27fb0ca7 | |||
| be4a8311d5 | |||
| 6d32d44fa3 | |||
| 9bacfb1424 | |||
| c3464be589 | |||
| 7fe71c60d0 | |||
| 0c6537fb36 | |||
| 854dc0eb45 | |||
| e90afb7e4a | |||
| 0453f6becf | |||
| c8a58ab515 | |||
| 553f8dbfa5 | |||
| 2bacdcdab7 | |||
| 99aecbfdbb | |||
| 27bda5dc28 | |||
| 962f3f5dd0 | |||
| 41077b43b3 | |||
| 4410ab892f | |||
| 60000cb0cf | |||
| 66b00255d5 | |||
| a5b68cf1fd | |||
| 4cff57fe71 | |||
| 38b603fc8f | |||
| 47684380a9 | |||
| e4bfbfb906 | |||
| 9db86c19f6 | |||
| d5b551cec3 | |||
| 7e500027e3 | |||
| dd786ba579 | |||
| 5a57888305 | |||
| 706aa5e1d7 | |||
| 19c1b1197d | |||
| 5cf62f5517 | |||
| 56d02ad8d4 | |||
| 006a72174f | |||
| 0cbc9dd9db | |||
| 60c31ff56d | |||
| 6a204643f6 | |||
| 59285d1630 | |||
| a850d6b1af | |||
| f17fa0f345 | |||
| 756d4e770d | |||
| 7bb5e8ce0d | |||
| 975533afba | |||
| 19749f7c87 | |||
| 7703c4b0ad | |||
| dc8f594eec | |||
| 4629b7302b | |||
| 02d83d1f16 | |||
| 91c9cef56d | |||
| f7d4912942 | |||
| eb8674b84f | |||
| ff44e4d916 | |||
| e66540f114 | |||
| 639c0c70e3 | |||
| 37b02352e2 | |||
| 31c8bd7fd2 | |||
| 808fe570a3 | |||
| e706cc9d13 | |||
| eb02cc4b6a | |||
| 31cca61d1c | |||
| 071e0d9021 | |||
| a494bfbb38 | |||
| baadf554cd | |||
| 9df16fede0 | |||
| dd0ad31ac6 | |||
| be26c9d103 | |||
| a448c8fb68 | |||
| de1a6a050f | |||
| 49c9abe91b | |||
| 3b05476689 | |||
| 1c032bfc47 | |||
| 1a7457f650 | |||
| e640eda771 | |||
| fc2b67608f | |||
| a3a990cc01 | |||
| f6a4674a2f | |||
| 865620b4a8 | |||
| 1e0ed350fc | |||
| 6ccc874583 | |||
| ca86dc5fb8 | |||
| e3605e4dc5 | |||
| cb9aef95ec | |||
| 09f97de0e6 | |||
| f5466b9982 | |||
| e176a60d28 | |||
| dc24d1b059 | |||
| fa3fc18ddf | |||
| c2941cd3e8 | |||
| bf15a5d957 | |||
| f01463bab3 | |||
| 54cd26b76f | |||
| 2bd8adaf69 | |||
| 26eba2def6 | |||
| 43852ce755 | |||
| 81fab06e3b | |||
| 77a90f9c0c | |||
| bc32f2a2f0 | |||
| 76bfecd466 | |||
| d4eb1e7b8d | |||
| 2ec307510d | |||
| 0b4e6003d6 | |||
| 7e603ffa89 | |||
| 6fc8570cf4 | |||
| 0bfd916df4 | |||
| 88aee0f4f5 | |||
| 0d3c3243a0 | |||
| 871b1136c2 | |||
| f64c935ffe | |||
| 600ec6789b | |||
| 65a3937592 | |||
| 719c8f49a6 | |||
| 29928c0b92 | |||
| a88a1f7cf7 | |||
| 46efbfbe9a | |||
| 26ff8dcc8f | |||
| 9c91e9d5fd | |||
| 3628d3c1fd | |||
| 6c9406147a | |||
| aae244de39 | |||
| d5b14c2679 | |||
| a54fbfb9e9 | |||
| 9cbbfe77b7 | |||
| 9b64c67068 | |||
| de0227a1cf | |||
| 1dfeabf195 | |||
| 6c5197f3f2 | |||
| 09453cc24e | |||
| 4b62310158 | |||
| 43f2190c3e | |||
| 3225da6b13 | |||
| 0c233b8764 | |||
| 027d0125ef | |||
| e4884c3e18 | |||
| b675f516e7 | |||
| d5f7363c33 | |||
| 7458962ad4 | |||
| 0a0b61287e |
+21
@@ -0,0 +1,21 @@
|
||||
#Editor generated files
|
||||
*.sln
|
||||
*.vcproj
|
||||
*.suo
|
||||
*.ncb
|
||||
*.user
|
||||
|
||||
#Directories
|
||||
Release/
|
||||
Debug/
|
||||
Out/
|
||||
|
||||
#Project generated files
|
||||
*.db
|
||||
*.o
|
||||
*.a
|
||||
*.exe
|
||||
|
||||
#Shell files
|
||||
*.bat
|
||||
*.sh
|
||||
@@ -0,0 +1,33 @@
|
||||
The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
||||
|
||||
Tortuga is a 2D multiplayer JRPG featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
||||
|
||||
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
|
||||
|
||||
## Documentation
|
||||
|
||||
Tortuga's full documentation can be found in a separate branch, see [Tortuga/docs](https://github.com/Ratstail91/Tortuga/tree/docs).
|
||||
For Tortuga's primary documentation, please read the [Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/Tortuga%20Game%20Design%20Document.docx?raw=true).
|
||||
|
||||
## External Dependencies
|
||||
|
||||
* [SDL 1.2](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||
* [SDL_net 1.2](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
||||
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
||||
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
||||
|
||||
## Copyright
|
||||
|
||||
(Future versions (to be determined) may be released under a modified version of the [Uplink Developer's License](http://www.introversion.co.uk/uplink/developer/license.html).)
|
||||
|
||||
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
||||
|
||||
Copyright (c) 2013, 2014 Kayne Ruse
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef CHANNELS_HPP_
|
||||
#define CHANNELS_HPP_
|
||||
|
||||
enum Channels {
|
||||
SERVER = 0
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* including commercial ClientApplications, 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
|
||||
@@ -19,13 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "application.hpp"
|
||||
#include "client_application.hpp"
|
||||
|
||||
#include "timer.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Scene headers
|
||||
@@ -35,71 +34,32 @@
|
||||
#include "splash_screen.hpp"
|
||||
#include "main_menu.hpp"
|
||||
#include "options_menu.hpp"
|
||||
#include "lobby_menu.hpp"
|
||||
#include "in_world.hpp"
|
||||
#include "in_combat.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
void Application::Init(int argc, char** argv) {
|
||||
std::cout << "Beginning " << argv[0] << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Initialize the APIs
|
||||
//-------------------------
|
||||
void ClientApplication::Init(int argc, char** argv) {
|
||||
//load the prerequisites
|
||||
config.Load("rsc\\config.cfg");
|
||||
|
||||
//initialize SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
throw(std::runtime_error("Failed to initialize SDL"));
|
||||
}
|
||||
std::cout << "Initialized SDL" << std::endl;
|
||||
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||
|
||||
//initialize lua
|
||||
lua = luaL_newstate();
|
||||
if (!lua) {
|
||||
throw(std::runtime_error("Failed to initialize lua"));
|
||||
//initialize SDL_net
|
||||
if (SDLNet_Init()) {
|
||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
luaL_openlibs(lua);
|
||||
std::cout << "Initialized lua" << std::endl;
|
||||
|
||||
if (luaL_dofile(lua, "rsc\\setup.lua")) {
|
||||
throw(std::runtime_error("Failed to initialize lua's startup script"));
|
||||
}
|
||||
std::cout << "Initialized lua's setup script" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Setup the screen
|
||||
//-------------------------
|
||||
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, 1, "screen");
|
||||
lua_getfield(lua, 2, "width");
|
||||
lua_getfield(lua, 2, "height");
|
||||
lua_getfield(lua, 2, "fullscreen");
|
||||
|
||||
int w = lua_tointeger(lua, 3);
|
||||
int h = lua_tointeger(lua, 4);
|
||||
int f = lua_toboolean(lua, 5);
|
||||
|
||||
lua_pop(lua, 5);
|
||||
|
||||
BaseScene::SetScreen(w ? w : 800, h ? h : 600, 0, f ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||
std::cout << "Initialized the screen" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//finalize the startup
|
||||
//-------------------------
|
||||
|
||||
std::cout << "Startup completed successfully" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//debugging
|
||||
//-------------------------
|
||||
|
||||
//...
|
||||
network.Open(0);
|
||||
}
|
||||
|
||||
void Application::Proc() {
|
||||
void ClientApplication::Proc() {
|
||||
LoadScene(SceneList::FIRST);
|
||||
|
||||
//prepare the time system
|
||||
@@ -120,8 +80,6 @@ void Application::Proc() {
|
||||
//update the current time
|
||||
realTime = Clock::now();
|
||||
|
||||
Timer runTimer("run");
|
||||
|
||||
//simulate game time
|
||||
while (simTime < realTime) {
|
||||
//call each user defined function
|
||||
@@ -129,57 +87,52 @@ void Application::Proc() {
|
||||
simTime += delta;
|
||||
}
|
||||
|
||||
runTimer.Stop();
|
||||
|
||||
Timer renderTimer("render");
|
||||
|
||||
//draw the game to the screen
|
||||
activeScene->RenderFrame();
|
||||
|
||||
renderTimer.Stop();
|
||||
|
||||
//debugging output
|
||||
// std::cout << runTimer << std::endl;
|
||||
// std::cout << renderTimer << std::endl;
|
||||
}
|
||||
|
||||
UnloadScene();
|
||||
}
|
||||
|
||||
void Application::Quit() {
|
||||
std::cout << "Shutting down" << std::endl;
|
||||
lua_close(lua);
|
||||
void ClientApplication::Quit() {
|
||||
network.Close();
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
std::cout << "Clean exit" << std::endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Private access members
|
||||
//-------------------------
|
||||
|
||||
void Application::LoadScene(SceneList sceneIndex) {
|
||||
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||
UnloadScene();
|
||||
switch(sceneIndex) {
|
||||
//add scene creation calls here
|
||||
case SceneList::FIRST:
|
||||
case SceneList::SPLASHSCREEN:
|
||||
activeScene = new SplashScreen(lua);
|
||||
activeScene = new SplashScreen(&config);
|
||||
break;
|
||||
case SceneList::MAINMENU:
|
||||
activeScene = new MainMenu(lua);
|
||||
activeScene = new MainMenu(&config);
|
||||
break;
|
||||
case SceneList::OPTIONSMENU:
|
||||
activeScene = new OptionsMenu(lua);
|
||||
activeScene = new OptionsMenu(&config);
|
||||
break;
|
||||
case SceneList::LOBBYMENU:
|
||||
activeScene = new LobbyMenu(&config, &network, &clientIndex, &accountIndex, &characterIndex);
|
||||
break;
|
||||
case SceneList::INWORLD:
|
||||
activeScene = new InWorld(lua);
|
||||
activeScene = new InWorld(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap);
|
||||
break;
|
||||
case SceneList::INCOMBAT:
|
||||
activeScene = new InCombat(&config, &network, &clientIndex, &accountIndex, &characterIndex, &combatMap, &characterMap, &enemyMap);
|
||||
break;
|
||||
default:
|
||||
throw(std::logic_error("Failed to recognize the scene index"));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::UnloadScene() {
|
||||
void ClientApplication::UnloadScene() {
|
||||
delete activeScene;
|
||||
activeScene = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef CLIENTAPPLICATION_HPP_
|
||||
#define CLIENTAPPLICATION_HPP_
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
class ClientApplication {
|
||||
public:
|
||||
ClientApplication() = default;
|
||||
~ClientApplication() = default;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility config;
|
||||
UDPNetworkUtility network;
|
||||
int clientIndex = -1;
|
||||
int accountIndex = -1;
|
||||
int characterIndex = -1;
|
||||
|
||||
std::map<int, CombatData> combatMap;
|
||||
std::map<int, CharacterData> characterMap;
|
||||
std::map<int, EnemyData> enemyMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "in_combat.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InCombat::InCombat(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap,
|
||||
std::map<int, EnemyData>* argEnemyMap
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex),
|
||||
combatMap(*argCombatMap),
|
||||
characterMap(*argCharacterMap),
|
||||
enemyMap(*argEnemyMap)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
InCombat::~InCombat() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InCombat::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::RenderFrame() {
|
||||
SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
void InCombat::Render(SDL_Surface* const screen) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InCombat::QuitEvent() {
|
||||
//exit the game AND the server
|
||||
// RequestDisconnect();
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InCombat::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void InCombat::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InCombat::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
//TODO: network handlers
|
||||
|
||||
//-------------------------
|
||||
//Server control
|
||||
//-------------------------
|
||||
|
||||
//TODO: server control
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef INCOMBAT_HPP_
|
||||
#define INCOMBAT_HPP_
|
||||
|
||||
//network
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//graphics
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
//common
|
||||
#include "config_utility.hpp"
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
#include "combat_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
class InCombat : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InCombat(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap,
|
||||
std::map<int, EnemyData>* argEnemyMap
|
||||
);
|
||||
~InCombat();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void RenderFrame();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
void QuitEvent();
|
||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
//TODO: more
|
||||
|
||||
//Server control
|
||||
void SendPlayerUpdate();
|
||||
void RequestDisconnect();
|
||||
void RequestShutdown();
|
||||
//TODO: more
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
std::map<int, CombatData>& combatMap;
|
||||
std::map<int, CharacterData>& characterMap;
|
||||
std::map<int, EnemyData>& enemyMap;
|
||||
|
||||
//graphics
|
||||
//TODO: graphics
|
||||
|
||||
//UI
|
||||
//TODO: UI
|
||||
FrameRate fps;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,452 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "in_world.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InWorld::InWorld(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex),
|
||||
combatMap(*argCombatMap),
|
||||
characterMap(*argCharacterMap)
|
||||
{
|
||||
//setup the utility objects
|
||||
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
disconnectButton.SetImage(&buttonImage);
|
||||
disconnectButton.SetFont(&font);
|
||||
shutDownButton.SetImage(&buttonImage);
|
||||
shutDownButton.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
disconnectButton.SetX(50);
|
||||
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||
shutDownButton.SetX(50);
|
||||
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
|
||||
|
||||
//set the button texts
|
||||
disconnectButton.SetText("Disconnect");
|
||||
shutDownButton.SetText("Shut Down");
|
||||
|
||||
//load the tilesheet
|
||||
//TODO: add the tilesheet to the map system?
|
||||
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||
|
||||
//request a sync
|
||||
RequestSynchronize();
|
||||
|
||||
//debug
|
||||
// RequestRegion(0, 0);
|
||||
}
|
||||
|
||||
InWorld::~InWorld() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InWorld::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::Update(double delta) {
|
||||
SerialPacket packet;
|
||||
|
||||
//suck in all waiting packets
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
|
||||
//update the characters
|
||||
for (auto& it : characterMap) {
|
||||
it.second.Update(delta);
|
||||
}
|
||||
|
||||
//update the camera
|
||||
if(localCharacter) {
|
||||
camera.x = localCharacter->position.x - camera.marginX;
|
||||
camera.y = localCharacter->position.y - camera.marginY;
|
||||
}
|
||||
|
||||
//check the map
|
||||
UpdateMap();
|
||||
}
|
||||
|
||||
void InWorld::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::RenderFrame() {
|
||||
// SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
void InWorld::Render(SDL_Surface* const screen) {
|
||||
//draw the map
|
||||
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw characters
|
||||
for (auto& it : characterMap) {
|
||||
//TODO: drawing order according to Y position
|
||||
it.second.DrawTo(screen, camera.x, camera.y);
|
||||
}
|
||||
|
||||
//draw UI
|
||||
disconnectButton.DrawTo(screen);
|
||||
shutDownButton.DrawTo(screen);
|
||||
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::QuitEvent() {
|
||||
//exit the game AND the server
|
||||
RequestDisconnect();
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
disconnectButton.MouseMotion(motion);
|
||||
shutDownButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
disconnectButton.MouseButtonDown(button);
|
||||
shutDownButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestDisconnect();
|
||||
}
|
||||
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
RequestShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE: {
|
||||
QuitEvent();
|
||||
}
|
||||
break;
|
||||
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
//player movement
|
||||
case SDLK_LEFT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.x -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y += CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
if (localCharacter) {
|
||||
localCharacter->motion.y -= CHARACTER_WALKING_SPEED;
|
||||
SendPlayerUpdate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
HandleRegionContent(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
HandleCharacterUpdate(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
HandleCharacterNew(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
HandleCharacterDelete(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in InWorld: " + to_string_custom(int(packet.meta.type))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandleDisconnect(SerialPacket packet) {
|
||||
network.Unbind(Channels::SERVER);
|
||||
clientIndex = -1;
|
||||
accountIndex = -1;
|
||||
characterIndex = -1;
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
void InWorld::HandleRegionContent(SerialPacket packet) {
|
||||
//replace existing regions
|
||||
regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
regionPager.PushRegion(packet.regionInfo.region);
|
||||
packet.regionInfo.region = nullptr;
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterUpdate(SerialPacket packet) {
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) {
|
||||
HandleCharacterNew(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
//update only if the message didn't originate from here
|
||||
if (packet.characterInfo.clientIndex != clientIndex) {
|
||||
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
|
||||
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
|
||||
}
|
||||
characterMap[packet.characterInfo.characterIndex].CorrectSprite();
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterNew(SerialPacket packet) {
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) != characterMap.end()) {
|
||||
throw(std::runtime_error("Cannot create duplicate characters"));
|
||||
}
|
||||
|
||||
//create the character object
|
||||
CharacterData& character = characterMap[packet.characterInfo.characterIndex];
|
||||
|
||||
//set the members
|
||||
character.handle = packet.characterInfo.handle;
|
||||
character.avatar = packet.characterInfo.avatar;
|
||||
character.sprite.LoadSurface(config["dir.sprites"] + character.avatar, 4, 4);
|
||||
character.mapIndex = packet.characterInfo.mapIndex;
|
||||
character.position = packet.characterInfo.position;
|
||||
character.motion = packet.characterInfo.motion;
|
||||
character.stats = packet.characterInfo.stats;
|
||||
|
||||
character.CorrectSprite();
|
||||
|
||||
//catch this client's player object
|
||||
if (packet.characterInfo.characterIndex == characterIndex && !localCharacter) {
|
||||
localCharacter = &character;
|
||||
|
||||
//setup the camera
|
||||
//TODO: can't change the screen size?
|
||||
camera.width = GetScreen()->w;
|
||||
camera.height = GetScreen()->h;
|
||||
|
||||
//center on the player's character
|
||||
camera.marginX = (GetScreen()->w / 2 - localCharacter->sprite.GetImage()->GetClipW() / 2);
|
||||
camera.marginY = (GetScreen()->h / 2 - localCharacter->sprite.GetImage()->GetClipH() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::HandleCharacterDelete(SerialPacket packet) {
|
||||
//TODO: authenticate when own character is being deleted (linked to a TODO in the server)
|
||||
//catch this client's player object
|
||||
if (packet.characterInfo.characterIndex == characterIndex) {
|
||||
characterIndex = -1;
|
||||
localCharacter = nullptr;
|
||||
}
|
||||
|
||||
characterMap.erase(packet.characterInfo.characterIndex);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Server control
|
||||
//-------------------------
|
||||
|
||||
void InWorld::RequestSynchronize() {
|
||||
SerialPacket packet;
|
||||
|
||||
//request a sync
|
||||
packet.meta.type = SerialPacket::Type::SYNCHRONIZE;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::SendPlayerUpdate() {
|
||||
SerialPacket packet;
|
||||
|
||||
//pack the packet
|
||||
packet.meta.type = SerialPacket::Type::CHARACTER_UPDATE;
|
||||
packet.characterInfo.clientIndex = clientIndex;
|
||||
packet.characterInfo.accountIndex = accountIndex;
|
||||
packet.characterInfo.characterIndex = characterIndex;
|
||||
packet.characterInfo.position = localCharacter->position;
|
||||
packet.characterInfo.motion = localCharacter->motion;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestDisconnect() {
|
||||
SerialPacket packet;
|
||||
|
||||
//send a disconnect request
|
||||
packet.meta.type = SerialPacket::Type::DISCONNECT;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestShutDown() {
|
||||
SerialPacket packet;
|
||||
|
||||
//send a shutdown request
|
||||
packet.meta.type = SerialPacket::Type::SHUTDOWN;
|
||||
packet.clientInfo.clientIndex = clientIndex;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
void InWorld::RequestRegion(int mapIndex, int x, int y) {
|
||||
SerialPacket packet;
|
||||
|
||||
//pack the region's data
|
||||
packet.meta.type = SerialPacket::Type::REGION_REQUEST;
|
||||
packet.regionInfo.mapIndex = mapIndex;
|
||||
packet.regionInfo.x = x;
|
||||
packet.regionInfo.y = y;
|
||||
|
||||
network.SendTo(Channels::SERVER, &packet);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Utilities
|
||||
//-------------------------
|
||||
|
||||
//TODO: convert this into a more generic function?; using parameters for the bounds
|
||||
void InWorld::UpdateMap() {
|
||||
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
|
||||
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
|
||||
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
|
||||
|
||||
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
|
||||
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
|
||||
|
||||
//prune distant regions
|
||||
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) {
|
||||
//check if the region is outside off this area
|
||||
if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) {
|
||||
|
||||
//clunky, but the alternative was time consuming
|
||||
int tmpX = (*it)->GetX();
|
||||
int tmpY = (*it)->GetY();
|
||||
++it;
|
||||
|
||||
regionPager.UnloadRegion(tmpX, tmpY);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
//request empty regions within this zone
|
||||
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
||||
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
||||
if (!regionPager.FindRegion(i, j)) {
|
||||
RequestRegion(0, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef INWORLD_HPP_
|
||||
#define INWORLD_HPP_
|
||||
|
||||
//maps
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//networking
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//graphics
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
#include "tile_sheet.hpp"
|
||||
|
||||
//common
|
||||
#include "config_utility.hpp"
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
#include "combat_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//STL
|
||||
#include <map>
|
||||
|
||||
class InWorld : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InWorld(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex,
|
||||
std::map<int, CombatData>* argCombatMap,
|
||||
std::map<int, CharacterData>* argCharacterMap
|
||||
);
|
||||
~InWorld();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void RenderFrame();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
void QuitEvent();
|
||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
void HandleCharacterNew(SerialPacket);
|
||||
void HandleCharacterDelete(SerialPacket);
|
||||
void HandleCharacterUpdate(SerialPacket);
|
||||
void HandleRegionContent(SerialPacket);
|
||||
|
||||
//Server control
|
||||
void RequestSynchronize();
|
||||
void SendPlayerUpdate();
|
||||
void RequestDisconnect();
|
||||
void RequestShutDown();
|
||||
void RequestRegion(int mapIndex, int x, int y);
|
||||
|
||||
//utilities
|
||||
void UpdateMap();
|
||||
|
||||
//shared parameters
|
||||
ConfigUtility& config;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
std::map<int, CombatData>& combatMap;
|
||||
std::map<int, CharacterData>& characterMap;
|
||||
|
||||
//graphics
|
||||
Image buttonImage;
|
||||
RasterFont font;
|
||||
TileSheet tileSheet;
|
||||
|
||||
//map
|
||||
RegionPager<BlankAllocator, DummyFormat> regionPager;
|
||||
|
||||
//UI
|
||||
Button disconnectButton;
|
||||
Button shutDownButton;
|
||||
//TODO: Review the camera
|
||||
struct {
|
||||
int x = 0, y = 0;
|
||||
int width = 0, height = 0;
|
||||
int marginX = 0, marginY = 0;
|
||||
} camera;
|
||||
FrameRate fps;
|
||||
|
||||
//game
|
||||
CharacterData* localCharacter = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "lobby_menu.hpp"
|
||||
|
||||
#include "channels.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
LobbyMenu::LobbyMenu(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex
|
||||
):
|
||||
config(*argConfig),
|
||||
network(*argNetwork),
|
||||
clientIndex(*argClientIndex),
|
||||
accountIndex(*argAccountIndex),
|
||||
characterIndex(*argCharacterIndex)
|
||||
{
|
||||
//setup the utility objects
|
||||
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
image.SetClipH(image.GetClipH()/3);
|
||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
search.SetImage(&image);
|
||||
search.SetFont(&font);
|
||||
join.SetImage(&image);
|
||||
join.SetFont(&font);
|
||||
back.SetImage(&image);
|
||||
back.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
search.SetX(50);
|
||||
search.SetY(50 + image.GetClipH() * 0);
|
||||
join.SetX(50);
|
||||
join.SetY(50 + image.GetClipH() * 1);
|
||||
back.SetX(50);
|
||||
back.SetY(50 + image.GetClipH() * 2);
|
||||
|
||||
//set the button texts
|
||||
search.SetText("Search");
|
||||
join.SetText("Join");
|
||||
back.SetText("Back");
|
||||
|
||||
//set the server list's position
|
||||
listBox = {300, 50, 200, font.GetCharH()};
|
||||
}
|
||||
|
||||
LobbyMenu::~LobbyMenu() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::Update(double delta) {
|
||||
//suck in and process all waiting packets
|
||||
SerialPacket packet;
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void LobbyMenu::Render(SDL_Surface* const screen) {
|
||||
//TODO: I need a proper UI system for the entire client and the editor
|
||||
|
||||
//UI
|
||||
search.DrawTo(screen);
|
||||
join.DrawTo(screen);
|
||||
back.DrawTo(screen);
|
||||
|
||||
//TODO: draw headers for the server list
|
||||
for (int i = 0; i < serverInfo.size(); i++) {
|
||||
//draw the selected server's highlight
|
||||
if (selection == &serverInfo[i]) {
|
||||
SDL_Rect r = listBox;
|
||||
r.y += i * listBox.h;
|
||||
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
|
||||
}
|
||||
|
||||
//draw the server name
|
||||
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h);
|
||||
|
||||
//draw the player count
|
||||
font.DrawStringTo(to_string_custom(serverInfo[i].playerCount), screen, listBox.x + listBox.w, listBox.y + i*listBox.h);
|
||||
|
||||
//compatible?
|
||||
if (!serverInfo[i].compatible) {
|
||||
font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h);
|
||||
}
|
||||
|
||||
//TODO: ping/delay?
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
search.MouseMotion(motion);
|
||||
join.MouseMotion(motion);
|
||||
back.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
search.MouseButtonDown(button);
|
||||
join.MouseButtonDown(button);
|
||||
back.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (search.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
//broadcast to the network, or a specific server
|
||||
SerialPacket packet;
|
||||
packet.meta.type = SerialPacket::Type::BROADCAST_REQUEST;
|
||||
network.SendTo(config["server.host"].c_str(), config.Int("server.port"), &packet);
|
||||
|
||||
//reset the server list
|
||||
serverInfo.clear();
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
|
||||
//pack the packet
|
||||
SerialPacket packet;
|
||||
packet.meta.type = SerialPacket::Type::JOIN_REQUEST;
|
||||
strncpy(packet.clientInfo.username, config["client.username"].c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.clientInfo.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.clientInfo.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
|
||||
|
||||
//join the selected server
|
||||
network.SendTo(&selection->address, &packet);
|
||||
selection = nullptr;
|
||||
}
|
||||
|
||||
else if (back.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
|
||||
else if (
|
||||
//has the user selected a server on the list?
|
||||
button.x > listBox.x &&
|
||||
button.x < listBox.x + listBox.w &&
|
||||
button.y > listBox.y &&
|
||||
button.y < listBox.y + listBox.h * serverInfo.size()
|
||||
) {
|
||||
selection = &serverInfo[(button.y - listBox.y)/listBox.h];
|
||||
}
|
||||
else {
|
||||
selection = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Network handlers
|
||||
//-------------------------
|
||||
|
||||
void LobbyMenu::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE: {
|
||||
//extract the data
|
||||
ServerInformation server;
|
||||
server.address = packet.meta.srcAddress;
|
||||
server.networkVersion = packet.serverInfo.networkVersion;
|
||||
server.name = packet.serverInfo.name;
|
||||
server.playerCount = packet.serverInfo.playerCount;
|
||||
|
||||
//NOTE: Check compatibility here
|
||||
server.compatible = server.networkVersion == NETWORK_VERSION;
|
||||
|
||||
//push
|
||||
serverInfo.push_back(server);
|
||||
}
|
||||
break;
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
clientIndex = packet.clientInfo.clientIndex;
|
||||
accountIndex = packet.clientInfo.accountIndex;
|
||||
characterIndex = packet.clientInfo.characterIndex;
|
||||
network.Bind(&packet.meta.srcAddress, Channels::SERVER);
|
||||
SetNextScene(SceneList::INWORLD);
|
||||
break;
|
||||
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error(std::string() + "Unknown SerialPacket::Type encountered in LobbyMenu: " + to_string_custom(int(packet.meta.type))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -19,75 +19,82 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef INWORLD_HPP_
|
||||
#define INWORLD_HPP_
|
||||
#ifndef LOBBYMENU_HPP_
|
||||
#define LOBBYMENU_HPP_
|
||||
|
||||
//graphics & ui
|
||||
//graphics & utilities
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
#include "config_utility.hpp"
|
||||
|
||||
//map stuff
|
||||
#include "tile_sheet.hpp"
|
||||
#include "region_pager_lua.hpp"
|
||||
//network
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//entities
|
||||
#include "character.hpp"
|
||||
|
||||
//utilities
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
//framework
|
||||
//client
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//APIs
|
||||
#include "lua/lua.hpp"
|
||||
//STL
|
||||
#include <vector>
|
||||
|
||||
class InWorld : public BaseScene {
|
||||
class LobbyMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InWorld(lua_State* L);
|
||||
~InWorld();
|
||||
LobbyMenu(
|
||||
ConfigUtility* const argConfig,
|
||||
UDPNetworkUtility* const argNetwork,
|
||||
int* const argClientIndex,
|
||||
int* const argAccountIndex,
|
||||
int* const argCharacterIndex
|
||||
);
|
||||
~LobbyMenu();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void RenderFrame();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
void QuitEvent();
|
||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
struct {
|
||||
struct {
|
||||
int x, y;
|
||||
}origin, margin;
|
||||
}camera;
|
||||
//Network handlers
|
||||
void HandlePacket(SerialPacket);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
ConfigUtility& config;
|
||||
UDPNetworkUtility& network;
|
||||
int& clientIndex;
|
||||
int& accountIndex;
|
||||
int& characterIndex;
|
||||
|
||||
//graphics
|
||||
Image buttonImage;
|
||||
//members
|
||||
Image image;
|
||||
RasterFont font;
|
||||
Button search;
|
||||
Button join;
|
||||
Button back;
|
||||
|
||||
//map stuff
|
||||
TileSheet tileSheet;
|
||||
RegionPagerLua pager;
|
||||
//server list
|
||||
struct ServerInformation {
|
||||
IPaddress address;
|
||||
int networkVersion;
|
||||
std::string name;
|
||||
int playerCount;
|
||||
bool compatible;
|
||||
};
|
||||
|
||||
//entities
|
||||
Character character;
|
||||
std::vector<ServerInformation> serverInfo;
|
||||
|
||||
//UI
|
||||
Button backButton;
|
||||
FrameRate fps;
|
||||
//a terrible hack, forgive me
|
||||
//I'd love a proper gui system for this
|
||||
SDL_Rect listBox;
|
||||
ServerInformation* selection = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "application.hpp"
|
||||
#include "client_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
@@ -27,8 +27,9 @@
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
cout << "Beginning client" << endl;
|
||||
try {
|
||||
Application app;
|
||||
ClientApplication app;
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
@@ -37,5 +38,6 @@ int main(int argc, char** argv) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
cout << "Clean exit" << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -25,20 +25,13 @@
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
MainMenu::MainMenu(lua_State* L): lua(L) {
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "interface");
|
||||
std::string interface = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -2, "fonts");
|
||||
std::string fonts = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 4);
|
||||
|
||||
MainMenu::MainMenu(ConfigUtility* const argConfig):
|
||||
config(*argConfig)
|
||||
{
|
||||
//setup the utility objects
|
||||
image.LoadSurface(interface + "button_menu.bmp");
|
||||
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
image.SetClipH(image.GetClipH()/3);
|
||||
font.LoadSurface(fonts + "pk_white_8.bmp");
|
||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
startButton.SetImage(&image);
|
||||
@@ -60,9 +53,6 @@ MainMenu::MainMenu(lua_State* L): lua(L) {
|
||||
startButton.SetText("Start");
|
||||
optionsButton.SetText("Options");
|
||||
quitButton.SetText("Quit");
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
@@ -109,7 +99,7 @@ void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
|
||||
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::INWORLD);
|
||||
SetNextScene(SceneList::LOBBYMENU);
|
||||
}
|
||||
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::OPTIONSMENU);
|
||||
@@ -120,7 +110,11 @@ void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
}
|
||||
|
||||
void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
@@ -24,16 +24,15 @@
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class MainMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
MainMenu(lua_State* L);
|
||||
MainMenu(ConfigUtility* const);
|
||||
~MainMenu();
|
||||
|
||||
protected:
|
||||
@@ -51,7 +50,7 @@ protected:
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
@@ -0,0 +1,37 @@
|
||||
#config
|
||||
INCLUDES+=. ../common/gameplay ../common/graphics ../common/map ../common/network ../common/ui ../common/utilities
|
||||
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
OUT=$(addprefix $(OUTDIR)/,client)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -25,20 +25,13 @@
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
OptionsMenu::OptionsMenu(lua_State* L): lua(L) {
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "interface");
|
||||
std::string interface = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -2, "fonts");
|
||||
std::string fonts = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 4);
|
||||
|
||||
OptionsMenu::OptionsMenu(ConfigUtility* const argConfig):
|
||||
config(*argConfig)
|
||||
{
|
||||
//setup the utility objects
|
||||
image.LoadSurface(interface + "button_menu.bmp");
|
||||
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||
image.SetClipH(image.GetClipH()/3);
|
||||
font.LoadSurface(fonts + "pk_white_8.bmp");
|
||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
backButton.SetImage(&image);
|
||||
@@ -97,7 +90,11 @@ void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
}
|
||||
|
||||
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
@@ -24,17 +24,15 @@
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
//TODO: The options screen needs to be USED
|
||||
class OptionsMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
OptionsMenu(lua_State* L);
|
||||
OptionsMenu(ConfigUtility* const);
|
||||
~OptionsMenu();
|
||||
|
||||
protected:
|
||||
@@ -52,7 +50,7 @@ protected:
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
@@ -32,7 +32,9 @@ enum class SceneList {
|
||||
SPLASHSCREEN,
|
||||
MAINMENU,
|
||||
OPTIONSMENU,
|
||||
LOBBYMENU,
|
||||
INWORLD,
|
||||
INCOMBAT,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -21,21 +21,14 @@
|
||||
*/
|
||||
#include "splash_screen.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
SplashScreen::SplashScreen(lua_State* L): lua(L) {
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "logos");
|
||||
std::string logos = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 3);
|
||||
|
||||
logo.LoadSurface(logos + "krstudios.bmp");
|
||||
SplashScreen::SplashScreen(ConfigUtility* const argConfig):
|
||||
config(*argConfig)
|
||||
{
|
||||
logo.LoadSurface(config["dir.logos"] + "krstudios.bmp");
|
||||
startTick = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "image.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class SplashScreen : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
SplashScreen(lua_State* L);
|
||||
SplashScreen(ConfigUtility* const);
|
||||
~SplashScreen();
|
||||
|
||||
protected:
|
||||
@@ -42,7 +41,7 @@ protected:
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
ConfigUtility& config;
|
||||
|
||||
//members
|
||||
std::chrono::steady_clock::time_point startTick;
|
||||
@@ -19,13 +19,18 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef TILESHEETAPI_HPP_
|
||||
#define TILESHEETAPI_HPP_
|
||||
#ifndef ACCOUNTDATA_HPP_
|
||||
#define ACCOUNTDATA_HPP_
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include <string>
|
||||
|
||||
#define TORTUGA_TILE_SHEET_PSEUDO_INDEX "TileSheetPseudoIndex"
|
||||
#define TORTUGA_TILE_SHEET_NAME "TileSheet"
|
||||
LUAMOD_API int openTileSheetAPI(lua_State* L);
|
||||
struct AccountData {
|
||||
std::string username;
|
||||
//TODO: password
|
||||
bool blackListed = false;
|
||||
bool whiteListed = true;
|
||||
|
||||
int clientIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,23 +19,27 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character.hpp"
|
||||
#include "character_data.hpp"
|
||||
|
||||
void Character::Update(double delta) {
|
||||
void CharacterData::Update(double delta) {
|
||||
if (motion.x && motion.y) {
|
||||
origin += motion * delta * CHARACTER_WALKING_MOD;
|
||||
position += motion * delta * CHARACTER_WALKING_MOD;
|
||||
}
|
||||
else if (motion != 0) {
|
||||
origin += motion * delta;
|
||||
position += motion * delta;
|
||||
}
|
||||
#ifdef GRAPHICS
|
||||
sprite.Update(delta);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Character::DrawTo(SDL_Surface* const dest, int camX, int camY) {
|
||||
sprite.DrawTo(dest, origin.x - camX, origin.y - camY);
|
||||
#ifdef GRAPHICS
|
||||
|
||||
void CharacterData::DrawTo(SDL_Surface* const dest, int camX, int camY) {
|
||||
sprite.DrawTo(dest, position.x - camX, position.y - camY);
|
||||
}
|
||||
|
||||
void Character::CorrectSprite() {
|
||||
void CharacterData::CorrectSprite() {
|
||||
//NOTE: These must correspond to the sprite sheet in use
|
||||
if (motion.y > 0) {
|
||||
sprite.SetYIndex(0);
|
||||
@@ -59,3 +63,5 @@ void Character::CorrectSprite() {
|
||||
sprite.SetXIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,51 +19,62 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef CHARACTER_HPP_
|
||||
#define CHARACTER_HPP_
|
||||
#ifndef CHARACTERDATA_HPP_
|
||||
#define CHARACTERDATA_HPP_
|
||||
|
||||
//components
|
||||
//POD members
|
||||
#include "bbox.hpp"
|
||||
#include "vector2.hpp"
|
||||
#include "bounding_box.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
//graphics
|
||||
#include "sprite_sheet.hpp"
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
//the speeds that the characters move
|
||||
constexpr double CHARACTER_WALKING_SPEED = 140.0;
|
||||
constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0);
|
||||
|
||||
class Character {
|
||||
public:
|
||||
Character() = default;
|
||||
~Character() = default;
|
||||
struct CharacterData {
|
||||
//metadata
|
||||
int owner;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
|
||||
//world position
|
||||
int mapIndex = 0;
|
||||
Vector2 position = {0.0,0.0};
|
||||
Vector2 motion = {0.0,0.0};
|
||||
|
||||
//base statistics
|
||||
Statistics stats;
|
||||
|
||||
//TODO: equipment
|
||||
//TODO: items
|
||||
//TODO: buffs
|
||||
//TODO: debuffs
|
||||
|
||||
//methods
|
||||
void Update(double delta);
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
void DrawTo(SDL_Surface* const, int camX, int camY);
|
||||
void CorrectSprite();
|
||||
SpriteSheet* GetSprite() { return &sprite; }
|
||||
#endif
|
||||
|
||||
//accessors and mutators
|
||||
Vector2 SetOrigin(Vector2 v) { return origin = v; }
|
||||
Vector2 GetOrigin() const { return origin; }
|
||||
Vector2 SetMotion(Vector2 v) { return motion = v; }
|
||||
Vector2 GetMotion() const { return motion; }
|
||||
BoundingBox SetBoundingBox(BoundingBox b) { return bounds = b; }
|
||||
BoundingBox GetBoundingBox() const { return bounds; }
|
||||
|
||||
private:
|
||||
//graphics
|
||||
//active gameplay members
|
||||
//NOTE: these are lost when unloaded
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
|
||||
//position
|
||||
Vector2 origin = {0.0,0.0};
|
||||
Vector2 motion = {0.0,0.0};
|
||||
BoundingBox bounds;
|
||||
#endif
|
||||
BBox bbox = {0,0,0,0};
|
||||
bool inCombat = false;
|
||||
int atbGauge = 0;
|
||||
//TODO: stored command
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,11 +19,13 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "timer.hpp"
|
||||
#ifndef CLIENTDATA_HPP_
|
||||
#define CLIENTDATA_HPP_
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Timer& t) {
|
||||
os << t.GetName() << ": ";
|
||||
os << std::chrono::duration_cast<std::chrono::nanoseconds>(t.GetTime()).count();
|
||||
os << "ns";
|
||||
return os;
|
||||
}
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
struct ClientData {
|
||||
IPaddress address = {0,0};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef COMBATDATA_HPP_
|
||||
#define COMBATDATA_HPP_
|
||||
|
||||
//POD members
|
||||
#include "vector2.hpp"
|
||||
#include "bbox.hpp"
|
||||
|
||||
//gameplay members
|
||||
#include "character_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
struct CombatData {
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
|
||||
//combatants, point to the std::map's internal pairs
|
||||
std::list<std::pair<const int, CharacterData>*> characterList;
|
||||
std::list<std::pair<const int, EnemyData>*> enemyList;
|
||||
|
||||
//world interaction
|
||||
int mapIndex = 0;
|
||||
Vector2 position = {0.0,0.0};
|
||||
BBox bbox = {0,0,0,0};
|
||||
|
||||
//time interval
|
||||
Clock::time_point lastTick = Clock::now();
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef ENEMYDATA_HPP_
|
||||
#define ENEMYDATA_HPP_
|
||||
|
||||
//gameplay
|
||||
#include "statistics.hpp"
|
||||
|
||||
//graphics
|
||||
#ifdef GRAPHICS
|
||||
#include "sprite_sheet.hpp"
|
||||
#endif
|
||||
|
||||
//std namespace
|
||||
#include <string>
|
||||
|
||||
struct EnemyData {
|
||||
//metadata
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
|
||||
//gameplay
|
||||
Statistics stats;
|
||||
|
||||
//TODO: equipment
|
||||
//TODO: items
|
||||
//TODO: buffs
|
||||
//TODO: debuffs
|
||||
|
||||
//active gameplay members
|
||||
//NOTE: these are lost when unloaded
|
||||
#ifdef GRAPHICS
|
||||
SpriteSheet sprite;
|
||||
#endif
|
||||
int tableIndex;
|
||||
int atbGauge = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#config
|
||||
INCLUDES+=. ../utilities ../graphics
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) -DGRAPHICS
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
ar -crs $(OUT) $(OBJ)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "account_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "client_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
/* DOCS: Sanity check, read more
|
||||
* Since most/all of the files in this directory are header files, I've created
|
||||
* this source file as a "sanity check", to ensure that the above header files
|
||||
* are written correctly via make.
|
||||
*
|
||||
* Oddly enough, I'm pretty sure this is the first directory compiled in a
|
||||
* clean build.
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef STATISTICS_HPP_
|
||||
#define STATISTICS_HPP_
|
||||
|
||||
struct Statistics {
|
||||
int level = 0;
|
||||
int exp = 0;
|
||||
int maxHP = 0;
|
||||
int health = 0;
|
||||
int maxMP = 0;
|
||||
int mana = 0;
|
||||
int attack = 0;
|
||||
int defence = 0;
|
||||
int intelligence = 0;
|
||||
int resistance = 0;
|
||||
int speed = 0;
|
||||
float accuracy = 0.0;
|
||||
float evasion = 0.0;
|
||||
float luck = 0.0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
INCLUDES+=. ../map
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
@@ -11,7 +11,7 @@ OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
@@ -21,24 +21,24 @@
|
||||
*/
|
||||
#include "tile_sheet.hpp"
|
||||
|
||||
void TileSheet::Load(std::string fname, int tileWidth, int tileHeight) {
|
||||
void TileSheet::Load(std::string fname, int xc, int yc) {
|
||||
XCount = xc;
|
||||
YCount = yc;
|
||||
image.LoadSurface(fname);
|
||||
image.SetClipW(tileWidth);
|
||||
image.SetClipH(tileHeight);
|
||||
xCount = image.GetSurface()->w / image.GetClipW();
|
||||
yCount = image.GetSurface()->h / image.GetClipH();
|
||||
image.SetClipW(image.GetClipW()/XCount);
|
||||
image.SetClipH(image.GetClipH()/YCount);
|
||||
}
|
||||
|
||||
void TileSheet::Unload() {
|
||||
image.FreeSurface();
|
||||
xCount = yCount = 0;
|
||||
XCount = YCount = 0;
|
||||
}
|
||||
|
||||
void TileSheet::DrawTileTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
|
||||
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
|
||||
//0 is invisible
|
||||
if (tile == 0) return;
|
||||
image.SetClipX((tile-1) % xCount * image.GetClipW());
|
||||
image.SetClipY((tile-1) / xCount * image.GetClipH());
|
||||
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||
image.DrawTo(dest, x, y);
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int
|
||||
tile = region->GetTile(i, j, k);
|
||||
//0 is invisible
|
||||
if (tile == 0) continue;
|
||||
image.SetClipX((tile-1) % xCount * image.GetClipW());
|
||||
image.SetClipY((tile-1) / xCount * image.GetClipH());
|
||||
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||
image.DrawTo(dest,
|
||||
(region->GetX() + i) * image.GetClipW() - camX,
|
||||
(region->GetY() + j) * image.GetClipH() - camY);
|
||||
@@ -31,24 +31,24 @@
|
||||
class TileSheet {
|
||||
public:
|
||||
TileSheet() = default;
|
||||
TileSheet(std::string f, int w, int h) { Load(f, w, h); }
|
||||
TileSheet(std::string f, int x, int y) { Load(f, x, y); }
|
||||
~TileSheet() = default;
|
||||
|
||||
void Load(std::string fname, int tileWidth, int tileHeight);
|
||||
void Load(std::string fname, int XCount, int YCount);
|
||||
void Unload();
|
||||
|
||||
void DrawTileTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
|
||||
void DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
|
||||
void DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY);
|
||||
|
||||
//accessors
|
||||
Image* GetImage() { return ℑ }
|
||||
int GetXCount() { return xCount; }
|
||||
int GetYCount() { return yCount; }
|
||||
int GetXCount() { return XCount; }
|
||||
int GetYCount() { return YCount; }
|
||||
int GetTileW() { return image.GetClipW(); }
|
||||
int GetTileH() { return image.GetClipH(); }
|
||||
private:
|
||||
Image image;
|
||||
int xCount = 0, yCount = 0;
|
||||
int XCount = 0, YCount = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
all:
|
||||
$(MAKE) -C gameplay
|
||||
$(MAKE) -C graphics
|
||||
$(MAKE) -C map
|
||||
$(MAKE) -C network
|
||||
$(MAKE) -C script
|
||||
$(MAKE) -C ui
|
||||
$(MAKE) -C utilities
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
INCLUDES+=. ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
@@ -11,7 +11,7 @@ OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
@@ -19,37 +19,42 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "map_allocator.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
Region::Region(int argX, int argY): x(argX), y(argY) {
|
||||
if (x != snapToBase(REGION_WIDTH, x) || y != snapToBase(REGION_HEIGHT, y)) {
|
||||
throw(std::invalid_argument("Region location is off grid"));
|
||||
void BlankAllocator::Create(Region** const ptr, int x, int y) {
|
||||
(*ptr) = new Region(x, y);
|
||||
}
|
||||
|
||||
void BlankAllocator::Unload(Region* const ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
void LuaAllocator::Create(Region** const ptr, int x, int y) {
|
||||
//something to work on
|
||||
(*ptr) = new Region(x, y);
|
||||
|
||||
//API hook
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "create");
|
||||
lua_pushlightuserdata(state, *ptr);
|
||||
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
}
|
||||
memset(tiles, 0, REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH*sizeof(type_t));
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
Region::Region(Region const& rhs): x(rhs.x), y(rhs.y) {
|
||||
memcpy(tiles, rhs.tiles, REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH*sizeof(type_t));
|
||||
solid = rhs.solid;
|
||||
}
|
||||
void LuaAllocator::Unload(Region* const ptr) {
|
||||
//API hook
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "unload");
|
||||
lua_pushlightuserdata(state, ptr);
|
||||
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
}
|
||||
lua_pop(state, 1);
|
||||
|
||||
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||
return tiles[x][y][z] = v;
|
||||
//clean up the memory
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
Region::type_t Region::GetTile(int x, int y, int z) {
|
||||
return tiles[x][y][z];
|
||||
}
|
||||
|
||||
bool Region::SetSolid(int x, int y, bool b) {
|
||||
return solid[x * REGION_WIDTH + y] = b;
|
||||
}
|
||||
|
||||
bool Region::GetSolid(int x, int y) {
|
||||
return solid[x * REGION_WIDTH + y];
|
||||
}
|
||||
@@ -19,24 +19,30 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SIMPLERNG_HPP_
|
||||
#define SIMPLERNG_HPP_
|
||||
#ifndef MAPALLOCATOR_HPP_
|
||||
#define MAPALLOCATOR_HPP_
|
||||
|
||||
//a simple, stateless, random number generator
|
||||
class SimpleRNG {
|
||||
#include "region.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class BlankAllocator {
|
||||
public:
|
||||
SimpleRNG() { SetSeed(8891.0); }
|
||||
SimpleRNG(double x) { SetSeed(x); }
|
||||
|
||||
double SetSeed(double s) { return seed = s; }
|
||||
double GetSeed() { return seed; }
|
||||
|
||||
double operator()(double x) {
|
||||
return (x + seed) * 11235.0 + 81321.0;
|
||||
};
|
||||
|
||||
void Create(Region** const, int x, int y);
|
||||
void Unload(Region* const);
|
||||
private:
|
||||
double seed;
|
||||
//
|
||||
};
|
||||
|
||||
#endif
|
||||
class LuaAllocator {
|
||||
public:
|
||||
void Create(Region** const, int x, int y);
|
||||
void Unload(Region* const);
|
||||
|
||||
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||
lua_State* GetLuaState() { return state; }
|
||||
private:
|
||||
lua_State* state = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "map_file_format.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void DummyFormat::Load(Region** const ptr, int x, int y) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void DummyFormat::Save(Region* const ptr) {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void LuaFormat::Load(Region** const ptr, int x, int y) {
|
||||
//something to load into
|
||||
|
||||
if (!(*ptr)) {
|
||||
(*ptr) = new Region(x, y);
|
||||
}
|
||||
|
||||
//API hook
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "load");
|
||||
lua_pushlightuserdata(state, *ptr);
|
||||
lua_pushstring(state, saveDir.c_str());
|
||||
if (lua_pcall(state, 2, 1, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
}
|
||||
if (lua_toboolean(state, -1) == false) {
|
||||
delete (*ptr);
|
||||
(*ptr) = nullptr;
|
||||
}
|
||||
lua_pop(state, 2);
|
||||
}
|
||||
|
||||
void LuaFormat::Save(Region* const ptr) {
|
||||
//API hook
|
||||
lua_getglobal(state, "map");
|
||||
lua_getfield(state, -1, "save");
|
||||
lua_pushlightuserdata(state, ptr);
|
||||
lua_pushstring(state, saveDir.c_str());
|
||||
if (lua_pcall(state, 2, 0, 0) != LUA_OK) {
|
||||
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||
}
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MAPFILEFORMAT_HPP_
|
||||
#define MAPFILEFORMAT_HPP_
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class DummyFormat {
|
||||
public:
|
||||
void Load(Region** const, int x, int y);
|
||||
void Save(Region* const);
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
std::string GetSaveDir() { return saveDir; }
|
||||
private:
|
||||
std::string saveDir;
|
||||
};
|
||||
|
||||
//TODO: verbose save file format
|
||||
//TODO: compact save file format
|
||||
|
||||
class LuaFormat {
|
||||
public:
|
||||
void Load(Region** const, int x, int y);
|
||||
void Save(Region* const);
|
||||
|
||||
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||
std::string GetSaveDir() { return saveDir; }
|
||||
|
||||
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||
lua_State* GetLuaState() { return state; }
|
||||
private:
|
||||
std::string saveDir;
|
||||
lua_State* state = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region.hpp"
|
||||
|
||||
Region::Region(int argX, int argY):
|
||||
x(argX),
|
||||
y(argY)
|
||||
{
|
||||
for (register int i = 0; i < REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH; ++i) {
|
||||
*(reinterpret_cast<type_t*>(tiles) + i) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||
return tiles[x][y][z] = v;
|
||||
}
|
||||
|
||||
Region::type_t Region::GetTile(int x, int y, int z) {
|
||||
return tiles[x][y][z];
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGION_HPP_
|
||||
#define REGION_HPP_
|
||||
|
||||
#define REGION_WIDTH 20
|
||||
#define REGION_HEIGHT 20
|
||||
#define REGION_DEPTH 3
|
||||
|
||||
class Region {
|
||||
public:
|
||||
typedef unsigned short type_t;
|
||||
|
||||
Region() = delete;
|
||||
Region(int x, int y);
|
||||
~Region() = default;
|
||||
|
||||
type_t SetTile(int x, int y, int z, type_t v);
|
||||
type_t GetTile(int x, int y, int z);
|
||||
|
||||
//accessors
|
||||
int GetX() const { return x; }
|
||||
int GetY() const { return y; }
|
||||
private:
|
||||
const int x;
|
||||
const int y;
|
||||
|
||||
type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,13 +19,10 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region_pager_base.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
|
||||
Region* ptr = GetRegion(x, y);
|
||||
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
|
||||
@@ -36,17 +33,8 @@ Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
|
||||
return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z);
|
||||
}
|
||||
|
||||
bool RegionPagerBase::SetSolid(int x, int y, int b) {
|
||||
Region* ptr = GetRegion(x, y);
|
||||
return ptr->SetSolid(x - ptr->GetX(), y - ptr->GetY(), b);
|
||||
}
|
||||
|
||||
bool RegionPagerBase::GetSolid(int x, int y) {
|
||||
Region* ptr = GetRegion(x, y);
|
||||
return ptr->GetSolid(x - ptr->GetX(), y - ptr->GetY());
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
@@ -60,41 +48,20 @@ Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::FindRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//find the region
|
||||
std::list<Region>::iterator it = find_if(regionList.begin(), regionList.end(), [x, y](Region& region) -> bool {
|
||||
return region.GetX() == x && region.GetY() == y;
|
||||
});
|
||||
return it != regionList.end() ? &(*it) : nullptr;
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::PushRegion(Region* const ptr) {
|
||||
regionList.push_front(*ptr);
|
||||
return ®ionList.front();
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::LoadRegion(int x, int y) {
|
||||
//TODO: load the region if possible
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::SaveRegion(int x, int y) {
|
||||
//TODO: find & save the region
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Region* RegionPagerBase::CreateRegion(int x, int y) {
|
||||
if (FindRegion(x, y)) {
|
||||
throw(std::logic_error("Cannot overwrite an existing region"));
|
||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
regionList.emplace_front(x, y);
|
||||
return ®ionList.front();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RegionPagerBase::UnloadRegion(int x, int y) {
|
||||
//custom loop, not FindRegion()
|
||||
regionList.remove_if([x, y](Region& region) -> bool { return region.GetX() == x && region.GetY() == y; });
|
||||
}
|
||||
|
||||
void RegionPagerBase::UnloadAll() {
|
||||
regionList.clear();
|
||||
Region* RegionPagerBase::PushRegion(Region* ptr) {
|
||||
regionList.push_front(ptr);
|
||||
return regionList.front();
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONPAGER_HPP_
|
||||
#define REGIONPAGER_HPP_
|
||||
|
||||
#include "region.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <list>
|
||||
|
||||
class RegionPagerBase {
|
||||
public:
|
||||
RegionPagerBase() {};
|
||||
virtual ~RegionPagerBase() {};
|
||||
|
||||
//tile manipulation
|
||||
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
|
||||
Region::type_t GetTile(int x, int y, int z);
|
||||
|
||||
//region manipulation
|
||||
Region* GetRegion(int x, int y);
|
||||
Region* FindRegion(int x, int y);
|
||||
Region* PushRegion(Region*);
|
||||
|
||||
//interface
|
||||
virtual Region* LoadRegion(int x, int y) = 0;
|
||||
virtual Region* SaveRegion(int x, int y) = 0;
|
||||
virtual Region* CreateRegion(int x, int y) = 0;
|
||||
virtual void UnloadRegion(int x, int y) = 0;
|
||||
//TODO: delete existing regions
|
||||
|
||||
//accessors & mutators
|
||||
std::list<Region*>* GetContainer() { return ®ionList; }
|
||||
protected:
|
||||
std::list<Region*> regionList;
|
||||
};
|
||||
|
||||
template<typename Allocator, typename FileFormat>
|
||||
class RegionPager : public RegionPagerBase {
|
||||
public:
|
||||
RegionPager() {};
|
||||
~RegionPager() {
|
||||
UnloadAll();
|
||||
}
|
||||
|
||||
Region* LoadRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//load the region if possible
|
||||
Region* ptr = nullptr;
|
||||
format.Load(&ptr, x, y);
|
||||
if (ptr) {
|
||||
return PushRegion(ptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Region* SaveRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//find & save the region
|
||||
Region* ptr = FindRegion(x, y);
|
||||
if (ptr) {
|
||||
format.Save(ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Region* CreateRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//create and push the object
|
||||
Region* ptr = nullptr;
|
||||
allocator.Create(&ptr, x, y);
|
||||
return PushRegion(ptr);
|
||||
}
|
||||
|
||||
void UnloadRegion(int x, int y) {
|
||||
//snap the coords
|
||||
x = snapToBase(REGION_WIDTH, x);
|
||||
y = snapToBase(REGION_HEIGHT, y);
|
||||
|
||||
//custom loop
|
||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
|
||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||
allocator.Unload(*it);
|
||||
it = regionList.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
void UnloadAll() {
|
||||
for (auto& it : regionList) {
|
||||
allocator.Unload(it);
|
||||
}
|
||||
regionList.clear();
|
||||
}
|
||||
|
||||
//accessors
|
||||
Allocator* GetAllocator() { return &allocator; }
|
||||
FileFormat* GetFormat() { return &format; }
|
||||
protected:
|
||||
Allocator allocator;
|
||||
FileFormat format;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#config
|
||||
INCLUDES+=. ../graphics ../utilities
|
||||
INCLUDES+=. ../gameplay ../map ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
@@ -11,7 +11,7 @@ OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
@@ -0,0 +1,433 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "serial.hpp"
|
||||
|
||||
#include "map_allocator.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
//-------------------------
|
||||
//Convenience Macros
|
||||
//-------------------------
|
||||
|
||||
#define SERIALIZE(buffer, data, size) memcpy(buffer, data, size); buffer += size;
|
||||
#define DESERIALIZE(buffer, data, size) memcpy(data, buffer, size); buffer += size;
|
||||
|
||||
//-------------------------
|
||||
//internal serialization functions
|
||||
//-------------------------
|
||||
|
||||
void serializeType(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
}
|
||||
|
||||
void serializeServer(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//server info
|
||||
SERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
|
||||
SERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
|
||||
}
|
||||
|
||||
void serializeClient(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
SERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
|
||||
//TODO: password
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
}
|
||||
|
||||
void serializeRegionFormat(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//format
|
||||
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
}
|
||||
|
||||
void serializeRegionContent(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//format
|
||||
SERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
|
||||
//content
|
||||
for (register int i = 0; i < REGION_WIDTH; i++) {
|
||||
for (register int j = 0; j < REGION_HEIGHT; j++) {
|
||||
for (register int k = 0; k < REGION_DEPTH; k++) {
|
||||
*reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k);
|
||||
buffer += sizeof(Region::type_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void serializeCombat(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//integers
|
||||
SERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
|
||||
//TODO: more comabat info
|
||||
}
|
||||
|
||||
void serializeStatistics(Statistics* stats, char* buffer) {
|
||||
//integers
|
||||
SERIALIZE(buffer, &stats->level, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->exp, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->maxHP, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->health, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->maxMP, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->mana, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->attack, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->defence, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->intelligence, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->resistance, sizeof(int));
|
||||
SERIALIZE(buffer, &stats->speed, sizeof(int));
|
||||
|
||||
//floats
|
||||
SERIALIZE(buffer, &stats->accuracy, sizeof(float));
|
||||
SERIALIZE(buffer, &stats->evasion, sizeof(float));
|
||||
SERIALIZE(buffer, &stats->luck, sizeof(float));
|
||||
}
|
||||
|
||||
void serializeCharacter(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
SERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
|
||||
SERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//vectors
|
||||
SERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
|
||||
SERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
|
||||
|
||||
//stats structure
|
||||
serializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
void serializeEnemy(SerialPacket* packet, char* buffer) {
|
||||
SERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//texts
|
||||
SERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
SERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//stats structure
|
||||
serializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//internal deserialization functions
|
||||
//-------------------------
|
||||
|
||||
void deserializeType(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
}
|
||||
|
||||
void deserializeServer(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//server info
|
||||
DESERIALIZE(buffer, &packet->serverInfo.networkVersion, sizeof(int));
|
||||
DESERIALIZE(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, &packet->serverInfo.playerCount, sizeof(int));
|
||||
}
|
||||
|
||||
void deserializeClient(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
DESERIALIZE(buffer, &packet->clientInfo.clientIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->clientInfo.accountIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->clientInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.username, PACKET_STRING_SIZE);
|
||||
//TODO: password
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
}
|
||||
|
||||
void deserializeRegionFormat(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//format
|
||||
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
}
|
||||
|
||||
void deserializeRegionContent(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//format
|
||||
DESERIALIZE(buffer, &packet->regionInfo.mapIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.x, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->regionInfo.y, sizeof(int));
|
||||
|
||||
//an object to work on
|
||||
BlankAllocator().Create(
|
||||
&packet->regionInfo.region,
|
||||
packet->regionInfo.x,
|
||||
packet->regionInfo.y
|
||||
);
|
||||
|
||||
//content
|
||||
for (register int i = 0; i < REGION_WIDTH; i++) {
|
||||
for (register int j = 0; j < REGION_HEIGHT; j++) {
|
||||
for (register int k = 0; k < REGION_DEPTH; k++) {
|
||||
packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
|
||||
buffer += sizeof(Region::type_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void deserializeCombat(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//integers
|
||||
DESERIALIZE(buffer, &packet->combatInfo.combatIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->combatInfo.difficulty, sizeof(int));
|
||||
//TODO: more comabat info
|
||||
}
|
||||
|
||||
|
||||
void deserializeStatistics(Statistics* stats, char* buffer) {
|
||||
//integers
|
||||
DESERIALIZE(buffer, &stats->level, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->exp, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->maxHP, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->health, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->maxMP, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->mana, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->attack, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->defence, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->intelligence, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->resistance, sizeof(int));
|
||||
DESERIALIZE(buffer, &stats->speed, sizeof(int));
|
||||
|
||||
//floats
|
||||
DESERIALIZE(buffer, &stats->accuracy, sizeof(float));
|
||||
DESERIALIZE(buffer, &stats->evasion, sizeof(float));
|
||||
DESERIALIZE(buffer, &stats->luck, sizeof(float));
|
||||
}
|
||||
|
||||
void deserializeCharacter(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//indexes
|
||||
DESERIALIZE(buffer, &packet->characterInfo.clientIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.accountIndex, sizeof(int));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.characterIndex, sizeof(int));
|
||||
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//vectors
|
||||
DESERIALIZE(buffer, &packet->characterInfo.position.x, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.position.y, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.motion.x, sizeof(double));
|
||||
DESERIALIZE(buffer, &packet->characterInfo.motion.y, sizeof(double));
|
||||
|
||||
//stats structure
|
||||
deserializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
void deserializeEnemy(SerialPacket* packet, char* buffer) {
|
||||
DESERIALIZE(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
|
||||
|
||||
//texts
|
||||
DESERIALIZE(buffer, packet->clientInfo.handle, PACKET_STRING_SIZE);
|
||||
DESERIALIZE(buffer, packet->clientInfo.avatar, PACKET_STRING_SIZE);
|
||||
|
||||
//stats structure
|
||||
deserializeStatistics(&packet->characterInfo.stats, buffer);
|
||||
buffer += sizeof(Statistics);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//the interface functions
|
||||
//-------------------------
|
||||
|
||||
void serialize(SerialPacket* packet, void* buffer) {
|
||||
switch(packet->meta.type) {
|
||||
//no extra data
|
||||
case SerialPacket::Type::NONE:
|
||||
case SerialPacket::Type::PING:
|
||||
case SerialPacket::Type::PONG:
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
|
||||
//all rejections
|
||||
case SerialPacket::Type::BROADCAST_REJECTION:
|
||||
case SerialPacket::Type::JOIN_REJECTION:
|
||||
case SerialPacket::Type::REGION_REJECTION:
|
||||
case SerialPacket::Type::CHARACTER_REJECTION:
|
||||
case SerialPacket::Type::ENEMY_REJECTION:
|
||||
case SerialPacket::Type::COMBAT_REJECTION:
|
||||
|
||||
serializeType(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//server info
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE:
|
||||
serializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//client info
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
serializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//region info
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//combat info
|
||||
case SerialPacket::Type::COMBAT_ENTER:
|
||||
case SerialPacket::Type::COMBAT_EXIT:
|
||||
serializeCombat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//character info
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
|
||||
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
|
||||
serializeCharacter(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//enemy info
|
||||
case SerialPacket::Type::ENEMY_NEW:
|
||||
case SerialPacket::Type::ENEMY_DELETE:
|
||||
case SerialPacket::Type::ENEMY_UPDATE:
|
||||
case SerialPacket::Type::ENEMY_STATS_REQUEST:
|
||||
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
|
||||
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void deserialize(SerialPacket* packet, void* buffer) {
|
||||
//find the type, so that you can actually deserialize the packet!
|
||||
deserializeType(packet, reinterpret_cast<char*>(buffer));
|
||||
switch(packet->meta.type) {
|
||||
//no extra data
|
||||
case SerialPacket::Type::NONE:
|
||||
case SerialPacket::Type::PING:
|
||||
case SerialPacket::Type::PONG:
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
|
||||
//all rejections
|
||||
case SerialPacket::Type::BROADCAST_REJECTION:
|
||||
case SerialPacket::Type::JOIN_REJECTION:
|
||||
case SerialPacket::Type::REGION_REJECTION:
|
||||
case SerialPacket::Type::CHARACTER_REJECTION:
|
||||
case SerialPacket::Type::ENEMY_REJECTION:
|
||||
case SerialPacket::Type::COMBAT_REJECTION:
|
||||
|
||||
//NOTHING
|
||||
break;
|
||||
|
||||
//server info
|
||||
case SerialPacket::Type::BROADCAST_RESPONSE:
|
||||
deserializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//client info
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
case SerialPacket::Type::JOIN_RESPONSE:
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
deserializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//region info
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
case SerialPacket::Type::REGION_CONTENT:
|
||||
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//combat info
|
||||
case SerialPacket::Type::COMBAT_ENTER:
|
||||
case SerialPacket::Type::COMBAT_EXIT:
|
||||
serializeCombat(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//character info
|
||||
case SerialPacket::Type::CHARACTER_NEW:
|
||||
case SerialPacket::Type::CHARACTER_DELETE:
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
case SerialPacket::Type::CHARACTER_STATS_REQUEST:
|
||||
case SerialPacket::Type::CHARACTER_STATS_RESPONSE:
|
||||
deserializeCharacter(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
|
||||
//enemy info
|
||||
case SerialPacket::Type::ENEMY_NEW:
|
||||
case SerialPacket::Type::ENEMY_DELETE:
|
||||
case SerialPacket::Type::ENEMY_UPDATE:
|
||||
case SerialPacket::Type::ENEMY_STATS_REQUEST:
|
||||
case SerialPacket::Type::ENEMY_STATS_RESPONSE:
|
||||
serializeEnemy(packet, reinterpret_cast<char*>(buffer));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SERIAL_HPP_
|
||||
#define SERIAL_HPP_
|
||||
|
||||
#include "serial_packet.hpp"
|
||||
|
||||
/* NOTE: Keep the PACKET_BUFFER_SIZE up to date
|
||||
* NOTE: REGION_CONTENT is currently the largest type of packet
|
||||
* map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t)
|
||||
* map format: sizeof(int) * 3
|
||||
* metadata: sizeof(SerialPacket::Type)
|
||||
*/
|
||||
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 3 + sizeof(SerialPacket::Type)
|
||||
|
||||
void serialize(SerialPacket* const, void* dest);
|
||||
void deserialize(SerialPacket* const, void* src);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SERIALPACKET_HPP_
|
||||
#define SERIALPACKET_HPP_
|
||||
|
||||
#include "vector2.hpp"
|
||||
#include "region.hpp"
|
||||
#include "statistics.hpp"
|
||||
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
#define NETWORK_VERSION 20140528
|
||||
#define PACKET_STRING_SIZE 100
|
||||
|
||||
union SerialPacket {
|
||||
//types of packets
|
||||
enum class Type {
|
||||
//default: there is something wrong
|
||||
NONE = 0,
|
||||
|
||||
//keep alive
|
||||
PING = 1,
|
||||
PONG = 2,
|
||||
|
||||
//searching for a server to join
|
||||
BROADCAST_REQUEST = 3,
|
||||
BROADCAST_RESPONSE = 4,
|
||||
BROADCAST_REJECTION = 5,
|
||||
|
||||
//try to join the server
|
||||
JOIN_REQUEST = 6,
|
||||
JOIN_RESPONSE = 7,
|
||||
JOIN_REJECTION = 8,
|
||||
|
||||
//mass update
|
||||
SYNCHRONIZE = 9,
|
||||
|
||||
//disconnect from the server
|
||||
DISCONNECT = 10,
|
||||
|
||||
//shut down the server
|
||||
SHUTDOWN = 11,
|
||||
|
||||
//map data
|
||||
REGION_REQUEST = 12,
|
||||
REGION_CONTENT = 13,
|
||||
REGION_REJECTION = 14,
|
||||
|
||||
//combat data
|
||||
COMBAT_ENTER = 15,
|
||||
COMBAT_EXIT = 16,
|
||||
|
||||
COMBAT_UPDATE = 17,
|
||||
|
||||
COMBAT_REJECTION = 18,
|
||||
|
||||
//character data
|
||||
CHARACTER_NEW = 19,
|
||||
CHARACTER_DELETE = 20,
|
||||
CHARACTER_UPDATE = 21,
|
||||
|
||||
CHARACTER_STATS_REQUEST = 22,
|
||||
CHARACTER_STATS_RESPONSE = 23,
|
||||
|
||||
CHARACTER_REJECTION = 24,
|
||||
|
||||
//enemy data
|
||||
ENEMY_NEW = 25,
|
||||
ENEMY_DELETE = 26,
|
||||
ENEMY_UPDATE = 27,
|
||||
|
||||
ENEMY_STATS_REQUEST = 28,
|
||||
ENEMY_STATS_RESPONSE = 29,
|
||||
|
||||
ENEMY_REJECTION = 30,
|
||||
|
||||
//more packet types go here
|
||||
|
||||
//not used
|
||||
LAST,
|
||||
};
|
||||
|
||||
//metadata on the packet itself
|
||||
struct Metadata {
|
||||
Type type;
|
||||
IPaddress srcAddress;
|
||||
}meta;
|
||||
|
||||
//info about the server
|
||||
struct ServerInformation {
|
||||
Metadata meta;
|
||||
int networkVersion;
|
||||
char name[PACKET_STRING_SIZE];
|
||||
int playerCount;
|
||||
}serverInfo;
|
||||
|
||||
//info about the client
|
||||
struct ClientInformation {
|
||||
Metadata meta;
|
||||
int clientIndex;
|
||||
int accountIndex;
|
||||
int characterIndex;
|
||||
char username[PACKET_STRING_SIZE];
|
||||
//TODO: password
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
}clientInfo;
|
||||
|
||||
//info about a region
|
||||
struct RegionInformation {
|
||||
Metadata meta;
|
||||
int mapIndex;
|
||||
int x, y;
|
||||
Region* region;
|
||||
}regionInfo;
|
||||
|
||||
//info about a combat scenario
|
||||
struct CombatInformation {
|
||||
Metadata meta;
|
||||
int combatIndex;
|
||||
int difficulty;
|
||||
//TODO: background image, based on terrain type
|
||||
//TODO: array of combatants
|
||||
//TODO: rewards
|
||||
}combatInfo;
|
||||
|
||||
//info about a character
|
||||
struct CharacterInformation {
|
||||
Metadata meta;
|
||||
int clientIndex;
|
||||
int accountIndex;
|
||||
int characterIndex;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
int mapIndex;
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
Statistics stats;
|
||||
}characterInfo;
|
||||
|
||||
//info about an enemy
|
||||
struct EnemyInformation {
|
||||
Metadata meta;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
Statistics stats;
|
||||
}enemyInfo;
|
||||
|
||||
//defaults
|
||||
SerialPacket() {
|
||||
meta.type = Type::NONE;
|
||||
meta.srcAddress = {0,0};
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,224 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//DOCS: memset() is used before sending a packet to remove old data; you don't want to send sensitive data over the network
|
||||
//NOTE: don't confuse SerialPacket with UDPpacket
|
||||
|
||||
void UDPNetworkUtility::Open(int port) {
|
||||
socket = SDLNet_UDP_Open(port);
|
||||
packet = SDLNet_AllocPacket(PACKET_BUFFER_SIZE);
|
||||
if (!socket || !packet) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to open UDPNetworkUtility"));
|
||||
}
|
||||
}
|
||||
|
||||
void UDPNetworkUtility::Close() {
|
||||
SDLNet_UDP_Close(socket);
|
||||
SDLNet_FreePacket(packet);
|
||||
socket = nullptr;
|
||||
packet = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//bind to a channel
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
return Bind(&add, channel);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Bind(IPaddress* add, int channel) {
|
||||
int ret = SDLNet_UDP_Bind(socket, channel, add);
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Failed to bind to a channel"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UDPNetworkUtility::Unbind(int channel) {
|
||||
SDLNet_UDP_Unbind(socket, channel);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//send a buffer
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::SendTo(const char* ip, int port, void* data, int len) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
SendTo(&add, data, len);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(IPaddress* add, void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
packet->address = *add;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(int channel, void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendToAllChannels(void* data, int len) {
|
||||
if (len > packet->maxlen) {
|
||||
throw(std::runtime_error("The buffer is to large for the UDPpacket"));
|
||||
}
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
memcpy(packet->data, data, len);
|
||||
packet->len = len;
|
||||
|
||||
int sent = 0;
|
||||
|
||||
//send to all bound channels
|
||||
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
|
||||
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
|
||||
sent += SDLNet_UDP_Send(socket, i, packet);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
//TODO: put a void* and int* parameter list here
|
||||
int UDPNetworkUtility::Receive() {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packet);
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Unknown network error occured"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//send a SerialPacket
|
||||
//-------------------------
|
||||
|
||||
int UDPNetworkUtility::SendTo(const char* ip, int port, SerialPacket* serialPacket) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
SendTo(&add, serialPacket);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(IPaddress* add, SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
packet->address = *add;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendTo(int channel, SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packet);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendToAllChannels(SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
serialize(serialPacket, packet->data);
|
||||
packet->len = PACKET_BUFFER_SIZE;
|
||||
|
||||
int sent = 0;
|
||||
|
||||
//send to all bound channels
|
||||
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
|
||||
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
|
||||
sent += SDLNet_UDP_Send(socket, i, packet);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Receive(SerialPacket* serialPacket) {
|
||||
memset(packet->data, 0, packet->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packet);
|
||||
deserialize(serialPacket, packet->data);
|
||||
serialPacket->meta.srcAddress = packet->address;
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Unknown network error occured"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef UDPNETWORKUTILITY_HPP_
|
||||
#define UDPNETWORKUTILITY_HPP_
|
||||
|
||||
#include "SDL/SDL_net.h"
|
||||
|
||||
#include "serial_packet.hpp"
|
||||
|
||||
class UDPNetworkUtility {
|
||||
public:
|
||||
UDPNetworkUtility() = default;
|
||||
~UDPNetworkUtility() = default;
|
||||
|
||||
void Open(int port);
|
||||
void Close();
|
||||
|
||||
//bind to a channel
|
||||
int Bind(const char* ip, int port, int channel = -1);
|
||||
int Bind(IPaddress* add, int channel = -1);
|
||||
void Unbind(int channel);
|
||||
|
||||
IPaddress* GetIPAddress(int channel) {
|
||||
return SDLNet_UDP_GetPeerAddress(socket, channel);
|
||||
}
|
||||
|
||||
//send a buffer
|
||||
int SendTo(const char* ip, int port, void* data, int len);
|
||||
int SendTo(IPaddress* add, void* data, int len);
|
||||
int SendTo(int channel, void* data, int len);
|
||||
int SendToAllChannels(void* data, int len);
|
||||
int Receive();
|
||||
|
||||
//send a SerialPacket
|
||||
int SendTo(const char* ip, int port, SerialPacket* serialPacket);
|
||||
int SendTo(IPaddress* add, SerialPacket* serialPacket);
|
||||
int SendTo(int channel, SerialPacket* serialPacket);
|
||||
int SendToAllChannels(SerialPacket* serialPacket);
|
||||
int Receive(SerialPacket* serialPacket);
|
||||
|
||||
//accessors
|
||||
UDPpacket* GetPacket() const {
|
||||
return packet;
|
||||
}
|
||||
UDPsocket GetSocket() const {
|
||||
return socket;
|
||||
}
|
||||
private:
|
||||
UDPsocket socket = nullptr;
|
||||
UDPpacket* packet = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
|
||||
** Initialization of libraries for lua.c and other clients
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
/* Modified for use in Tortuga, renamed to linit.cpp
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** If you embed Lua in your program and need to open the standard
|
||||
** libraries, call luaL_openlibs in your program. If you need a
|
||||
** different set of libraries, copy this file to your project and edit
|
||||
** it to suit your needs.
|
||||
*/
|
||||
|
||||
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include "map_api.hpp"
|
||||
|
||||
|
||||
/*
|
||||
** these libs are loaded by lua.c and are readily available to any Lua
|
||||
** program
|
||||
*/
|
||||
static const luaL_Reg loadedlibs[] = {
|
||||
/* Standard libs */
|
||||
{"_G", luaopen_base},
|
||||
{LUA_LOADLIBNAME, luaopen_package},
|
||||
{LUA_COLIBNAME, luaopen_coroutine},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_IOLIBNAME, luaopen_io},
|
||||
{LUA_OSLIBNAME, luaopen_os},
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_BITLIBNAME, luaopen_bit32},
|
||||
{LUA_MATHLIBNAME, luaopen_math},
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
|
||||
/* custom libs */
|
||||
{LUA_MAPLIBNAME, luaopen_mapapi},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** these libs are preloaded and must be required before used
|
||||
*/
|
||||
static const luaL_Reg preloadedlibs[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||
const luaL_Reg *lib;
|
||||
/* call open functions from 'loadedlibs' and set results to global table */
|
||||
for (lib = loadedlibs; lib->func; lib++) {
|
||||
luaL_requiref(L, lib->name, lib->func, 1);
|
||||
lua_pop(L, 1); /* remove lib */
|
||||
}
|
||||
/* add open functions from 'preloadedlibs' into 'package.preload' table */
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
for (lib = preloadedlibs; lib->func; lib++) {
|
||||
lua_pushcfunction(L, lib->func);
|
||||
lua_setfield(L, -2, lib->name);
|
||||
}
|
||||
lua_pop(L, 1); /* remove _PRELOAD table */
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#config
|
||||
INCLUDES+=. ../map ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
ar -crs $(OUT) $(OBJ)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,126 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "map_api.hpp"
|
||||
|
||||
//map headers
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//NOTE: When operating on a region, setTile() & getTile() *are not* zero indexed, but when operating on the entire map they *are* zero indexed.
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
if (lua_gettop(L) == 5) {
|
||||
//operating on a region
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||
}
|
||||
else {
|
||||
//operating on the whole map
|
||||
lua_pushstring(L, "pager");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//assume the pager is using lua
|
||||
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
|
||||
|
||||
//balance the stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
pager->SetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
if (lua_gettop(L) == 4) {
|
||||
//operating on a region
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
else {
|
||||
//operating on the whole map
|
||||
lua_pushstring(L, "pager");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//assume the pager is using lua
|
||||
RegionPager<LuaAllocator, LuaFormat>* pager = reinterpret_cast<RegionPager<LuaAllocator, LuaFormat>*>(lua_touserdata(L, -1));
|
||||
|
||||
//balance the stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
int ret = pager->GetTile(lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushnumber(L, ret);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getX(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetX());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getY(lua_State* L) {
|
||||
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||
lua_pushinteger(L, ptr->GetY());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionWidth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_WIDTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionHeight(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_HEIGHT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegionDepth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_DEPTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dummy(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionlib[] = {
|
||||
{"create", dummy},
|
||||
{"unload", dummy},
|
||||
{"load", dummy},
|
||||
{"save", dummy},
|
||||
{"settile",setTile},
|
||||
{"gettile",getTile},
|
||||
{"getx",getX},
|
||||
{"gety",getY},
|
||||
{"getregionwidth",getRegionWidth},
|
||||
{"getregionheight",getRegionHeight},
|
||||
{"getregiondepth",getRegionDepth},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int luaopen_mapapi(lua_State* L) {
|
||||
luaL_newlib(L, regionlib);
|
||||
return 1;
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONAPI_HPP_
|
||||
#define REGIONAPI_HPP_
|
||||
#ifndef MAPAPI_HPP_
|
||||
#define MAPAPI_HPP_
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#define TORTUGA_REGION_NAME "Region"
|
||||
LUAMOD_API int openRegionAPI(lua_State* L);
|
||||
#define LUA_MAPLIBNAME "map"
|
||||
LUAMOD_API int luaopen_mapapi(lua_State* L);
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@ OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
@@ -36,7 +36,6 @@
|
||||
* This class needs a rewrite.
|
||||
*/
|
||||
|
||||
//TODO: This thing is fucking terrible, fix it and the button class
|
||||
class MenuBar {
|
||||
public:
|
||||
MenuBar() = default;
|
||||
@@ -19,59 +19,57 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef BOUNDINGBOX_HPP_
|
||||
#define BOUNDINGBOX_HPP_
|
||||
#ifndef BBOX_HPP_
|
||||
#define BBOX_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
class BoundingBox {
|
||||
//TODO: This is supposed to interact with the vector
|
||||
class BBox {
|
||||
public:
|
||||
//This is explicitly a POD
|
||||
int x, y;
|
||||
int w, h;
|
||||
double x, y;
|
||||
double w, h;
|
||||
|
||||
BoundingBox() = default;
|
||||
BoundingBox(int i, int j, int k, int l): x(i), y(j), w(k), h(l) {};
|
||||
~BoundingBox() = default;
|
||||
BoundingBox& operator=(BoundingBox const&) = default;
|
||||
BBox() = default;
|
||||
BBox(double i, double j, double k, double l): x(i), y(j), w(k), h(l) {};
|
||||
~BBox() = default;
|
||||
BBox& operator=(BBox const&) = default;
|
||||
|
||||
int Size() {
|
||||
return std::max(w*h,0);
|
||||
double Size() {
|
||||
return std::max(w*h,0.0);
|
||||
}
|
||||
|
||||
bool CheckOverlap(BoundingBox rhs) {
|
||||
return !(
|
||||
bool IsCollision(BBox rhs) {
|
||||
return not (
|
||||
x >= rhs.x + rhs.w ||
|
||||
y >= rhs.y + rhs.h ||
|
||||
rhs.x >= x + w ||
|
||||
rhs.y >= y + h);
|
||||
rhs.y >= y + h
|
||||
);
|
||||
}
|
||||
|
||||
BoundingBox CalcOverlap(BoundingBox rhs) {
|
||||
if (!CheckOverlap(rhs)) {
|
||||
BBox Intersection(BBox rhs) {
|
||||
if (!IsCollision(rhs)) {
|
||||
return {0, 0, 0, 0};
|
||||
}
|
||||
BoundingBox ret;
|
||||
BBox ret;
|
||||
ret.x = std::max(x, rhs.x);
|
||||
ret.y = std::max(y, rhs.y);
|
||||
ret.w = std::min(x+w, rhs.x+rhs.w) - ret.x;
|
||||
ret.h = std::min(y+h, rhs.y+rhs.h) - ret.y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
double operator[](size_t i) {
|
||||
if (i >= 4)
|
||||
throw(std::domain_error("Out of range"));
|
||||
return *(&x+i);
|
||||
}
|
||||
};
|
||||
|
||||
//This is explicitly a POD
|
||||
static_assert(std::is_pod<Vector2>::value, "BoundingBox is not a POD");
|
||||
static_assert(std::is_pod<BBox>::value, "BBox is not a POD");
|
||||
|
||||
#include "vector2.hpp"
|
||||
|
||||
//operators
|
||||
inline BoundingBox operator+(BoundingBox b, Vector2 v) {
|
||||
return {b.x + (int)v.x, b.y + (int)v.y, b.w, b.h};
|
||||
}
|
||||
inline BoundingBox operator+(Vector2 v, BoundingBox b) {
|
||||
return b + v;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "config_utility.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ConfigUtility::Load(string fname) {
|
||||
ifstream is(fname);
|
||||
|
||||
if (!is.is_open()) {
|
||||
throw(runtime_error("Failed to open config file"));
|
||||
}
|
||||
|
||||
string key, val;
|
||||
|
||||
for (;;) { //forever
|
||||
//eat whitespace
|
||||
while(isspace(is.peek()))
|
||||
is.ignore();
|
||||
|
||||
//end of file
|
||||
if (is.eof())
|
||||
break;
|
||||
|
||||
//skip comment lines
|
||||
if (is.peek() == '#') {
|
||||
while(is.peek() != '\n' && !is.eof()) {
|
||||
is.ignore();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//read in the pair
|
||||
getline(is, key,'=');
|
||||
getline(is, val);
|
||||
|
||||
//trim the strings at the start & end
|
||||
while(key.size() && isspace(*key.begin())) key.erase(0, 1);
|
||||
while(val.size() && isspace(*val.begin())) val.erase(0, 1);
|
||||
|
||||
while(key.size() && isspace(*(key.end()-1))) key.erase(key.end() - 1);
|
||||
while(val.size() && isspace(*(val.end()-1))) val.erase(val.end() - 1);
|
||||
|
||||
//allow empty/wiped values
|
||||
if (key.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//save the pair
|
||||
table[key] = val;
|
||||
}
|
||||
|
||||
is.close();
|
||||
}
|
||||
|
||||
std::string& ConfigUtility::String(std::string s) {
|
||||
return table[s];
|
||||
}
|
||||
|
||||
int ConfigUtility::Integer(std::string s) {
|
||||
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||
if (it == table.end()) {
|
||||
return 0;
|
||||
}
|
||||
return atoi(it->second.c_str());
|
||||
}
|
||||
|
||||
double ConfigUtility::Double(std::string s) {
|
||||
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||
if (it == table.end()) {
|
||||
return 0.0;
|
||||
}
|
||||
return atof(it->second.c_str());
|
||||
}
|
||||
|
||||
bool ConfigUtility::Boolean(std::string s) {
|
||||
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||
if (it == table.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second == "true";
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,36 +19,42 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef TIMER_HPP_
|
||||
#define TIMER_HPP_
|
||||
#ifndef CONFIGUTILITY_HPP_
|
||||
#define CONFIGUTILITY_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
class Timer {
|
||||
class ConfigUtility {
|
||||
public:
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
ConfigUtility() = default;
|
||||
ConfigUtility(std::string s) { Load(s); }
|
||||
|
||||
Timer() = default;
|
||||
Timer(std::string s) : name(s), start(Clock::now()) {};
|
||||
~Timer() = default;
|
||||
void Load(std::string fname);
|
||||
|
||||
inline void Start() { start = Clock::now(); }
|
||||
inline void Stop() { time = Clock::now() - start; }
|
||||
//convert to a type
|
||||
std::string& String(std::string);
|
||||
int Integer(std::string);
|
||||
double Double(std::string);
|
||||
bool Boolean(std::string);
|
||||
|
||||
//accessors and mutators
|
||||
Clock::duration GetTime() { return time; }
|
||||
|
||||
std::string SetName(std::string s) { return name = s; }
|
||||
std::string GetName() { return name; }
|
||||
//shorthand
|
||||
std::string& operator[](std::string s) {
|
||||
return String(s);
|
||||
}
|
||||
int Int(std::string s) {
|
||||
return Integer(s);
|
||||
}
|
||||
bool Bool(std::string s) {
|
||||
return Boolean(s);
|
||||
}
|
||||
|
||||
//OO breaker
|
||||
std::map<std::string, std::string>* GetMap() {
|
||||
return &table;
|
||||
}
|
||||
private:
|
||||
std::string name;
|
||||
Clock::time_point start;
|
||||
Clock::duration time;
|
||||
std::map<std::string, std::string> table;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Timer& t);
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@ OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUTDIR=../..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
|
||||
#targets
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "sql_utility.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
|
||||
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**), void* argPtr) {
|
||||
//load the file into a string
|
||||
std::ifstream is(fname);
|
||||
if (!is.is_open()) {
|
||||
return -1;
|
||||
}
|
||||
std::string script;
|
||||
getline(is, script, '\0');
|
||||
is.close();
|
||||
|
||||
//run the SQL loaded from the file
|
||||
char* errmsg = nullptr;
|
||||
int ret = sqlite3_exec(db, script.c_str(), callback, argPtr, &errmsg);
|
||||
if (ret != SQLITE_OK) {
|
||||
//handle any errors received from the SQL
|
||||
std::runtime_error e(std::string() + "SQL Script Error " + to_string_custom(ret) + ": " + errmsg);
|
||||
free(errmsg);
|
||||
throw(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -19,13 +19,13 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONPAGERAPI_HPP_
|
||||
#define REGIONPAGERAPI_HPP_
|
||||
#ifndef SERVERUTILITY_HPP_
|
||||
#define SERVERUTILITY_HPP_
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include "sqlite3/sqlite3.h"
|
||||
|
||||
#define TORTUGA_REGION_PAGER_PSEUDO_INDEX "RegionPagerPseudoIndex"
|
||||
#define TORTUGA_REGION_PAGER_NAME "RegionPager"
|
||||
LUAMOD_API int openRegionPagerAPI(lua_State* L);
|
||||
#include <string>
|
||||
|
||||
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**) = nullptr, void* argPtr = nullptr);
|
||||
|
||||
#endif
|
||||
@@ -26,16 +26,12 @@
|
||||
int snapToBase(int base, int x) {
|
||||
//snap to a grid
|
||||
if (x < 0) {
|
||||
++x;
|
||||
x++;
|
||||
return x / base * base - base;
|
||||
}
|
||||
return x / base * base;
|
||||
}
|
||||
|
||||
double snapToBase(double base, double x) {
|
||||
return floor(x / base) * base;
|
||||
}
|
||||
|
||||
std::string truncatePath(std::string pathname) {
|
||||
return std::string(
|
||||
std::find_if(
|
||||
@@ -25,8 +25,6 @@
|
||||
#include <string>
|
||||
|
||||
int snapToBase(int base, int x);
|
||||
double snapToBase(double base, double x);
|
||||
|
||||
std::string truncatePath(std::string pathname);
|
||||
|
||||
//fixing known bugs in g++
|
||||
@@ -34,4 +32,17 @@ std::string to_string_custom(int i);
|
||||
|
||||
int to_integer_custom(std::string);
|
||||
|
||||
//wow
|
||||
template<typename ContainerT, typename PredicateT>
|
||||
void erase_if(ContainerT& items, const PredicateT& predicate) {
|
||||
for(auto it = items.begin(); it != items.end(); /* empty */) {
|
||||
if(predicate(*it)) {
|
||||
it = items.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -41,12 +41,11 @@ public:
|
||||
double SquaredLength() const {
|
||||
return x*x+y*y;
|
||||
}
|
||||
void Normalize() {
|
||||
double l = Length();
|
||||
if (l == 0)
|
||||
throw(std::domain_error("Divide by zero"));
|
||||
x /= l;
|
||||
y /= l;
|
||||
|
||||
double operator[](size_t i) {
|
||||
if (i >= 2)
|
||||
throw(std::domain_error("Out of range"));
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
//Arithmetic operators
|
||||
@@ -104,6 +103,15 @@ public:
|
||||
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
|
||||
};
|
||||
|
||||
//non-member templates (flip the order)
|
||||
template<typename T> Vector2 operator+(T t, Vector2 v) { return v + t; }
|
||||
template<typename T> Vector2 operator-(T t, Vector2 v) { return v - t; }
|
||||
template<typename T> Vector2 operator*(T t, Vector2 v) { return v * t; }
|
||||
template<typename T> Vector2 operator/(T t, Vector2 v) { return v / t; }
|
||||
|
||||
template<typename T> bool operator==(T t, Vector2 v) { return v == t; }
|
||||
template<typename T> bool operator!=(T t, Vector2 v) { return v != t; }
|
||||
|
||||
//This is explicitly a POD
|
||||
static_assert(std::is_pod<Vector2>::value, "Vector2 is not a POD");
|
||||
|
||||
@@ -3,15 +3,17 @@
|
||||
#MKDIR=mkdir
|
||||
#RM=del /y
|
||||
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++ -g -fno-inline-functions -Wall
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||
CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||
CFLAGS+=-static-libgcc
|
||||
|
||||
#export
|
||||
export
|
||||
|
||||
OUTDIR=out
|
||||
|
||||
all: $(OUTDIR)
|
||||
$(MAKE) -C src
|
||||
$(MAKE) -C common
|
||||
$(MAKE) -C server
|
||||
$(MAKE) -C client
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
@@ -0,0 +1,30 @@
|
||||
#configuration of the programs
|
||||
server.host = 255.255.255.255
|
||||
server.port = 21795
|
||||
server.name = local
|
||||
|
||||
server.dbname = database.db
|
||||
|
||||
screen.w = 800
|
||||
screen.h = 600
|
||||
screen.f = false
|
||||
|
||||
#directories
|
||||
dir.fonts = rsc/graphics/fonts/
|
||||
dir.logos = rsc/graphics/logos/
|
||||
dir.sprites = rsc/graphics/sprites/
|
||||
dir.tilesets = rsc/graphics/tilesets/
|
||||
dir.interface = rsc/graphics/interface/
|
||||
dir.scripts = rsc/scripts/
|
||||
|
||||
#map system
|
||||
map.pager.width = 20
|
||||
map.pager.height = 20
|
||||
map.pager.depth = 3
|
||||
|
||||
#player options
|
||||
client.username = Kayne Ruse
|
||||
client.handle = Ratstail91
|
||||
client.avatar = elliot2.bmp
|
||||
|
||||
#debugging
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 768 KiB |
@@ -1,9 +0,0 @@
|
||||
--overwriting the existing hard coded methods
|
||||
function Region.Load(region)
|
||||
--the return value signals if this succeeded or failed
|
||||
return false
|
||||
end
|
||||
|
||||
function Region.Save(region)
|
||||
--
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
--uber lazy declarations
|
||||
function math.sqr(x) return x*x end
|
||||
function math.dist(x, y, i, j) return math.sqrt(math.sqr(x-i) + math.sqr(y-j)) end
|
||||
|
||||
--define these
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
Region.SetTile(region, i, j, 1, 1) --to show the basics are working
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Region.Unload(region)
|
||||
--
|
||||
end
|
||||
@@ -1,33 +0,0 @@
|
||||
local sheet = TileSheet.GetTileSheet()
|
||||
local pager = RegionPager.GetRegionPager()
|
||||
|
||||
--the selected tilesheet
|
||||
TileSheet.Load(sheet, config.dir.tilesets .. "terrain.bmp", 32, 32)
|
||||
|
||||
--tile macros, mapped to this tilesheet
|
||||
local base = 14
|
||||
local shift = 36
|
||||
tiles = {
|
||||
plains = base + shift * 0,
|
||||
grass = base + shift * 1,
|
||||
dirt = base + shift * 2,
|
||||
sand = base + shift * 3,
|
||||
water = base + shift * 4
|
||||
}
|
||||
|
||||
--could set custom generation systems here, that differ from the global generators, etc.
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1)
|
||||
if dist < 10 then
|
||||
Region.SetTile(region, i, j, 1, tiles.plains)
|
||||
elseif dist < 12 then
|
||||
Region.SetTile(region, i, j, 1, tiles.sand)
|
||||
else
|
||||
Region.SetTile(region, i, j, 1, tiles.water)
|
||||
Region.SetSolid(region, i, j, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
print("Lua script check (./rsc)")
|
||||
|
||||
-------------------------
|
||||
--Map API overrides
|
||||
-------------------------
|
||||
|
||||
function map.create(region)
|
||||
for i = 1, map.getregionwidth() do
|
||||
for j = 1, map.getregionheight() do
|
||||
if math.abs(map.getx(region) + i -1) == math.abs(map.gety(region) + j -1) then
|
||||
map.settile(region, i, j, 1, 50)
|
||||
else
|
||||
map.settile(region, i, j, 1, 14)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function map.unload(region)
|
||||
--
|
||||
end
|
||||
|
||||
function map.load(region, dir)
|
||||
--return true if file loaded, otherwise return false
|
||||
return false
|
||||
end
|
||||
|
||||
function map.save(region, dir)
|
||||
--
|
||||
end
|
||||
|
||||
-------------------------
|
||||
--Enemy API
|
||||
-------------------------
|
||||
|
||||
--TODO
|
||||
@@ -0,0 +1,63 @@
|
||||
CREATE TABLE IF NOT EXISTS Accounts (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username varchar(100) UNIQUE,
|
||||
--TODO: server-client security
|
||||
-- password varchar(100),
|
||||
blacklisted BIT DEFAULT 0,
|
||||
whitelisted BIT DEFAULT 1,
|
||||
administrator BIT DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS Characters (
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
--metadata
|
||||
owner INTEGER REFERENCES Accounts(uid),
|
||||
handle varchar(100) UNIQUE,
|
||||
avatar varchar(100),
|
||||
birth timestamp NOT NULL DEFAULT (datetime()),
|
||||
|
||||
--position
|
||||
mapIndex INTEGER DEFAULT 0,
|
||||
positionX INTEGER DEFAULT 0,
|
||||
positionY INTEGER DEFAULT 0,
|
||||
|
||||
--statistics
|
||||
level INTEGER DEFAULT 0,
|
||||
exp INTEGER DEFAULT 0,
|
||||
maxHP INTEGER DEFAULT 0,
|
||||
health INTEGER DEFAULT 0,
|
||||
maxMP INTEGER DEFAULT 0,
|
||||
mana INTEGER DEFAULT 0,
|
||||
attack INTEGER DEFAULT 0,
|
||||
defence INTEGER DEFAULT 0,
|
||||
intelligence INTEGER DEFAULT 0,
|
||||
resistance INTEGER DEFAULT 0,
|
||||
speed INTEGER DEFAULT 0,
|
||||
accuracy REAL DEFAULT 0.0,
|
||||
evasion REAL DEFAULT 0.0,
|
||||
luck REAL DEFAULT 0.0,
|
||||
|
||||
--equipment
|
||||
weapon INTEGER REFERENCES WornEquipment(uid),
|
||||
helmet INTEGER REFERENCES WornEquipment(uid),
|
||||
armour INTEGER REFERENCES WornEquipment(uid)
|
||||
--etc.
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS InventoryItems (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemID INTEGER, --type
|
||||
stackSize INTEGER DEFAULT 0,
|
||||
owner INTEGER REFERENCES Characters(uid)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS WornEquipment (
|
||||
--metadata
|
||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
itemID INTEGER, --type
|
||||
owner INTEGER REFERENCES Characters(uid)
|
||||
--hold all equipment info
|
||||
--stat mods, special effects, etc.
|
||||
);
|
||||
@@ -1,42 +0,0 @@
|
||||
--[[
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
--]]
|
||||
|
||||
--catch the debug signal if the program was rerouted
|
||||
local debug = false
|
||||
if config ~= nil then
|
||||
debug = config.debug
|
||||
end
|
||||
|
||||
--the program's configuration
|
||||
config = {
|
||||
debug = debug,
|
||||
screen = {
|
||||
width = 800,
|
||||
height = 600,
|
||||
fullscreen = false
|
||||
},
|
||||
dir = {
|
||||
fonts = "rsc/graphics/fonts/",
|
||||
logos = "rsc/graphics/logos/",
|
||||
sprites = "rsc/graphics/sprites/",
|
||||
tilesets = "rsc/graphics/tilesets/",
|
||||
interface = "rsc/graphics/interface/",
|
||||
scripts = "rsc/scripts/",
|
||||
maps = "rsc/maps/"
|
||||
},
|
||||
mapname = "mapname"
|
||||
}
|
||||
|
||||
--development environment
|
||||
if config.debug then
|
||||
for k, v in pairs(config.dir) do
|
||||
config.dir[k] = string.format("../%s", v)
|
||||
end
|
||||
end
|
||||
|
||||
--"load" the scripted systems
|
||||
dofile(config.dir.scripts .. "file_format.lua")
|
||||
dofile(config.dir.scripts .. "generator.lua")
|
||||
@@ -0,0 +1,191 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include "sqlite3/sqlite3.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES (?);";
|
||||
static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;";
|
||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3 WHERE uid = ?1;";
|
||||
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
|
||||
|
||||
//-------------------------
|
||||
//Define the methods
|
||||
//-------------------------
|
||||
|
||||
int ServerApplication::CreateUserAccount(std::string username, int clientIndex) {
|
||||
//create this user account, failing if it exists, leave this account in memory
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, CREATE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than this account exists
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//load this account into memory
|
||||
return LoadUserAccount(username, clientIndex);
|
||||
}
|
||||
|
||||
int ServerApplication::LoadUserAccount(std::string username, int clientIndex) {
|
||||
//load this user account, failing if it is in memory, creating it if it doesn't exist
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, LOAD_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, username.c_str(), username.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
int ret = sqlite3_step(statement);
|
||||
|
||||
//process the result
|
||||
if (ret == SQLITE_ROW) {
|
||||
//get the index
|
||||
int uid = sqlite3_column_int(statement, 0);
|
||||
|
||||
//check to see if this account is already loaded
|
||||
if (accountMap.find(uid) != accountMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
AccountData& newAccount = accountMap[uid];
|
||||
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
|
||||
newAccount.blackListed = sqlite3_column_int(statement, 2);
|
||||
newAccount.whiteListed = sqlite3_column_int(statement, 3);
|
||||
newAccount.clientIndex = clientIndex;
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return uid;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
if (ret == SQLITE_DONE) {
|
||||
//create the non-existant account instead
|
||||
return CreateUserAccount(username, clientIndex);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadUserAccount: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int ServerApplication::SaveUserAccount(int uid) {
|
||||
//save this user account from memory, replacing it if it exists in the database
|
||||
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
|
||||
|
||||
//this method fails if this account is not loaded
|
||||
if (accountMap.find(uid) == accountMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AccountData& account = accountMap[uid];
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, SAVE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 2, account.blackListed) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, account.whiteListed) != SQLITE_OK;
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//successful execution
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerApplication::UnloadUserAccount(int uid) {
|
||||
//save this user account, and then unload it
|
||||
//NOTE: the associated characters are unloaded externally
|
||||
SaveUserAccount(uid);
|
||||
accountMap.erase(uid);
|
||||
}
|
||||
|
||||
void ServerApplication::DeleteUserAccount(int uid) {
|
||||
//delete a user account from the database, and remove it from memory
|
||||
//NOTE: the associated characters are unloaded externally
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, DELETE_USER_ACCOUNT, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
accountMap.erase(uid);
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include "sqlite3/sqlite3.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
//-------------------------
|
||||
//Define the queries
|
||||
//-------------------------
|
||||
|
||||
//TODO: save and load the statistics
|
||||
static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, avatar) VALUES (?, ?, ?);";
|
||||
static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;";
|
||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET mapIndex = ?2, positionX = ?3, positionY = ?4 WHERE uid = ?1;";
|
||||
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
|
||||
|
||||
//-------------------------
|
||||
//Define the methods
|
||||
//-------------------------
|
||||
|
||||
//TODO: default stats as a parameter
|
||||
int ServerApplication::CreateCharacter(int owner, std::string handle, std::string avatar) {
|
||||
//Create the character, failing if it exists
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, CREATE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, owner);
|
||||
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
|
||||
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than this character exists
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//load this character into memory
|
||||
return LoadCharacter(owner, handle, avatar);
|
||||
}
|
||||
|
||||
int ServerApplication::LoadCharacter(int owner, std::string handle, std::string avatar) {
|
||||
//load the specified character, creating it if it doesn't exist
|
||||
//fail if it is already loaded, or does not belong to this account
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, LOAD_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_text(statement, 1, handle.c_str(), handle.size() + 1, SQLITE_STATIC) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
int ret = sqlite3_step(statement);
|
||||
|
||||
//process the result
|
||||
if (ret == SQLITE_ROW) {
|
||||
//get the index
|
||||
int uid = sqlite3_column_int(statement, 0);
|
||||
|
||||
//check to see if this character is already loaded
|
||||
if (characterMap.find(uid) != characterMap.end()) {
|
||||
sqlite3_finalize(statement);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//check the owner
|
||||
if (owner != sqlite3_column_int(statement, 1)) {
|
||||
sqlite3_finalize(statement);
|
||||
return -2;
|
||||
}
|
||||
|
||||
//extract the data into memory
|
||||
CharacterData& newChar = characterMap[uid];
|
||||
|
||||
//metadata
|
||||
newChar.owner = owner;
|
||||
newChar.handle = reinterpret_cast<const char*>(sqlite3_column_text(statement, 2));
|
||||
newChar.avatar = reinterpret_cast<const char*>(sqlite3_column_text(statement, 3));
|
||||
//Don't cache the birth
|
||||
|
||||
//world position
|
||||
newChar.mapIndex = sqlite3_column_int(statement, 5);
|
||||
newChar.position.x = (double)sqlite3_column_int(statement, 6);
|
||||
newChar.position.y = (double)sqlite3_column_int(statement, 7);
|
||||
|
||||
//statistics
|
||||
newChar.stats.level = sqlite3_column_int(statement, 8);
|
||||
newChar.stats.exp = sqlite3_column_int(statement, 9);
|
||||
newChar.stats.maxHP = sqlite3_column_int(statement, 10);
|
||||
newChar.stats.health = sqlite3_column_int(statement, 11);
|
||||
newChar.stats.maxMP = sqlite3_column_int(statement, 12);
|
||||
newChar.stats.mana = sqlite3_column_int(statement, 13);
|
||||
newChar.stats.attack = sqlite3_column_int(statement, 14);
|
||||
newChar.stats.defence = sqlite3_column_int(statement, 15);
|
||||
newChar.stats.intelligence = sqlite3_column_int(statement, 16);
|
||||
newChar.stats.resistance = sqlite3_column_int(statement, 17);
|
||||
newChar.stats.speed = sqlite3_column_int(statement, 18);
|
||||
newChar.stats.accuracy = sqlite3_column_double(statement, 19);
|
||||
newChar.stats.evasion = sqlite3_column_double(statement, 20);
|
||||
newChar.stats.luck = sqlite3_column_double(statement, 21);
|
||||
|
||||
//TODO: equipment
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
return uid;
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
if (ret == SQLITE_DONE) {
|
||||
//create the non-existant character instead
|
||||
return CreateCharacter(owner, handle, avatar);
|
||||
}
|
||||
|
||||
throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
|
||||
int ServerApplication::SaveCharacter(int uid) {
|
||||
//save this character from memory, replacing it if it exists in the database
|
||||
//DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID.
|
||||
|
||||
//this method fails if this character is not loaded
|
||||
if (characterMap.find(uid) == characterMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
CharacterData& character = characterMap[uid];
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, SAVE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameters
|
||||
bool ret = false;
|
||||
ret |= sqlite3_bind_int(statement, 1, uid) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 2, character.mapIndex) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 3, (int)character.position.x) != SQLITE_OK;
|
||||
ret |= sqlite3_bind_int(statement, 4, (int)character.position.y) != SQLITE_OK;
|
||||
//TODO: stats, etc.
|
||||
|
||||
//check for binding errors
|
||||
if (ret) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
sqlite3_finalize(statement);
|
||||
|
||||
//successful execution
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerApplication::UnloadCharacter(int uid) {
|
||||
//save this character, then unload it
|
||||
SaveCharacter(uid);
|
||||
characterMap.erase(uid);
|
||||
}
|
||||
|
||||
void ServerApplication::DeleteCharacter(int uid) {
|
||||
//delete this character from the database, then remove it from memory
|
||||
sqlite3_stmt* statement = nullptr;
|
||||
|
||||
//prep
|
||||
if (sqlite3_prepare_v2(database, DELETE_CHARACTER, -1, &statement, nullptr) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//parameter
|
||||
if (sqlite3_bind_int(statement, 1, uid) != SQLITE_OK) {
|
||||
throw( std::runtime_error(std::string() + "Failed to replace a prepared statement's parameter: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//execute
|
||||
if (sqlite3_step(statement) != SQLITE_DONE) {
|
||||
//if this fails, than something went horribly wrong
|
||||
sqlite3_finalize(statement);
|
||||
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
|
||||
}
|
||||
|
||||
//finish the routine
|
||||
sqlite3_finalize(statement);
|
||||
characterMap.erase(uid);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "enemy_factory_generic.hpp"
|
||||
|
||||
EnemyFactoryGeneric::EnemyFactoryGeneric() : EnemyFactoryInterface() {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
EnemyFactoryGeneric::~EnemyFactoryGeneric() noexcept {
|
||||
//EMPTY
|
||||
}
|
||||
|
||||
void EnemyFactoryGeneric::Generate(std::list<EnemyData>* container) {
|
||||
//TODO: fill this out
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef ENEMYFACTORYGENERIC_HPP_
|
||||
#define ENEMYFACTORYGENERIC_HPP_
|
||||
|
||||
#include "enemy_factory_interface.hpp"
|
||||
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include <list>
|
||||
|
||||
//DOCS: Not really intended for use, but rather for copying and tweaking
|
||||
class EnemyFactoryGeneric : public EnemyFactoryInterface {
|
||||
public:
|
||||
EnemyFactoryGeneric();
|
||||
~EnemyFactoryGeneric() noexcept override;
|
||||
|
||||
void Generate(std::list<EnemyData>* container) override;
|
||||
private:
|
||||
//TODO: hold the parameters specified by the room
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,33 +19,38 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONPAGERLUA_HPP_
|
||||
#define REGIONPAGERLUA_HPP_
|
||||
#ifndef ENEMYFACTORYINTERFACE_HPP_
|
||||
#define ENEMYFACTORYINTERFACE_HPP_
|
||||
|
||||
#include "region_pager_base.hpp"
|
||||
#include "enemy_data.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include <list>
|
||||
|
||||
#include <string>
|
||||
//TODO: move this elsewhere
|
||||
enum RoomType {
|
||||
OVERWORLD,
|
||||
RUINS,
|
||||
TOWERS,
|
||||
FORESTS,
|
||||
CAVES,
|
||||
};
|
||||
|
||||
class RegionPagerLua : public RegionPagerBase {
|
||||
//NOTE: Based on biome, world difficulty, etc.
|
||||
class EnemyFactoryInterface {
|
||||
public:
|
||||
RegionPagerLua() = default;
|
||||
~RegionPagerLua() = default;
|
||||
EnemyFactoryInterface() = default;
|
||||
virtual ~EnemyFactoryInterface() = default;
|
||||
|
||||
//region manipulation
|
||||
Region* LoadRegion(int x, int y) override;
|
||||
Region* SaveRegion(int x, int y) override;
|
||||
Region* CreateRegion(int x, int y) override;
|
||||
void UnloadRegion(int x, int y) override;
|
||||
virtual void Generate(std::list<EnemyData>* container) = 0;
|
||||
|
||||
void UnloadAll() override;
|
||||
|
||||
//accessors & mutators
|
||||
lua_State* SetLuaState(lua_State* L) { return lua = L; }
|
||||
lua_State* GetLuaState() { return lua; }
|
||||
//control the difficulty of the room
|
||||
RoomType SetType(RoomType t) { return type = t; }
|
||||
int SetDifficulty(int d) { return difficulty = d; }
|
||||
RoomType GetType() { return type; }
|
||||
int GetDifficulty() { return difficulty; }
|
||||
protected:
|
||||
lua_State* lua = nullptr;
|
||||
RoomType type;
|
||||
int difficulty;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,31 +19,27 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef APPLICATION_HPP_
|
||||
#define APPLICATION_HPP_
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application() = default;
|
||||
~Application() = default;
|
||||
using namespace std;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
lua_State* lua = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
int main(int argc, char** argv) {
|
||||
cout << "Beginning server" << endl;
|
||||
try {
|
||||
ServerApplication app;
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal error: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
cout << "Clean exit" << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#config
|
||||
INCLUDES+=. debugging graphics map ui utilities
|
||||
LIBS+=libcommon.a -lmingw32 -lSDLmain -lSDL -llua
|
||||
INCLUDES+=. ../common/gameplay ../common/map ../common/network ../common/script ../common/utilities
|
||||
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
@@ -12,15 +12,10 @@ OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
OUT=$(addprefix $(OUTDIR)/,jam)
|
||||
OUT=$(addprefix $(OUTDIR)/,server)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(MAKE) -C debugging
|
||||
$(MAKE) -C graphics
|
||||
$(MAKE) -C map
|
||||
$(MAKE) -C ui
|
||||
$(MAKE) -C utilities
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
@@ -0,0 +1,123 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SERVERAPPLICATION_HPP_
|
||||
#define SERVERAPPLICATION_HPP_
|
||||
|
||||
//server specific stuff
|
||||
#include "client_data.hpp"
|
||||
#include "account_data.hpp"
|
||||
#include "character_data.hpp"
|
||||
#include "combat_data.hpp"
|
||||
#include "enemy_factory_generic.hpp"
|
||||
|
||||
//maps
|
||||
#include "map_allocator.hpp"
|
||||
#include "map_file_format.hpp"
|
||||
#include "region_pager.hpp"
|
||||
|
||||
//networking
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
//common
|
||||
#include "config_utility.hpp"
|
||||
#include "vector2.hpp"
|
||||
|
||||
//APIs
|
||||
#include "lua/lua.hpp"
|
||||
#include "sqlite3/sqlite3.h"
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
//STL
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
//The main application class
|
||||
//TODO: modulate this god class
|
||||
class ServerApplication {
|
||||
public:
|
||||
//standard functions
|
||||
ServerApplication() = default;
|
||||
~ServerApplication() = default;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
void HandlePacket(SerialPacket);
|
||||
|
||||
//handle incoming traffic
|
||||
void HandleBroadcastRequest(SerialPacket);
|
||||
void HandleJoinRequest(SerialPacket);
|
||||
void HandleSynchronize(SerialPacket);
|
||||
void HandleDisconnect(SerialPacket);
|
||||
void HandleShutdown(SerialPacket);
|
||||
void HandleCharacterUpdate(SerialPacket);
|
||||
void HandleRegionRequest(SerialPacket);
|
||||
|
||||
//TODO: a function that only sends to characters in a certain proximity
|
||||
void PumpPacket(SerialPacket);
|
||||
void PumpCharacterUnload(int uid);
|
||||
|
||||
//Account management
|
||||
int CreateUserAccount(std::string username, int clientIndex);
|
||||
int LoadUserAccount(std::string username, int clientIndex);
|
||||
int SaveUserAccount(int uid);
|
||||
void UnloadUserAccount(int uid);
|
||||
void DeleteUserAccount(int uid);
|
||||
|
||||
//character management
|
||||
int CreateCharacter(int owner, std::string handle, std::string avatar);
|
||||
int LoadCharacter(int owner, std::string handle, std::string avatar);
|
||||
int SaveCharacter(int uid);
|
||||
void UnloadCharacter(int uid);
|
||||
void DeleteCharacter(int uid);
|
||||
|
||||
//TODO: combat management
|
||||
|
||||
//APIs
|
||||
UDPNetworkUtility network;
|
||||
sqlite3* database = nullptr;
|
||||
lua_State* luaState = nullptr;
|
||||
|
||||
//server tables
|
||||
std::map<int, ClientData> clientMap;
|
||||
std::map<int, AccountData> accountMap;
|
||||
std::map<int, CharacterData> characterMap;
|
||||
std::map<int, CombatData> combatMap;
|
||||
std::map<int, EnemyData> enemyMap;
|
||||
|
||||
//maps
|
||||
//TODO: I need to handle multiple map objects
|
||||
//TODO: Unload regions that are distant from any characters
|
||||
RegionPager<LuaAllocator, LuaFormat> regionPager;
|
||||
EnemyFactoryGeneric enemyFactory;
|
||||
|
||||
//misc
|
||||
bool running = true;
|
||||
ConfigUtility config;
|
||||
int clientUID = 0;
|
||||
int combatUID = 0;
|
||||
int enemyUID = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Handle various network input
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandleBroadcastRequest(SerialPacket packet) {
|
||||
//pack the server's data
|
||||
packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
|
||||
packet.serverInfo.networkVersion = NETWORK_VERSION;
|
||||
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
||||
packet.serverInfo.playerCount = characterMap.size();
|
||||
|
||||
//bounce this packet
|
||||
network.SendTo(&packet.meta.srcAddress, &packet);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleJoinRequest(SerialPacket packet) {
|
||||
//create the new client
|
||||
ClientData newClient;
|
||||
newClient.address = packet.meta.srcAddress;
|
||||
|
||||
//load the user account
|
||||
int accountIndex = LoadUserAccount(packet.clientInfo.username, clientUID);
|
||||
if (accountIndex < 0) {
|
||||
//TODO: send rejection packet
|
||||
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//load the new character
|
||||
int characterIndex = LoadCharacter(accountIndex, packet.clientInfo.handle, packet.clientInfo.avatar);
|
||||
if (characterIndex < 0) {
|
||||
//TODO: send rejection packet
|
||||
std::cerr << "Error: Character already loaded: " << characterIndex << std::endl;
|
||||
UnloadUserAccount(accountIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
//send the client their info
|
||||
packet.meta.type = SerialPacket::Type::JOIN_RESPONSE;
|
||||
packet.clientInfo.clientIndex = clientUID;
|
||||
packet.clientInfo.accountIndex = accountIndex;
|
||||
packet.clientInfo.characterIndex = characterIndex;
|
||||
|
||||
//bounce this packet
|
||||
network.SendTo(&newClient.address, &packet);
|
||||
|
||||
//send the new character to all clients
|
||||
packet.meta.type = SerialPacket::Type::CHARACTER_NEW;
|
||||
packet.characterInfo.characterIndex = characterIndex;
|
||||
strncpy(packet.characterInfo.handle, characterMap[characterIndex].handle.c_str(), PACKET_STRING_SIZE);
|
||||
strncpy(packet.characterInfo.avatar, characterMap[characterIndex].avatar.c_str(), PACKET_STRING_SIZE);
|
||||
packet.characterInfo.position = characterMap[characterIndex].position;
|
||||
packet.characterInfo.motion = characterMap[characterIndex].motion;
|
||||
PumpPacket(packet);
|
||||
|
||||
//TODO: don't send anything to a certain client until they send the OK (the sync packet? or ignore client side?)
|
||||
//finished this routine
|
||||
clientMap[clientUID++] = newClient;
|
||||
std::cout << "Connect, total: " << clientMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleSynchronize(SerialPacket packet) {
|
||||
//TODO: compensate for large distances
|
||||
|
||||
//send all the server's data to this client
|
||||
SerialPacket newPacket;
|
||||
|
||||
//characters
|
||||
newPacket.meta.type = SerialPacket::Type::CHARACTER_UPDATE;
|
||||
for (auto& it : characterMap) {
|
||||
//TODO: update this for the expanded CharacterData structure
|
||||
newPacket.characterInfo.characterIndex = it.first;
|
||||
snprintf(newPacket.characterInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
||||
snprintf(newPacket.characterInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
||||
newPacket.characterInfo.mapIndex = it.second.mapIndex;
|
||||
newPacket.characterInfo.position = it.second.position;
|
||||
newPacket.characterInfo.motion = it.second.motion;
|
||||
newPacket.characterInfo.stats = it.second.stats;
|
||||
|
||||
network.SendTo(&clientMap[packet.clientInfo.clientIndex].address, &newPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::HandleDisconnect(SerialPacket packet) {
|
||||
//TODO: authenticate who is disconnecting/kicking
|
||||
|
||||
//forward to the specified client
|
||||
network.SendTo(&clientMap[accountMap[packet.clientInfo.accountIndex].clientIndex].address, &packet);
|
||||
|
||||
//unload client and server-side characters
|
||||
for (std::map<int, CharacterData>::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) {
|
||||
if (it->second.owner == packet.clientInfo.accountIndex) {
|
||||
PumpCharacterUnload(it->first);
|
||||
SaveCharacter(it->first);
|
||||
it = characterMap.erase(it); //efficient
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//erase the in-memory stuff
|
||||
clientMap.erase(accountMap[packet.clientInfo.accountIndex].clientIndex);
|
||||
UnloadUserAccount(packet.clientInfo.accountIndex);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "Disconnect, total: " << clientMap.size() << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleShutdown(SerialPacket packet) {
|
||||
//TODO: authenticate who is shutting the server down
|
||||
|
||||
//end the server
|
||||
running = false;
|
||||
|
||||
//disconnect all clients
|
||||
packet.meta.type = SerialPacket::Type::DISCONNECT;
|
||||
PumpPacket(packet);
|
||||
|
||||
//finished this routine
|
||||
std::cout << "Shutdown signal accepted" << std::endl;
|
||||
}
|
||||
|
||||
void ServerApplication::HandleCharacterUpdate(SerialPacket packet) {
|
||||
//TODO: this should be moved elsewhere
|
||||
if (characterMap.find(packet.characterInfo.characterIndex) == characterMap.end()) {
|
||||
throw(std::runtime_error("Cannot update a non-existant character"));
|
||||
}
|
||||
|
||||
//TODO: the server needs it's own movement system too
|
||||
characterMap[packet.characterInfo.characterIndex].position = packet.characterInfo.position;
|
||||
characterMap[packet.characterInfo.characterIndex].motion = packet.characterInfo.motion;
|
||||
|
||||
PumpPacket(packet);
|
||||
}
|
||||
|
||||
void ServerApplication::HandleRegionRequest(SerialPacket packet) {
|
||||
//TODO: this should be moved elsewhere
|
||||
packet.meta.type = SerialPacket::Type::REGION_CONTENT;
|
||||
packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||
|
||||
//send the content
|
||||
network.SendTo(&packet.meta.srcAddress, &packet);
|
||||
}
|
||||
|
||||
void ServerApplication::PumpPacket(SerialPacket packet) {
|
||||
//NOTE: I don't really like this, but it'll do for now
|
||||
for (auto& it : clientMap) {
|
||||
network.SendTo(&it.second.address, &packet);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::PumpCharacterUnload(int uid) {
|
||||
//delete the client-side character(s)
|
||||
SerialPacket delPacket;
|
||||
delPacket.meta.type = SerialPacket::Type::CHARACTER_DELETE;
|
||||
delPacket.characterInfo.characterIndex = uid;
|
||||
PumpPacket(delPacket);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include "sql_utility.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//-------------------------
|
||||
//Define the public members
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::Init(int argc, char** argv) {
|
||||
//NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed.
|
||||
std::cout << "Beginning startup" << std::endl;
|
||||
|
||||
//initial setup
|
||||
config.Load("rsc\\config.cfg");
|
||||
|
||||
//-------------------------
|
||||
//Initialize the APIs
|
||||
//-------------------------
|
||||
|
||||
//Init SDL
|
||||
if (SDL_Init(0)) {
|
||||
throw(std::runtime_error("Failed to initialize SDL"));
|
||||
}
|
||||
std::cout << "Initialized SDL" << std::endl;
|
||||
|
||||
//Init SDL_net
|
||||
if (SDLNet_Init()) {
|
||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
network.Open(config.Int("server.port"));
|
||||
std::cout << "Initialized SDL_net" << std::endl;
|
||||
|
||||
//Init SQL
|
||||
int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
|
||||
if (ret != SQLITE_OK || !database) {
|
||||
throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
|
||||
}
|
||||
std::cout << "Initialized SQL" << std::endl;
|
||||
|
||||
//Init lua
|
||||
luaState = luaL_newstate();
|
||||
if (!luaState) {
|
||||
throw(std::runtime_error("Failed to initialize lua"));
|
||||
}
|
||||
luaL_openlibs(luaState);
|
||||
std::cout << "Initialized lua" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Setup the objects
|
||||
//-------------------------
|
||||
|
||||
//setup the map object
|
||||
regionPager.GetAllocator()->SetLuaState(luaState);
|
||||
regionPager.GetFormat()->SetLuaState(luaState);
|
||||
//TODO: config parameter
|
||||
regionPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||
std::cout << "Prepared the map system" << std::endl;
|
||||
|
||||
//push the pager onto the lua registry
|
||||
lua_pushstring(luaState, "pager");
|
||||
lua_pushlightuserdata(luaState, reinterpret_cast<void*>(®ionPager));
|
||||
lua_settable(luaState, LUA_REGISTRYINDEX);
|
||||
std::cout << "Registered the map system in lua" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Run the startup scripts
|
||||
//-------------------------
|
||||
|
||||
//setup the database
|
||||
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
|
||||
throw(std::runtime_error("Failed to initialize SQL's setup script"));
|
||||
}
|
||||
std::cout << "Completed SQL's setup script" << std::endl;
|
||||
|
||||
//run lua's startup script
|
||||
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
|
||||
throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
|
||||
}
|
||||
std::cout << "Completed lua's setup script" << std::endl;
|
||||
|
||||
//debug output
|
||||
std::cout << "Internal sizes:" << std::endl;
|
||||
std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl;
|
||||
std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl;
|
||||
|
||||
//finalize the startup
|
||||
std::cout << "Startup completed successfully" << std::endl;
|
||||
|
||||
//debugging
|
||||
//
|
||||
}
|
||||
|
||||
void ServerApplication::Proc() {
|
||||
SerialPacket packet;
|
||||
while(running) {
|
||||
//suck in the waiting packets & process them
|
||||
while(network.Receive(&packet)) {
|
||||
HandlePacket(packet);
|
||||
}
|
||||
//update the internals
|
||||
//TODO: update the internals i.e. player positions
|
||||
//give the computer a break
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::Quit() {
|
||||
std::cout << "Shutting down" << std::endl;
|
||||
|
||||
//save the server state
|
||||
for (auto& it : accountMap) {
|
||||
SaveUserAccount(it.first);
|
||||
}
|
||||
for (auto& it : characterMap) {
|
||||
SaveCharacter(it.first);
|
||||
}
|
||||
|
||||
//empty the members
|
||||
accountMap.clear();
|
||||
characterMap.clear();
|
||||
regionPager.UnloadAll();
|
||||
|
||||
//APIs
|
||||
lua_close(luaState);
|
||||
sqlite3_close_v2(database);
|
||||
network.Close();
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
std::cout << "Shutdown finished" << std::endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Define the uber switch
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::HandlePacket(SerialPacket packet) {
|
||||
switch(packet.meta.type) {
|
||||
case SerialPacket::Type::BROADCAST_REQUEST:
|
||||
HandleBroadcastRequest(packet);
|
||||
break;
|
||||
case SerialPacket::Type::JOIN_REQUEST:
|
||||
HandleJoinRequest(packet);
|
||||
break;
|
||||
case SerialPacket::Type::SYNCHRONIZE:
|
||||
HandleSynchronize(packet);
|
||||
break;
|
||||
case SerialPacket::Type::DISCONNECT:
|
||||
HandleDisconnect(packet);
|
||||
break;
|
||||
case SerialPacket::Type::SHUTDOWN:
|
||||
HandleShutdown(packet);
|
||||
break;
|
||||
case SerialPacket::Type::CHARACTER_UPDATE:
|
||||
HandleCharacterUpdate(packet);
|
||||
break;
|
||||
case SerialPacket::Type::REGION_REQUEST:
|
||||
HandleRegionRequest(packet);
|
||||
break;
|
||||
//handle errors
|
||||
default:
|
||||
throw(std::runtime_error("Unknown SerialPacket::Type encountered"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "in_world.hpp"
|
||||
|
||||
#include "timer.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "region_pager_api.hpp"
|
||||
#include "tile_sheet_api.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InWorld::InWorld(lua_State* L): lua(L) {
|
||||
//register the pager
|
||||
lua_pushstring(lua, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_pushlightuserdata(lua, &pager);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//register the tilesheet
|
||||
lua_pushstring(lua, TORTUGA_TILE_SHEET_PSEUDO_INDEX);
|
||||
lua_pushlightuserdata(lua, &tileSheet);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//setup the component objecrs
|
||||
pager.SetLuaState(lua);
|
||||
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "fonts");
|
||||
std::string fonts = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -2, "interface");
|
||||
std::string interface = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -3, "sprites");
|
||||
std::string sprites = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -4, "scripts");
|
||||
std::string scripts = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 6);
|
||||
|
||||
//run the additional scripts
|
||||
if (luaL_dofile(lua, (scripts + "in_world.lua").c_str())) {
|
||||
throw(std::runtime_error(std::string() + "Failed to run in_world.lua: " + lua_tostring(lua, -1) ));
|
||||
}
|
||||
|
||||
//setup the utility objects
|
||||
buttonImage.LoadSurface(interface + "button_menu.bmp");
|
||||
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||
font.LoadSurface(fonts + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
backButton.SetImage(&buttonImage);
|
||||
backButton.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
backButton.SetX(50);
|
||||
backButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||
|
||||
//set the button texts
|
||||
backButton.SetText("Back");
|
||||
|
||||
//entities
|
||||
character.GetSprite()->LoadSurface(sprites + "elliot2.bmp", 4, 4);
|
||||
character.SetBoundingBox({0, 0,
|
||||
character.GetSprite()->GetImage()->GetClipW(),
|
||||
character.GetSprite()->GetImage()->GetClipH()
|
||||
});
|
||||
|
||||
//setup the camera
|
||||
camera.margin.x = GetScreen()->w / 2 - character.GetSprite()->GetImage()->GetClipW() / 2;
|
||||
camera.margin.y = GetScreen()->h / 2 - character.GetSprite()->GetImage()->GetClipH() / 2;
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
InWorld::~InWorld() {
|
||||
//unregister the map components
|
||||
lua_pushstring(lua, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_pushstring(lua, TORTUGA_TILE_SHEET_PSEUDO_INDEX);
|
||||
lua_pushnil(lua);
|
||||
lua_settable(lua, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(lua);
|
||||
lua_settable(lua, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InWorld::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::Update(double delta) {
|
||||
//update the entities
|
||||
character.Update(delta);
|
||||
|
||||
//check for collisions with the map
|
||||
BoundingBox wallBounds = {0, 0, tileSheet.GetTileW(), tileSheet.GetTileH()};
|
||||
const int xCount = character.GetBoundingBox().w / wallBounds.w + 1;
|
||||
const int yCount = character.GetBoundingBox().h / wallBounds.h + 1;
|
||||
|
||||
for (int i = -1; i <= xCount; ++i) {
|
||||
for (int j = -1; j <= yCount; ++j) {
|
||||
//set the wall's position
|
||||
wallBounds.x = wallBounds.w * i + snapToBase((double)wallBounds.w, character.GetOrigin().x);
|
||||
wallBounds.y = wallBounds.h * j + snapToBase((double)wallBounds.h, character.GetOrigin().y);
|
||||
|
||||
if (!pager.GetSolid(wallBounds.x / wallBounds.w, wallBounds.y / wallBounds.h)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((character.GetOrigin() + character.GetBoundingBox()).CheckOverlap(wallBounds)) {
|
||||
character.SetOrigin(character.GetOrigin() - (character.GetMotion() * delta));
|
||||
character.SetMotion({0,0});
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//update the camera
|
||||
camera.origin.x = character.GetOrigin().x - camera.margin.x;
|
||||
camera.origin.y = character.GetOrigin().y - camera.margin.y;
|
||||
|
||||
//TODO: prune distant regions
|
||||
|
||||
//summon nearby unloaded regions
|
||||
const int left = snapToBase(REGION_WIDTH, camera.origin.x / tileSheet.GetTileW());
|
||||
const int top = snapToBase(REGION_HEIGHT, camera.origin.y / tileSheet.GetTileH());
|
||||
const int right = snapToBase(REGION_WIDTH, (camera.origin.x + GetScreen()->w) / tileSheet.GetTileW());
|
||||
const int bottom = snapToBase(REGION_HEIGHT, (camera.origin.y + GetScreen()->h) / tileSheet.GetTileH());
|
||||
|
||||
for (int i = left - REGION_WIDTH; i <= right + REGION_WIDTH; i += REGION_WIDTH) {
|
||||
for (int j = top - REGION_HEIGHT; j <= bottom + REGION_HEIGHT; j += REGION_HEIGHT) {
|
||||
pager.GetRegion(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::RenderFrame() {
|
||||
// SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
void InWorld::Render(SDL_Surface* const screen) {
|
||||
//draw all regions
|
||||
for (std::list<Region>::iterator it = pager.GetContainer()->begin(); it != pager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(screen, &(*it), camera.origin.x, camera.origin.y);
|
||||
}
|
||||
|
||||
//draw the characters
|
||||
character.DrawTo(screen, camera.origin.x, camera.origin.y);
|
||||
|
||||
//draw the UI
|
||||
backButton.DrawTo(screen);
|
||||
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::QuitEvent() {
|
||||
//exit the game
|
||||
SetNextScene(SceneList::QUIT);
|
||||
}
|
||||
|
||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
backButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
backButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//player movement
|
||||
Vector2 motion = character.GetMotion();
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_LEFT:
|
||||
motion.x -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
motion.x += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_UP:
|
||||
motion.y -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
motion.y += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
}
|
||||
if (character.GetMotion() != motion) {
|
||||
character.SetMotion(motion);
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//player movement
|
||||
Vector2 motion = character.GetMotion();
|
||||
switch(key.keysym.sym) {
|
||||
//NOTE: The use of min/max here are to prevent awkward movements
|
||||
case SDLK_LEFT:
|
||||
motion.x = std::min(motion.x + CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
motion.x = std::max(motion.x - CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_UP:
|
||||
motion.y = std::min(motion.y + CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
motion.y = std::max(motion.y - CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
}
|
||||
if (character.GetMotion() != motion) {
|
||||
character.SetMotion(motion);
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/* $Id: linit.c,v 1.32, modified
|
||||
* Initialization of libraries for lua.c and other clients
|
||||
* See Copyright Notice in lua.h
|
||||
*
|
||||
* If you embed Lua in your program and need to open the standard
|
||||
* libraries, call luaL_openlibs in your program. If you need a
|
||||
* different set of libraries, copy this file to your project and edit
|
||||
* it to suit your needs.
|
||||
*
|
||||
* Modified for use in Tortuga, renamed to linit.cpp
|
||||
* Modifications are released under the zlib license:
|
||||
*
|
||||
* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#include "region_api.hpp"
|
||||
#include "region_pager_api.hpp"
|
||||
#include "tile_sheet_api.hpp"
|
||||
|
||||
//these libs are loaded by lua.c and are readily available to any Lua program
|
||||
static const luaL_Reg loadedlibs[] = {
|
||||
//Standard libs
|
||||
{"_G", luaopen_base},
|
||||
{LUA_LOADLIBNAME, luaopen_package},
|
||||
{LUA_COLIBNAME, luaopen_coroutine},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_IOLIBNAME, luaopen_io},
|
||||
{LUA_OSLIBNAME, luaopen_os},
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_BITLIBNAME, luaopen_bit32},
|
||||
{LUA_MATHLIBNAME, luaopen_math},
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
|
||||
//Tortuga's API
|
||||
{TORTUGA_REGION_NAME, openRegionAPI},
|
||||
{TORTUGA_REGION_PAGER_NAME, openRegionPagerAPI},
|
||||
{TORTUGA_TILE_SHEET_NAME, openTileSheetAPI},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
//these libs are preloaded and must be required before used
|
||||
static const luaL_Reg preloadedlibs[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||
const luaL_Reg *lib;
|
||||
//call open functions from 'loadedlibs' and set results to global table
|
||||
for (lib = loadedlibs; lib->func; lib++) {
|
||||
luaL_requiref(L, lib->name, lib->func, 1);
|
||||
lua_pop(L, 1); //remove lib
|
||||
}
|
||||
//add open functions from 'preloadedlibs' into 'package.preload' table
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
for (lib = preloadedlibs; lib->func; lib++) {
|
||||
lua_pushcfunction(L, lib->func);
|
||||
lua_setfield(L, -2, lib->name);
|
||||
}
|
||||
lua_pop(L, 1); //remove _PRELOAD table
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGION_HPP_
|
||||
#define REGION_HPP_
|
||||
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
|
||||
//the region's storage format
|
||||
constexpr int REGION_WIDTH = 20;
|
||||
constexpr int REGION_HEIGHT = 20;
|
||||
constexpr int REGION_DEPTH = 3;
|
||||
|
||||
//the size of the solid map
|
||||
constexpr int REGION_SOLID_FOOTPRINT = ceil(REGION_WIDTH * REGION_HEIGHT / 8.0);
|
||||
|
||||
class Region {
|
||||
public:
|
||||
typedef unsigned char type_t;
|
||||
|
||||
Region() = delete;
|
||||
Region(int x, int y);
|
||||
Region(Region const&);
|
||||
~Region() = default;
|
||||
|
||||
type_t SetTile(int x, int y, int z, type_t v);
|
||||
type_t GetTile(int x, int y, int z);
|
||||
|
||||
bool SetSolid(int x, int y, bool b);
|
||||
bool GetSolid(int x, int y);
|
||||
|
||||
//accessors
|
||||
int GetX() const { return x; }
|
||||
int GetY() const { return y; }
|
||||
|
||||
std::bitset<REGION_WIDTH*REGION_HEIGHT>* GetSolidBitset() { return &solid; }
|
||||
private:
|
||||
const int x;
|
||||
const int y;
|
||||
|
||||
type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
|
||||
std::bitset<REGION_WIDTH*REGION_HEIGHT> solid;
|
||||
};
|
||||
|
||||
//the memory footprint of the tile and solid data; not including any metadata
|
||||
constexpr int REGION_FOOTPRINT = REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + REGION_SOLID_FOOTPRINT;
|
||||
|
||||
#endif
|
||||
@@ -1,122 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region_api.hpp"
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
int ret = region->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
int ret = region->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setSolid(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
bool ret = region->SetSolid(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_toboolean(L, 4));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getSolid(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
bool ret = region->GetSolid(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1);
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getX(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, region->GetX());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getY(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, region->GetY());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getWidth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_WIDTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getHeight(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_HEIGHT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getDepth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_DEPTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int load(lua_State* L) {
|
||||
//EMPTY
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int save(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionLib[] = {
|
||||
{"SetTile",setTile},
|
||||
{"GetTile",getTile},
|
||||
{"SetSolid",setSolid},
|
||||
{"GetSolid",getSolid},
|
||||
{"GetX",getX},
|
||||
{"GetY",getY},
|
||||
{"GetWidth",getWidth},
|
||||
{"GetHeight",getHeight},
|
||||
{"GetDepth",getDepth},
|
||||
{"Load",load},
|
||||
{"Save",save},
|
||||
{"Create",create},
|
||||
{"Unload",unload},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openRegionAPI(lua_State* L) {
|
||||
luaL_newlib(L, regionLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region_pager_api.hpp"
|
||||
|
||||
#include "region_pager_lua.hpp"
|
||||
#include "region.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
static int getRegionPager(lua_State* L) {
|
||||
lua_pushstring(L, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
//DOCS: These glue functions simply wrap RegionPagerLua's methods
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
int ret = pager->SetTile(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
int ret = pager->GetTile(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setSolid(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
bool ret = pager->SetSolid(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_toboolean(L, 4));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getSolid(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
bool ret = pager->GetSolid(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->GetRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int loadRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->LoadRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int saveRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->SaveRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int createRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->CreateRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int unloadRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
pager->UnloadRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionPagerLib[] = {
|
||||
{"GetRegionPager", getRegionPager},
|
||||
{"SetTile", setTile},
|
||||
{"GetTile", getTile},
|
||||
{"SetSolid", setSolid},
|
||||
{"GetSolid", getSolid},
|
||||
{"GetRegion", getRegion},
|
||||
{"LoadRegion", loadRegion},
|
||||
{"SaveRegion", saveRegion},
|
||||
{"CreateRegion", createRegion},
|
||||
{"UnloadRegion", unloadRegion},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openRegionPagerAPI(lua_State* L) {
|
||||
luaL_newlib(L, regionPagerLib);
|
||||
return 1;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user