diff --git a/data/uking_functions.csv b/data/uking_functions.csv index f1792f47..ecc929b1 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -78175,13 +78175,13 @@ 0x0000007100e4d1a8,GlobalParameter::loadActorPack,84, 0x0000007100e4d1fc,GlobalParameter::resIsReady,60, 0x0000007100e4d238,GlobalParameter::loadActorFiles,256, -0x0000007100e4d338,ActorLimiter::List::init,236, -0x0000007100e4d424,ActorLimiter::List::addActor,428, -0x0000007100e4d5d0,ActorLimiter::Disposer::dtor,204, -0x0000007100e4d69c,ActorLimiter::Disposer::dtorDelete,212, -0x0000007100e4d770,ActorLimiter::createInstance,148, -0x0000007100e4d804,ActorLimiter::init,212, -0x0000007100e4d8d8,ActorLimiter_::ctor,320, +0x0000007100e4d338,ActorLimiter::List::init,236,_ZN4ksys3act12ActorLimiter4List4initEPN4sead4HeapEi +0x0000007100e4d424,ActorLimiter::List::addActor,428,_ZN4ksys3act12ActorLimiter4List8addActorEPNS0_8BaseProcEb +0x0000007100e4d5d0,ActorLimiter::Disposer::dtor,204,_ZN4ksys3act12ActorLimiter18SingletonDisposer_D2Ev +0x0000007100e4d69c,ActorLimiter::Disposer::dtorDelete,212,_ZN4ksys3act12ActorLimiter18SingletonDisposer_D0Ev +0x0000007100e4d770,ActorLimiter::createInstance,148,_ZN4ksys3act12ActorLimiter14createInstanceEPN4sead4HeapE +0x0000007100e4d804,ActorLimiter::init,212,_ZN4ksys3act12ActorLimiter4initEPN4sead4HeapERKNS2_9SafeArrayIiLi8EEE +0x0000007100e4d8d8,ActorLimiter_::ctor,320,_ZN4sead9SafeArrayIN4ksys3act12ActorLimiter4ListELi8EEC2Ev 0x0000007100e4da18,sub_7100E4DA18,60, 0x0000007100e4da54,sub_7100E4DA54,296, 0x0000007100e4db7c,sub_7100E4DB7C,128, diff --git a/lib/sead b/lib/sead index 09f3cdd5..d0635a9d 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 09f3cdd5c83e0bcf6e67eb983e3f992e17f44b39 +Subproject commit d0635a9d2fdcaa6b5b9446de22c6691f05b4adef diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index eb4318aa..6e255033 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -13,6 +13,8 @@ target_sources(uking PRIVATE actActorFactory.h actActorHeapUtil.cpp actActorHeapUtil.h + actActorLimiter.cpp + actActorLimiter.h actActorLinkConstDataAccess.cpp actActorLinkConstDataAccess.h actActorParam.cpp diff --git a/src/KingSystem/ActorSystem/actActorConstDataAccess.h b/src/KingSystem/ActorSystem/actActorConstDataAccess.h index 037e1c8b..125021ed 100644 --- a/src/KingSystem/ActorSystem/actActorConstDataAccess.h +++ b/src/KingSystem/ActorSystem/actActorConstDataAccess.h @@ -2,6 +2,7 @@ #include #include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include "KingSystem/ActorSystem/actBaseProc.h" #include "KingSystem/ActorSystem/actBaseProcLink.h" #include "KingSystem/Utils/Types.h" @@ -42,6 +43,11 @@ public: bool acquireConnectedCalcChild(ActorLinkConstDataAccess* accessor) const; bool hasConnectedCalcParent() const; + bool deleteLater(BaseProc::DeleteReason reason) const; + bool fadeOutDelete(BaseProc::DeleteReason reason) const; + bool sleep(BaseProc::SleepWakeReason reason) const; + bool wakeUp(BaseProc::SleepWakeReason reason) const; + bool isAttClientEnabled(const sead::SafeString& client) const; private: diff --git a/src/KingSystem/ActorSystem/actActorLimiter.cpp b/src/KingSystem/ActorSystem/actActorLimiter.cpp new file mode 100644 index 00000000..08925e8a --- /dev/null +++ b/src/KingSystem/ActorSystem/actActorLimiter.cpp @@ -0,0 +1,71 @@ +#include "KingSystem/ActorSystem/actActorLimiter.h" +#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actTag.h" + +namespace ksys::act { + +bool ActorLimiter::List::init(sead::Heap* heap, int capacity) { + mNodes.allocBufferAssert(capacity, heap); + if (!mNodes.isBufferReady()) + return false; + + for (auto& node : mNodes) + mActorList.pushBack(&node); + + return true; +} + +bool ActorLimiter::List::addActor(BaseProc* proc, bool allow_evicting_old_actors) { + const auto lock = sead::makeScopedLock(mCritSection); + + // Find a free node. + Node* target_node = nullptr; + for (auto& node : mActorList) { + if (node.proc_link.hasProc()) + continue; + + mActorList.erase(&node); + target_node = &node; + break; + } + + if (target_node == nullptr) { + if (!allow_evicting_old_actors) + return false; + + target_node = mActorList.popFront(); + if (target_node) { + ActorConstDataAccess acc; + acquireActor(&target_node->proc_link, &acc); + + // Priority material actors will not be evicted if possible. + if (acc.hasTag(tags::PriorityMaterial)) { + mActorList.pushBack(target_node); + target_node = mActorList.popFront(); + if (target_node) + acquireActor(&target_node->proc_link, &acc); + } + + acc.fadeOutDelete(BaseProc::DeleteReason::_15); + } + + if (target_node == nullptr) + return false; + } + + target_node->proc_link.acquire(proc, false); + mActorList.pushBack(target_node); + return true; +} + +SEAD_SINGLETON_DISPOSER_IMPL(ActorLimiter) + +bool ActorLimiter::init(sead::Heap* heap, const sead::SafeArray& capacities) { + for (s32 i = 0; i < NumCategories; ++i) { + if (!mLists.ref()[i].init(heap, capacities[i])) + return false; + } + return true; +} + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorLimiter.h b/src/KingSystem/ActorSystem/actActorLimiter.h new file mode 100644 index 00000000..b2d98bfe --- /dev/null +++ b/src/KingSystem/ActorSystem/actActorLimiter.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "KingSystem/ActorSystem/actBaseProcLink.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::act { + +class ActorLimiter { + SEAD_SINGLETON_DISPOSER(ActorLimiter) + ActorLimiter() = default; + ~ActorLimiter() { mLists.destruct(); } + +public: + enum class Category { + LumberjackTreeDrops = 0, + DroppedItems = 1, + PlayerTrash = 2, + Drops = 3, + SandSeal = 4, + Bullets = 5, + AmiiboDrops = 6, + _7 = 7, + }; + static constexpr int NumCategories = 8; + + class List { + public: + List() { mActorList.initOffset(offsetof(Node, node)); } + ~List() { mNodes.freeBuffer(); } + + bool init(sead::Heap* heap, int capacity); + bool addActor(BaseProc* proc, bool allow_evicting_old_actors); + + private: + struct Node { + sead::ListNode node; + BaseProcLink proc_link; + }; + + sead::Buffer mNodes; + sead::OffsetList mActorList; + sead::CriticalSection mCritSection; + }; + KSYS_CHECK_SIZE_NX150(List, 0x68); + + bool init(sead::Heap* heap, const sead::SafeArray& capacities); + + List& get(Category category) { return mLists.ref()[s32(category)]; } + const List& get(Category category) const { return mLists.ref()[s32(category)]; } + +private: + sead::StorageFor> mLists{sead::ZeroInitializeTag{}}; +}; +KSYS_CHECK_SIZE_NX150(ActorLimiter, 0x360); + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h index de5a1a86..7cd1388b 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.h +++ b/src/KingSystem/ActorSystem/actBaseProc.h @@ -44,6 +44,7 @@ public: _0 = 0, _1 = 1, _2 = 2, + _15 = 15, }; enum class SleepWakeReason : u32 {