Skip to content

Commit

Permalink
Merge branch 'stability'
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed Dec 11, 2021
2 parents 113e6c0 + aa2fa23 commit d4fa374
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 45 deletions.
1 change: 0 additions & 1 deletion Code/client/Events/EquipmentChangeEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
struct EquipmentChangeEvent
{
uint32_t ActorId{ 0 };
String InventoryBuffer{};
};
9 changes: 7 additions & 2 deletions Code/client/Games/References.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,15 @@ String TESObjectREFR::SerializeInventory() const noexcept
{
ScopedSaveLoadOverride _;

char buffer[1 << 15];
// TODO: buffer[1 << 15] is too small for some inventories
// buffer[1 << 18] does the job, but these inventories seem to be bugged
// ask cosi for repro
// temp solution: increase the buffer
// only happened in skyrim, idk if fallout 4 needs it
char buffer[1 << 18];
BGSSaveFormBuffer saveBuffer;
saveBuffer.buffer = buffer;
saveBuffer.capacity = 1 << 15;
saveBuffer.capacity = 1 << 18;
saveBuffer.changeFlags = 1024;

SaveInventory(&saveBuffer);
Expand Down
6 changes: 0 additions & 6 deletions Code/client/Games/Skyrim/EquipManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ void* TP_MAKE_THISCALL(EquipHook, EquipManager, Actor* apActor, TESForm* apItem,
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -169,7 +168,6 @@ void* TP_MAKE_THISCALL(UnEquipHook, EquipManager, Actor* apActor, TESForm* apIte
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -190,7 +188,6 @@ void* TP_MAKE_THISCALL(EquipSpellHook, EquipManager, Actor* apActor, TESForm* ap
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -211,7 +208,6 @@ void* TP_MAKE_THISCALL(UnEquipSpellHook, EquipManager, Actor* apActor, TESForm*
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -232,7 +228,6 @@ void* TP_MAKE_THISCALL(EquipShoutHook, EquipManager, Actor* apActor, TESForm* ap
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand All @@ -253,7 +248,6 @@ void* TP_MAKE_THISCALL(UnEquipShoutHook, EquipManager, Actor* apActor, TESForm*
{
EquipmentChangeEvent evt;
evt.ActorId = apActor->formID;
evt.InventoryBuffer = apActor->SerializeInventory();

World::Get().GetRunner().Trigger(evt);
}
Expand Down
13 changes: 12 additions & 1 deletion Code/client/Games/Skyrim/TESObjectREFR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,18 @@ ExtraContainerChanges::Data* TESObjectREFR::GetContainerChanges() const noexcept

void TESObjectREFR::SaveInventory(BGSSaveFormBuffer* apBuffer) const noexcept
{
GetContainerChanges()->Save(apBuffer);
auto changes = GetContainerChanges();

auto entries = changes->entries;
uint32_t entryCount = 0;
for (auto entry : *entries)
{
entryCount++;
}
if (entryCount > 1024)
spdlog::error("Inventory entry count is really big: {:X}:{}", formID, entryCount);

changes->Save(apBuffer);
}

void TESObjectREFR::LoadInventory(BGSLoadFormBuffer* apBuffer) noexcept
Expand Down
50 changes: 17 additions & 33 deletions Code/client/Services/Generic/InventoryService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void InventoryService::OnInventoryChangeEvent(const InventoryChangeEvent& acEven
const auto* pForm = TESForm::GetById(acEvent.FormId);
if (RTTI_CAST(pForm, TESForm, Actor))
{
m_charactersWithInventoryChanges[acEvent.FormId] = String{};
m_charactersWithInventoryChanges.insert(acEvent.FormId);
}
else
{
Expand All @@ -62,7 +62,7 @@ void InventoryService::OnInventoryChangeEvent(const InventoryChangeEvent& acEven

void InventoryService::OnEquipmentChangeEvent(const EquipmentChangeEvent& acEvent) noexcept
{
m_charactersWithInventoryChanges[acEvent.ActorId] = acEvent.InventoryBuffer;
m_charactersWithInventoryChanges.insert(acEvent.ActorId);
}

void InventoryService::OnObjectInventoryChanges(const NotifyObjectInventoryChanges& acMessage) noexcept
Expand Down Expand Up @@ -168,12 +168,10 @@ void InventoryService::RunCharacterInventoryUpdates() noexcept
{
RequestCharacterInventoryChanges message;

for (const auto change : m_charactersWithInventoryChanges)
for (const auto formId : m_charactersWithInventoryChanges)
{
auto view = m_world.view<FormIdComponent>();

auto formId = change.first;

const auto iter = std::find_if(std::begin(view), std::end(view), [view, formId](auto entity)
{
return view.get<FormIdComponent>(entity).Id == formId;
Expand All @@ -193,19 +191,7 @@ void InventoryService::RunCharacterInventoryUpdates() noexcept
if (!pActor)
continue;

Inventory inventory = pActor->GetInventory();

if (change.second != String{})
{
spdlog::warn("Using cached inventory snapshot for {:X} ({:X})", formId, serverId);
//inventory.Buffer = change.second;
}
else
{
spdlog::warn("Using new inventory for {:X} ({:X})", formId, serverId);
}

message.Changes[serverId] = inventory;
message.Changes[serverId] = pActor->GetInventory();
}

m_transport.Send(message);
Expand All @@ -216,6 +202,9 @@ void InventoryService::RunCharacterInventoryUpdates() noexcept

void InventoryService::ApplyCachedObjectInventoryChanges() noexcept
{
if (!m_transport.IsConnected())
return;

if (UI::Get()->IsOpen(BSFixedString("ContainerMenu")))
return;

Expand Down Expand Up @@ -250,30 +239,25 @@ void InventoryService::ApplyCachedCharacterInventoryChanges() noexcept
if (UI::Get()->IsOpen(BSFixedString("ContainerMenu")))
return;

auto view = m_world.view<FormIdComponent>();
for (const auto entity : view)
auto view = m_world.view<FormIdComponent, RemoteComponent>();
for (const auto& [id, inventory] : m_cachedCharacterInventoryChanges)
{
std::optional<uint32_t> serverIdRes = utils::GetServerId(entity);
if (!serverIdRes.has_value())
continue;
const auto it = std::find_if(std::begin(view), std::end(view), [id = id, view](entt::entity entity) {
return view.get<RemoteComponent>(entity).Id == id;
});

uint32_t serverId = serverIdRes.value();

const auto change = m_cachedCharacterInventoryChanges.find(serverId);

if (change == m_cachedCharacterInventoryChanges.end())
if (it == std::end(view))
continue;

const auto& formIdComponent = view.get<FormIdComponent>(entity);
const auto& formIdComponent = view.get<FormIdComponent>(*it);
auto* const pActor = RTTI_CAST(TESForm::GetById(formIdComponent.Id), TESForm, Actor);
if (!pActor)
continue;

auto* cpRemoteComponent = m_world.try_get<RemoteComponent>(entity);
if (cpRemoteComponent)
cpRemoteComponent->SpawnRequest.InventoryContent = change.value();
auto& remoteComponent = m_world.get<RemoteComponent>(*it);
remoteComponent.SpawnRequest.InventoryContent = inventory;

pActor->SetInventory(change.value());
pActor->SetInventory(inventory);
}

m_cachedCharacterInventoryChanges.clear();
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Services/InventoryService.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct InventoryService
TransportService& m_transport;

Set<uint32_t> m_objectsWithInventoryChanges;
Map<uint32_t, String> m_charactersWithInventoryChanges;
Set<uint32_t> m_charactersWithInventoryChanges;
Map<GameId, Inventory> m_cachedObjectInventoryChanges;
Map<uint32_t, Inventory> m_cachedCharacterInventoryChanges;

Expand Down
3 changes: 2 additions & 1 deletion Code/client/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ std::optional<uint32_t> GetServerId(entt::entity aEntity) noexcept
serverId = pRemoteComponent->Id;
else
{
spdlog::warn("This entity has neither a local or remote component: {:X}", aEntity);
const auto* pFormIdComponent = World::Get().try_get<FormIdComponent>(aEntity);
spdlog::warn("This entity has neither a local or remote component: {:X}, form id: {:X}", aEntity, pFormIdComponent ? pFormIdComponent->Id : 0);
return std::nullopt;
}

Expand Down

0 comments on commit d4fa374

Please sign in to comment.