Remade Snapshot logic from component based to entity based.
This commit is contained in:
@@ -64,6 +64,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);
|
||||||
|
|||||||
@@ -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");
|
||||||
@@ -176,66 +176,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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,35 +175,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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user