Skip to content

Commit

Permalink
Fixed deadlock in ShouldBackgroundClone.
Browse files Browse the repository at this point in the history
  • Loading branch information
adya committed Jan 11, 2025
1 parent 65e9fd6 commit 029c271
Showing 1 changed file with 37 additions and 36 deletions.
73 changes: 37 additions & 36 deletions SPID/src/OutfitManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,18 +465,46 @@ namespace Outfits
static inline constexpr std::size_t offset = OFFSET(0x86, 0x86);
};

RE::BSEventNotifyControl Manager::ProcessEvent(const RE::TESFormDeleteEvent* a_event, RE::BSTEventSource<RE::TESFormDeleteEvent>*)
{
WriteLocker lock(_lock);
if (a_event && a_event->formID != 0) {
wornReplacements.erase(a_event->formID);
pendingReplacements.erase(a_event->formID);
initialOutfits.erase(a_event->formID);
}
return RE::BSEventNotifyControl::kContinue;
}

RE::BSEventNotifyControl Manager::ProcessEvent(const RE::TESDeathEvent* a_event, RE::BSTEventSource<RE::TESDeathEvent>*)
{
if (!a_event || a_event->dead) {
return RE::BSEventNotifyControl::kContinue;
}

if (const auto actor = a_event->actorDying->As<RE::Actor>(); actor && !actor->IsPlayerRef()) {
WriteLocker lock(_lock);
if (const auto outfit = ResolveWornOutfit(actor, true); outfit) {
ApplyOutfit(actor, outfit->distributed);
}
}

return RE::BSEventNotifyControl::kContinue;
}
#pragma endregion

void Manager::HandleMessage(SKSE::MessagingInterface::Message* message)
{
switch (message->type) {
case SKSE::MessagingInterface::kPostLoad:
{
{
logger::info("Outfit Manager:");

const auto serializationInterface = SKSE::GetSerializationInterface();
serializationInterface->SetUniqueID(serializationKey);
serializationInterface->SetSaveCallback(Save);
serializationInterface->SetLoadCallback(Load);

if (const auto scripts = RE::ScriptEventSourceHolder::GetSingleton()) {
scripts->AddEventSink<RE::TESFormDeleteEvent>(this);
logger::info("\t\tRegistered for {}.", typeid(RE::TESFormDeleteEvent).name());
Expand All @@ -487,7 +515,6 @@ namespace Outfits
logger::info("\t\tRegistered for {}.", typeid(RE::TESDeathEvent).name());
}

// TODO: Test size of RAM with/without hook
stl::write_vfunc<RE::TESNPC, InitItemImpl>();
logger::info("\t\tInstalled InitItemImpl hook.");

Expand All @@ -505,9 +532,7 @@ namespace Outfits

stl::write_thunk_call<SetOutfitActor>();
logger::info("\t\tInstalled SetOutfit hook.");


}
}
break;
case SKSE::MessagingInterface::kDataLoaded:
{
Expand All @@ -525,34 +550,6 @@ namespace Outfits
}
}

RE::BSEventNotifyControl Manager::ProcessEvent(const RE::TESFormDeleteEvent* a_event, RE::BSTEventSource<RE::TESFormDeleteEvent>*)
{
WriteLocker lock(_lock);
if (a_event && a_event->formID != 0) {
wornReplacements.erase(a_event->formID);
pendingReplacements.erase(a_event->formID);
initialOutfits.erase(a_event->formID);
}
return RE::BSEventNotifyControl::kContinue;
}

RE::BSEventNotifyControl Manager::ProcessEvent(const RE::TESDeathEvent* a_event, RE::BSTEventSource<RE::TESDeathEvent>*)
{
if (!a_event || a_event->dead) {
return RE::BSEventNotifyControl::kContinue;
}

if (const auto actor = a_event->actorDying->As<RE::Actor>(); actor && !actor->IsPlayerRef()) {
WriteLocker lock(_lock);
if (const auto outfit = ResolveWornOutfit(actor, true); outfit) {
ApplyOutfit(actor, outfit->distributed);
}
}

return RE::BSEventNotifyControl::kContinue;
}
#pragma endregion

#pragma region Outfit Management
bool Manager::HasDefaultOutfit(const RE::TESNPC* npc, const RE::BGSOutfit* outfit) const
{
Expand Down Expand Up @@ -901,8 +898,12 @@ namespace Outfits
#pragma region Hooks Handling
bool Manager::ProcessShouldBackgroundClone(RE::Actor* actor, std::function<bool()> funcCall)
{
ReadLocker lock(_lock);
if (!pendingReplacements.contains(actor->formID)) {
bool hasPending = false;
{
ReadLocker lock(_lock);
hasPending = pendingReplacements.contains(actor->formID);
}
if (!hasPending) {
SetOutfit(actor, nullptr, NPCData::IsDead(actor), false);
}

Expand Down

0 comments on commit 029c271

Please sign in to comment.