Skip to content

Commit 6982156

Browse files
committed
fix: equipment desync
1 parent fb177fb commit 6982156

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

Code/client/Components.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <Components/CacheComponent.h>
1717
#include <Components/WaitingFor3D.h>
1818
#include <Components/PendingInventoryComponent.h>
19+
#include <Components/PendingEquipmentComponent.h>
1920
#include <Components/ActorValuesComponent.h>
2021
#include <Components/ObjectComponent.h>
2122
#include <Components/PlayerComponent.h>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#ifndef TP_INTERNAL_COMPONENTS_GUARD
4+
#error Include Components.h instead
5+
#endif
6+
7+
#include <TiltedCore/Stl.hpp>
8+
#include <Messages/NotifyEquipmentChanges.h>
9+
10+
struct PendingEquipmentComponent
11+
{
12+
TiltedPhoques::Vector<NotifyEquipmentChanges> PendingChanges;
13+
};

Code/client/Services/Generic/InventoryService.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <Services/InventoryService.h>
22

33
#include <cstdlib>
4+
#include <TiltedCore/Stl.hpp>
45

56
#include <Messages/RequestObjectInventoryChanges.h>
67
#include <Messages/NotifyObjectInventoryChanges.h>
@@ -15,6 +16,7 @@
1516
#include <Events/InventoryChangeEvent.h>
1617
#include <Events/EquipmentChangeEvent.h>
1718

19+
#include <Components.h>
1820
#include <World.h>
1921
#include <Games/Skyrim/Interface/UI.h>
2022
#include <PlayerCharacter.h>
@@ -44,6 +46,7 @@ InventoryService::InventoryService(World& aWorld, entt::dispatcher& aDispatcher,
4446

4547
void InventoryService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
4648
{
49+
ProcessPendingEquipment();
4750
RunWeaponStateUpdates();
4851
RunNakedNPCBugChecks();
4952
}
@@ -252,6 +255,33 @@ void InventoryService::OnNotifyEquipmentChanges(const NotifyEquipmentChanges& ac
252255
return;
253256
}
254257

258+
if (!pActor->GetNiNode())
259+
{
260+
auto view = m_world.view<FormIdComponent>();
261+
const auto itor = std::find_if(std::begin(view), std::end(view), [formId = pActor->formID, view](entt::entity entity) { return view.get<FormIdComponent>(entity).Id == formId; });
262+
263+
if (itor != std::end(view))
264+
{
265+
auto* pPending = m_world.try_get<PendingEquipmentComponent>(*itor);
266+
if (!pPending)
267+
pPending = &m_world.emplace<PendingEquipmentComponent>(*itor);
268+
269+
pPending->PendingChanges.push_back(acMessage);
270+
spdlog::debug("Queued equipment change for actor {:X} until 3D is ready", pActor->formID);
271+
}
272+
else
273+
{
274+
spdlog::warn("{}: could not queue equipment change, entity not found for form id {:X}", __FUNCTION__, pActor->formID);
275+
}
276+
277+
return;
278+
}
279+
280+
ApplyEquipmentChange(pActor, acMessage);
281+
}
282+
283+
void InventoryService::ApplyEquipmentChange(Actor* pActor, const NotifyEquipmentChanges& acMessage) noexcept
284+
{
255285
auto& modSystem = World::Get().GetModSystem();
256286

257287
uint32_t itemId = modSystem.GetGameId(acMessage.ItemId);
@@ -326,6 +356,30 @@ void InventoryService::OnNotifyEquipmentChanges(const NotifyEquipmentChanges& ac
326356
}
327357
}
328358

359+
void InventoryService::ProcessPendingEquipment() noexcept
360+
{
361+
auto view = m_world.view<FormIdComponent, PendingEquipmentComponent>();
362+
TiltedPhoques::Vector<entt::entity> toClear;
363+
364+
for (auto entity : view)
365+
{
366+
auto& formIdComponent = view.get<FormIdComponent>(entity);
367+
auto& pending = view.get<PendingEquipmentComponent>(entity);
368+
369+
Actor* pActor = Cast<Actor>(TESForm::GetById(formIdComponent.Id));
370+
if (!pActor || !pActor->GetNiNode())
371+
continue;
372+
373+
for (const auto& change : pending.PendingChanges)
374+
ApplyEquipmentChange(pActor, change);
375+
376+
toClear.push_back(entity);
377+
}
378+
379+
for (auto entity : toClear)
380+
m_world.remove<PendingEquipmentComponent>(entity);
381+
}
382+
329383
void InventoryService::RunWeaponStateUpdates() noexcept
330384
{
331385
if (!m_transport.IsConnected())

Code/client/Services/InventoryService.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
struct World;
44
struct TransportService;
5+
class Actor;
56

67
struct UpdateEvent;
78
struct NotifyObjectInventoryChanges;
@@ -51,6 +52,9 @@ struct InventoryService
5152
void OnNotifyEquipmentChanges(const NotifyEquipmentChanges& acMessage) noexcept;
5253

5354
private:
55+
void ApplyEquipmentChange(Actor* pActor, const NotifyEquipmentChanges& acMessage) noexcept;
56+
void ProcessPendingEquipment() noexcept;
57+
5458
/**
5559
* Checks whether local actors their weapon draw states have changed,
5660
* and if so, send the new states to the server.

0 commit comments

Comments
 (0)