ksys: Implement ActorLimiter

This commit is contained in:
Léo Lam 2020-12-31 17:56:31 +01:00
parent 1f12ab9237
commit 3f9172043c
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
7 changed files with 150 additions and 8 deletions

View File

@ -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,

Can't render this file because it is too large.

@ -1 +1 @@
Subproject commit 09f3cdd5c83e0bcf6e67eb983e3f992e17f44b39
Subproject commit d0635a9d2fdcaa6b5b9446de22c6691f05b4adef

View File

@ -13,6 +13,8 @@ target_sources(uking PRIVATE
actActorFactory.h
actActorHeapUtil.cpp
actActorHeapUtil.h
actActorLimiter.cpp
actActorLimiter.h
actActorLinkConstDataAccess.cpp
actActorLinkConstDataAccess.h
actActorParam.cpp

View File

@ -2,6 +2,7 @@
#include <prim/seadRuntimeTypeInfo.h>
#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:

View File

@ -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<int, NumCategories>& capacities) {
for (s32 i = 0; i < NumCategories; ++i) {
if (!mLists.ref()[i].init(heap, capacities[i]))
return false;
}
return true;
}
} // namespace ksys::act

View File

@ -0,0 +1,62 @@
#pragma once
#include <container/seadBuffer.h>
#include <container/seadOffsetList.h>
#include <container/seadSafeArray.h>
#include <heap/seadDisposer.h>
#include <prim/seadStorageFor.h>
#include <thread/seadCriticalSection.h>
#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<Node> mNodes;
sead::OffsetList<Node> mActorList;
sead::CriticalSection mCritSection;
};
KSYS_CHECK_SIZE_NX150(List, 0x68);
bool init(sead::Heap* heap, const sead::SafeArray<int, NumCategories>& capacities);
List& get(Category category) { return mLists.ref()[s32(category)]; }
const List& get(Category category) const { return mLists.ref()[s32(category)]; }
private:
sead::StorageFor<sead::SafeArray<List, NumCategories>> mLists{sead::ZeroInitializeTag{}};
};
KSYS_CHECK_SIZE_NX150(ActorLimiter, 0x360);
} // namespace ksys::act

View File

@ -44,6 +44,7 @@ public:
_0 = 0,
_1 = 1,
_2 = 2,
_15 = 15,
};
enum class SleepWakeReason : u32 {