Skip to content

Commit

Permalink
Merge branch 'master' into feat-forcestuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Force67 committed Dec 20, 2021
2 parents 0a1e7cb + 19d87a0 commit 8e1d71a
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 48 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## [1.5.1](https://github.com/tiltedphoques/TiltedEvolution/compare/v1.5.0...v1.5.1) (2021-12-20)


### Bug Fixes

* projectile related crashes ([48eec06](https://github.com/tiltedphoques/TiltedEvolution/commit/48eec065e282898bdbd02ed7a2ad195665cd92d7))

# [1.5.0](https://github.com/tiltedphoques/TiltedEvolution/compare/v1.4.1...v1.5.0) (2021-12-11)


### Features

* progress on leveled actor sync ([94d4039](https://github.com/tiltedphoques/TiltedEvolution/commit/94d4039174b565398ff5d4482b6be33c6f6e527f))

## [1.4.1](https://github.com/tiltedphoques/TiltedEvolution/compare/v1.4.0...v1.4.1) (2021-12-11)


### Bug Fixes

* inventory crash fix ([7358e7f](https://github.com/tiltedphoques/TiltedEvolution/commit/7358e7f031418efef456d0f6218d8fa64e24ddf0))

# [1.4.0](https://github.com/tiltedphoques/TiltedEvolution/compare/v1.3.0...v1.4.0) (2021-12-10)


Expand Down
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{};
};
6 changes: 6 additions & 0 deletions Code/client/Games/Fallout4/Forms/TESForm.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ struct TESForm : BaseFormComponent
uint32_t unkC;
};

enum FormFlags
{
DISABLED = 1 << 0xB,
};

static TESForm* GetById(uint32_t aId);

virtual void sub_7();
Expand Down Expand Up @@ -106,6 +111,7 @@ struct TESForm : BaseFormComponent
// TODO: fallout 4 impl
return;
}
bool IsDisabled() const noexcept { return (flags & DISABLED) != 0; }

uintptr_t unk8;
uint32_t flags;
Expand Down
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
2 changes: 2 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESForm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct TESForm : BaseFormComponent

enum FormFlags
{
DISABLED = 1 << 0xB,
IGNORE_FRIENDLY_HITS = 1 << 0x14,
};

Expand Down Expand Up @@ -101,6 +102,7 @@ struct TESForm : BaseFormComponent
else
flags &= IGNORE_FRIENDLY_HITS;
}
bool IsDisabled() const noexcept { return (flags & DISABLED) != 0; }

uintptr_t unk4;
uint32_t flags;
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
12 changes: 9 additions & 3 deletions Code/client/Services/Generic/CharacterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ void CharacterService::OnCharacterSpawn(const CharacterSpawnRequest& acMessage)
const auto cNpcId = World::Get().GetModSystem().GetGameId(acMessage.BaseId);
if(cNpcId == 0)
{
spdlog::error("Failed to retrieve NPC, it will not be spawned, possibly missing mod");
spdlog::error("Failed to retrieve NPC, it will not be spawned, possibly missing mod, base: {:X}:{:X}, form: {:X}:{:X}", acMessage.BaseId.BaseId, acMessage.BaseId.ModId, acMessage.FormId.BaseId, acMessage.FormId.ModId);
return;
}

Expand Down Expand Up @@ -337,6 +337,9 @@ void CharacterService::OnCharacterSpawn(const CharacterSpawnRequest& acMessage)
spdlog::error("Actor object {:X} could not be created.", acMessage.ServerId);
return;
}

if (pActor->IsDisabled())
pActor->Enable();

pActor->GetExtension()->SetRemote(true);
pActor->rotation.x = acMessage.Rotation.x;
Expand Down Expand Up @@ -1070,9 +1073,7 @@ void CharacterService::OnNotifyProjectileLaunch(const NotifyProjectileLaunch& ac
ProjectileLaunchData launchData{};
#endif

#if TP_FALLOUT4
launchData.pShooter = RTTI_CAST(TESForm::GetById(formIdComponent.Id), TESForm, TESObjectREFR);
#endif

launchData.Origin.x = acMessage.OriginX;
launchData.Origin.y = acMessage.OriginY;
Expand All @@ -1081,6 +1082,11 @@ void CharacterService::OnNotifyProjectileLaunch(const NotifyProjectileLaunch& ac
const uint32_t cProjectileBaseId = modSystem.GetGameId(acMessage.ProjectileBaseID);
launchData.pProjectileBase = TESForm::GetById(cProjectileBaseId);

#if TP_SKYRIM64
const uint32_t cFromWeaponId = modSystem.GetGameId(acMessage.WeaponID);
launchData.pFromWeapon = RTTI_CAST(TESForm::GetById(cFromWeaponId), TESForm, TESObjectWEAP);
#endif

#if TP_FALLOUT4
Actor* pShooter = RTTI_CAST(launchData.pShooter, TESObjectREFR, Actor);
pShooter->GetCurrentWeapon(&launchData.FromWeapon, 0);
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 8e1d71a

Please sign in to comment.