botw/src/KingSystem/ActorSystem/actActorLimiter.cpp

72 lines
1.9 KiB
C++

#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.deleteEx(BaseProc::DeleteReason::_f);
}
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