Skip to content

Commit

Permalink
Networking: Better entity GUID coherence across disconnects
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Aug 7, 2022
1 parent eba0b4f commit cf224a6
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 15 deletions.
1 change: 1 addition & 0 deletions schema/Welcome.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace nier;
table Welcome {
guid: ulong;
isMasterClient: bool;
highestEntityGuid: uint;
}

root_type Welcome;
17 changes: 16 additions & 1 deletion server/nier/Welcome.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ func makeEntityPacketBytes(guid uint32, id nier.PacketType, data []uint8) []uint
var connections = make(map[enet.Peer]*Connection)
var clients = make(map[*Connection]*Client)
var connectionCount uint64 = 0
var highestEntityGuid uint32 = 0

type ActiveEntity struct {
guid uint32
Expand Down Expand Up @@ -403,6 +404,7 @@ func main() {
nier.WelcomeStart(builder)
nier.WelcomeAddGuid(builder, client.guid)
nier.WelcomeAddIsMasterClient(builder, client.isMasterClient)
nier.WelcomeAddHighestEntityGuid(builder, highestEntityGuid)
return nier.WelcomeEnd(builder)
})

Expand Down Expand Up @@ -533,6 +535,10 @@ func main() {
spawnInfo := &nier.EntitySpawnParams{}
flatbuffers.GetRootAs(entityPkt.DataBytes(), 0, spawnInfo)

if entityPkt.Guid() > highestEntityGuid {
highestEntityGuid = entityPkt.Guid()
}

entities[entityPkt.Guid()] = new(ActiveEntity)
entities[entityPkt.Guid()].guid = entityPkt.Guid()
entities[entityPkt.Guid()].spawnInfo = spawnInfo
Expand Down
11 changes: 10 additions & 1 deletion src/mods/multiplayer/EntitySync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ void NetworkEntity::startAnimationHook(Entity* ent, uint32_t anim, uint32_t vari
original(ent, anim, variant, a3, a4);
}

EntitySync::EntitySync() {
EntitySync::EntitySync(uint32_t highestGuid)
: m_maxGuid{highestGuid}
{
g_entitySync = this;
}

Expand Down Expand Up @@ -137,6 +139,13 @@ std::shared_ptr<NetworkEntity> EntitySync::addEntity(EntityContainer* entity, ui
spdlog::info("Adding entity {:x} with guid {}", (uintptr_t)entity, guid);

scoped_lock _(m_mapMutex);

// This allows someone taking over as master client
// to not screw up any previously spawned entities.
if (guid > m_maxGuid) {
m_maxGuid = guid;
}

auto& networkEntity = m_networkEntities[guid];

if (networkEntity == nullptr || networkEntity->getEntity() != entity) {
Expand Down
2 changes: 1 addition & 1 deletion src/mods/multiplayer/EntitySync.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class NetworkEntity {

class EntitySync {
public:
EntitySync();
EntitySync(uint32_t highestGuid = 0);

void onEntityCreated(EntityContainer* entity, EntitySpawnParams* data);
void onEntityDeleted(EntityContainer* entity);
Expand Down
20 changes: 11 additions & 9 deletions src/mods/multiplayer/NierClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void NierClient::think() {
//*npc->getPosition() = *(Vector3f*)&data.position();
}

m_networkEntities.think();
m_networkEntities->think();
}
}

Expand Down Expand Up @@ -459,7 +459,7 @@ void NierClient::sendEntityData(uint32_t guid, Entity* entity) {

builder.Finish(builder.CreateStruct(newData));

m_networkEntities.processEntityData(guid, &newData);
m_networkEntities->processEntityData(guid, &newData);
sendEntityPacket(nier::PacketType_ID_ENTITY_DATA, guid, builder.GetBufferPointer(), builder.GetSize());
}

Expand All @@ -482,11 +482,11 @@ void NierClient::onEntityCreated(EntityContainer* entity, EntitySpawnParams* dat
return;
}

m_networkEntities.onEntityCreated(entity, data);
m_networkEntities->onEntityCreated(entity, data);
}

void NierClient::onEntityDeleted(EntityContainer* entity) {
m_networkEntities.onEntityDeleted(entity);
m_networkEntities->onEntityDeleted(entity);
}

void NierClient::sendHello() {
Expand Down Expand Up @@ -597,10 +597,12 @@ bool NierClient::handleWelcome(const nier::Packet* packet) {

m_isMasterClient = welcome->isMasterClient();
m_guid = welcome->guid();
const auto highestGuid = welcome->highestEntityGuid();

spdlog::info("Welcome packet received, isMasterClient: {}, guid: {}", m_isMasterClient, m_guid);

m_networkEntities.onEnterServer(m_isMasterClient);
m_networkEntities = std::make_unique<EntitySync>(highestGuid);
m_networkEntities->onEnterServer(m_isMasterClient);

return true;
}
Expand Down Expand Up @@ -754,7 +756,7 @@ bool NierClient::handleCreateEntity(const nier::EntityPacket* packet) {
//ent->entity->setSuspend(false);

spdlog::info(" Entity spawned @ {:x}", (uintptr_t)ent);
auto newNetworkEnt = m_networkEntities.addEntity(ent, packet->guid());
auto newNetworkEnt = m_networkEntities->addEntity(ent, packet->guid());

if (newNetworkEnt != nullptr) {
spdlog::info(" Network entity created");
Expand All @@ -770,7 +772,7 @@ bool NierClient::handleCreateEntity(const nier::EntityPacket* packet) {
bool NierClient::handleDestroyEntity(const nier::EntityPacket* packet) {
spdlog::info("Destroy entity packet received");

m_networkEntities.removeEntity(packet->guid());
m_networkEntities->removeEntity(packet->guid());

return true;
}
Expand All @@ -779,7 +781,7 @@ bool NierClient::handleEntityData(const nier::EntityPacket* packet) {
spdlog::info("Entity data packet received");

const auto entityData = flatbuffers::GetRoot<nier::EntityData>(packet->data()->data());
m_networkEntities.processEntityData(packet->guid(), entityData);
m_networkEntities->processEntityData(packet->guid(), entityData);

return true;
}
Expand All @@ -788,7 +790,7 @@ bool NierClient::handleEntityAnimationStart(const nier::EntityPacket* packet) {
spdlog::info("Entity animation start packet received");

const auto guid = packet->guid();
auto entityNetworked = m_networkEntities.getNetworkEntityFromGuid(guid);
auto entityNetworked = m_networkEntities->getNetworkEntityFromGuid(guid);

if (entityNetworked == nullptr) {
spdlog::error(" (nullptr) Entity data packet received for unknown entity {}", guid);
Expand Down
2 changes: 1 addition & 1 deletion src/mods/multiplayer/NierClient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class NierClient : public enetpp::client {
bool handleAnimationStart(const nier::PlayerPacket* packet);
bool handleButtons(const nier::PlayerPacket* packet);

EntitySync m_networkEntities{};
std::unique_ptr<EntitySync> m_networkEntities{};

std::recursive_mutex m_mtx{};
std::recursive_mutex m_playersMtx{};
Expand Down
14 changes: 12 additions & 2 deletions src/mods/multiplayer/schema/Packets_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,18 +764,23 @@ struct Welcome FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef WelcomeBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_GUID = 4,
VT_ISMASTERCLIENT = 6
VT_ISMASTERCLIENT = 6,
VT_HIGHESTENTITYGUID = 8
};
uint64_t guid() const {
return GetField<uint64_t>(VT_GUID, 0);
}
bool isMasterClient() const {
return GetField<uint8_t>(VT_ISMASTERCLIENT, 0) != 0;
}
uint32_t highestEntityGuid() const {
return GetField<uint32_t>(VT_HIGHESTENTITYGUID, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, VT_GUID) &&
VerifyField<uint8_t>(verifier, VT_ISMASTERCLIENT) &&
VerifyField<uint32_t>(verifier, VT_HIGHESTENTITYGUID) &&
verifier.EndTable();
}
};
Expand All @@ -790,6 +795,9 @@ struct WelcomeBuilder {
void add_isMasterClient(bool isMasterClient) {
fbb_.AddElement<uint8_t>(Welcome::VT_ISMASTERCLIENT, static_cast<uint8_t>(isMasterClient), 0);
}
void add_highestEntityGuid(uint32_t highestEntityGuid) {
fbb_.AddElement<uint32_t>(Welcome::VT_HIGHESTENTITYGUID, highestEntityGuid, 0);
}
explicit WelcomeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
Expand All @@ -804,9 +812,11 @@ struct WelcomeBuilder {
inline flatbuffers::Offset<Welcome> CreateWelcome(
flatbuffers::FlatBufferBuilder &_fbb,
uint64_t guid = 0,
bool isMasterClient = false) {
bool isMasterClient = false,
uint32_t highestEntityGuid = 0) {
WelcomeBuilder builder_(_fbb);
builder_.add_guid(guid);
builder_.add_highestEntityGuid(highestEntityGuid);
builder_.add_isMasterClient(isMasterClient);
return builder_.Finish();
}
Expand Down

0 comments on commit cf224a6

Please sign in to comment.