diff options
| author | Léo Lam <leo@leolam.fr> | 2020-12-21 16:41:28 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-12-21 16:53:44 +0100 |
| commit | b1470e45fad6a43bb2583aed7f6e9bce3172f0bf (patch) | |
| tree | 52314b2d75328d3166a7b6ed6ab74559752cf0f4 /src/KingSystem/ActorSystem/actAiQueries.cpp | |
| parent | 64b93c984e2109771f7b8210f6906f2069316ba1 (diff) | |
ksys/act: Add Queries
Diffstat (limited to 'src/KingSystem/ActorSystem/actAiQueries.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actAiQueries.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/KingSystem/ActorSystem/actAiQueries.cpp b/src/KingSystem/ActorSystem/actAiQueries.cpp new file mode 100644 index 00000000..5d900bcc --- /dev/null +++ b/src/KingSystem/ActorSystem/actAiQueries.cpp @@ -0,0 +1,143 @@ +#include "KingSystem/ActorSystem/actAiQueries.h" +#include <codec/seadHashCRC32.h> +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actAiQuery.h" +#include "KingSystem/ActorSystem/queryDummyQuery.h" +#include "KingSystem/Resource/resResourceAIProgram.h" + +namespace ksys::act::ai { + +Queries::Queries() = default; + +Queries::~Queries() { + finalize(); +} + +void Queries::finalize() { + for (s32 i = 0; i < mClasses.size(); ++i) { + if (mClasses[i]) { + delete mClasses[i]; + mClasses[i] = nullptr; + } + } + + mOnPreDeleteCbs.freeBuffer(); + mUpdateForPreDeleteCbs.freeBuffer(); + mClasses.freeBuffer(); +} + +bool Queries::init(Actor* actor, sead::Heap* heap) { + const auto* aiprog = actor->getParam()->getRes().mAIProgram; + + const auto num_Queries = aiprog->getQueries().size(); + if (num_Queries == 0) + return true; + + if (!mClasses.tryAllocBuffer(num_Queries, heap)) + return false; + for (s32 i = 0, n = mClasses.size(); i != n; ++i) + mClasses(i) = nullptr; + auto it_class = mClasses.begin(); + const auto it_class_end = mClasses.end(); + + Query::InitArg arg; + arg.actor = actor; + s32 predelete_cb_num = 0; + s32 update_cb_num = 0; + for (; it_class != it_class_end; ++it_class) { + arg.def_idx = it_class.getIndex(); + const char* name = aiprog->getQueries()[it_class.getIndex()].mClassName; + + auto* factory = getFactory(name); + if (factory) + *it_class = factory->create_fn(arg, heap); + else + *it_class = new (heap) DummyQuery(arg); + + if (!*it_class) + return false; + + update_cb_num += (*it_class)->hasUpdateForPreDeleteCb(); + predelete_cb_num += (*it_class)->hasPreDeleteCb(); + } + + // Allocate the callback lists. + if (predelete_cb_num != 0) { + if (!mOnPreDeleteCbs.tryAllocBuffer(predelete_cb_num, heap)) + return false; + for (s32 i = 0; i < predelete_cb_num; ++i) + mOnPreDeleteCbs(i) = nullptr; + } + + if (update_cb_num != 0) { + if (!mUpdateForPreDeleteCbs.tryAllocBuffer(update_cb_num, heap)) + return false; + for (s32 i = 0; i < update_cb_num; ++i) + mUpdateForPreDeleteCbs(i) = nullptr; + } + + // Initialize each class. + s32 idx_cb1 = 0, idx_cb2 = 0; + for (auto it = mClasses.begin(), end = mClasses.end(); it != end; ++it) { + if (!(*it)->init(heap)) + return false; + + if ((*it)->hasUpdateForPreDeleteCb()) { + mUpdateForPreDeleteCbs[idx_cb2] = *it; + ++idx_cb2; + } + + if ((*it)->hasPreDeleteCb()) { + mOnPreDeleteCbs[idx_cb1] = *it; + ++idx_cb1; + } + } + + return true; +} + +bool Queries::updateForPreDelete() const { + bool ok = true; + for (auto* cb : mUpdateForPreDeleteCbs) { + if (cb) + ok &= cb->updateForPreDelete(); + } + return ok; +} + +void Queries::onPreDelete() const { + for (auto* cb : mOnPreDeleteCbs) { + if (cb) + cb->onPreDelete(); + } +} + +Query* Queries::getQuery(const sead::SafeString& name) const { + for (auto* query : mClasses) { + if (name == query->getName()) + return query; + } + return nullptr; +} + +QueryFactory* Queries::getFactory(const sead::SafeString& name) { + const u32 name_hash = sead::HashCRC32::calcStringHash(name); + const s32 idx = sFactories.binarySearch( + name_hash, +[](const QueryFactory& factory, const u32& hash) { + if (factory.hash < hash) + return -1; + if (factory.hash > hash) + return 1; + return 0; + }); + if (idx < 0) + return nullptr; + return sFactories.get(idx); +} + +void Queries::setFactories(int count, QueryFactory* factories) { + sFactories.setBuffer(count, factories); +} + +} // namespace ksys::act::ai |
