Merge remote-tracking branch 'origin/Networking'
# Conflicts: # src/Engine/Network/Client.cpp # src/Game/Systems/WeaponSystem.cpp
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef EComponentDeleted_h__
|
||||||
|
#define EComponentDeleted_h__
|
||||||
|
|
||||||
|
#include "../Common.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ComponentDeleted : Event
|
||||||
|
{
|
||||||
|
EntityID Entity;
|
||||||
|
std::string ComponentType;
|
||||||
|
// True if the component was deleted as a result of the entity it was attached to being deleted
|
||||||
|
bool Cascaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef EEntityDeleted_h__
|
||||||
|
#define EEntityDeleted_h__
|
||||||
|
|
||||||
|
#include "Event.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
struct EntityDeleted : Event
|
||||||
|
{
|
||||||
|
EntityID DeletedEntity;
|
||||||
|
// True if the entity deletion was triggered because the entity's parent was deleted before it
|
||||||
|
bool Cascaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,11 +5,15 @@
|
|||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "ObjectPool.h"
|
#include "ObjectPool.h"
|
||||||
#include "ComponentPool.h"
|
#include "ComponentPool.h"
|
||||||
|
#include "EventBroker.h"
|
||||||
|
|
||||||
class World
|
class World
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
World() = default;
|
World() = default;
|
||||||
|
World(EventBroker* eventBroker)
|
||||||
|
: m_EventBroker(eventBroker)
|
||||||
|
{ }
|
||||||
~World();
|
~World();
|
||||||
|
|
||||||
// Create empty entity
|
// Create empty entity
|
||||||
@@ -46,6 +50,7 @@ public:
|
|||||||
std::string GetName(EntityID entity) const;
|
std::string GetName(EntityID entity) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
EventBroker* m_EventBroker = nullptr;
|
||||||
EntityID m_CurrentEntityID = 0;
|
EntityID m_CurrentEntityID = 0;
|
||||||
|
|
||||||
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
||||||
@@ -55,6 +60,7 @@ private:
|
|||||||
std::unordered_map<EntityID, std::string> m_EntityNames;
|
std::unordered_map<EntityID, std::string> m_EntityNames;
|
||||||
|
|
||||||
EntityID generateEntityID();
|
EntityID generateEntityID();
|
||||||
|
void deleteEntityRecursive(EntityID entity, bool cascaded = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -79,6 +79,8 @@ private:
|
|||||||
void parsePing();
|
void parsePing();
|
||||||
void parseKick();
|
void parseKick();
|
||||||
void parsePlayersSpawned(Packet& packet);
|
void parsePlayersSpawned(Packet& packet);
|
||||||
|
void parseEntityDeletion(Packet& packet);
|
||||||
|
void parseComponentDeletion(Packet& packet);
|
||||||
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
||||||
void parseSnapshot(Packet& packet);
|
void parseSnapshot(Packet& packet);
|
||||||
void identifyPacketLoss();
|
void identifyPacketLoss();
|
||||||
@@ -92,6 +94,7 @@ private:
|
|||||||
// Returns if server EntityID exist in map
|
// Returns if server EntityID exist in map
|
||||||
bool serverClientMapsHasEntity(EntityID serverEntityID);
|
bool serverClientMapsHasEntity(EntityID serverEntityID);
|
||||||
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
||||||
|
void deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ enum class MessageType
|
|||||||
PlayerConnected,
|
PlayerConnected,
|
||||||
BecomePlayer,
|
BecomePlayer,
|
||||||
Kick,
|
Kick,
|
||||||
OnPlayerSpawned
|
OnPlayerSpawned,
|
||||||
|
EntityDeleted,
|
||||||
|
ComponentDeleted
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "Core/EPlayerDamage.h"
|
#include "Core/EPlayerDamage.h"
|
||||||
#include "Network/EPlayerDisconnected.h"
|
#include "Network/EPlayerDisconnected.h"
|
||||||
#include "Core/EPlayerSpawned.h"
|
#include "Core/EPlayerSpawned.h"
|
||||||
|
#include "Core/EEntityDeleted.h"
|
||||||
|
#include "Core/EComponentDeleted.h"
|
||||||
|
|
||||||
class Server : public Network
|
class Server : public Network
|
||||||
{
|
{
|
||||||
@@ -63,6 +65,7 @@ private:
|
|||||||
void send(Packet& packet);
|
void send(Packet& packet);
|
||||||
void broadcast(Packet& packet);
|
void broadcast(Packet& packet);
|
||||||
void sendSnapshot();
|
void sendSnapshot();
|
||||||
|
void addChildrenToPacket(Packet& packet, EntityID entityID);
|
||||||
void sendPing();
|
void sendPing();
|
||||||
void checkForTimeOuts();
|
void checkForTimeOuts();
|
||||||
void disconnect(UserID user);
|
void disconnect(UserID user);
|
||||||
@@ -82,6 +85,10 @@ private:
|
|||||||
bool OnInputCommand(const Events::InputCommand& e);
|
bool OnInputCommand(const Events::InputCommand& e);
|
||||||
EventRelay<Server, Events::PlayerSpawned> m_EPlayerSpawned;
|
EventRelay<Server, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||||
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||||
|
EventRelay<Server, Events::EntityDeleted> m_EEntityDeleted;
|
||||||
|
bool OnEntityDeleted(const Events::EntityDeleted& e);
|
||||||
|
EventRelay<Server, Events::ComponentDeleted> m_EComponentDeleted;
|
||||||
|
bool OnComponentDeleted(const Events::ComponentDeleted& e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,3 +22,4 @@ X=EditorToggleTransformSpace
|
|||||||
C=ConnectToServer
|
C=ConnectToServer
|
||||||
N=SwitchToServer
|
N=SwitchToServer
|
||||||
M=SwitchToClient
|
M=SwitchToClient
|
||||||
|
P=SwitchToPlayer
|
||||||
+61
-32
@@ -1,4 +1,6 @@
|
|||||||
#include "Core/World.h"
|
#include "Core/World.h"
|
||||||
|
#include "Core/EEntityDeleted.h"
|
||||||
|
#include "Core/EComponentDeleted.h"
|
||||||
|
|
||||||
World::~World()
|
World::~World()
|
||||||
{
|
{
|
||||||
@@ -21,37 +23,7 @@ EntityID World::CreateEntity(EntityID parent /*= 0*/)
|
|||||||
|
|
||||||
void World::DeleteEntity(EntityID entity)
|
void World::DeleteEntity(EntityID entity)
|
||||||
{
|
{
|
||||||
// Delete components
|
deleteEntityRecursive(entity, false);
|
||||||
for (auto& pair : m_ComponentPools) {
|
|
||||||
auto& pool = pair.second;
|
|
||||||
if (pool->KnowsEntity(entity)) {
|
|
||||||
auto& c = pool->GetByEntity(entity);
|
|
||||||
pool->Delete(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through children
|
|
||||||
std::vector<EntityID> childrenToDelete;
|
|
||||||
auto children = m_EntityChildren.equal_range(entity);
|
|
||||||
for (auto it = children.first; it != children.second; ++it) {
|
|
||||||
childrenToDelete.push_back(it->second);
|
|
||||||
}
|
|
||||||
for (auto& child : childrenToDelete) {
|
|
||||||
DeleteEntity(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID parent = m_EntityParents.at(entity);
|
|
||||||
m_EntityParents.erase(entity);
|
|
||||||
auto parentChildren = m_EntityChildren.equal_range(parent);
|
|
||||||
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
|
||||||
if (it->second == entity) {
|
|
||||||
m_EntityChildren.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Erase potential name
|
|
||||||
m_EntityNames.erase(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::ValidEntity(EntityID entity) const
|
bool World::ValidEntity(EntityID entity) const
|
||||||
@@ -96,7 +68,15 @@ void World::DeleteComponent(EntityID entity, const std::string& componentType)
|
|||||||
{
|
{
|
||||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||||
ComponentWrapper c = pool->GetByEntity(entity);
|
ComponentWrapper c = pool->GetByEntity(entity);
|
||||||
return pool->Delete(c);
|
pool->Delete(c);
|
||||||
|
|
||||||
|
if (m_EventBroker != nullptr) {
|
||||||
|
Events::ComponentDeleted e;
|
||||||
|
e.Entity = entity;
|
||||||
|
e.ComponentType = componentType;
|
||||||
|
e.Cascaded = false;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ComponentPool* World::GetComponents(const std::string& componentType)
|
const ComponentPool* World::GetComponents(const std::string& componentType)
|
||||||
@@ -155,3 +135,52 @@ EntityID World::generateEntityID()
|
|||||||
return m_CurrentEntityID++;
|
return m_CurrentEntityID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::deleteEntityRecursive(EntityID entity, bool cascaded /*= false*/)
|
||||||
|
{
|
||||||
|
if (m_EventBroker != nullptr) {
|
||||||
|
Events::EntityDeleted e;
|
||||||
|
e.DeletedEntity = entity;
|
||||||
|
e.Cascaded = cascaded;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete components
|
||||||
|
for (auto& pair : m_ComponentPools) {
|
||||||
|
auto& pool = pair.second;
|
||||||
|
if (pool->KnowsEntity(entity)) {
|
||||||
|
auto& c = pool->GetByEntity(entity);
|
||||||
|
pool->Delete(c);
|
||||||
|
if (m_EventBroker != nullptr) {
|
||||||
|
Events::ComponentDeleted e;
|
||||||
|
e.Entity = entity;
|
||||||
|
e.ComponentType = pair.first;
|
||||||
|
e.Cascaded = true;
|
||||||
|
m_EventBroker->Publish(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through children
|
||||||
|
std::vector<EntityID> childrenToDelete;
|
||||||
|
auto children = m_EntityChildren.equal_range(entity);
|
||||||
|
for (auto it = children.first; it != children.second; ++it) {
|
||||||
|
childrenToDelete.push_back(it->second);
|
||||||
|
}
|
||||||
|
for (auto& child : childrenToDelete) {
|
||||||
|
deleteEntityRecursive(child, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityID parent = m_EntityParents.at(entity);
|
||||||
|
m_EntityParents.erase(entity);
|
||||||
|
auto parentChildren = m_EntityChildren.equal_range(parent);
|
||||||
|
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
||||||
|
if (it->second == entity) {
|
||||||
|
m_EntityChildren.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase potential name
|
||||||
|
m_EntityNames.erase(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
|||||||
{
|
{
|
||||||
Network::initialize();
|
Network::initialize();
|
||||||
|
|
||||||
// Asumes root node is EntityID 0
|
// Asumes root node is EntityID_Invalid
|
||||||
insertIntoServerClientMaps(0, 0);
|
insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid);
|
||||||
// Init timer
|
// Init timer
|
||||||
m_TimeSinceSentInputs = std::clock();
|
m_TimeSinceSentInputs = std::clock();
|
||||||
// Default is local host
|
// Default is local host
|
||||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||||
int port = config->Get<int>("Networking.Port", 13);
|
int port = config->Get<int>("Networking.Port", 27666);
|
||||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
||||||
// Set up network stream
|
// Set up network stream
|
||||||
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
||||||
@@ -96,6 +96,12 @@ void Client::parseMessageType(Packet& packet)
|
|||||||
case MessageType::OnPlayerSpawned:
|
case MessageType::OnPlayerSpawned:
|
||||||
parsePlayersSpawned(packet);
|
parsePlayersSpawned(packet);
|
||||||
break;
|
break;
|
||||||
|
case MessageType::EntityDeleted:
|
||||||
|
parseEntityDeletion(packet);
|
||||||
|
break;
|
||||||
|
case MessageType::ComponentDeleted:
|
||||||
|
parseComponentDeletion(packet);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -142,6 +148,25 @@ void Client::parsePlayersSpawned(Packet& packet)
|
|||||||
m_EventBroker->Publish(e);
|
m_EventBroker->Publish(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::parseEntityDeletion(Packet & packet)
|
||||||
|
{
|
||||||
|
EntityID entityToDelete = packet.ReadPrimitive<EntityID>();
|
||||||
|
EntityID localEntity = m_ServerIDToClientID.at(entityToDelete);
|
||||||
|
if (m_World->ValidEntity(localEntity)) {
|
||||||
|
m_World->DeleteEntity(localEntity);
|
||||||
|
deleteFromServerClientMaps(entityToDelete, localEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::parseComponentDeletion(Packet & packet)
|
||||||
|
{
|
||||||
|
EntityID entity = packet.ReadPrimitive<EntityID>();
|
||||||
|
std::string componentType = packet.ReadString();
|
||||||
|
if (m_World->HasComponent(entity, componentType)) {
|
||||||
|
m_World->DeleteComponent(m_ServerIDToClientID.at(entity), componentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fields with strings will not work right now
|
// Fields with strings will not work right now
|
||||||
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
||||||
{
|
{
|
||||||
@@ -176,66 +201,50 @@ void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, co
|
|||||||
|
|
||||||
void Client::parseSnapshot(Packet& packet)
|
void Client::parseSnapshot(Packet& packet)
|
||||||
{
|
{
|
||||||
std::string componentType = packet.ReadString();
|
|
||||||
while (packet.DataReadSize() < packet.Size()) {
|
while (packet.DataReadSize() < packet.Size()) {
|
||||||
// HACK
|
EntityID serverEntityID = packet.ReadPrimitive<EntityID>();
|
||||||
std::string entityName = packet.ReadString();
|
EntityID serverParentID = packet.ReadPrimitive<EntityID>();
|
||||||
// Components EntityID
|
std::string serverEntityName = packet.ReadString();
|
||||||
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
|
int ammountOfComponents = packet.ReadPrimitive<int>();
|
||||||
// HACK
|
for (int i = 0; i < ammountOfComponents; i++) {
|
||||||
m_World->SetName(receivedEntityID, entityName);
|
std::string componentType = packet.ReadString();
|
||||||
// Parents EntityID
|
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||||
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
|
if (serverClientMapsHasEntity(serverEntityID)) {
|
||||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||||
// Check if the received EntityID is mapped to one of our local EntityIDs
|
// Update entity
|
||||||
if (serverClientMapsHasEntity(receivedEntityID)) {
|
if (m_World->HasComponent(localEntityID, componentType)) {
|
||||||
// Get the local EntityID
|
// Update component
|
||||||
EntityID entityID = m_ServerIDToClientID.at(receivedEntityID);
|
if (componentType == "Transform") {
|
||||||
// Check if the component exists
|
// Interpolate only transform components
|
||||||
if (m_World->HasComponent(entityID, componentType)) {
|
InterpolateFields(packet, componentInfo, localEntityID, componentType);
|
||||||
// If the entity and the component exists update it
|
} else {
|
||||||
if (componentType == "Transform") {
|
// Set component values
|
||||||
InterpolateFields(packet, componentInfo, entityID, componentType);
|
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
updateFields(packet, componentInfo, entityID, componentType);
|
// Has entity but no component
|
||||||
|
m_World->AttachComponent(localEntityID, componentType);
|
||||||
|
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||||
}
|
}
|
||||||
// if entity exists but not the component
|
|
||||||
} else {
|
} else {
|
||||||
// Create component
|
// Create Entity and component
|
||||||
m_World->AttachComponent(entityID, componentType);
|
EntityID newLocalEntityID;
|
||||||
// Copy data to newly created component
|
if (serverParentID == EntityID_Invalid) {
|
||||||
updateFields(packet, componentInfo, entityID, componentType);
|
newLocalEntityID = m_World->CreateEntity(EntityID_Invalid);
|
||||||
|
} else {
|
||||||
|
newLocalEntityID = m_World->CreateEntity(m_ServerIDToClientID.at(serverParentID));
|
||||||
|
}
|
||||||
|
m_World->SetName(newLocalEntityID, serverEntityName);
|
||||||
|
insertIntoServerClientMaps(serverEntityID, newLocalEntityID);
|
||||||
|
m_World->AttachComponent(newLocalEntityID, componentType);
|
||||||
|
updateFields(packet, componentInfo, newLocalEntityID, componentType);
|
||||||
}
|
}
|
||||||
// If the entity dosent exist nor the component
|
|
||||||
} else {
|
|
||||||
// Create Entity
|
|
||||||
// If entity dosen't exist
|
|
||||||
EntityID newEntityID = m_World->CreateEntity();
|
|
||||||
insertIntoServerClientMaps(receivedEntityID, newEntityID);
|
|
||||||
// Check if EntityIDs are out of sync
|
|
||||||
if (newEntityID != receivedEntityID) {
|
|
||||||
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
|
|
||||||
same as the one sent by server (EntityIDs are out of sync)");
|
|
||||||
}
|
|
||||||
// Create component
|
|
||||||
m_World->AttachComponent(newEntityID, componentType);
|
|
||||||
// Copy data to newly created component
|
|
||||||
updateFields(packet, componentInfo, newEntityID, componentType);
|
|
||||||
}
|
}
|
||||||
|
// Parent logic
|
||||||
// Parent Logic
|
// This should be enough beacause we know that the entities arives in pre-order (there will always be a parent)
|
||||||
// Don't need to check if receivedEntityID is mapped. (It should have been set)
|
if (serverParentID != EntityID_Invalid) {
|
||||||
if (receivedParentEntityID != std::numeric_limits<EntityID>::max()) {
|
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||||
if (serverClientMapsHasEntity(receivedParentEntityID)) {
|
m_World->SetParent(localEntityID, m_ServerIDToClientID.at(serverParentID));
|
||||||
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.at(receivedParentEntityID));
|
|
||||||
// If Parent dosen't exist create one and map receivedParentEntityID to it.
|
|
||||||
} else {
|
|
||||||
// Create the new parent and add it to map
|
|
||||||
EntityID newParentEntityID = m_World->CreateEntity();
|
|
||||||
insertIntoServerClientMaps(receivedParentEntityID, newParentEntityID);
|
|
||||||
// Set the newly created Entity as parent.
|
|
||||||
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), newParentEntityID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +335,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
|
|||||||
|
|
||||||
bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
|
bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||||
{
|
{
|
||||||
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
|
Packet packet(MessageType::OnPlayerDamage, m_SendPacketID);
|
||||||
packet.WritePrimitive(e.Damage);
|
packet.WritePrimitive(e.Damage);
|
||||||
packet.WritePrimitive(e.Player.ID);
|
packet.WritePrimitive(e.Player.ID);
|
||||||
send(packet);
|
send(packet);
|
||||||
@@ -386,12 +395,26 @@ void Client::becomePlayer()
|
|||||||
|
|
||||||
bool Client::clientServerMapsHasEntity(EntityID clientEntityID)
|
bool Client::clientServerMapsHasEntity(EntityID clientEntityID)
|
||||||
{
|
{
|
||||||
return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end();
|
if (m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end()) {
|
||||||
|
if (m_World->ValidEntity(clientEntityID)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EntityID serverEntityID = m_ClientIDToServerID.at(clientEntityID);
|
||||||
|
deleteFromServerClientMaps(serverEntityID, clientEntityID);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::serverClientMapsHasEntity(EntityID serverEntityID)
|
bool Client::serverClientMapsHasEntity(EntityID serverEntityID)
|
||||||
{
|
{
|
||||||
return m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end();
|
if (m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end()) {
|
||||||
|
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||||
|
if (m_World->ValidEntity(localEntityID)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
deleteFromServerClientMaps(serverEntityID, localEntityID);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
|
void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
|
||||||
@@ -400,3 +423,9 @@ void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID client
|
|||||||
m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID));
|
m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
|
||||||
|
{
|
||||||
|
m_ServerIDToClientID.erase(serverEntityID);
|
||||||
|
m_ClientIDToServerID.erase(clientEntityID);
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ void Server::Start(World* world, EventBroker* eventBroker)
|
|||||||
// Subscribe to events
|
// Subscribe to events
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
|
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted);
|
||||||
|
EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted);
|
||||||
for (size_t i = 0; i < m_MaxConnections; i++) {
|
for (size_t i = 0; i < m_MaxConnections; i++) {
|
||||||
m_PlayerDefinitions[i].StopTime = std::clock();
|
m_PlayerDefinitions[i].StopTime = std::clock();
|
||||||
}
|
}
|
||||||
@@ -175,35 +177,51 @@ void Server::broadcast(Packet& packet)
|
|||||||
// Send snapshot fields
|
// Send snapshot fields
|
||||||
void Server::sendSnapshot()
|
void Server::sendSnapshot()
|
||||||
{
|
{
|
||||||
// Should time this
|
Packet packet(MessageType::Snapshot);
|
||||||
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
addChildrenToPacket(packet, EntityID_Invalid);
|
||||||
for (auto& it : worldComponentPools) {
|
broadcast(packet);
|
||||||
Packet packet(MessageType::Snapshot);
|
}
|
||||||
ComponentPool* componentPool = it.second;
|
|
||||||
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
|
||||||
|
|
||||||
// Component Type
|
void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
|
||||||
packet.WriteString(componentInfo.Name);
|
{
|
||||||
for (auto& componentWrapper : *componentPool) {
|
auto itPair = m_World->GetChildren(entityID);
|
||||||
// HACK: Send entity name
|
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
||||||
packet.WriteString(m_World->GetName(componentWrapper.EntityID));
|
// Loop through every child
|
||||||
// Components EntityID
|
for (auto it = itPair.first; it != itPair.second; it++) {
|
||||||
packet.WritePrimitive(componentWrapper.EntityID);
|
EntityID childEntityID = it->second;
|
||||||
// Parents EntityID
|
// Write EntityID and parentsID and Entity name
|
||||||
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID));
|
packet.WritePrimitive(childEntityID);
|
||||||
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
packet.WritePrimitive(entityID);
|
||||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
|
packet.WriteString(m_World->GetName(childEntityID));
|
||||||
if (fieldInfo.Type == "string") {
|
// Write components to child
|
||||||
std::string& value = componentWrapper[componentField];
|
int numberOfComponents = 0;
|
||||||
packet.WriteString(value);
|
for (auto& i : worldComponentPools) {
|
||||||
} else {
|
if (i.second->KnowsEntity(childEntityID)) {
|
||||||
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
|
numberOfComponents++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Write how many components should be read
|
||||||
|
packet.WritePrimitive(numberOfComponents);
|
||||||
|
for (auto& i : worldComponentPools) {
|
||||||
|
// If the entity exist in the pool
|
||||||
|
if (i.second->KnowsEntity(childEntityID)) {
|
||||||
|
ComponentWrapper componentWrapper = i.second->GetByEntity(childEntityID);
|
||||||
|
// ComponentType
|
||||||
|
packet.WriteString(componentWrapper.Info.Name);
|
||||||
|
// Loop through fields
|
||||||
|
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
||||||
|
ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField);
|
||||||
|
if (fieldInfo.Type == "string") {
|
||||||
|
std::string& value = componentWrapper[componentField];
|
||||||
|
packet.WriteString(value);
|
||||||
|
} else {
|
||||||
|
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (packet.Size() > packet.HeaderSize() + componentInfo.Name.size()) {
|
// Go to to your children
|
||||||
broadcast(packet);
|
addChildrenToPacket(packet, childEntityID);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,3 +467,24 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e)
|
|||||||
send(e.PlayerID, packet);
|
send(e.PlayerID, packet);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::OnEntityDeleted(const Events::EntityDeleted & e)
|
||||||
|
{
|
||||||
|
if (!e.Cascaded) {
|
||||||
|
Packet packet = Packet(MessageType::EntityDeleted);
|
||||||
|
packet.WritePrimitive<EntityID>(e.DeletedEntity);
|
||||||
|
broadcast(packet);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::OnComponentDeleted(const Events::ComponentDeleted & e)
|
||||||
|
{
|
||||||
|
if (!e.Cascaded) {
|
||||||
|
Packet packet = Packet(MessageType::ComponentDeleted);
|
||||||
|
packet.WritePrimitive<EntityID>(e.Entity);
|
||||||
|
packet.WriteString(e.ComponentType);
|
||||||
|
broadcast(packet);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -57,7 +57,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
m_FrameStack->Height = m_Renderer->Resolution().Height;
|
m_FrameStack->Height = m_Renderer->Resolution().Height;
|
||||||
|
|
||||||
// Create a world
|
// Create a world
|
||||||
m_World = new World();
|
m_World = new World(m_EventBroker);
|
||||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||||
if (!mapToLoad.empty()) {
|
if (!mapToLoad.empty()) {
|
||||||
auto file = ResourceManager::Load<EntityFile>(mapToLoad);
|
auto file = ResourceManager::Load<EntityFile>(mapToLoad);
|
||||||
@@ -77,7 +77,7 @@ Game::Game(int argc, char* argv[])
|
|||||||
// All systems with orderlevel 0 will be updated first.
|
// All systems with orderlevel 0 will be updated first.
|
||||||
unsigned int updateOrderLevel = 0;
|
unsigned int updateOrderLevel = 0;
|
||||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
//m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
||||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker)
|
|||||||
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||||
{
|
{
|
||||||
//if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity)
|
//if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity)
|
||||||
ComponentWrapper player = m_World->GetComponent(component.EntityID, "Player");
|
|
||||||
double maxHealth = (double)component["MaxHealth"];
|
double maxHealth = (double)component["MaxHealth"];
|
||||||
|
|
||||||
//process the DeltaHealthVector and change the entitys health accordingly
|
//process the DeltaHealthVector and change the entitys health accordingly
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
|
|||||||
|
|
||||||
bool WeaponSystem::OnShoot(const Events::Shoot& eShoot) {
|
bool WeaponSystem::OnShoot(const Events::Shoot& eShoot) {
|
||||||
// Screen center, based on current resolution!
|
// Screen center, based on current resolution!
|
||||||
|
//TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||||
Rectangle screenResolution = m_Renderer->Resolution();
|
Rectangle screenResolution = m_Renderer->Resolution();
|
||||||
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user