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.
This commit is contained in:
@@ -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
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#pragma pack(push, 0)
|
#pragma pack(push, 0)
|
||||||
|
|
||||||
|
//TODO: update the code here to match the entity code
|
||||||
union NetworkPacket {
|
union NetworkPacket {
|
||||||
//types of packets
|
//types of packets
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
|||||||
+4
-1
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/* 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.hpp"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
//This is explicitly a POD
|
||||||
|
static_assert(std::is_pod<Client>::value, "Client is not a POD");
|
||||||
|
|
||||||
|
unsigned int Client::uidCounter;
|
||||||
@@ -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 CLIENT_HPP_
|
||||||
|
#define CLIENT_HPP_
|
||||||
|
|
||||||
|
#include "SDL/SDL_net.h"
|
||||||
|
|
||||||
|
struct Client {
|
||||||
|
IPaddress address;
|
||||||
|
static unsigned int uidCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/* 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 "entity.hpp"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
//This is explicitly a POD
|
||||||
|
static_assert(std::is_pod<Entity>::value, "Entity is not a POD");
|
||||||
|
|
||||||
|
unsigned int Entity::uidCounter;
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* 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 ENTITY_HPP_
|
||||||
|
#define ENTITY_HPP_
|
||||||
|
|
||||||
|
//POD members
|
||||||
|
#include "vector2.hpp"
|
||||||
|
#include "bbox.hpp"
|
||||||
|
|
||||||
|
struct Entity {
|
||||||
|
enum Type {
|
||||||
|
PLAYER,
|
||||||
|
PORTAL,
|
||||||
|
ITEMS,
|
||||||
|
CHEST,
|
||||||
|
DOOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
int mapIndex;
|
||||||
|
Vector2 position;
|
||||||
|
Vector2 motion;
|
||||||
|
BBox bbox;
|
||||||
|
unsigned int externalID;
|
||||||
|
static unsigned int uidCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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_entity.hpp"
|
||||||
|
|
||||||
|
unsigned int PlayerEntity::uidCounter;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* 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 PLAYERENTITY_HPP_
|
||||||
|
#define PLAYERENTITY_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct PlayerEntity {
|
||||||
|
//metadata
|
||||||
|
int clientIndex;
|
||||||
|
std::string handle;
|
||||||
|
std::string avatar;
|
||||||
|
|
||||||
|
//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
|
||||||
+120
-63
@@ -51,9 +51,11 @@ int runSQLScript(sqlite3* db, std::string fname) {
|
|||||||
|
|
||||||
void ServerApplication::Init(int argc, char** argv) {
|
void ServerApplication::Init(int argc, char** argv) {
|
||||||
cout << "Beginning startup" << endl;
|
cout << "Beginning startup" << endl;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
//load config
|
//initial setup
|
||||||
|
Client::uidCounter = 0;
|
||||||
|
Entity::uidCounter = 0;
|
||||||
|
PlayerEntity::uidCounter = 0;
|
||||||
config.Load("rsc\\config.cfg");
|
config.Load("rsc\\config.cfg");
|
||||||
|
|
||||||
//Init SDL
|
//Init SDL
|
||||||
@@ -70,7 +72,7 @@ void ServerApplication::Init(int argc, char** argv) {
|
|||||||
cout << "Initialized SDL_net" << endl;
|
cout << "Initialized SDL_net" << 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(runtime_error(string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
|
||||||
}
|
}
|
||||||
@@ -97,12 +99,13 @@ void ServerApplication::Init(int argc, char** argv) {
|
|||||||
cout << "Initialized lua's setup script" << endl;
|
cout << "Initialized lua's setup script" << endl;
|
||||||
|
|
||||||
//setup the map object
|
//setup the map object
|
||||||
mapPager.SetRegionWidth(REGION_WIDTH);
|
regionPager.SetRegionWidth(REGION_WIDTH);
|
||||||
mapPager.SetRegionHeight(REGION_HEIGHT);
|
regionPager.SetRegionHeight(REGION_HEIGHT);
|
||||||
mapPager.SetRegionDepth(REGION_DEPTH);
|
regionPager.SetRegionDepth(REGION_DEPTH);
|
||||||
mapPager.GetGenerator()->SetLuaState(luaState);
|
regionPager.GetGenerator()->SetLuaState(luaState);
|
||||||
mapPager.GetFormat()->SetLuaState(luaState);
|
regionPager.GetFormat()->SetLuaState(luaState);
|
||||||
mapPager.GetFormat()->SetSaveDir("save/mapname/");
|
//TODO: config parameter
|
||||||
|
regionPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||||
//TODO: pass args to the generator & format as needed
|
//TODO: pass args to the generator & format as needed
|
||||||
//NOTE: I might need to rearrange the init process so that lua & SQL can interact
|
//NOTE: I might need to rearrange the init process so that lua & SQL can interact
|
||||||
// with the map system as needed.
|
// with the map system as needed.
|
||||||
@@ -130,6 +133,7 @@ void ServerApplication::Loop() {
|
|||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
//give the computer a break
|
//give the computer a break
|
||||||
|
//TODO: remove this?
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,9 +141,7 @@ void ServerApplication::Loop() {
|
|||||||
void ServerApplication::Quit() {
|
void ServerApplication::Quit() {
|
||||||
cout << "Shutting down" << endl;
|
cout << "Shutting down" << 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);
|
||||||
@@ -207,44 +209,54 @@ void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
|
|||||||
|
|
||||||
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
||||||
//register the new client
|
//register the new client
|
||||||
ClientEntry c;
|
clientMap[Client::uidCounter] = {packet.meta.srcAddress};
|
||||||
c.address = packet.meta.srcAddress;
|
|
||||||
clientMap[clientCounter] = c;
|
|
||||||
|
|
||||||
//send the client their info
|
//send the client their index
|
||||||
char buffer[PACKET_BUFFER_SIZE];
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
||||||
packet.clientInfo.index = clientCounter;
|
packet.clientInfo.index = Client::uidCounter;
|
||||||
serialize(&packet, buffer);
|
serialize(&packet, buffer);
|
||||||
|
|
||||||
network.Send(&clientMap[clientCounter].address, buffer, PACKET_BUFFER_SIZE);
|
//bounce this packet
|
||||||
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
//finished this routine
|
//finished this routine
|
||||||
clientCounter++;
|
Client::uidCounter++;
|
||||||
cout << "Connect, total: " << clientMap.size() << endl;
|
cout << "Connect, total: " << clientMap.size() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
void ServerApplication::HandleDisconnect(NetworkPacket 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;
|
NetworkPacket delPacket;
|
||||||
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||||
|
|
||||||
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
|
//TODO: can this use DeletePlayer() instead?
|
||||||
|
//delete PlayerEntity, Entity, and client side players
|
||||||
|
erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntity> playerIter) -> bool {
|
||||||
//find the internal players to delete
|
//find the internal players to delete
|
||||||
if (it.second.clientIndex == packet.clientInfo.index) {
|
if (playerIter.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 = playerIter.first;
|
||||||
PumpPacket(delPacket);
|
PumpPacket(delPacket);
|
||||||
|
|
||||||
|
//erase the corresponding Entity
|
||||||
|
erase_if(entityMap, [&](std::pair<unsigned int, Entity> entityIter) -> bool {
|
||||||
|
return entityIter.second.type == Entity::Type::PLAYER && entityIter.second.externalID == playerIter.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
//delete this player object
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//don't delete this player object
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -253,19 +265,40 @@ void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
||||||
//send all the server's data to this client
|
|
||||||
//TODO: compensate for large distances
|
//TODO: compensate for large distances
|
||||||
|
|
||||||
|
//send all the server's data to this client
|
||||||
NetworkPacket newPacket;
|
NetworkPacket newPacket;
|
||||||
char buffer[PACKET_BUFFER_SIZE];
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
//players
|
//TODO: map?
|
||||||
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
|
||||||
for (auto& it : playerMap) {
|
//entities
|
||||||
newPacket.playerInfo.playerIndex = it.first;
|
for (auto& it : entityMap) {
|
||||||
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
//what are we sending?
|
||||||
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
switch(it.second.type) {
|
||||||
newPacket.playerInfo.position = it.second.position;
|
case Entity::Type::PLAYER:
|
||||||
newPacket.playerInfo.motion = it.second.motion;
|
//TODO: update the network code to match the entity code
|
||||||
|
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
|
newPacket.playerInfo.playerIndex = it.first;
|
||||||
|
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", playerMap[it.second.externalID].handle.c_str());
|
||||||
|
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", playerMap[it.second.externalID].avatar.c_str());
|
||||||
|
newPacket.playerInfo.position = it.second.position;
|
||||||
|
newPacket.playerInfo.motion = it.second.motion;
|
||||||
|
break;
|
||||||
|
case Entity::Type::PORTAL:
|
||||||
|
//TODO
|
||||||
|
break;
|
||||||
|
case Entity::Type::ITEMS:
|
||||||
|
//TODO
|
||||||
|
break;
|
||||||
|
case Entity::Type::CHEST:
|
||||||
|
//TODO
|
||||||
|
break;
|
||||||
|
case Entity::Type::DOOR:
|
||||||
|
//TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
serialize(&newPacket, buffer);
|
serialize(&newPacket, buffer);
|
||||||
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
@@ -284,47 +317,70 @@ void ServerApplication::HandleShutdown(NetworkPacket packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
||||||
//create the new player object
|
//register the new Entity
|
||||||
PlayerEntry newPlayer;
|
entityMap[Entity::uidCounter] = {
|
||||||
newPlayer.clientIndex = packet.playerInfo.clientIndex;
|
Entity::Type::PLAYER,
|
||||||
newPlayer.mapIndex = 0;
|
0,
|
||||||
newPlayer.handle = packet.playerInfo.handle;
|
{0, 0},
|
||||||
newPlayer.avatar = packet.playerInfo.avatar;
|
{0, 0},
|
||||||
newPlayer.position = {0,0};
|
{0, 0, 0, 0},
|
||||||
newPlayer.motion = {0,0};
|
PlayerEntity::uidCounter
|
||||||
|
};
|
||||||
|
|
||||||
//push this player
|
//register the new PlayerEntity
|
||||||
playerMap[playerCounter] = newPlayer;
|
playerMap[PlayerEntity::uidCounter] = {
|
||||||
|
packet.playerInfo.clientIndex,
|
||||||
|
packet.playerInfo.handle,
|
||||||
|
packet.playerInfo.avatar,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
//send the client their info
|
//send the client their info
|
||||||
packet.playerInfo.playerIndex = playerCounter;
|
packet.playerInfo.playerIndex = PlayerEntity::uidCounter;
|
||||||
packet.playerInfo.position = playerMap[playerCounter].position;
|
packet.playerInfo.position = entityMap[Entity::uidCounter].position;
|
||||||
packet.playerInfo.motion = playerMap[playerCounter].motion;
|
packet.playerInfo.motion = entityMap[Entity::uidCounter].motion;
|
||||||
|
|
||||||
//actually send to everyone
|
//actually send to everyone
|
||||||
PumpPacket(packet);
|
PumpPacket(packet);
|
||||||
|
|
||||||
//finish this routine
|
//finish this routine
|
||||||
playerCounter++;
|
Entity::uidCounter++;
|
||||||
|
PlayerEntity::uidCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
||||||
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
//TODO: remove this?
|
||||||
|
if (entityMap.find(packet.playerInfo.playerIndex) == entityMap.end()) {
|
||||||
throw(std::runtime_error("Cannot delete a non-existant player"));
|
throw(std::runtime_error("Cannot delete a non-existant player"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//delete players
|
//prep the delete packet
|
||||||
erase_if(playerMap, [&](pair<int, PlayerEntry> it) -> bool {
|
NetworkPacket delPacket;
|
||||||
if (it.first == packet.playerInfo.playerIndex) {
|
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||||
NetworkPacket delPacket;
|
|
||||||
|
|
||||||
//data to delete one specific player
|
|
||||||
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
|
||||||
delPacket.playerInfo.playerIndex = it.first;
|
|
||||||
|
|
||||||
|
//delete the specified Entity, PlayerEntity
|
||||||
|
erase_if(entityMap, [&](std::pair<unsigned int, Entity> entityIter) -> bool {
|
||||||
|
//find the specified Entity
|
||||||
|
if (entityIter.first == packet.playerInfo.playerIndex) {
|
||||||
//send to all
|
//send to all
|
||||||
|
delPacket.playerInfo.playerIndex = entityIter.first;
|
||||||
PumpPacket(delPacket);
|
PumpPacket(delPacket);
|
||||||
|
//erase matching PlayerEntity
|
||||||
|
erase_if(playerMap, [&](std::pair<unsigned int, PlayerEntity> playerIter) -> bool {
|
||||||
|
return playerIter.first == entityIter.second.externalID;
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -332,13 +388,14 @@ void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
||||||
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
//TODO: Lookup the reference once, and operate on that instead of looking it up 3 times
|
||||||
|
if (entityMap.find(packet.playerInfo.playerIndex) == entityMap.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;
|
entityMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position;
|
||||||
playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
|
entityMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
|
||||||
|
|
||||||
PumpPacket(packet);
|
PumpPacket(packet);
|
||||||
}
|
}
|
||||||
@@ -346,7 +403,7 @@ void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
|||||||
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
||||||
char buffer[PACKET_BUFFER_SIZE];
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
packet.meta.type = NetworkPacket::Type::REGION_CONTENT;
|
packet.meta.type = NetworkPacket::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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
#ifndef SERVERAPPLICATION_HPP_
|
#ifndef SERVERAPPLICATION_HPP_
|
||||||
#define SERVERAPPLICATION_HPP_
|
#define SERVERAPPLICATION_HPP_
|
||||||
|
|
||||||
|
//server specific stuff
|
||||||
|
#include "client.hpp"
|
||||||
|
#include "entity.hpp"
|
||||||
|
#include "player_entity.hpp"
|
||||||
|
|
||||||
//maps
|
//maps
|
||||||
#include "map_generator.hpp"
|
#include "map_generator.hpp"
|
||||||
#include "map_file_format.hpp"
|
#include "map_file_format.hpp"
|
||||||
@@ -45,19 +50,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#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 {
|
||||||
public:
|
public:
|
||||||
@@ -83,29 +75,26 @@ private:
|
|||||||
void HandlePlayerUpdate(NetworkPacket);
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
void HandleRegionRequest(NetworkPacket);
|
void HandleRegionRequest(NetworkPacket);
|
||||||
|
|
||||||
|
//TODO: a function that sends to players in a certain proximity
|
||||||
void PumpPacket(NetworkPacket);
|
void PumpPacket(NetworkPacket);
|
||||||
|
|
||||||
//maps
|
//APIs
|
||||||
RegionPager<LuaGenerator, LuaFormat> mapPager;
|
|
||||||
|
|
||||||
//networking
|
|
||||||
UDPNetworkUtility network;
|
UDPNetworkUtility network;
|
||||||
|
|
||||||
//database
|
|
||||||
sqlite3* database = nullptr;
|
sqlite3* database = nullptr;
|
||||||
|
|
||||||
//lua
|
|
||||||
lua_State* luaState = nullptr;
|
lua_State* luaState = nullptr;
|
||||||
|
|
||||||
|
//server tables
|
||||||
|
std::map<unsigned int, Client> clientMap;
|
||||||
|
std::map<unsigned int, Entity> entityMap;
|
||||||
|
std::map<unsigned int, PlayerEntity> playerMap;
|
||||||
|
|
||||||
|
//maps
|
||||||
|
//TODO: I need to handle multiple map objects
|
||||||
|
RegionPager<LuaGenerator, LuaFormat> regionPager;
|
||||||
|
|
||||||
//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
|
||||||
|
|||||||
Reference in New Issue
Block a user