Compare commits

...

22 Commits

Author SHA1 Message Date
Kayne Ruse c534158c2e Merge branch 'login' (read more)
This branch was originally intended to rewrite the login system, but I've discovered some serious problems that could not wait. See the previous commit for more information. Hopefully I can get back to this soon.

I believe this version deserves a new release tag.
2014-04-21 04:00:37 +10:00
Kayne Ruse b47191a0c1 Fixed a horrible region coordinate bug
Coordinates are supposed to be stored by their x & y, but the sizes of the
tile sheets were getting mixed in as well. When trying to store a region
at (0, 20), it was being stored at (0, 260).

Another visual bug inside the tile sheet's rendering function masked this
issue until now.

Another thing to note is that I've removed an incredibly complex system
for updating the client's map. The new system may seem complex at first,
but it is straight forward compared to what it replaced.

I've also fixed a few logarithmic lagging points in the code.
2014-04-21 03:56:48 +10:00
Kayne Ruse 6c6a025f2a Adjusted a few comments 2014-04-21 02:13:00 +10:00
Kayne Ruse 60edc97ea5 Added rejections for incompatible servers 2014-04-21 01:38:28 +10:00
Kayne Ruse a5b209d9e0 Merge branch 'login' (read more)
Made a few tweaks to the code, but the build still works, so I'm merging it into master.
2014-04-21 01:02:38 +10:00
Kayne Ruse fd673a415f Removed singleton pattern 2014-04-21 01:01:00 +10:00
Kayne Ruse 4270765146 Renamed NetworkPacket to SerialPacket, updated build 2014-04-20 23:54:59 +10:00
Kayne Ruse f56cb58dfb Revised SQL setup script, and the script function 2014-04-20 23:11:46 +10:00
Kayne Ruse f315f4bf35 Merge branch 'map' (read more)
After refactoring the map system, this new build uses the preprocessor macros to define the sizes of each region object. These macros, which are defined in region.hpp, were being used anyway; these modifications simply speed up the process by cutting out a lot of the fat.
2014-04-20 05:41:49 +10:00
Kayne Ruse 69765de433 Removed the TODO file; I think it's fairly stable again 2014-04-20 05:34:15 +10:00
Kayne Ruse 35d463d4ba Removed some annoying debugging messages 2014-04-20 05:30:08 +10:00
Kayne Ruse 894b46c5db Found the error in the format functor
I shouldn't automatically guess where an error is, since this project is
so complex.
2014-04-20 05:14:25 +10:00
Kayne Ruse eb0b18af6f Brought the programs into line, (BUG, read more)
It seems that the serialization code has a bug in it. I was expecting
something like this. When the server tries to send the region content, it
exits. I'll try and find the cause of the error, but I'm committing my
changes anyway.
2014-04-20 04:41:06 +10:00
Kayne Ruse fba183fa27 Brought the common/ directory up to date with the region's preprocessors
I really hope the serialization code still works.
2014-04-20 04:02:26 +10:00
Kayne Ruse c5a627004a Refactored the map system (read more)
The region's width, height and depth are all defined by preprocessor
macros. The rest of the map system has been updated to match. The
programs proper need to be updated as well. It would be a good idea to
include the macros' values as part of the initial communication protocols,
so that the clients don't connect to a server that is using the wrong
sized regions.
2014-04-20 03:41:08 +10:00
Kayne Ruse ac27fb0ca7 Found a list of TODO comments 2014-04-20 02:40:06 +10:00
Kayne Ruse be4a8311d5 Adjusted a few comments 2014-04-20 02:39:29 +10:00
Kayne Ruse 6d32d44fa3 Reverted some of the changes, stable 2014-04-15 23:23:15 +10:00
Kayne Ruse 9bacfb1424 Merge branch 'entity' (early part) (read more)
I've had some issues with the entity system I created, so I'm trying to
revert it right now, while also retaining the other few tweaks I've made.
2014-04-15 22:40:07 +10:00
Kayne Ruse c3464be589 The server is working correctly, using the entity system 2014-04-13 22:20:30 +10:00
Kayne Ruse 7fe71c60d0 This will not build; working on refactoring 2014-04-13 03:49:35 +10:00
Kayne Ruse 0c6537fb36 Began work on the server's generic entity system 2014-04-13 03:02:26 +10:00
40 changed files with 857 additions and 709 deletions
+3 -15
View File
@@ -21,15 +21,11 @@
*/ */
#include "client_application.hpp" #include "client_application.hpp"
#include "serial.hpp"
#include <stdexcept> #include <stdexcept>
#include <chrono> #include <chrono>
//-------------------------
//Static declarations
//-------------------------
ClientApplication ClientApplication::instance;
//------------------------- //-------------------------
//Scene headers //Scene headers
//------------------------- //-------------------------
@@ -46,15 +42,7 @@ ClientApplication ClientApplication::instance;
//Public access members //Public access members
//------------------------- //-------------------------
ClientApplication::ClientApplication() { void ClientApplication::Init(int argc, char** argv) {
//
}
ClientApplication::~ClientApplication() {
//
}
void ClientApplication::Init() {
//load the prerequisites //load the prerequisites
config.Load("rsc\\config.cfg"); config.Load("rsc\\config.cfg");
+3 -8
View File
@@ -26,19 +26,14 @@
#include "base_scene.hpp" #include "base_scene.hpp"
#include "config_utility.hpp" #include "config_utility.hpp"
#include "network_packet.hpp"
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
class ClientApplication { class ClientApplication {
private:
ClientApplication();
~ClientApplication();
static ClientApplication instance;
public: public:
static ClientApplication* GetInstance() { return &instance; } ClientApplication() = default;
~ClientApplication() = default;
void Init(); void Init(int argc, char** argv);
void Proc(); void Proc();
void Quit(); void Quit();
+5 -4
View File
@@ -26,12 +26,13 @@
using namespace std; using namespace std;
int main(int, char**) { int main(int argc, char** argv) {
cout << "Beginning client" << endl; cout << "Beginning client" << endl;
try { try {
ClientApplication::GetInstance()->Init(); ClientApplication app;
ClientApplication::GetInstance()->Proc(); app.Init(argc, argv);
ClientApplication::GetInstance()->Quit(); app.Proc();
app.Quit();
} }
catch(exception& e) { catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl; cerr << "Fatal exception thrown: " << e.what() << endl;
+1
View File
@@ -25,6 +25,7 @@
#include "vector2.hpp" #include "vector2.hpp"
#include "sprite_sheet.hpp" #include "sprite_sheet.hpp"
//TODO: correct the PlayerCharacter class and it's movement system
class PlayerCharacter { class PlayerCharacter {
public: public:
enum class Direction { enum class Direction {
+51 -110
View File
@@ -27,11 +27,6 @@
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>
//debugging
#include <iostream>
using std::cout;
using std::endl;
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
@@ -63,16 +58,13 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
shutDownButton.SetText("Shut Down"); shutDownButton.SetText("Shut Down");
//load the tilesheet //load the tilesheet
//TODO: add the tilesheet to the map system?
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15); tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
//setup the map object
mapPager.SetRegionWidth(REGION_WIDTH);
mapPager.SetRegionHeight(REGION_HEIGHT);
mapPager.SetRegionDepth(REGION_DEPTH);
//create the server-side player object //create the server-side player object
NetworkPacket packet; //TODO: the login system needs an overhaul
packet.meta.type = NetworkPacket::Type::PLAYER_NEW; SerialPacket packet;
packet.meta.type = SerialPacket::Type::PLAYER_NEW;
packet.playerInfo.clientIndex = clientIndex; packet.playerInfo.clientIndex = clientIndex;
snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str()); snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str());
snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str()); snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str());
@@ -85,7 +77,7 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
//request a sync //request a sync
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE; packet.meta.type = SerialPacket::Type::SYNCHRONIZE;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
@@ -106,7 +98,7 @@ void InWorld::FrameStart() {
} }
void InWorld::Update(double delta) { void InWorld::Update(double delta) {
NetworkPacket packet; SerialPacket packet;
//suck in all waiting packets //suck in all waiting packets
while(network.Receive()) { while(network.Receive()) {
@@ -143,7 +135,8 @@ void InWorld::RenderFrame() {
void InWorld::Render(SDL_Surface* const screen) { void InWorld::Render(SDL_Surface* const screen) {
//draw the map //draw the map
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); it++) { //TODO: figure out something to fix the region container access
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y); tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
} }
@@ -264,37 +257,37 @@ void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
//Network handlers //Network handlers
//------------------------- //-------------------------
void InWorld::HandlePacket(NetworkPacket packet) { void InWorld::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) { switch(packet.meta.type) {
case NetworkPacket::Type::DISCONNECT: case SerialPacket::Type::DISCONNECT:
HandleDisconnect(packet); HandleDisconnect(packet);
break; break;
case NetworkPacket::Type::PLAYER_NEW: case SerialPacket::Type::PLAYER_NEW:
HandlePlayerNew(packet); HandlePlayerNew(packet);
break; break;
case NetworkPacket::Type::PLAYER_DELETE: case SerialPacket::Type::PLAYER_DELETE:
HandlePlayerDelete(packet); HandlePlayerDelete(packet);
break; break;
case NetworkPacket::Type::PLAYER_UPDATE: case SerialPacket::Type::PLAYER_UPDATE:
HandlePlayerUpdate(packet); HandlePlayerUpdate(packet);
break; break;
case NetworkPacket::Type::REGION_CONTENT: case SerialPacket::Type::REGION_CONTENT:
HandleRegionContent(packet); HandleRegionContent(packet);
break; break;
//handle errors //handle errors
default: default:
throw(std::runtime_error("Unknown NetworkPacket::Type encountered")); throw(std::runtime_error("Unknown SerialPacket::Type encountered"));
break; break;
} }
} }
void InWorld::HandleDisconnect(NetworkPacket packet) { void InWorld::HandleDisconnect(SerialPacket packet) {
network.Unbind(Channels::SERVER); network.Unbind(Channels::SERVER);
clientIndex = -1; clientIndex = -1;
SetNextScene(SceneList::MAINMENU); SetNextScene(SceneList::MAINMENU);
} }
void InWorld::HandlePlayerNew(NetworkPacket packet) { void InWorld::HandlePlayerNew(SerialPacket packet) {
if (playerCharacters.find(packet.playerInfo.playerIndex) != playerCharacters.end()) { if (playerCharacters.find(packet.playerInfo.playerIndex) != playerCharacters.end()) {
throw(std::runtime_error("Cannot create duplicate players")); throw(std::runtime_error("Cannot create duplicate players"));
} }
@@ -317,7 +310,7 @@ void InWorld::HandlePlayerNew(NetworkPacket packet) {
} }
} }
void InWorld::HandlePlayerDelete(NetworkPacket packet) { void InWorld::HandlePlayerDelete(SerialPacket packet) {
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) { if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
throw(std::runtime_error("Cannot delete non-existant players")); throw(std::runtime_error("Cannot delete non-existant players"));
} }
@@ -331,7 +324,7 @@ void InWorld::HandlePlayerDelete(NetworkPacket packet) {
} }
} }
void InWorld::HandlePlayerUpdate(NetworkPacket packet) { void InWorld::HandlePlayerUpdate(SerialPacket packet) {
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) { if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
HandlePlayerNew(packet); HandlePlayerNew(packet);
return; return;
@@ -345,22 +338,13 @@ void InWorld::HandlePlayerUpdate(NetworkPacket packet) {
playerCharacters[packet.playerInfo.playerIndex].ResetDirection(); playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
} }
void InWorld::HandleRegionContent(NetworkPacket packet) { void InWorld::HandleRegionContent(SerialPacket packet) {
//replace existing regions //replace existing regions
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) { if (regionPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
mapPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y); regionPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
} }
mapPager.PushRegion(packet.regionInfo.region); regionPager.PushRegion(packet.regionInfo.region);
packet.regionInfo.region = nullptr; packet.regionInfo.region = nullptr;
//debugging
cout << "Received region: " << packet.regionInfo.x << ", " << packet.regionInfo.y << endl;
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
cout << "Success" << endl;
}
else {
cout << "Failure" << endl;
}
} }
//------------------------- //-------------------------
@@ -368,11 +352,11 @@ void InWorld::HandleRegionContent(NetworkPacket packet) {
//------------------------- //-------------------------
void InWorld::SendState() { void InWorld::SendState() {
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//pack the packet //pack the packet
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE; packet.meta.type = SerialPacket::Type::PLAYER_UPDATE;
packet.playerInfo.clientIndex = clientIndex; packet.playerInfo.clientIndex = clientIndex;
packet.playerInfo.playerIndex = playerIndex; packet.playerInfo.playerIndex = playerIndex;
packet.playerInfo.position = localCharacter->GetPosition(); packet.playerInfo.position = localCharacter->GetPosition();
@@ -383,33 +367,33 @@ void InWorld::SendState() {
} }
void InWorld::RequestDisconnect() { void InWorld::RequestDisconnect() {
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//send a disconnect request //send a disconnect request
packet.meta.type = NetworkPacket::Type::DISCONNECT; packet.meta.type = SerialPacket::Type::DISCONNECT;
packet.clientInfo.index = clientIndex; packet.clientInfo.index = clientIndex;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
} }
void InWorld::RequestShutDown() { void InWorld::RequestShutDown() {
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//send a shutdown request //send a shutdown request
packet.meta.type = NetworkPacket::Type::SHUTDOWN; packet.meta.type = SerialPacket::Type::SHUTDOWN;
packet.clientInfo.index = clientIndex; packet.clientInfo.index = clientIndex;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE); network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
} }
void InWorld::RequestRegion(int x, int y) { void InWorld::RequestRegion(int x, int y) {
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//pack the region's data //pack the region's data
packet.meta.type = NetworkPacket::Type::REGION_REQUEST; packet.meta.type = SerialPacket::Type::REGION_REQUEST;
packet.regionInfo.x = x; packet.regionInfo.x = x;
packet.regionInfo.y = y; packet.regionInfo.y = y;
serialize(&packet, buffer); serialize(&packet, buffer);
@@ -420,78 +404,35 @@ void InWorld::RequestRegion(int x, int y) {
//Utilities //Utilities
//------------------------- //-------------------------
int InWorld::CheckBufferDistance(Region* const region) { //TODO: convert this into a more generic function?; using parameters for the bounds
/* DOCUMENTATION
* This algorithm is extremely complex and involed, but initial tests show
* that it gives the right answers. The purpose is to determine how far off screen
* a certain region is, so that it can be unloaded when necessary.
*
* If the region is actually onscreen, then there's no reason to run the rest, so
* the algorithm corrects for the camera's location, before checking the bounds of
* the screen.
*
* The next part is tricky. If X or Y is negative, then it is divided by the
* graphical size of the regions, resulting in a usable integer, representing how
* far from the screen it is in "region units". If, however, X or Y is larger than
* 0, than first, the size of the screen is subtracted from that variable, before
* it is then divided by the graphical size of a region. Finally, to compensate for
* the off by one error, 1 is added at the end.
*
* Since only the magnitude of the distance in either direction is needed, this
* method returns the largest absolute value of X or Y.
*
* The final result of this algorithm is an integer representing how far, rounded
* up, a certain region is from the screen's edges in any direction, measured in
* "region units". This algorithm may be flawed, in which case, I recommend simply
* replacing it with a boolean check, to see if the region's distance from the player
* is larger than a certain value. This algorithm lacks the advantages I initially
* expected, so that may be beneficial at some point.
*/
//locations relative to the camera
int x = region->GetX() - camera.x;
int y = region->GetY() - camera.y;
//if the region is visible, return -1
if (x >= -mapPager.GetRegionWidth() * tileSheet.GetTileW() && x < camera.width &&
y >= -mapPager.GetRegionHeight() * tileSheet.GetTileH() && y < camera.height) {
return -1;
}
//prune the screen's area from the algorithm; get the pseudo-indexes
if (x < 0) x /= (mapPager.GetRegionWidth() * tileSheet.GetTileW());
if (y < 0) y /= (mapPager.GetRegionHeight() * tileSheet.GetTileH());
if (x > 0) x = (x - camera.width) / (mapPager.GetRegionWidth() * tileSheet.GetTileW()) + 1;
if (y > 0) y = (y - camera.height) / (mapPager.GetRegionHeight() * tileSheet.GetTileH()) + 1;
//return the pseudo-index with the greatest magnitude
return std::max(abs(x), abs(y));
}
void InWorld::UpdateMap() { 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 //prune distant regions
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); /* EMPTY */) { for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) {
if (CheckBufferDistance(*it) > 2) { //check if the region is outside off this area
//debugging if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) {
cout << "unloading: " << (*it)->GetX() << ", " << (*it)->GetY() << endl;
mapPager.UnloadRegion((*it)->GetX(), (*it)->GetY()); //clunky, but the alternative was time consuming
int tmpX = (*it)->GetX();
int tmpY = (*it)->GetY();
++it;
//reset regionPager.UnloadRegion(tmpX, tmpY);
it = mapPager.GetContainer()->begin();
continue; continue;
} }
++it; ++it;
} }
//TODO: make the region units official //request empty regions within this zone
int regionUnitX = mapPager.GetRegionWidth() * tileSheet.GetTileW(); for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
int regionUnitY = mapPager.GetRegionHeight() * tileSheet.GetTileH(); for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
if (!regionPager.FindRegion(i, j)) {
//request empty regions, including buffers (-1 & +1 region unit)
for (int i = snapToBase(regionUnitX, camera.x - regionUnitX); i <= snapToBase(regionUnitX, camera.x + camera.width + regionUnitX); i += regionUnitX) {
for (int j = snapToBase(regionUnitY, camera.y - regionUnitY); j <= snapToBase(regionUnitY, camera.y + camera.height + regionUnitY); j += regionUnitY) {
if (!mapPager.FindRegion(i, j)) {
RequestRegion(i, j); RequestRegion(i, j);
} }
} }
+10 -10
View File
@@ -23,13 +23,13 @@
#define INWORLD_HPP_ #define INWORLD_HPP_
//maps //maps
#include "map_generator.hpp" #include "map_allocator.hpp"
#include "map_file_format.hpp" #include "map_file_format.hpp"
#include "region_pager.hpp" #include "region_pager.hpp"
//networking //networking
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
#include "network_packet.hpp" #include "serial_packet.hpp"
#include "serial.hpp" #include "serial.hpp"
//graphics //graphics
@@ -72,12 +72,12 @@ protected:
void KeyUp(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&);
//Network handlers //Network handlers
void HandlePacket(NetworkPacket); void HandlePacket(SerialPacket);
void HandleDisconnect(NetworkPacket); void HandleDisconnect(SerialPacket);
void HandlePlayerNew(NetworkPacket); void HandlePlayerNew(SerialPacket);
void HandlePlayerDelete(NetworkPacket); void HandlePlayerDelete(SerialPacket);
void HandlePlayerUpdate(NetworkPacket); void HandlePlayerUpdate(SerialPacket);
void HandleRegionContent(NetworkPacket); void HandleRegionContent(SerialPacket);
//Server control //Server control
void SendState(); void SendState();
@@ -86,7 +86,6 @@ protected:
void RequestRegion(int x, int y); void RequestRegion(int x, int y);
//utilities //utilities
int CheckBufferDistance(Region* const);
void UpdateMap(); void UpdateMap();
//globals //globals
@@ -101,11 +100,12 @@ protected:
TileSheet tileSheet; TileSheet tileSheet;
//map //map
RegionPager<BlankGenerator, DummyFormat> mapPager; RegionPager<BlankAllocator, DummyFormat> regionPager;
//UI //UI
Button disconnectButton; Button disconnectButton;
Button shutDownButton; Button shutDownButton;
//TODO: Fix the camera
struct { struct {
int x = 0, y = 0; int x = 0, y = 0;
int width = 0, height = 0; int width = 0, height = 0;
+36 -11
View File
@@ -22,6 +22,7 @@
#include "lobby_menu.hpp" #include "lobby_menu.hpp"
#include "channels.hpp" #include "channels.hpp"
#include "utility.hpp"
#include <stdexcept> #include <stdexcept>
@@ -78,7 +79,7 @@ void LobbyMenu::FrameStart() {
void LobbyMenu::Update(double delta) { void LobbyMenu::Update(double delta) {
//suck in all waiting packets //suck in all waiting packets
NetworkPacket packet; SerialPacket packet;
while(network.Receive()) { while(network.Receive()) {
deserialize(&packet, network.GetInData()); deserialize(&packet, network.GetInData());
packet.meta.srcAddress = network.GetInPacket()->address; packet.meta.srcAddress = network.GetInPacket()->address;
@@ -91,9 +92,13 @@ void LobbyMenu::FrameEnd() {
} }
void LobbyMenu::Render(SDL_Surface* const screen) { 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); search.DrawTo(screen);
join.DrawTo(screen); join.DrawTo(screen);
back.DrawTo(screen); back.DrawTo(screen);
//TODO: draw headers for the server list
for (int i = 0; i < serverInfo.size(); i++) { for (int i = 0; i < serverInfo.size(); i++) {
//draw the selected server's highlight //draw the selected server's highlight
if (selection == &serverInfo[i]) { if (selection == &serverInfo[i]) {
@@ -104,6 +109,16 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
//draw the server name //draw the server name
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h); 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?
} }
} }
@@ -126,11 +141,11 @@ void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) { void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (search.MouseButtonUp(button) == Button::State::HOVER) { if (search.MouseButtonUp(button) == Button::State::HOVER) {
//the vars //the vars
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//broadcast to the network, or a specific server //broadcast to the network, or a specific server
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST; packet.meta.type = SerialPacket::Type::BROADCAST_REQUEST;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(config["server.host"].c_str(), config.Int("server.port"), buffer, PACKET_BUFFER_SIZE); network.Send(config["server.host"].c_str(), config.Int("server.port"), buffer, PACKET_BUFFER_SIZE);
@@ -139,13 +154,14 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
selection = nullptr; selection = nullptr;
} }
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) { else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
//TODO: The player login information should be collected by the lobby screen
//the vars //the vars
NetworkPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//join the selected server //join the selected server
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST; packet.meta.type = SerialPacket::Type::JOIN_REQUEST;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE); network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE);
selection = nullptr; selection = nullptr;
@@ -181,16 +197,25 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
// //
} }
void LobbyMenu::HandlePacket(NetworkPacket packet) { void LobbyMenu::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) { switch(packet.meta.type) {
case NetworkPacket::Type::BROADCAST_RESPONSE: { case SerialPacket::Type::BROADCAST_RESPONSE: {
//extract the data
ServerInformation server; ServerInformation server;
server.name = packet.serverInfo.name;
server.address = packet.meta.srcAddress; server.address = packet.meta.srcAddress;
server.name = packet.serverInfo.name;
server.playerCount = packet.serverInfo.playerCount;
//NOTE: Check compatibility here
server.compatible = packet.serverInfo.regionWidth == REGION_WIDTH &&
packet.serverInfo.regionHeight == REGION_HEIGHT &&
packet.serverInfo.regionDepth == REGION_DEPTH;
//push
serverInfo.push_back(server); serverInfo.push_back(server);
} }
break; break;
case NetworkPacket::Type::JOIN_RESPONSE: case SerialPacket::Type::JOIN_RESPONSE:
clientIndex = packet.clientInfo.index; clientIndex = packet.clientInfo.index;
network.Bind(&packet.meta.srcAddress, Channels::SERVER); network.Bind(&packet.meta.srcAddress, Channels::SERVER);
SetNextScene(SceneList::INWORLD); SetNextScene(SceneList::INWORLD);
@@ -198,7 +223,7 @@ void LobbyMenu::HandlePacket(NetworkPacket packet) {
//handle errors //handle errors
default: default:
throw(std::runtime_error("Unknown NetworkPacket::Type encountered")); throw(std::runtime_error("Unknown SerialPacket::Type encountered"));
break; break;
} }
} }
+16 -6
View File
@@ -22,17 +22,24 @@
#ifndef LOBBYMENU_HPP_ #ifndef LOBBYMENU_HPP_
#define LOBBYMENU_HPP_ #define LOBBYMENU_HPP_
#include "base_scene.hpp" //graphics & utilities
#include "image.hpp" #include "image.hpp"
#include "raster_font.hpp" #include "raster_font.hpp"
#include "button.hpp" #include "button.hpp"
#include "config_utility.hpp" #include "config_utility.hpp"
//map
#include "region.hpp"
//network
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
#include "network_packet.hpp" #include "serial_packet.hpp"
#include "serial.hpp" #include "serial.hpp"
//client
#include "base_scene.hpp"
//STL
#include <vector> #include <vector>
class LobbyMenu : public BaseScene { class LobbyMenu : public BaseScene {
@@ -55,7 +62,7 @@ protected:
void KeyDown(SDL_KeyboardEvent const&); void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&);
void HandlePacket(NetworkPacket); void HandlePacket(SerialPacket);
//global //global
ConfigUtility& config; ConfigUtility& config;
@@ -71,8 +78,11 @@ protected:
//server list //server list
struct ServerInformation { struct ServerInformation {
std::string name;
IPaddress address; IPaddress address;
//TODO: version info
std::string name;
int playerCount;
bool compatible;
}; };
std::vector<ServerInformation> serverInfo; std::vector<ServerInformation> serverInfo;
+75
View File
@@ -0,0 +1,75 @@
/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef BBOX_HPP_
#define BBOX_HPP_
#include <type_traits>
#include <stdexcept>
#include <algorithm>
//TODO: This is supposed to interact with the vector
class BBox {
public:
double x, y;
double w, h;
BBox() = default;
BBox(double i, double j, double k, double l): x(i), y(j), w(k), h(l) {};
~BBox() = default;
BBox& operator=(BBox const&) = default;
double Size() {
return std::max(w*h,0.0);
}
bool IsCollision(BBox rhs) {
return not (
x >= rhs.x + rhs.w ||
y >= rhs.y + rhs.h ||
rhs.x >= x + w ||
rhs.y >= y + h
);
}
BBox Intersection(BBox rhs) {
if (!IsCollision(rhs)) {
return {0, 0, 0, 0};
}
BBox ret;
ret.x = std::max(x, rhs.x);
ret.y = std::max(y, rhs.y);
ret.w = std::min(x+w, rhs.x+rhs.w) - ret.x;
ret.h = std::min(y+h, rhs.y+rhs.h) - ret.y;
return ret;
}
double operator[](size_t i) {
if (i >= 4)
throw(std::domain_error("Out of range"));
return *(&x+i);
}
};
//This is explicitly a POD
static_assert(std::is_pod<BBox>::value, "BBox is not a POD");
#endif
+5 -5
View File
@@ -44,17 +44,17 @@ void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t til
void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) { void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) {
Region::type_t tile = 0; Region::type_t tile = 0;
for (register int i = 0; i < region->GetWidth(); ++i) { for (register int i = 0; i < REGION_WIDTH; ++i) {
for (register int j = 0; j < region->GetHeight(); ++j) { for (register int j = 0; j < REGION_HEIGHT; ++j) {
for (register int k = 0; k < region->GetDepth(); ++k) { for (register int k = 0; k < REGION_DEPTH; ++k) {
tile = region->GetTile(i, j, k); tile = region->GetTile(i, j, k);
//0 is invisible //0 is invisible
if (tile == 0) continue; if (tile == 0) continue;
image.SetClipX((tile-1) % XCount * image.GetClipW()); image.SetClipX((tile-1) % XCount * image.GetClipW());
image.SetClipY((tile-1) / XCount * image.GetClipH()); image.SetClipY((tile-1) / XCount * image.GetClipH());
image.DrawTo(dest, image.DrawTo(dest,
region->GetX() + i * image.GetClipW() - camX, (region->GetX() + i) * image.GetClipW() - camX,
region->GetY() + j * image.GetClipH() - camY); (region->GetY() + j) * image.GetClipH() - camY);
} }
} }
} }
@@ -19,29 +19,21 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#include "map_generator.hpp" #include "map_allocator.hpp"
#include <stdexcept> #include <stdexcept>
void BlankGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) { void BlankAllocator::Create(Region** const ptr, int x, int y) {
(*ptr) = new Region(width, height, depth, x, y); (*ptr) = new Region(x, y);
} }
void BlankGenerator::Unload(Region* const ptr) { void BlankAllocator::Unload(Region* const ptr) {
delete ptr; delete ptr;
} }
/*
void PerlinGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
(*ptr) = new Region(width, height, depth, x, y);
}
void PerlinGenerator::Unload(Region* const ptr) { void LuaAllocator::Create(Region** const ptr, int x, int y) {
delete ptr;
}
*/
void LuaGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
//something to work on //something to work on
(*ptr) = new Region(width, height, depth, x, y); (*ptr) = new Region(x, y);
//API hook //API hook
lua_getglobal(state, "Region"); lua_getglobal(state, "Region");
@@ -53,7 +45,7 @@ void LuaGenerator::Create(Region** const ptr, int width, int height, int depth,
lua_pop(state, 1); lua_pop(state, 1);
} }
void LuaGenerator::Unload(Region* const ptr) { void LuaAllocator::Unload(Region* const ptr) {
//API hook //API hook
lua_getglobal(state, "Region"); lua_getglobal(state, "Region");
lua_getfield(state, -1, "Unload"); lua_getfield(state, -1, "Unload");
@@ -19,32 +19,24 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#ifndef MAPGENERATOR_HPP_ #ifndef MAPALLOCATOR_HPP_
#define MAPGENERATOR_HPP_ #define MAPALLOCATOR_HPP_
#include "region.hpp" #include "region.hpp"
#include "lua/lua.hpp" #include "lua/lua.hpp"
class BlankGenerator { class BlankAllocator {
public: public:
void Create(Region** const, int width, int height, int depth, int x, int y); void Create(Region** const, int x, int y);
void Unload(Region* const); void Unload(Region* const);
private: private:
// //
}; };
/*
class PerlinGenerator { class LuaAllocator {
public: public:
void Create(Region** const, int width, int height, int depth, int x, int y); void Create(Region** const, int x, int y);
void Unload(Region* const);
private:
//
};
*/
class LuaGenerator {
public:
void Create(Region** const, int width, int height, int depth, int x, int y);
void Unload(Region* const); void Unload(Region* const);
lua_State* SetLuaState(lua_State* L) { return state = L; } lua_State* SetLuaState(lua_State* L) { return state = L; }
+6 -19
View File
@@ -23,33 +23,20 @@
#include <stdexcept> #include <stdexcept>
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) { void DummyFormat::Load(Region** const ptr, int x, int y) {
//EMPTY //EMPTY
} }
void DummyFormat::Save(Region* const ptr) { void DummyFormat::Save(Region* const ptr) {
//EMPTY //EMPTY
} }
/*
void VerboseFormat::Load(Region** const ptr, int x, int y) {
//TODO
}
void VerboseFormat::Save(Region* const ptr) { void LuaFormat::Load(Region** const ptr, int x, int y) {
//TODO
}
void CompactFormat::Load(Region** const ptr, int x, int y) {
//TODO
}
void CompactFormat::Save(Region* const ptr) {
//TODO
}
*/
void LuaFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
//something to load into //something to load into
(*ptr) = new Region(width, height, depth, x, y);
if (!(*ptr)) {
(*ptr) = new Region(x, y);
}
//API hook //API hook
lua_getglobal(state, "Region"); lua_getglobal(state, "Region");
+4 -23
View File
@@ -30,18 +30,7 @@
class DummyFormat { class DummyFormat {
public: public:
void Load(Region** const, int width, int height, int depth, int x, int y); void Load(Region** const, int x, int y);
void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; }
std::string GetSaveDir() { return saveDir; }
private:
std::string saveDir;
};
/*
class VerboseFormat {
public:
void Load(Region** const, int width, int height, int depth, int x, int y);
void Save(Region* const); void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; } std::string SetSaveDir(std::string s) { return saveDir = s; }
@@ -50,20 +39,12 @@ private:
std::string saveDir; std::string saveDir;
}; };
class CompactFormat { //TODO: verbose save file format
public: //TODO: compact save file format
void Load(Region** const, int width, int height, int depth, int x, int y);
void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; }
std::string GetSaveDir() { return saveDir; }
private:
std::string saveDir;
};
*/
class LuaFormat { class LuaFormat {
public: public:
void Load(Region** const, int width, int height, int depth, int x, int y); void Load(Region** const, int x, int y);
void Save(Region* const); void Save(Region* const);
std::string SetSaveDir(std::string s) { return saveDir = s; } std::string SetSaveDir(std::string s) { return saveDir = s; }
+3 -23
View File
@@ -21,33 +21,13 @@
*/ */
#include "region.hpp" #include "region.hpp"
Region::Region(int argWidth, int argHeight, int argDepth, int argX, int argY): Region::Region(int argX, int argY):
width(argWidth),
height(argHeight),
depth(argDepth),
x(argX), x(argX),
y(argY) y(argY)
{ {
tiles = new type_t**[width]; for (register int i = 0; i < REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH; ++i) {
for (register int i = 0; i < width; ++i) { *(reinterpret_cast<type_t*>(tiles) + i) = 0;
tiles[i] = new type_t*[height];
for (register int j = 0; j < height; ++j) {
tiles[i][j] = new type_t[depth];
for (register int k = 0; k < depth; ++k) {
tiles[i][j][k] = 0;
} }
}
}
}
Region::~Region() {
for (register int i = 0; i < width; ++i) {
for (register int j = 0; j < height; j++) {
delete tiles[i][j];
}
delete tiles[i];
}
delete tiles;
} }
Region::type_t Region::SetTile(int x, int y, int z, type_t v) { Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
+3 -10
View File
@@ -22,7 +22,6 @@
#ifndef REGION_HPP_ #ifndef REGION_HPP_
#define REGION_HPP_ #define REGION_HPP_
//temporary?
#define REGION_WIDTH 20 #define REGION_WIDTH 20
#define REGION_HEIGHT 20 #define REGION_HEIGHT 20
#define REGION_DEPTH 3 #define REGION_DEPTH 3
@@ -32,26 +31,20 @@ public:
typedef unsigned short type_t; typedef unsigned short type_t;
Region() = delete; Region() = delete;
Region(int width, int height, int depth, int x, int y); Region(int x, int y);
~Region(); ~Region() = default;
type_t SetTile(int x, int y, int z, type_t v); type_t SetTile(int x, int y, int z, type_t v);
type_t GetTile(int x, int y, int z); type_t GetTile(int x, int y, int z);
//accessors //accessors
int GetWidth() const { return width; }
int GetHeight() const { return height; }
int GetDepth() const { return depth; }
int GetX() const { return x; } int GetX() const { return x; }
int GetY() const { return y; } int GetY() const { return y; }
private: private:
const int width;
const int height;
const int depth;
const int x; const int x;
const int y; const int y;
type_t*** tiles = nullptr; type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
}; };
#endif #endif
+6 -16
View File
@@ -23,18 +23,6 @@
#include "utility.hpp" #include "utility.hpp"
RegionPagerBase::RegionPagerBase(int argWidth, int argHeight, int argDepth):
regionWidth(argWidth),
regionHeight(argHeight),
regionDepth(argDepth)
{
//EMPTY
}
RegionPagerBase::~RegionPagerBase() {
//EMPTY
}
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) { Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
Region* ptr = GetRegion(x, y); Region* ptr = GetRegion(x, y);
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v); return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
@@ -47,12 +35,10 @@ Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
Region* RegionPagerBase::GetRegion(int x, int y) { Region* RegionPagerBase::GetRegion(int x, int y) {
//snap the coords //snap the coords
x = snapToBase(regionWidth, x); x = snapToBase(REGION_WIDTH, x);
y = snapToBase(regionHeight, y); y = snapToBase(REGION_HEIGHT, y);
//get the region by various means //get the region by various means
//TODO: revert this try/catch point
Region* ptr = nullptr; Region* ptr = nullptr;
ptr = FindRegion(x, y); ptr = FindRegion(x, y);
if (ptr) return ptr; if (ptr) return ptr;
@@ -62,6 +48,10 @@ Region* RegionPagerBase::GetRegion(int x, int y) {
} }
Region* RegionPagerBase::FindRegion(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 //find the region
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) { for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
if ((*it)->GetX() == x && (*it)->GetY() == y) { if ((*it)->GetX() == x && (*it)->GetY() == y) {
+29 -53
View File
@@ -29,9 +29,8 @@
class RegionPagerBase { class RegionPagerBase {
public: public:
RegionPagerBase() = default; RegionPagerBase() {};
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth); virtual ~RegionPagerBase() {};
virtual ~RegionPagerBase();
//tile manipulation //tile manipulation
Region::type_t SetTile(int x, int y, int z, Region::type_t v); Region::type_t SetTile(int x, int y, int z, Region::type_t v);
@@ -47,93 +46,70 @@ public:
virtual Region* SaveRegion(int x, int y) = 0; virtual Region* SaveRegion(int x, int y) = 0;
virtual Region* CreateRegion(int x, int y) = 0; virtual Region* CreateRegion(int x, int y) = 0;
virtual void UnloadRegion(int x, int y) = 0; virtual void UnloadRegion(int x, int y) = 0;
//TODO: delete? //TODO: delete existing regions
//accessors & mutators //accessors & mutators
//NOTE: don't change the sizes mid-program, it will cause issues
int SetRegionWidth(int i) { return regionWidth = i; }
int SetRegionHeight(int i) { return regionHeight = i; }
int SetRegionDepth(int i) { return regionDepth = i; }
int GetRegionWidth() const { return regionWidth; }
int GetRegionHeight() const { return regionHeight; }
int GetRegionDepth() const { return regionDepth; }
std::list<Region*>* GetContainer() { return &regionList; } std::list<Region*>* GetContainer() { return &regionList; }
protected: protected:
int regionWidth;
int regionHeight;
int regionDepth;
std::list<Region*> regionList; std::list<Region*> regionList;
}; };
template<typename MapGenerator, typename MapFileFormat> template<typename Allocator, typename FileFormat>
class RegionPager : public RegionPagerBase { class RegionPager : public RegionPagerBase {
public: public:
RegionPager() = default; RegionPager() {};
RegionPager(int w, int h, int d):
RegionPagerBase(w, h, d)
{
//EMPTY
}
~RegionPager() { ~RegionPager() {
UnloadAll(); UnloadAll();
} }
Region* LoadRegion(int x, int y) { Region* LoadRegion(int x, int y) {
//snap the coords //snap the coords
x = snapToBase(regionWidth, x); x = snapToBase(REGION_WIDTH, x);
y = snapToBase(regionHeight, y); y = snapToBase(REGION_HEIGHT, y);
//load the region if possible //load the region if possible
Region* ptr = nullptr; Region* ptr = nullptr;
format.Load(&ptr, regionWidth, regionHeight, regionDepth, x, y); format.Load(&ptr, x, y);
if (ptr) { if (ptr) {
regionList.push_back(ptr); return PushRegion(ptr);
return ptr;
} }
return nullptr; return nullptr;
} }
Region* SaveRegion(int x, int y) { Region* SaveRegion(int x, int y) {
//snap the coords //snap the coords
x = snapToBase(regionWidth, x); x = snapToBase(REGION_WIDTH, x);
y = snapToBase(regionHeight, y); y = snapToBase(REGION_HEIGHT, y);
//find & save the region //find & save the region
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) { Region* ptr = FindRegion(x, y);
if ((*it)->GetX() == x && (*it)->GetY() == y) { if (ptr) {
format.Save(*it); format.Save(ptr);
return *it;
} }
} return ptr;
return nullptr;
} }
Region* CreateRegion(int x, int y) { Region* CreateRegion(int x, int y) {
//snap the coords //snap the coords
x = snapToBase(regionWidth, x); x = snapToBase(REGION_WIDTH, x);
y = snapToBase(regionHeight, y); y = snapToBase(REGION_HEIGHT, y);
//create and push the object //create and push the object
Region* ptr = nullptr; Region* ptr = nullptr;
generator.Create(&ptr, regionWidth, regionHeight, regionDepth, x, y); allocator.Create(&ptr, x, y);
regionList.push_back(ptr); return PushRegion(ptr);
return ptr;
} }
void UnloadRegion(int x, int y) { void UnloadRegion(int x, int y) {
//snap the coords //snap the coords
x = snapToBase(regionWidth, x); x = snapToBase(REGION_WIDTH, x);
y = snapToBase(regionHeight, y); y = snapToBase(REGION_HEIGHT, y);
//custom loop
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) { for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
if ((*it)->GetX() == x && (*it)->GetY() == y) { if ((*it)->GetX() == x && (*it)->GetY() == y) {
generator.Unload(*it); allocator.Unload(*it);
regionList.erase(it); it = regionList.erase(it);
//reset the loop, because of reasons
it = regionList.begin();
continue; continue;
} }
++it; ++it;
@@ -141,17 +117,17 @@ public:
} }
void UnloadAll() { void UnloadAll() {
for (auto& it : regionList) { for (auto& it : regionList) {
generator.Unload(it); allocator.Unload(it);
} }
regionList.clear(); regionList.clear();
} }
//accessors //accessors
MapGenerator* GetGenerator() { return &generator; } Allocator* GetAllocator() { return &allocator; }
MapFileFormat* GetFormat() { return &format; } FileFormat* GetFormat() { return &format; }
protected: protected:
MapGenerator generator; Allocator allocator;
MapFileFormat format; FileFormat format;
}; };
#endif #endif
+106 -102
View File
@@ -21,7 +21,7 @@
*/ */
#include "serial.hpp" #include "serial.hpp"
#include "map_generator.hpp" #include "map_allocator.hpp"
#include <cstring> #include <cstring>
@@ -29,25 +29,38 @@
//internal serialization functions //internal serialization functions
//------------------------- //-------------------------
void serializeType(NetworkPacket* packet, char* buffer) { void serializeType(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
} }
void serializeServer(NetworkPacket* packet, char* buffer) { void serializeServer(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//server info
//Note: version info serialization goes here
memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE); memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
buffer += PACKET_STRING_SIZE;
memcpy(buffer, &packet->serverInfo.playerCount, sizeof(int));
buffer += sizeof(int);
//map format
memcpy(buffer, &packet->serverInfo.regionWidth, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->serverInfo.regionHeight, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->serverInfo.regionDepth, sizeof(int));
} }
void serializeClient(NetworkPacket* packet, char* buffer) { void serializeClient(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
memcpy(buffer, &packet->clientInfo.index, sizeof(int)); memcpy(buffer, &packet->clientInfo.index, sizeof(int));
} }
void serializePlayer(NetworkPacket* packet, char* buffer) { void serializePlayer(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//indexes //indexes
memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int)); memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int));
@@ -71,17 +84,9 @@ void serializePlayer(NetworkPacket* packet, char* buffer) {
memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double)); memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double));
} }
void serializeRegionFormat(NetworkPacket* packet, char* buffer) { void serializeRegionFormat(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//size
memcpy(buffer, &packet->regionInfo.width, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->regionInfo.height, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->regionInfo.depth, sizeof(int));
buffer += sizeof(int);
//x & y //x & y
memcpy(buffer, &packet->regionInfo.x, sizeof(int)); memcpy(buffer, &packet->regionInfo.x, sizeof(int));
@@ -89,18 +94,10 @@ void serializeRegionFormat(NetworkPacket* packet, char* buffer) {
memcpy(buffer, &packet->regionInfo.y, sizeof(int)); memcpy(buffer, &packet->regionInfo.y, sizeof(int));
} }
void serializeRegionContent(NetworkPacket* packet, char* buffer) { void serializeRegionContent(SerialPacket* packet, char* buffer) {
//format //format
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//size
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetWidth();
buffer += sizeof(int);
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetHeight();
buffer += sizeof(int);
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetDepth();
buffer += sizeof(int);
//x & y //x & y
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetX(); *reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetX();
@@ -109,9 +106,9 @@ void serializeRegionContent(NetworkPacket* packet, char* buffer) {
buffer += sizeof(int); buffer += sizeof(int);
//content //content
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) { for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) { for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) { for (register int k = 0; k < REGION_DEPTH; k++) {
*reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k); *reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k);
buffer += sizeof(Region::type_t); buffer += sizeof(Region::type_t);
} }
@@ -123,25 +120,38 @@ void serializeRegionContent(NetworkPacket* packet, char* buffer) {
//internal deserialization functions //internal deserialization functions
//------------------------- //-------------------------
void deserializeType(NetworkPacket* packet, char* buffer) { void deserializeType(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
} }
void deserializeServer(NetworkPacket* packet, char* buffer) { void deserializeServer(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//server info
//Note: version info deserialization goes here
memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE); memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE);
buffer += PACKET_STRING_SIZE;
memcpy(&packet->serverInfo.playerCount, buffer, sizeof(int));
buffer += sizeof(int);
//map format
memcpy(&packet->serverInfo.regionWidth, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->serverInfo.regionHeight, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->serverInfo.regionDepth, buffer, sizeof(int));
} }
void deserializeClient(NetworkPacket* packet, char* buffer) { void deserializeClient(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
memcpy(&packet->clientInfo.index, buffer, sizeof(int)); memcpy(&packet->clientInfo.index, buffer, sizeof(int));
} }
void deserializePlayer(NetworkPacket* packet, char* buffer) { void deserializePlayer(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//indexes //indexes
memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int)); memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int));
@@ -165,17 +175,9 @@ void deserializePlayer(NetworkPacket* packet, char* buffer) {
memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double)); memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double));
} }
void deserializeRegionFormat(NetworkPacket* packet, char* buffer) { void deserializeRegionFormat(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
buffer += sizeof(NetworkPacket::Type); buffer += sizeof(SerialPacket::Type);
//size
memcpy(&packet->regionInfo.width, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->regionInfo.height, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->regionInfo.depth, buffer, sizeof(int));
buffer += sizeof(int);
//x & y //x & y
memcpy(&packet->regionInfo.x, buffer, sizeof(int)); memcpy(&packet->regionInfo.x, buffer, sizeof(int));
@@ -183,24 +185,26 @@ void deserializeRegionFormat(NetworkPacket* packet, char* buffer) {
memcpy(&packet->regionInfo.y, buffer, sizeof(int)); memcpy(&packet->regionInfo.y, buffer, sizeof(int));
} }
void deserializeRegionContent(NetworkPacket* packet, char* buffer) { void deserializeRegionContent(SerialPacket* packet, char* buffer) {
//format memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
deserializeRegionFormat(packet, buffer); buffer += sizeof(SerialPacket::Type);
buffer += sizeof(int) * 5 + sizeof(NetworkPacket::Type);
//x & y
memcpy(&packet->regionInfo.x, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->regionInfo.y, buffer, sizeof(int));
buffer += sizeof(int);
//content //content
BlankGenerator().Create( BlankAllocator().Create(
&packet->regionInfo.region, &packet->regionInfo.region,
packet->regionInfo.width,
packet->regionInfo.height,
packet->regionInfo.depth,
packet->regionInfo.x, packet->regionInfo.x,
packet->regionInfo.y packet->regionInfo.y
); );
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) { for (register int i = 0; i < REGION_WIDTH; i++) {
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) { for (register int j = 0; j < REGION_HEIGHT; j++) {
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) { for (register int k = 0; k < REGION_DEPTH; k++) {
packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer)); packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
buffer += sizeof(Region::type_t); buffer += sizeof(Region::type_t);
} }
@@ -212,87 +216,87 @@ void deserializeRegionContent(NetworkPacket* packet, char* buffer) {
//the interface functions //the interface functions
//------------------------- //-------------------------
void serialize(NetworkPacket* packet, void* buffer) { void serialize(SerialPacket* packet, void* buffer) {
switch(packet->meta.type) { switch(packet->meta.type) {
//No extra data //No extra data
case NetworkPacket::Type::NONE: case SerialPacket::Type::NONE:
case NetworkPacket::Type::PING: case SerialPacket::Type::PING:
case NetworkPacket::Type::PONG: case SerialPacket::Type::PONG:
case NetworkPacket::Type::BROADCAST_REQUEST: case SerialPacket::Type::BROADCAST_REQUEST:
case NetworkPacket::Type::JOIN_REQUEST: case SerialPacket::Type::JOIN_REQUEST:
case NetworkPacket::Type::SYNCHRONIZE: case SerialPacket::Type::SYNCHRONIZE:
serializeType(packet, reinterpret_cast<char*>(buffer)); serializeType(packet, reinterpret_cast<char*>(buffer));
break; break;
//Server info //Server info
case NetworkPacket::Type::BROADCAST_RESPONSE: case SerialPacket::Type::BROADCAST_RESPONSE:
serializeServer(packet, reinterpret_cast<char*>(buffer)); serializeServer(packet, reinterpret_cast<char*>(buffer));
break; break;
//Client info //Client info
case NetworkPacket::Type::JOIN_RESPONSE: case SerialPacket::Type::JOIN_RESPONSE:
case NetworkPacket::Type::DISCONNECT: case SerialPacket::Type::DISCONNECT:
case NetworkPacket::Type::SHUTDOWN: case SerialPacket::Type::SHUTDOWN:
serializeClient(packet, reinterpret_cast<char*>(buffer)); serializeClient(packet, reinterpret_cast<char*>(buffer));
break; break;
//Player info //Player info
case NetworkPacket::Type::PLAYER_NEW: case SerialPacket::Type::PLAYER_NEW:
case NetworkPacket::Type::PLAYER_DELETE: case SerialPacket::Type::PLAYER_DELETE:
case NetworkPacket::Type::PLAYER_UPDATE: case SerialPacket::Type::PLAYER_UPDATE:
serializePlayer(packet, reinterpret_cast<char*>(buffer)); serializePlayer(packet, reinterpret_cast<char*>(buffer));
break; break;
//region info //region info
case NetworkPacket::Type::REGION_REQUEST: case SerialPacket::Type::REGION_REQUEST:
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer)); serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
break; break;
case NetworkPacket::Type::REGION_CONTENT: case SerialPacket::Type::REGION_CONTENT:
serializeRegionContent(packet, reinterpret_cast<char*>(buffer)); serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
break; break;
} }
} }
void deserialize(NetworkPacket* packet, void* buffer) { void deserialize(SerialPacket* packet, void* buffer) {
//find the type, so that you can actually deserialize the packet! //find the type, so that you can actually deserialize the packet!
deserializeType(packet, reinterpret_cast<char*>(buffer)); deserializeType(packet, reinterpret_cast<char*>(buffer));
switch(packet->meta.type) { switch(packet->meta.type) {
//No extra data //No extra data
case NetworkPacket::Type::NONE: case SerialPacket::Type::NONE:
case NetworkPacket::Type::PING: case SerialPacket::Type::PING:
case NetworkPacket::Type::PONG: case SerialPacket::Type::PONG:
case NetworkPacket::Type::BROADCAST_REQUEST: case SerialPacket::Type::BROADCAST_REQUEST:
case NetworkPacket::Type::JOIN_REQUEST: case SerialPacket::Type::JOIN_REQUEST:
case NetworkPacket::Type::SYNCHRONIZE: case SerialPacket::Type::SYNCHRONIZE:
//NOTHING //NOTHING
break; break;
//Server info //Server info
case NetworkPacket::Type::BROADCAST_RESPONSE: case SerialPacket::Type::BROADCAST_RESPONSE:
deserializeServer(packet, reinterpret_cast<char*>(buffer)); deserializeServer(packet, reinterpret_cast<char*>(buffer));
break; break;
//Client info //Client info
case NetworkPacket::Type::JOIN_RESPONSE: case SerialPacket::Type::JOIN_RESPONSE:
case NetworkPacket::Type::DISCONNECT: case SerialPacket::Type::DISCONNECT:
case NetworkPacket::Type::SHUTDOWN: case SerialPacket::Type::SHUTDOWN:
deserializeClient(packet, reinterpret_cast<char*>(buffer)); deserializeClient(packet, reinterpret_cast<char*>(buffer));
break; break;
//Player info //Player info
case NetworkPacket::Type::PLAYER_NEW: case SerialPacket::Type::PLAYER_NEW:
case NetworkPacket::Type::PLAYER_DELETE: case SerialPacket::Type::PLAYER_DELETE:
case NetworkPacket::Type::PLAYER_UPDATE: case SerialPacket::Type::PLAYER_UPDATE:
deserializePlayer(packet, reinterpret_cast<char*>(buffer)); deserializePlayer(packet, reinterpret_cast<char*>(buffer));
break; break;
//region info //region info
case NetworkPacket::Type::REGION_REQUEST: case SerialPacket::Type::REGION_REQUEST:
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer)); deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
break; break;
case NetworkPacket::Type::REGION_CONTENT: case SerialPacket::Type::REGION_CONTENT:
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer)); deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
break; break;
} }
+8 -7
View File
@@ -22,16 +22,17 @@
#ifndef SERIAL_HPP_ #ifndef SERIAL_HPP_
#define SERIAL_HPP_ #define SERIAL_HPP_
#include "network_packet.hpp" #include "serial_packet.hpp"
/* Sending regions are the largest type of packet /* NOTE: Keep the PACKET_BUFFER_SIZE up to date
* content: width * height * depth * sizoeof(type) * NOTE: REGION_CONTENT is currently the largest type of packet
* map format: sizeof(int) * 5 * map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t)
* map format: sizeof(int) * 2
* metadata: sizeof(metadata) * metadata: sizeof(metadata)
*/ */
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 5 + sizeof(NetworkPacket::Metadata) #define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 2 + sizeof(SerialPacket::Metadata)
void serialize(NetworkPacket* const, void*); void serialize(SerialPacket* const, void*);
void deserialize(NetworkPacket* const, void*); void deserialize(SerialPacket* const, void*);
#endif #endif
@@ -19,8 +19,8 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#ifndef NETWORKPACKET_HPP_ #ifndef SERIALPACKET_HPP_
#define NETWORKPACKET_HPP_ #define SERIALPACKET_HPP_
#include "vector2.hpp" #include "vector2.hpp"
#include "region.hpp" #include "region.hpp"
@@ -31,7 +31,7 @@
#pragma pack(push, 0) #pragma pack(push, 0)
union NetworkPacket { union SerialPacket {
//types of packets //types of packets
enum class Type { enum class Type {
//default: there is something wrong //default: there is something wrong
@@ -79,11 +79,16 @@ union NetworkPacket {
Metadata meta; Metadata meta;
//TODO: version info //TODO: version info
char name[PACKET_STRING_SIZE]; char name[PACKET_STRING_SIZE];
//TODO: player count int playerCount;
//TODO: map format
//map format
int regionWidth;
int regionHeight;
int regionDepth;
}serverInfo; }serverInfo;
//information about the client //information about the client
//TODO: login credentials
struct ClientInformation { struct ClientInformation {
Metadata meta; Metadata meta;
int index; int index;
@@ -94,6 +99,7 @@ union NetworkPacket {
Metadata meta; Metadata meta;
int clientIndex; int clientIndex;
int playerIndex; int playerIndex;
//TODO: should move handle/avatar into clientInfo; these might actually do better during the login system
char handle[PACKET_STRING_SIZE]; char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE]; char avatar[PACKET_STRING_SIZE];
Vector2 position; Vector2 position;
@@ -103,12 +109,12 @@ union NetworkPacket {
//map data //map data
struct RegionInformation { struct RegionInformation {
Metadata meta; Metadata meta;
int width, height, depth, x, y; int x, y;
Region* region; Region* region;
}regionInfo; }regionInfo;
//defaults //defaults
NetworkPacket() { SerialPacket() {
meta.type = Type::NONE; meta.type = Type::NONE;
meta.srcAddress = {0,0}; meta.srcAddress = {0,0};
} }
+3 -6
View File
@@ -37,20 +37,17 @@ static int getTile(lua_State* L) {
} }
static int getWidth(lua_State* L) { static int getWidth(lua_State* L) {
Region* ptr = (Region*)lua_touserdata(L, 1); lua_pushinteger(L, REGION_WIDTH);
lua_pushinteger(L, ptr->GetWidth());
return 1; return 1;
} }
static int getHeight(lua_State* L) { static int getHeight(lua_State* L) {
Region* ptr = (Region*)lua_touserdata(L, 1); lua_pushinteger(L, REGION_HEIGHT);
lua_pushinteger(L, ptr->GetHeight());
return 1; return 1;
} }
static int getDepth(lua_State* L) { static int getDepth(lua_State* L) {
Region* ptr = (Region*)lua_touserdata(L, 1); lua_pushinteger(L, REGION_DEPTH);
lua_pushinteger(L, ptr->GetDepth());
return 1; return 1;
} }
+4 -1
View File
@@ -22,6 +22,7 @@
#ifndef VECTOR2_HPP_ #ifndef VECTOR2_HPP_
#define VECTOR2_HPP_ #define VECTOR2_HPP_
#include <type_traits>
#include <stdexcept> #include <stdexcept>
#include <cmath> #include <cmath>
@@ -29,7 +30,6 @@ class Vector2 {
public: public:
double x, y; double x, y;
//This is explicitly a POD
Vector2() = default; Vector2() = default;
Vector2(double i, double j): x(i), y(j) {}; Vector2(double i, double j): x(i), y(j) {};
~Vector2() = default; ~Vector2() = default;
@@ -112,4 +112,7 @@ template<typename T> Vector2 operator/(T t, Vector2 v) { return v / t; }
template<typename T> bool operator==(T t, Vector2 v) { return v == t; } template<typename T> bool operator==(T t, Vector2 v) { return v == t; }
template<typename T> bool operator!=(T t, Vector2 v) { return v != t; } template<typename T> bool operator!=(T t, Vector2 v) { return v != t; }
//This is explicitly a POD
static_assert(std::is_pod<Vector2>::value, "Vector2 is not a POD");
#endif #endif
+1 -15
View File
@@ -24,12 +24,6 @@
#include <stdexcept> #include <stdexcept>
#include <chrono> #include <chrono>
//-------------------------
//Static declarations
//-------------------------
EditorApplication EditorApplication::instance;
//------------------------- //-------------------------
//Scene headers //Scene headers
//------------------------- //-------------------------
@@ -42,15 +36,7 @@ EditorApplication EditorApplication::instance;
//Public access members //Public access members
//------------------------- //-------------------------
EditorApplication::EditorApplication() { void EditorApplication::Init(int argc, char** argv) {
//
}
EditorApplication::~EditorApplication() {
//
}
void EditorApplication::Init() {
config.Load("rsc\\config.cfg"); config.Load("rsc\\config.cfg");
if (SDL_Init(SDL_INIT_VIDEO)) if (SDL_Init(SDL_INIT_VIDEO))
throw(std::runtime_error("Failed to initialize SDL")); throw(std::runtime_error("Failed to initialize SDL"));
+3 -7
View File
@@ -27,15 +27,11 @@
#include "config_utility.hpp" #include "config_utility.hpp"
class EditorApplication { class EditorApplication {
private:
EditorApplication();
~EditorApplication();
static EditorApplication instance;
public: public:
static EditorApplication* GetInstance() { return &instance; } EditorApplication() = default;
~EditorApplication() = default;
void Init(); void Init(int argc, char** argv);
void Proc(); void Proc();
void Quit(); void Quit();
+1 -6
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013 /* Copyright: (c) Kayne Ruse 2013, 2014
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@@ -55,11 +55,6 @@ EditorScene::EditorScene(ConfigUtility* const arg1):
{"Debug", "Debug On", "Debug Off", "Toggle", "Testificate"} {"Debug", "Debug On", "Debug Off", "Toggle", "Testificate"}
}); });
//setup the map
pager.SetRegionWidth(REGION_WIDTH);
pager.SetRegionHeight(REGION_HEIGHT);
pager.SetRegionDepth(REGION_DEPTH);
//debug //debug
tsheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15); tsheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
for (int i = 0; i < REGION_WIDTH; i++) { for (int i = 0; i < REGION_WIDTH; i++) {
+3 -3
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013 /* Copyright: (c) Kayne Ruse 2013, 2014
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@@ -30,7 +30,7 @@
#include "menu_bar.hpp" #include "menu_bar.hpp"
#include "region_pager.hpp" #include "region_pager.hpp"
#include "map_generator.hpp" #include "map_allocator.hpp"
#include "map_file_format.hpp" #include "map_file_format.hpp"
#include "tile_sheet.hpp" #include "tile_sheet.hpp"
@@ -73,7 +73,7 @@ protected:
int x = 0, y = 0; int x = 0, y = 0;
} camera; } camera;
RegionPager<BlankGenerator, DummyFormat> pager; RegionPager<BlankAllocator, DummyFormat> pager;
TileSheet tsheet; TileSheet tsheet;
}; };
+5 -4
View File
@@ -26,12 +26,13 @@
using namespace std; using namespace std;
int main(int, char**) { int main(int argc, char** argv) {
cout << "Beginning editor" << endl; cout << "Beginning editor" << endl;
try { try {
EditorApplication::GetInstance()->Init(); EditorApplication app;
EditorApplication::GetInstance()->Proc(); app.Init(argc, argv);
EditorApplication::GetInstance()->Quit(); app.Proc();
app.Quit();
} }
catch(exception& e) { catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl; cerr << "Fatal exception thrown: " << e.what() << endl;
+1
View File
@@ -1,3 +1,4 @@
#TODO: The build process needs revising
#for use on Windows: #for use on Windows:
#MKDIR=mkdir #MKDIR=mkdir
+5 -5
View File
@@ -1,7 +1,7 @@
print("Lua script check OK (./rsc)") print("Lua script check OK (./rsc)")
function Region.Create(r) function Region.Create(r)
print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")") -- print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")")
for i = 1, Region.GetWidth(r) do for i = 1, Region.GetWidth(r) do
for j = 1, Region.GetHeight(r) do for j = 1, Region.GetHeight(r) do
if math.abs(i) == math.abs(j) then if math.abs(i) == math.abs(j) then
@@ -11,19 +11,19 @@ function Region.Create(r)
end end
end end
end end
print("done") -- print("done")
end end
function Region.Unload(r) function Region.Unload(r)
print("Region:Unload(r", Region.GetX(r), Region.GetY(r), ")") -- print("Region:Unload(r", Region.GetX(r), Region.GetY(r), ")")
end end
--return true if file loaded, otherwise return false --return true if file loaded, otherwise return false
function Region.Load(r, saveDir) function Region.Load(r, saveDir)
print("Region:Load(r,", saveDir, Region.GetX(r), Region.GetY(r), ")") -- print("Region:Load(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
return false return false
end end
function Region.Save(r, saveDir) function Region.Save(r, saveDir)
print("Region:Save(r,", saveDir, Region.GetX(r), Region.GetY(r), ")") -- print("Region:Save(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
end end
+46 -37
View File
@@ -1,11 +1,13 @@
--TODO: The SQL startup script needs revising
------------------------- -------------------------
--Server --Server
------------------------- -------------------------
CREATE TABLE IF NOT EXISTS UserAccounts ( CREATE TABLE IF NOT EXISTS UserAccounts (
userAccountID INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(30) UNIQUE, username varchar(100) UNIQUE,
password varchar(30), password varchar(100), --NOTE: DO NOT DO THIS!!
blacklisted BIT DEFAULT 0, blacklisted BIT DEFAULT 0,
whitelisted BIT DEFAULT 1 whitelisted BIT DEFAULT 1
); );
@@ -14,31 +16,30 @@ CREATE TABLE IF NOT EXISTS UserAccounts (
--Items --Items
------------------------- -------------------------
CREATE TABLE IF NOT EXISTS GlobalItemList (
globalItemListID INTEGER PRIMARY KEY AUTOINCREMENT,
itemName varchar(30) UNIQUE,
itemImage varchar(30),
type varchar(15), --{'mundane', 'consumable', 'equipment'}
maxStackSize INTEGER, --{1-max; 0 for non-stackable}
maxUniqueCopies INTEGER --{1-max; 0 for unlimited}
);
CREATE TABLE IF NOT EXISTS MundaneItems ( CREATE TABLE IF NOT EXISTS MundaneItems (
mundaneItemID INTEGER PRIMARY KEY AUTOINCREMENT, --metadata
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID) uid INTEGER PRIMARY KEY AUTOINCREMENT,
--holds whatever itemID INTEGER,
stackSize INTEGER DEFAULT 0,
owner INTEGER REFERENCES PlayerCharacters(uid)
); );
CREATE TABLE IF NOT EXISTS Consumables ( CREATE TABLE IF NOT EXISTS Consumables (
consumableID INTEGER PRIMARY KEY AUTOINCREMENT, --metadata
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID) uid INTEGER PRIMARY KEY AUTOINCREMENT,
itemID INTEGER,
stackSize INTEGER DEFAULT 0,
owner INTEGER REFERENCES PlayerCharacters(uid)
--holds all consumable items info (food, potions, etc.) --holds all consumable items info (food, potions, etc.)
); );
CREATE TABLE IF NOT EXISTS Equipment ( CREATE TABLE IF NOT EXISTS Equipment (
equipmentID INTEGER PRIMARY KEY AUTOINCREMENT, --metadata
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID) uid INTEGER PRIMARY KEY AUTOINCREMENT,
itemID INTEGER,
owner INTEGER REFERENCES PlayerCharacters(uid)
--hold all equipment info --hold all equipment info
--stat mods, special effects, etc.
); );
------------------------- -------------------------
@@ -46,28 +47,36 @@ CREATE TABLE IF NOT EXISTS Equipment (
------------------------- -------------------------
CREATE TABLE IF NOT EXISTS PlayerCharacters ( CREATE TABLE IF NOT EXISTS PlayerCharacters (
playerCharacterID INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
name varchar(30) UNIQUE,
--stats --metadata
currentLevel INTEGER DEFAULT 0, handle varchar(100) UNIQUE,
currentExperience INTEGER DEFAULT 0, avatar varchar(100),
maxHealth INTEGER DEFAULT 0, birth timestamp NOT NULL DEFAULT (datetime()),
maxMana INTEGER DEFAULT 0,
currentHealth INTEGER DEFAULT 0, --position
currentMana INTEGER DEFAULT 0, 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, attack INTEGER DEFAULT 0,
defence INTEGER DEFAULT 0, defence INTEGER DEFAULT 0,
--etc. intelligence INTEGER DEFAULT 0,
resistance INTEGER DEFAULT 0,
accuracy REAL DEFAULT 0.0,
evasion REAL DEFAULT 0.0,
luck REAL DEFAULT 0.0,
--equipment --equipment
weapon INTEGER REFERENCES Equipment(equipmentID), weapon INTEGER REFERENCES Equipment(uid),
helmet INTEGER REFERENCES Equipment(equipmentID), helmet INTEGER REFERENCES Equipment(uid),
armour INTEGER REFERENCES Equipment(equipmentID) armour INTEGER REFERENCES Equipment(uid)
--etc. --etc.
); );
CREATE TABLE IF NOT EXISTS PlayerInventoryItems (
characterID INTEGER REFERENCES PlayerCharacters(characterID),
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
);
+24
View File
@@ -0,0 +1,24 @@
/* 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 "client_entry.hpp"
unsigned int ClientEntry::uidCounter;
+32
View File
@@ -0,0 +1,32 @@
/* 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 CLIENTENTRY_HPP_
#define CLIENTENTRY_HPP_
#include "SDL/SDL_net.h"
struct ClientEntry {
IPaddress address;
static unsigned int uidCounter;
};
#endif
+1 -1
View File
@@ -33,7 +33,7 @@ int main(int argc, char** argv) {
try { try {
ServerApplication app; ServerApplication app;
app.Init(argc, argv); app.Init(argc, argv);
app.Loop(); app.Proc();
app.Quit(); app.Quit();
} }
catch(exception& e) { catch(exception& e) {
+24
View File
@@ -0,0 +1,24 @@
/* 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 "player_entry.hpp"
unsigned int PlayerEntry::uidCounter;
+62
View File
@@ -0,0 +1,62 @@
/* 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 PLAYERENTRY_HPP_
#define PLAYERENTRY_HPP_
//POD members
#include "bbox.hpp"
#include "vector2.hpp"
#include <string>
struct PlayerEntry {
//metadata
int clientIndex;
std::string handle;
std::string avatar;
//world position
int mapIndex;
Vector2 position;
Vector2 motion;
BBox bbox;
//statistics
int level;
int exp;
int maxHP;
int health;
int maxMP;
int mana;
int attack;
int defence;
int intelligence;
int resistance;
float accuracy;
float evasion;
float luck;
//uid
static unsigned int uidCounter;
};
#endif
+130 -118
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013 /* Copyright: (c) Kayne Ruse 2013, 2014
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@@ -26,99 +26,79 @@
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <fstream>
using namespace std;
int runSQLScript(sqlite3* db, std::string fname) {
ifstream is(fname);
if (!is.is_open()) {
return -1;
}
string script;
getline(is, script, '\0');
is.close();
//TODO: flesh out this error if needed
if (sqlite3_exec(db, script.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK) {
return -2;
}
return 0;
}
//------------------------- //-------------------------
//Define the public members //Define the public members
//------------------------- //-------------------------
void ServerApplication::Init(int argc, char** argv) { void ServerApplication::Init(int argc, char** argv) {
cout << "Beginning startup" << endl; //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed.
int ret = 0; std::cout << "Beginning startup" << std::endl;
//load config //initial setup
ClientEntry::uidCounter = 0;
PlayerEntry::uidCounter = 0;
config.Load("rsc\\config.cfg"); config.Load("rsc\\config.cfg");
//Init SDL //Init SDL
if (SDL_Init(0)) { if (SDL_Init(0)) {
throw(runtime_error("Failed to initialize SDL")); throw(std::runtime_error("Failed to initialize SDL"));
} }
cout << "Initialized SDL" << endl; std::cout << "Initialized SDL" << std::endl;
//Init SDL_net //Init SDL_net
if (SDLNet_Init()) { if (SDLNet_Init()) {
throw(runtime_error("Failed to initialize SDL_net")); throw(std::runtime_error("Failed to initialize SDL_net"));
} }
network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE); network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE);
cout << "Initialized SDL_net" << endl; std::cout << "Initialized SDL_net" << std::endl;
//Init SQL //Init SQL
ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr); int ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
if (ret != SQLITE_OK || !database) { if (ret != SQLITE_OK || !database) {
throw(runtime_error(string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) )); throw(std::runtime_error(std::string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
} }
cout << "Initialized SQL" << endl; std::cout << "Initialized SQL" << std::endl;
//setup the database //setup the database
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) { if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
throw(runtime_error("Failed to initialize SQL's setup script")); throw(std::runtime_error("Failed to initialize SQL's setup script"));
} }
cout << "Initialized SQL's setup script" << endl; std::cout << "Initialized SQL's setup script" << std::endl;
//lua //lua
luaState = luaL_newstate(); luaState = luaL_newstate();
if (!luaState) { if (!luaState) {
throw(runtime_error("Failed to initialize lua")); throw(std::runtime_error("Failed to initialize lua"));
} }
luaL_openlibs(luaState); luaL_openlibs(luaState);
cout << "Initialized lua" << endl; std::cout << "Initialized lua" << std::endl;
//run the startup script //run the startup script
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) { if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
throw(runtime_error(string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) )); throw(std::runtime_error(std::string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
} }
cout << "Initialized lua's setup script" << endl; std::cout << "Initialized lua's setup script" << std::endl;
//setup the map object //setup the map object
mapPager.SetRegionWidth(REGION_WIDTH); regionPager.GetAllocator()->SetLuaState(luaState);
mapPager.SetRegionHeight(REGION_HEIGHT); regionPager.GetFormat()->SetLuaState(luaState);
mapPager.SetRegionDepth(REGION_DEPTH); //TODO: config parameter
mapPager.GetGenerator()->SetLuaState(luaState); regionPager.GetFormat()->SetSaveDir("save/mapname/");
mapPager.GetFormat()->SetLuaState(luaState);
mapPager.GetFormat()->SetSaveDir("save/mapname/"); std::cout << "Initialized the map system" << std::endl;
//TODO: pass args to the generator & format as needed std::cout << "\tsizeof(SerialPacket): " << sizeof(SerialPacket) << std::endl;
//NOTE: I might need to rearrange the init process so that lua & SQL can interact std::cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << std::endl;
// with the map system as needed.
cout << "Initialized the map system" << endl;
cout << "\tsizeof(NetworkPacket): " << sizeof(NetworkPacket) << endl;
cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << endl;
//finalize the startup //finalize the startup
cout << "Startup completed successfully" << endl; std::cout << "Startup completed successfully" << std::endl;
//debugging //debugging
// //
} }
void ServerApplication::Loop() { void ServerApplication::Proc() {
NetworkPacket packet; SerialPacket packet;
while(running) { while(running) {
//suck in the waiting packets & process them //suck in the waiting packets & process them
while(network.Receive()) { while(network.Receive()) {
@@ -130,16 +110,15 @@ void ServerApplication::Loop() {
HandlePacket(packet); HandlePacket(packet);
} }
//give the computer a break //give the computer a break
//TODO: remove this delay?
SDL_Delay(10); SDL_Delay(10);
} }
} }
void ServerApplication::Quit() { void ServerApplication::Quit() {
cout << "Shutting down" << endl; std::cout << "Shutting down" << std::endl;
//empty the members //empty the members
mapPager.UnloadAll(); regionPager.UnloadAll();
//TODO: player manager
//TODO: client manager
//APIs //APIs
lua_close(luaState); lua_close(luaState);
@@ -147,45 +126,45 @@ void ServerApplication::Quit() {
network.Close(); network.Close();
SDLNet_Quit(); SDLNet_Quit();
SDL_Quit(); SDL_Quit();
cout << "Shutdown finished" << endl; std::cout << "Shutdown finished" << std::endl;
} }
//------------------------- //-------------------------
//Define the uber switch //Define the uber switch
//------------------------- //-------------------------
void ServerApplication::HandlePacket(NetworkPacket packet) { void ServerApplication::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) { switch(packet.meta.type) {
case NetworkPacket::Type::BROADCAST_REQUEST: case SerialPacket::Type::BROADCAST_REQUEST:
HandleBroadcastRequest(packet); HandleBroadcastRequest(packet);
break; break;
case NetworkPacket::Type::JOIN_REQUEST: case SerialPacket::Type::JOIN_REQUEST:
HandleJoinRequest(packet); HandleJoinRequest(packet);
break; break;
case NetworkPacket::Type::DISCONNECT: case SerialPacket::Type::DISCONNECT:
HandleDisconnect(packet); HandleDisconnect(packet);
break; break;
case NetworkPacket::Type::SYNCHRONIZE: case SerialPacket::Type::SYNCHRONIZE:
HandleSynchronize(packet); HandleSynchronize(packet);
break; break;
case NetworkPacket::Type::SHUTDOWN: case SerialPacket::Type::SHUTDOWN:
HandleShutdown(packet); HandleShutdown(packet);
break; break;
case NetworkPacket::Type::PLAYER_NEW: case SerialPacket::Type::PLAYER_NEW:
HandlePlayerNew(packet); HandlePlayerNew(packet);
break; break;
case NetworkPacket::Type::PLAYER_DELETE: case SerialPacket::Type::PLAYER_DELETE:
HandlePlayerDelete(packet); HandlePlayerDelete(packet);
break; break;
case NetworkPacket::Type::PLAYER_UPDATE: case SerialPacket::Type::PLAYER_UPDATE:
HandlePlayerUpdate(packet); HandlePlayerUpdate(packet);
break; break;
case NetworkPacket::Type::REGION_REQUEST: case SerialPacket::Type::REGION_REQUEST:
HandleRegionRequest(packet); HandleRegionRequest(packet);
break; break;
//handle errors //handle errors
default: default:
throw(runtime_error("Unknown NetworkPacket::Type encountered")); throw(std::runtime_error("Unknown SerialPacket::Type encountered"));
break; break;
} }
} }
@@ -194,73 +173,91 @@ void ServerApplication::HandlePacket(NetworkPacket packet) {
//Handle various network input //Handle various network input
//------------------------- //-------------------------
void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) { void ServerApplication::HandleBroadcastRequest(SerialPacket packet) {
//send back the server's metadata //send back the server's metadata
packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE; packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
//pack the data
//TODO: version info //TODO: version info
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
//TODO: player count packet.serverInfo.playerCount = playerMap.size();
packet.serverInfo.regionWidth = REGION_WIDTH;
packet.serverInfo.regionHeight = REGION_HEIGHT;
packet.serverInfo.regionDepth = REGION_DEPTH;
//send the data
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE); network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
} }
void ServerApplication::HandleJoinRequest(NetworkPacket packet) { void ServerApplication::HandleJoinRequest(SerialPacket packet) {
//register the new client //register the new client
ClientEntry c; ClientEntry newClient;
c.address = packet.meta.srcAddress; newClient.address = packet.meta.srcAddress;
clientMap[clientCounter] = c; clientMap[ClientEntry::uidCounter] = newClient;
//send the client their info //send the client their index
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
packet.meta.type = SerialPacket::Type::JOIN_RESPONSE;
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE; packet.clientInfo.index = ClientEntry::uidCounter;
packet.clientInfo.index = clientCounter;
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&clientMap[clientCounter].address, buffer, PACKET_BUFFER_SIZE); //bounce this packet
network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE);
//finished this routine //finished this routine
clientCounter++; ClientEntry::uidCounter++;
cout << "Connect, total: " << clientMap.size() << endl; std::cout << "Connect, total: " << clientMap.size() << std::endl;
} }
void ServerApplication::HandleDisconnect(NetworkPacket packet) { void ServerApplication::HandleDisconnect(SerialPacket packet) {
//disconnect the specified client
//TODO: authenticate who is disconnecting/kicking //TODO: authenticate who is disconnecting/kicking
//disconnect the specified client
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE); network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
clientMap.erase(packet.clientInfo.index); clientMap.erase(packet.clientInfo.index);
//delete players from all clients //prep the delete packet
NetworkPacket delPacket; SerialPacket delPacket;
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE; delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE;
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool { //TODO: can this use DeletePlayer() instead?
//delete server and client side players
erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntry> it) -> bool {
//find the internal players to delete //find the internal players to delete
if (it.second.clientIndex == packet.clientInfo.index) { if (it.second.clientIndex == packet.clientInfo.index) {
delPacket.playerInfo.playerIndex = it.first;
//send the delete player command to all clients //send the delete player command to all clients
delPacket.playerInfo.playerIndex = it.first;
PumpPacket(delPacket); PumpPacket(delPacket);
//delete this player object
return true; return true;
} }
//don't delete this player object
return false; return false;
}); });
//finished this routine //finished this routine
cout << "Disconnect, total: " << clientMap.size() << endl; std::cout << "Disconnect, total: " << clientMap.size() << std::endl;
} }
void ServerApplication::HandleSynchronize(NetworkPacket packet) { void ServerApplication::HandleSynchronize(SerialPacket packet) {
//send all the server's data to this client
//TODO: compensate for large distances //TODO: compensate for large distances
NetworkPacket newPacket;
//send all the server's data to this client
SerialPacket newPacket;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//TODO: syncronize the map?
//players //players
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE; newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE;
for (auto& it : playerMap) { for (auto& it : playerMap) {
//TODO: update this for the expanded PlayerEntry structure
newPacket.playerInfo.playerIndex = it.first; newPacket.playerInfo.playerIndex = it.first;
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
@@ -271,87 +268,102 @@ void ServerApplication::HandleSynchronize(NetworkPacket packet) {
} }
} }
void ServerApplication::HandleShutdown(NetworkPacket packet) { void ServerApplication::HandleShutdown(SerialPacket packet) {
//end the server //end the server
running = false; running = false;
//disconnect all clients //disconnect all clients
packet.meta.type = NetworkPacket::Type::DISCONNECT; packet.meta.type = SerialPacket::Type::DISCONNECT;
PumpPacket(packet); PumpPacket(packet);
//finished this routine //finished this routine
cout << "Shutdown signal accepted" << endl; std::cout << "Shutdown signal accepted" << std::endl;
} }
void ServerApplication::HandlePlayerNew(NetworkPacket packet) { void ServerApplication::HandlePlayerNew(SerialPacket packet) {
//create the new player object //register the new PlayerEntry
//NOTE: assigning each field one-by-one so adding or moving a field doesn't break this code
PlayerEntry newPlayer; PlayerEntry newPlayer;
//metadata
newPlayer.clientIndex = packet.playerInfo.clientIndex; newPlayer.clientIndex = packet.playerInfo.clientIndex;
newPlayer.mapIndex = 0;
newPlayer.handle = packet.playerInfo.handle; newPlayer.handle = packet.playerInfo.handle;
newPlayer.avatar = packet.playerInfo.avatar; newPlayer.avatar = packet.playerInfo.avatar;
//position
newPlayer.mapIndex = 0;
newPlayer.position = {0,0}; newPlayer.position = {0,0};
newPlayer.motion = {0,0}; newPlayer.motion = {0,0};
newPlayer.bbox = {0, 0, 0, 0};
//stats
//TODO
//push this player //push this player
playerMap[playerCounter] = newPlayer; playerMap[PlayerEntry::uidCounter] = newPlayer;
//send the client their info //send the client their info
packet.playerInfo.playerIndex = playerCounter; packet.playerInfo.playerIndex = PlayerEntry::uidCounter;
packet.playerInfo.position = playerMap[playerCounter].position; packet.playerInfo.position = newPlayer.position;
packet.playerInfo.motion = playerMap[playerCounter].motion; packet.playerInfo.motion = newPlayer.motion;
//actually send to everyone //actually send to everyone
PumpPacket(packet); PumpPacket(packet);
//finish this routine //finish this routine
playerCounter++; PlayerEntry::uidCounter++;
} }
void ServerApplication::HandlePlayerDelete(NetworkPacket packet) { //TODO: differentiate between delete and unload
void ServerApplication::HandlePlayerDelete(SerialPacket packet) {
//TODO: authenticate who is deleting this player
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) { if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
throw(std::runtime_error("Cannot delete a non-existant player")); throw(std::runtime_error("Cannot delete a non-existant player"));
} }
//delete players //TODO: remove the deleted player from the database?
erase_if(playerMap, [&](pair<int, PlayerEntry> it) -> bool {
//prep the delete packet
SerialPacket delPacket;
delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE;
//delete the specified playerEntry
erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntry> it) -> bool {
//find the specified PlayerEntry
if (it.first == packet.playerInfo.playerIndex) { if (it.first == packet.playerInfo.playerIndex) {
NetworkPacket delPacket;
//data to delete one specific player
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
delPacket.playerInfo.playerIndex = it.first;
//send to all //send to all
delPacket.playerInfo.playerIndex = it.first;
PumpPacket(delPacket); PumpPacket(delPacket);
//delete this player
return true; return true;
} }
//skip this player
return false; return false;
}); });
} }
void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) { void ServerApplication::HandlePlayerUpdate(SerialPacket packet) {
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) { if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
throw(std::runtime_error("Cannot update a non-existant player")); throw(std::runtime_error("Cannot update a non-existant player"));
} }
//server is the slave to the clients, but only for now //TODO: the server needs it's own movement system too
playerMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position; playerMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position;
playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion; playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
PumpPacket(packet); PumpPacket(packet);
} }
void ServerApplication::HandleRegionRequest(NetworkPacket packet) { void ServerApplication::HandleRegionRequest(SerialPacket packet) {
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
packet.meta.type = NetworkPacket::Type::REGION_CONTENT; packet.meta.type = SerialPacket::Type::REGION_CONTENT;
packet.regionInfo.region = mapPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y); packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE); network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
} }
void ServerApplication::PumpPacket(NetworkPacket packet) { void ServerApplication::PumpPacket(SerialPacket packet) {
//I don't really like this, but it'll do for now //I don't really like this, but it'll do for now
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer); serialize(&packet, buffer);
+32 -45
View File
@@ -1,4 +1,4 @@
/* Copyright: (c) Kayne Ruse 2013 /* Copyright: (c) Kayne Ruse 2013, 2014
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@@ -22,13 +22,18 @@
#ifndef SERVERAPPLICATION_HPP_ #ifndef SERVERAPPLICATION_HPP_
#define SERVERAPPLICATION_HPP_ #define SERVERAPPLICATION_HPP_
//server specific stuff
#include "server_utility.hpp"
#include "client_entry.hpp"
#include "player_entry.hpp"
//maps //maps
#include "map_generator.hpp" #include "map_allocator.hpp"
#include "map_file_format.hpp" #include "map_file_format.hpp"
#include "region_pager.hpp" #include "region_pager.hpp"
//networking //networking
#include "network_packet.hpp" #include "serial_packet.hpp"
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
#include "serial.hpp" #include "serial.hpp"
@@ -43,20 +48,6 @@
//STL //STL
#include <map> #include <map>
#include <string>
struct ClientEntry {
IPaddress address;
};
struct PlayerEntry {
int clientIndex;
int mapIndex;
std::string handle;
std::string avatar;
Vector2 position;
Vector2 motion;
};
//The main application class //The main application class
class ServerApplication { class ServerApplication {
@@ -66,46 +57,42 @@ public:
~ServerApplication() = default; ~ServerApplication() = default;
void Init(int argc, char** argv); void Init(int argc, char** argv);
void Loop(); void Proc();
void Quit(); void Quit();
private: private:
void HandlePacket(NetworkPacket); void HandlePacket(SerialPacket);
//high cohesion utility functions //high cohesion utility functions
void HandleBroadcastRequest(NetworkPacket); void HandleBroadcastRequest(SerialPacket);
void HandleJoinRequest(NetworkPacket); void HandleJoinRequest(SerialPacket);
void HandleDisconnect(NetworkPacket); void HandleDisconnect(SerialPacket);
void HandleSynchronize(NetworkPacket); void HandleSynchronize(SerialPacket);
void HandleShutdown(NetworkPacket); void HandleShutdown(SerialPacket);
void HandlePlayerNew(NetworkPacket); void HandlePlayerNew(SerialPacket);
void HandlePlayerDelete(NetworkPacket); void HandlePlayerDelete(SerialPacket);
void HandlePlayerUpdate(NetworkPacket); void HandlePlayerUpdate(SerialPacket);
void HandleRegionRequest(NetworkPacket); void HandleRegionRequest(SerialPacket);
void PumpPacket(NetworkPacket); //TODO: a function that only sends to players in a certain proximity
void PumpPacket(SerialPacket);
//APIs
UDPNetworkUtility network;
sqlite3* database = nullptr;
lua_State* luaState = nullptr;
//server tables
std::map<unsigned int, ClientEntry> clientMap;
std::map<unsigned int, PlayerEntry> playerMap;
//maps //maps
RegionPager<LuaGenerator, LuaFormat> mapPager; //TODO: I need to handle multiple map objects
RegionPager<LuaAllocator, LuaFormat> regionPager;
//networking
UDPNetworkUtility network;
//database
sqlite3* database = nullptr;
//lua
lua_State* luaState = nullptr;
//misc //misc
bool running = true; bool running = true;
ConfigUtility config; ConfigUtility config;
std::map<int, ClientEntry> clientMap;
std::map<int, PlayerEntry> playerMap;
int clientCounter = 0;
int playerCounter = 0;
}; };
#endif #endif
+50
View File
@@ -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 "server_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;
}
+31
View File
@@ -0,0 +1,31 @@
/* Copyright: (c) Kayne Ruse 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef SERVERUTILITY_HPP_
#define SERVERUTILITY_HPP_
#include "sqlite3/sqlite3.h"
#include <string>
int runSQLScript(sqlite3* db, std::string fname, int (*callback)(void*,int,char**,char**) = nullptr, void* argPtr = nullptr);
#endif