mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-15 00:07:13 +00:00
fix: constructions keep pending changes of five more components
The level, forced movement, possessable, possessor and combat AI parts are each read behind a flag bit (LWOLevelProgressionComponent:: Deserialize 0x00c63bd0 and the others). DLU cleared their dirty flags when it wrote a construction, which goes only to the client the object came into range of, so a change waiting for the next update never reached the clients already watching: a level up, a mount or dismount, a rail ride. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -551,7 +551,7 @@ void BaseCombatAIComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsI
|
||||
if (m_DirtyStateOrTarget || bIsInitialUpdate) {
|
||||
outBitStream.Write(m_State);
|
||||
outBitStream.Write(m_Target);
|
||||
m_DirtyStateOrTarget = false;
|
||||
if (!bIsInitialUpdate) m_DirtyStateOrTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ void LevelProgressionComponent::LoadFromSaveData(const tinyxml2::XMLDocument& do
|
||||
void LevelProgressionComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
outBitStream.Write(bIsInitialUpdate || m_DirtyLevelInfo);
|
||||
if (bIsInitialUpdate || m_DirtyLevelInfo) outBitStream.Write(m_Level);
|
||||
m_DirtyLevelInfo = false;
|
||||
// A construction goes to one client; the players already watching still need a waiting change
|
||||
if (!bIsInitialUpdate) m_DirtyLevelInfo = false;
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::HandleLevelUp() {
|
||||
|
||||
@@ -14,7 +14,7 @@ void PlayerForcedMovementComponent::Serialize(RakNet::BitStream& outBitStream, b
|
||||
outBitStream.Write(m_PlayerOnRail);
|
||||
outBitStream.Write(m_ShowBillboard);
|
||||
}
|
||||
m_DirtyInfo = false;
|
||||
if (!bIsInitialUpdate) m_DirtyInfo = false;
|
||||
}
|
||||
|
||||
void PlayerForcedMovementComponent::Allocator(Entity& entity, ObjectLoadState& state) {
|
||||
|
||||
@@ -38,7 +38,7 @@ PossessorComponent::~PossessorComponent() {
|
||||
void PossessorComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
outBitStream.Write(m_DirtyPossesor || bIsInitialUpdate);
|
||||
if (m_DirtyPossesor || bIsInitialUpdate) {
|
||||
m_DirtyPossesor = false;
|
||||
if (!bIsInitialUpdate) m_DirtyPossesor = false;
|
||||
outBitStream.Write(m_Possessable != LWOOBJID_EMPTY);
|
||||
if (m_Possessable != LWOOBJID_EMPTY) {
|
||||
outBitStream.Write(m_Possessable);
|
||||
|
||||
@@ -37,7 +37,7 @@ void PossessableComponent::LoadDataFromTemplate() {
|
||||
void PossessableComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
outBitStream.Write(m_DirtyPossessable || bIsInitialUpdate);
|
||||
if (m_DirtyPossessable || bIsInitialUpdate) {
|
||||
m_DirtyPossessable = false; // reset flag
|
||||
if (!bIsInitialUpdate) m_DirtyPossessable = false; // reset flag
|
||||
outBitStream.Write(m_Possessor != LWOOBJID_EMPTY);
|
||||
if (m_Possessor != LWOOBJID_EMPTY) outBitStream.Write(m_Possessor);
|
||||
|
||||
@@ -45,7 +45,7 @@ void PossessableComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIn
|
||||
if (m_AnimationFlag != eAnimationFlags::IDLE_NONE) outBitStream.Write(m_AnimationFlag);
|
||||
|
||||
outBitStream.Write(m_ImmediatelyDepossess);
|
||||
m_ImmediatelyDepossess = false; // reset flag
|
||||
if (!bIsInitialUpdate) m_ImmediatelyDepossess = false; // reset flag
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "Entity.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "ItemComponent.h"
|
||||
#include "LevelProgressionComponent.h"
|
||||
#include "PlayerForcedMovementComponent.h"
|
||||
#include "Item.h"
|
||||
#include "ModelComponent.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
@@ -338,6 +340,36 @@ TEST_F(ReplicaConstructionTest, PhantomPhysicsConstructionKeepsThePendingEffect)
|
||||
EXPECT_LE(again.GetNumberOfBitsUsed(), idle);
|
||||
}
|
||||
|
||||
// A construction goes to the one client the object came into range of. It must not use up a change the clients
|
||||
// already watching are still waiting for (the level, rail and billboard flags are each read behind a flag bit).
|
||||
TEST_F(ReplicaConstructionTest, AConstructionKeepsPendingLevelAndForcedMovementChanges) {
|
||||
Entity player(1152921506064087008, info);
|
||||
auto* const level = player.AddComponent<LevelProgressionComponent>(-1);
|
||||
auto* const forcedMovement = player.AddComponent<PlayerForcedMovementComponent>(-1);
|
||||
|
||||
level->SetLevel(7);
|
||||
forcedMovement->SetPlayerOnRail(true);
|
||||
RakNet::BitStream construction;
|
||||
level->Serialize(construction, true);
|
||||
forcedMovement->Serialize(construction, true);
|
||||
|
||||
RakNet::BitStream update;
|
||||
level->Serialize(update, false);
|
||||
forcedMovement->Serialize(update, false);
|
||||
RakNet::BitStream expected;
|
||||
expected.Write1();
|
||||
expected.Write<uint32_t>(7);
|
||||
expected.Write1();
|
||||
expected.Write1(); // on rail
|
||||
expected.Write0(); // show billboard
|
||||
ExpectSameBits(update, expected);
|
||||
|
||||
RakNet::BitStream again;
|
||||
level->Serialize(again, false);
|
||||
forcedMovement->Serialize(again, false);
|
||||
EXPECT_EQ(again.GetNumberOfBitsUsed(), 2u);
|
||||
}
|
||||
|
||||
// A guild change (docs/Guilds.md) is written once: the client reads guild id, a u8 length and 16-bit characters, and
|
||||
// redraws the name billboard every time it reads a name.
|
||||
TEST_F(ReplicaConstructionTest, CharacterGuildChangeIsWrittenOnce) {
|
||||
|
||||
Reference in New Issue
Block a user