From 1cbf7fae43a9baa7ed2368a31e4c2dfe36cc40f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 15 Nov 2020 18:03:26 +0100 Subject: ksys/act: Start adding ActorInfoData --- src/KingSystem/ActorSystem/actInfoData.cpp | 295 +++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 src/KingSystem/ActorSystem/actInfoData.cpp (limited to 'src/KingSystem/ActorSystem/actInfoData.cpp') diff --git a/src/KingSystem/ActorSystem/actInfoData.cpp b/src/KingSystem/ActorSystem/actInfoData.cpp new file mode 100644 index 00000000..036ab557 --- /dev/null +++ b/src/KingSystem/ActorSystem/actInfoData.cpp @@ -0,0 +1,295 @@ +#include "KingSystem/ActorSystem/actInfoData.h" +#include +#include +#include "KingSystem/Utils/Byaml/Byaml.h" +#include "KingSystem/Utils/Byaml/ByamlArrayIter.h" +#include "KingSystem/Utils/Byaml/ByamlData.h" +#include "KingSystem/Utils/Byaml/ByamlHashIter.h" + +namespace ksys::act { + +SEAD_SINGLETON_DISPOSER_IMPL(InfoData) + +InfoData::~InfoData() { + if (mHashesIter) + delete mHashesIter; + + if (mActorsIter) + delete mActorsIter; + + if (mRootIter) + delete mRootIter; + + mRootIter = nullptr; + mHashesIter = nullptr; + mActorsIter = nullptr; + mHashesBytes = nullptr; + mHashes = nullptr; + mActorsBytes = nullptr; + mActorOffsets = nullptr; +} + +void InfoData::init(u8* data, sead::Heap* heap, sead::Heap* debug_heap) { + mRootIter = new (heap) al::ByamlIter(data); + mHashesIter = new (heap) al::ByamlIter(); + mActorsIter = new (heap) al::ByamlIter(); + + if (debug_heap) { + mDebugEntries = new (debug_heap) DebugEntry[NumDebugEntries]; + for (s32 i = 0; i != NumDebugEntries; ++i) + mDebugEntries[i].used = false; + } else { + mDebugEntries = nullptr; + } + + if (mRootIter->tryGetIterByKey(mHashesIter, "Hashes")) { + mHashesBytes = mHashesIter->getData(); + mHashes = al::ByamlArrayIter(mHashesIter->getRootNode()).getDataTable(); + } + + if (mRootIter->tryGetIterByKey(mActorsIter, "Actors")) { + mActorsBytes = mActorsIter->getData(); + mActorOffsets = al::ByamlArrayIter(mActorsIter->getRootNode()).getDataTable(); + } + + mNumActors = mActorsIter->getSize(); + _88 = 0; + mDebugHeap = debug_heap; + mTagsIdx = mRootIter->getKeyIndex("tags"); + mProfileIdx = mRootIter->getKeyIndex("profile"); + mInvalidWeathersIdx = mRootIter->getKeyIndex("invalidWeathers"); + mInvalidTimesIdx = mRootIter->getKeyIndex("invalidTimes"); + mNameIdx = mRootIter->getKeyIndex("name"); + mSystemSameGroupActorNameIdx = mRootIter->getKeyIndex("systemSameGroupActorName"); +} + +bool InfoData::getActorIter(al::ByamlIter* iter, const char* actor, bool x) const { + const u32 hash = sead::HashCRC32::calcStringHash(actor); + + // Perform a binary search. + s32 a = 0; + s32 b = mNumActors; + while (a < b) { + const s32 idx = (a + b) / 2; + const u32 hash_i = mHashes[idx]; + + if (hash_i == hash) { + *iter = al::ByamlIter(mActorsBytes, mActorsBytes + mActorOffsets[idx]); + return true; + } + + if (hash_i >= hash) + b = idx; + else + a = idx + 1; + } + + if (x) + static_cast(logFailure(actor)); + + return false; +} + +void InfoData::getRecipeInfo(const char* actor, InfoData::RecipeInfo& info) const { + al::ByamlIter iter; + if (getActorIter(&iter, actor)) { + info.num_items = iter.getIntByKey("normal0StuffNum"); + + info.items[0].name = iter.getStringByKey("normal0ItemName01"); + info.items[0].num = iter.getIntByKey("normal0ItemNum01"); + + info.items[1].name = iter.getStringByKey("normal0ItemName02"); + info.items[1].num = iter.getIntByKey("normal0ItemNum02"); + + info.items[2].name = iter.getStringByKey("normal0ItemName03"); + info.items[2].num = iter.getIntByKey("normal0ItemNum03"); + + } else { + info.num_items = 0; + + info.items[0].name = sead::SafeString::cEmptyString; + info.items[0].num = 0; + + info.items[1].name = sead::SafeString::cEmptyString; + info.items[1].num = 0; + + info.items[2].name = sead::SafeString::cEmptyString; + info.items[2].num = 0; + } +} + +s32 InfoData::getIntByKey(const al::ByamlIter& iter, const char* key, s32 default_) { + s32 value; + return iter.tryGetIntByKey(&value, key) ? value : default_; +} + +const char* InfoData::getStringByKey(const al::ByamlIter& iter, const char* key, + const sead::SafeString& default_) { + const char* value; + return iter.tryGetStringByKey(&value, key) ? value : default_.cstr(); +} + +[[gnu::noinline]] static InfoData::Locator::Type +getLocatorTypeFromStr(const sead::SafeString& type) { + static constexpr const char* types[] = {"Trunk", "Branch", "GlowStone", + "OnTree", "MagnePos", "StopTimerPos"}; + for (s32 i = 0; i < s32(std::size(types)); ++i) { + if (type == types[i]) + return InfoData::Locator::Type(i); + } + return InfoData::Locator::Type::Invalid; +} + +void InfoData::getLocators(const char* actor, Locators& info) const { + info.num = 0; + + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return; + + al::ByamlIter iter_locators; + if (!iter.tryGetIterByKey(&iter_locators, "locators")) + return; + + info.num = iter_locators.getSize(); + for (s32 i = 0; i < info.num; ++i) { + al::ByamlIter it; + if (!iter_locators.tryGetIterByIndex(&it, i)) + continue; + + const char* type_str{}; + auto& locator = info.locators[i]; + + it.tryGetFloatByKey(&locator.pos.x, "pos_x"); + it.tryGetFloatByKey(&locator.pos.y, "pos_y"); + it.tryGetFloatByKey(&locator.pos.z, "pos_z"); + + it.tryGetFloatByKey(&locator.rot.x, "rot_x"); + it.tryGetFloatByKey(&locator.rot.y, "rot_y"); + it.tryGetFloatByKey(&locator.rot.z, "rot_z"); + + it.tryGetStringByKey(&type_str, "type"); + locator.type = type_str ? getLocatorTypeFromStr(type_str) : Locator::Type::Invalid; + + locator.rot *= 2 * sead::numbers::pi / 360.0; + } +} + +void InfoData::getHomeAreas(const char* actor, HomeAreas& info) const { + info.names.fill(""); + + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return; + + al::ByamlIter home_area; + if (!iter.tryGetIterByKey(&home_area, "homeArea")) + return; + + for (s32 i = 0, n = home_area.getSize(); i < info.names.size() && i < n; ++i) { + al::ByamlIter it; + if (home_area.tryGetIterByIndex(&it, i)) + it.tryGetStringByKey(&info.names[i], "name"); + } +} + +// NON_MATCHING: stack +const char* InfoData::getSameGroupActorName(const char* actor) const { + al::ByamlIter iter; + if (getActorIter(&iter, actor, false)) { + al::ByamlHashIter hash_iter{iter.getRootNode()}; + al::ByamlData data; + if (hash_iter.getDataByKey(&data, mSystemSameGroupActorNameIdx)) { + const char* name; + if (iter.tryConvertString(&name, &data)) + return name; + } + } + return sead::SafeString::cEmptyString.cstr(); +} + +const char* InfoData::getString(const char* actor, const char* key, + const sead::SafeString& default_, bool x) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor, x)) + return default_.cstr(); + + return getStringByKey(iter, key, default_); +} + +const char* InfoData::getSLinkUser(const char* actor) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor)) + return "Dummy"; + + return getStringByKey(iter, "slink", "Dummy"); +} + +bool InfoData::getSLinkAndELinkUsers(const char* actor, const char** elink, + const char** slink) const { + al::ByamlIter iter; + if (getActorIter(&iter, actor)) { + *elink = getStringByKey(iter, "elink", "Dummy"); + *slink = getStringByKey(iter, "slink", "Dummy"); + return true; + } + *elink = "Dummy"; + *slink = "Dummy"; + return false; +} + +const char* InfoData::getXLinkUser(const char* actor) const { + return getString(actor, "xlink", "Dummy"); +} + +bool InfoData::getActorProfile(const char** profile, const char* actor) const { + al::ByamlIter iter; + if (getActorIter(&iter, actor)) { + al::ByamlHashIter hash_iter{iter.getRootNode()}; + al::ByamlData data; + if (hash_iter.getDataByKey(&data, mProfileIdx)) + return iter.tryConvertString(profile, &data); + } + *profile = "Dummy"; + return false; +} + +s32 InfoData::getInt(const char* actor, const char* key, s32 default_, bool x) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor, x)) + return default_; + + return getIntByKey(iter, key, default_); +} + +f32 InfoData::getFloat(const char* actor, const char* key, f32 default_, bool x) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor, x)) + return default_; + + return getFloatByKey(iter, key, default_); +} + +bool InfoData::getBool(const char* actor, const char* key, bool default_, bool x) const { + al::ByamlIter iter; + if (!getActorIter(&iter, actor, x)) + return default_; + + return getBoolByKey(iter, key, default_); +} + +f32 InfoData::getFloatByKey(const al::ByamlIter& iter, const char* key, f32 default_) { + f32 value; + return iter.tryGetFloatByKey(&value, key) ? value : default_; +} + +bool InfoData::getBoolByKey(const al::ByamlIter& iter, const char* key, bool default_) { + bool value; + return iter.tryGetBoolByKey(&value, key) ? value != 0 : default_; +} + +f32 InfoData::getScale(const char* actor) const { + return getFloat(actor, "actorScale", 1.0); +} + +} // namespace ksys::act -- cgit v1.2.3