mirror of
https://github.com/zeldaret/botw
synced 2026-06-04 10:48:32 -04:00
1273 lines
43 KiB
C++
1273 lines
43 KiB
C++
#include "KingSystem/GameData/gdtManager.h"
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <devenv/seadEnvUtil.h>
|
|
#include <framework/seadFramework.h>
|
|
#include <mc/seadCoreInfo.h>
|
|
#include <prim/seadStringUtil.h>
|
|
#include <thread/seadThreadUtil.h>
|
|
#include <time/seadTickTime.h>
|
|
#include <type_traits>
|
|
#include "Game/DLC/aocManager.h"
|
|
#include "KingSystem/GameData/gdtSaveMgr.h"
|
|
#include "KingSystem/GameData/gdtTriggerParam.h"
|
|
#include "KingSystem/Map/mapMubinIter.h"
|
|
#include "KingSystem/Resource/resEntryFactory.h"
|
|
#include "KingSystem/Resource/resLoadRequest.h"
|
|
#include "KingSystem/Resource/resResourceGameData.h"
|
|
#include "KingSystem/Resource/resSystem.h"
|
|
#include "KingSystem/System/OverlayArenaSystem.h"
|
|
#include "KingSystem/Utils/Byaml/Byaml.h"
|
|
#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
|
|
#include "KingSystem/Utils/Debug.h"
|
|
#include "KingSystem/Utils/HeapUtil.h"
|
|
#include "KingSystem/Utils/InitTimeInfo.h"
|
|
#include "KingSystem/Utils/SafeDelete.h"
|
|
|
|
namespace ksys::gdt {
|
|
|
|
SEAD_SINGLETON_DISPOSER_IMPL(Manager)
|
|
|
|
static util::InitTimeInfoEx sInitTimeInfo;
|
|
|
|
Manager::Manager() {
|
|
mRetryBuffer = nullptr;
|
|
mGimmickResetBuffer = nullptr;
|
|
mFlagBuffer1 = nullptr;
|
|
mFlagBuffer = nullptr;
|
|
}
|
|
|
|
Manager::~Manager() {
|
|
mShopGameDataInfoHandle.requestUnload();
|
|
|
|
if (mGameDataHeap) {
|
|
if (mFlagBuffer1) {
|
|
mFlagBuffer1->destroyHeap();
|
|
mFlagBuffer1 = nullptr;
|
|
}
|
|
|
|
if (mFlagBuffer) {
|
|
mFlagBuffer->destroyHeap();
|
|
mFlagBuffer = nullptr;
|
|
}
|
|
|
|
if (mRetryBuffer) {
|
|
mRetryBuffer->destroyHeap();
|
|
mRetryBuffer = nullptr;
|
|
}
|
|
|
|
if (mGimmickResetBuffer) {
|
|
mGimmickResetBuffer->destroyHeap();
|
|
mGimmickResetBuffer = nullptr;
|
|
}
|
|
|
|
if (mSaveAreaHeap) {
|
|
mSaveAreaHeap->destroy();
|
|
mSaveAreaHeap = nullptr;
|
|
}
|
|
|
|
mGameDataHeap->destroy();
|
|
mGameDataHeap = nullptr;
|
|
}
|
|
|
|
if (mGameDataComHeap) {
|
|
mGameDataComHeap->destroy();
|
|
mGameDataComHeap = nullptr;
|
|
}
|
|
}
|
|
|
|
// address differences for the static bgdata_factory that causes different regalloc
|
|
#ifdef NON_MATCHING
|
|
void Manager::init(sead::Heap* heap, sead::Framework* framework) {
|
|
sead::TickTime a;
|
|
sead::TickTime b;
|
|
|
|
mGameDataHeap = util::DualHeap::create(0xf00000, "GameDataHeap", heap, nullptr, sizeof(void*),
|
|
sead::Heap::cHeapDirection_Forward, true);
|
|
mIncreaseLogger = new (mGameDataHeap) IncreaseLogger;
|
|
SaveMgr::createInstance(mGameDataHeap);
|
|
|
|
SaveMgr::InitArg arg;
|
|
arg.heap = mGameDataHeap;
|
|
arg._8 = 0x300000;
|
|
arg.buf_size = 0x100000;
|
|
arg.buf_alignment = 0x200;
|
|
arg.size2 = 0x10000;
|
|
arg.thread_priority = sead::ThreadUtil::ConvertPrioritySeadToPlatform(18);
|
|
arg.thread_affinity = sead::CoreIdMask(sead::CoreId::cSub1);
|
|
arg._1c = 0x7000;
|
|
arg.is_demo = sead::EnvUtil::getRomType() == "Show_2017_1st";
|
|
if (sead::EnvUtil::getRomType() == "RID_Demo") {
|
|
arg.is_demo = true;
|
|
arg.save_rid_demo_dir = "Save/RID_Demo/";
|
|
}
|
|
|
|
arg._60 = nullptr;
|
|
if (util::getDebugHeap2())
|
|
arg._68 = 0x80000;
|
|
|
|
SaveMgr::instance()->init(arg);
|
|
|
|
static res::EntryFactory<res::GameData> bgdata_factory{5.0, 0xc0000};
|
|
res::registerEntryFactory(&bgdata_factory, "bgdata");
|
|
|
|
mSaveAreaHeap =
|
|
util::DualHeap::create(0x500000, "SaveAreaHeap", mGameDataHeap, nullptr, sizeof(void*),
|
|
sead::Heap::cHeapDirection_Reverse, false);
|
|
|
|
SaveMgr::instance()->loadGameSaveData();
|
|
|
|
KingEditor::instance()->registerComponent(this);
|
|
|
|
sead::FixedSafeString<1024> gamedata_sarc_path;
|
|
gamedata_sarc_path.format("%s/%s.%s", "GameData", "gamedata", "sarc");
|
|
loadGameData(gamedata_sarc_path);
|
|
|
|
sead::FixedSafeString<1024> shop_gamedata_info_path;
|
|
shop_gamedata_info_path.format("%s/%s.byml", "GameData", "ShopGameDataInfo");
|
|
loadShopGameDataInfo(shop_gamedata_info_path);
|
|
|
|
mParam.setBuffers(&mFlagBuffer1, &mFlagBuffer);
|
|
mParamBypassPerm.setBuffers(&mFlagBuffer1, &mFlagBuffer);
|
|
|
|
mMethodTreeNode.method_tree_mgr = framework->getMethodTreeMgr();
|
|
mMethodTreeNode.node.setPauseFlag(sead::MethodTreeNode::cPause_None);
|
|
|
|
mBitFlags.reset(BitFlag::_1);
|
|
unloadResources();
|
|
mBitFlags.set(BitFlag::_1000);
|
|
mNumFlagsToReset = 0;
|
|
}
|
|
#endif
|
|
|
|
void Manager::loadShopGameDataInfo(const sead::SafeString& path) {
|
|
res::LoadRequest req;
|
|
req.mRequester = "gdtManager";
|
|
req._26 = false;
|
|
if (!sead::DynamicCast<res::Resource>(mShopGameDataInfoHandle.load(path, &req)))
|
|
return;
|
|
|
|
auto* res = sead::DynamicCast<sead::DirectResource>(mShopGameDataInfoHandle.getResource());
|
|
if (!res)
|
|
return;
|
|
|
|
al::ByamlIter root{res->getRawData()};
|
|
al::ByamlIter iter;
|
|
al::ByamlIter hashes;
|
|
|
|
if (root.tryGetIterByKey(&iter, "ShopAreaInfo")) {
|
|
iter.tryGetIterByKey(&mShopAreaInfoValues, "Values");
|
|
if (iter.tryGetIterByKey(&hashes, "Hashes")) {
|
|
mShopAreaInfoHashes = al::ByamlArrayIter(hashes.getRootNode()).getDataTable();
|
|
}
|
|
}
|
|
util::PrintDebugFmt("ShopAreaInfo: %d %d", mShopAreaInfoValues.getSize(), hashes.getSize());
|
|
|
|
if (root.tryGetIterByKey(&iter, "SoldOutInfo")) {
|
|
iter.tryGetIterByKey(&mShopSoldOutInfoValues, "Values");
|
|
if (iter.tryGetIterByKey(&hashes, "Hashes")) {
|
|
mShopSoldOutInfoHashes = al::ByamlArrayIter(hashes.getRootNode()).getDataTable();
|
|
}
|
|
}
|
|
util::PrintDebugFmt("SoldOutInfo: %d %d", mShopSoldOutInfoValues.getSize(), hashes.getSize());
|
|
}
|
|
|
|
void Manager::unloadResources() {
|
|
for (s32 i = 0; i < mBgdataHandles.size(); ++i)
|
|
mBgdataHandles[i].requestUnload();
|
|
|
|
mGameDataArcHandle.requestUnload();
|
|
}
|
|
|
|
void Manager::addReinitCallback(sead::DelegateEvent<ReinitEvent*>::Slot&) {
|
|
// Stubbed in release builds.
|
|
}
|
|
|
|
void Manager::removeReinitCallback(sead::DelegateEvent<Manager::ReinitEvent*>::Slot& slot) {
|
|
// Stubbed in release builds.
|
|
}
|
|
|
|
void Manager::setCurrentRupeeFlagName(const sead::SafeString& name) {
|
|
getParam().get1().getBuffer()->setCurrentRupeeFlagName(name);
|
|
}
|
|
|
|
void Manager::requestResetAllFlagsToInitial() {
|
|
mBitFlags.set(BitFlag::RequestResetAllFlagsToInitial);
|
|
}
|
|
|
|
namespace {
|
|
|
|
template <int N>
|
|
bool loadAllFlags(Manager* mgr, sead::SafeArray<bool, N>* flags,
|
|
const sead::SafeString (&names)[N]) {
|
|
#ifdef MATCHING_HACK_NX_CLANG
|
|
#pragma clang loop unroll(full)
|
|
#endif
|
|
for (int i = 0; i < N; ++i) {
|
|
if (!mgr->getParam().get1().getBool(&(*flags)[i], names[i]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void fixDarkWoodsFlags(Manager* mgr) {
|
|
enum {
|
|
DarkWoods_Giant_Clear,
|
|
DarkWoods_Finish,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"DarkWoods_Giant_Clear",
|
|
"DarkWoods_Finish",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (!loadAllFlags(mgr, &flags, names))
|
|
return;
|
|
if (flags[DarkWoods_Giant_Clear] && !flags[DarkWoods_Finish])
|
|
mgr->getParamBypassPerm().get1().setBool(false, names[DarkWoods_Giant_Clear], true);
|
|
}
|
|
|
|
void fixGiantQuestFlags(Manager* mgr) {
|
|
enum {
|
|
giant_ball1,
|
|
giant_ball2,
|
|
giant_ball3,
|
|
giant_dungeon,
|
|
MainField_DgnObj_RemainsLithogragh_A_02_789666109,
|
|
MainField_DgnObj_RemainsLithogragh_A_02_2456751716,
|
|
MainField_DgnObj_RemainsLithogragh_A_02_1822262999,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"giant_ball1",
|
|
"giant_ball2",
|
|
"giant_ball3",
|
|
"giant_dungeon",
|
|
"MainField_DgnObj_RemainsLithogragh_A_02_789666109",
|
|
"MainField_DgnObj_RemainsLithogragh_A_02_2456751716",
|
|
"MainField_DgnObj_RemainsLithogragh_A_02_1822262999",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (!loadAllFlags(mgr, &flags, names))
|
|
return;
|
|
|
|
if (flags[giant_ball1] && !flags[MainField_DgnObj_RemainsLithogragh_A_02_789666109])
|
|
mgr->setBool(true, names[MainField_DgnObj_RemainsLithogragh_A_02_789666109]);
|
|
if (flags[giant_ball2] && !flags[MainField_DgnObj_RemainsLithogragh_A_02_2456751716])
|
|
mgr->setBool(true, names[MainField_DgnObj_RemainsLithogragh_A_02_2456751716]);
|
|
if (flags[giant_ball3] && !flags[MainField_DgnObj_RemainsLithogragh_A_02_1822262999])
|
|
mgr->setBool(true, names[MainField_DgnObj_RemainsLithogragh_A_02_1822262999]);
|
|
|
|
if (flags[giant_ball1] && flags[giant_ball2] && flags[giant_ball3] && !flags[giant_dungeon])
|
|
mgr->getParamBypassPerm().get1().setBool(true, names[giant_dungeon], true);
|
|
}
|
|
|
|
void fixBowOfLightFlag(Manager* mgr) {
|
|
enum { MainField_Weapon_Bow_071_2178255681 };
|
|
sead::SafeString names[] = {"MainField_Weapon_Bow_071_2178255681"};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (loadAllFlags(mgr, &flags, names) && flags[MainField_Weapon_Bow_071_2178255681])
|
|
mgr->setBool(false, names[MainField_Weapon_Bow_071_2178255681]);
|
|
}
|
|
|
|
void fixBalladOfHeroesFlags(Manager* mgr) {
|
|
enum {
|
|
BalladOfHeroes_Step02,
|
|
BalladOfHeroes_Step03,
|
|
Defeat_OneHitDungeon001,
|
|
Defeat_OneHitDungeon002,
|
|
Defeat_OneHitDungeon003,
|
|
Defeat_OneHitDungeon004,
|
|
Lock_OneHitDungeon001,
|
|
Lock_OneHitDungeon002,
|
|
Lock_OneHitDungeon003,
|
|
Lock_OneHitDungeon004,
|
|
BalladOfHeroes_Step02_Dungeon01,
|
|
BalladOfHeroes_Step02_Dungeon02,
|
|
BalladOfHeroes_Step02_Dungeon03,
|
|
BalladOfHeroes_Step2_Dungeon4,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"BalladOfHeroes_Step02",
|
|
"BalladOfHeroes_Step03",
|
|
//
|
|
"Defeat_OneHitDungeon001",
|
|
"Defeat_OneHitDungeon002",
|
|
"Defeat_OneHitDungeon003",
|
|
"Defeat_OneHitDungeon004",
|
|
//
|
|
"Lock_OneHitDungeon001",
|
|
"Lock_OneHitDungeon002",
|
|
"Lock_OneHitDungeon003",
|
|
"Lock_OneHitDungeon004",
|
|
//
|
|
"BalladOfHeroes_Step02_Dungeon01",
|
|
"BalladOfHeroes_Step02_Dungeon02",
|
|
"BalladOfHeroes_Step02_Dungeon03",
|
|
"BalladOfHeroes_Step2_Dungeon4",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (!loadAllFlags(mgr, &flags, names))
|
|
return;
|
|
|
|
if (!flags[BalladOfHeroes_Step02] || flags[BalladOfHeroes_Step03])
|
|
return;
|
|
|
|
s8 count = 0;
|
|
bool not_locked = false;
|
|
|
|
if (flags[Defeat_OneHitDungeon001]) {
|
|
++count;
|
|
if (!flags[Lock_OneHitDungeon001])
|
|
not_locked = true;
|
|
}
|
|
if (flags[Defeat_OneHitDungeon002]) {
|
|
++count;
|
|
if (!flags[Lock_OneHitDungeon002])
|
|
not_locked = true;
|
|
}
|
|
if (flags[Defeat_OneHitDungeon003]) {
|
|
++count;
|
|
if (!flags[Lock_OneHitDungeon003])
|
|
not_locked = true;
|
|
}
|
|
if (flags[Defeat_OneHitDungeon004]) {
|
|
++count;
|
|
if (!flags[Lock_OneHitDungeon004])
|
|
not_locked = true;
|
|
}
|
|
|
|
if (not_locked) {
|
|
if (count >= 1 && !flags[BalladOfHeroes_Step02_Dungeon01])
|
|
mgr->setBool(true, names[BalladOfHeroes_Step02_Dungeon01]);
|
|
if (count >= 2 && !flags[BalladOfHeroes_Step02_Dungeon02])
|
|
mgr->setBool(true, names[BalladOfHeroes_Step02_Dungeon02]);
|
|
if (count >= 3 && !flags[BalladOfHeroes_Step02_Dungeon03])
|
|
mgr->setBool(true, names[BalladOfHeroes_Step02_Dungeon03]);
|
|
if (count >= 4 && !flags[BalladOfHeroes_Step2_Dungeon4])
|
|
mgr->setBool(true, names[BalladOfHeroes_Step2_Dungeon4]);
|
|
}
|
|
}
|
|
|
|
void fixAllShrinesFlags(Manager* mgr) {
|
|
enum {
|
|
IsGet_Armor_005_Head,
|
|
IsGet_Armor_005_Upper,
|
|
IsGet_Armor_005_Lower,
|
|
CompleteDungeon_Finish,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"IsGet_Armor_005_Head",
|
|
"IsGet_Armor_005_Upper",
|
|
"IsGet_Armor_005_Lower",
|
|
"CompleteDungeon_Finish",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (!loadAllFlags(mgr, &flags, names))
|
|
return;
|
|
|
|
if (flags[IsGet_Armor_005_Head] && flags[IsGet_Armor_005_Upper] &&
|
|
flags[IsGet_Armor_005_Lower] && !flags[CompleteDungeon_Finish]) {
|
|
mgr->setBool(true, names[CompleteDungeon_Finish]);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void Manager::fixQuestFlags() {
|
|
fixDarkWoodsFlags(this);
|
|
fixGiantQuestFlags(this);
|
|
fixBowOfLightFlag(this);
|
|
fixBalladOfHeroesFlags(this);
|
|
fixAllShrinesFlags(this);
|
|
|
|
{
|
|
enum {
|
|
NightStoneBreak,
|
|
NightStoneDungeonAppear,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"NightStoneBreak",
|
|
"NightStoneDungeonAppear",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (loadAllFlags(this, &flags, names)) {
|
|
if (flags[NightStoneBreak] && !flags[NightStoneDungeonAppear])
|
|
getParamBypassPerm().get().setBool(false, names[NightStoneBreak], true);
|
|
}
|
|
}
|
|
|
|
{
|
|
enum {
|
|
Animal_Forest_Finish,
|
|
HateeluMini_Treasure_Finish,
|
|
Thunder_Sword_Finish,
|
|
Relief_Landing_Finish,
|
|
Shadow_Sign_Finish,
|
|
MouthofDragon_Finish,
|
|
TwoWheels_Finish,
|
|
BloodyMoonRelief_Finish,
|
|
Rito_BrosRock_Finish,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"Animal_Forest_Finish",
|
|
"HateeluMini_Treasure_Finish",
|
|
"Thunder_Sword_Finish",
|
|
"Relief_Landing_Finish",
|
|
"Shadow_Sign_Finish",
|
|
"MouthofDragon_Finish",
|
|
"TwoWheels_Finish",
|
|
"BloodyMoonRelief_Finish",
|
|
// Not a shrine quest
|
|
"Rito_BrosRock_Finish",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (loadAllFlags(this, &flags, names)) {
|
|
if (std::all_of(flags.begin(), flags.end(), [](bool b) { return b; }))
|
|
getParamBypassPerm().get().setBool(true, "Npc_Musician_Come", true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Manager::fixQuestFlagsDlc2() {
|
|
if (uking::aoc::Manager::instance()->hasAoc3())
|
|
return;
|
|
|
|
enum {
|
|
Ichigeki_Sword_Appear,
|
|
BalladOfHeroes_Retire_Dungeon04,
|
|
BalladOfHeroes_Step02,
|
|
BalladOfHeroes_Step02_Dungeon01,
|
|
BalladOfHeroes_Step02_Dungeon02,
|
|
BalladOfHeroes_Step02_Dungeon03,
|
|
BalladOfHeroes_Step2_Dungeon4,
|
|
BalladOfHeroes_Step03,
|
|
};
|
|
sead::SafeString names[] = {
|
|
"Ichigeki_Sword_Appear",
|
|
"BalladOfHeroes_Retire_Dungeon04",
|
|
// OhO plateau phase
|
|
"BalladOfHeroes_Step02",
|
|
"BalladOfHeroes_Step02_Dungeon01",
|
|
"BalladOfHeroes_Step02_Dungeon02",
|
|
"BalladOfHeroes_Step02_Dungeon03",
|
|
"BalladOfHeroes_Step2_Dungeon4",
|
|
"BalladOfHeroes_Step03",
|
|
};
|
|
sead::SafeArray<bool, std::size(names)> flags;
|
|
if (!loadAllFlags(this, &flags, names))
|
|
return;
|
|
|
|
const bool value_BalladOfHeroes_Step2_Dungeon4 = flags[BalladOfHeroes_Step2_Dungeon4];
|
|
|
|
if (!flags[BalladOfHeroes_Step02] || flags[BalladOfHeroes_Step03])
|
|
return;
|
|
|
|
setBool(false, names[BalladOfHeroes_Step2_Dungeon4]);
|
|
setBool(false, names[BalladOfHeroes_Step02_Dungeon03]);
|
|
setBool(false, names[BalladOfHeroes_Step02_Dungeon02]);
|
|
setBool(false, names[BalladOfHeroes_Step02_Dungeon01]);
|
|
setBool(false, names[BalladOfHeroes_Step02]);
|
|
if (!value_BalladOfHeroes_Step2_Dungeon4)
|
|
setBool(false, names[BalladOfHeroes_Retire_Dungeon04]);
|
|
setBool(true, names[Ichigeki_Sword_Appear]);
|
|
|
|
const char* temp_horse;
|
|
if (getParam().get().getStr64(&temp_horse, "Horse_ActorName", 5) &&
|
|
sead::SafeString(temp_horse) == "GameRomHorseBone_AllDay") {
|
|
setStr64("", "Horse_ActorName", 5);
|
|
}
|
|
}
|
|
|
|
#define GDT_SET_IMPL_(NAME, TRAITS) \
|
|
/* Setters (by name) */ \
|
|
bool Manager::NAME(TRAITS::ArgType value, const sead::SafeString& name) { \
|
|
return NAME(value, name, false, false); \
|
|
} \
|
|
bool Manager::NAME##_(TRAITS::ArgType value, const sead::SafeString& name) { \
|
|
return NAME(value, name, false, false); \
|
|
} \
|
|
bool Manager::NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name) { \
|
|
return NAME(value, name, true, false); \
|
|
} \
|
|
bool Manager::NAME##NoCheck_(TRAITS::ArgType value, const sead::SafeString& name) { \
|
|
return NAME(value, name, true, false); \
|
|
} \
|
|
bool Manager::NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, \
|
|
const sead::SafeString& name) { \
|
|
return NAME(value, name, true, true); \
|
|
} \
|
|
/* Setters for arrays (by name) */ \
|
|
bool Manager::NAME(TRAITS::ArgType value, const sead::SafeString& name, s32 sub_idx) { \
|
|
return NAME(value, name, false, false, sub_idx); \
|
|
} \
|
|
bool Manager::NAME##_(TRAITS::ArgType value, const sead::SafeString& name, s32 sub_idx) { \
|
|
return NAME(value, name, false, false, sub_idx); \
|
|
} \
|
|
bool Manager::NAME##NoCheck(TRAITS::ArgType value, const sead::SafeString& name, \
|
|
s32 sub_idx) { \
|
|
return NAME(value, name, true, false, sub_idx); \
|
|
} \
|
|
bool Manager::NAME##NoCheckForce(TRAITS::NoCheckForceArgType value, \
|
|
const sead::SafeString& name, s32 sub_idx) { \
|
|
return NAME(value, name, true, true, sub_idx); \
|
|
}
|
|
|
|
GDT_SET_IMPL_(setBool, detail::SetterTraits<bool>)
|
|
GDT_SET_IMPL_(setS32, detail::SetterTraits<s32>)
|
|
GDT_SET_IMPL_(setF32, detail::SetterTraits<f32>)
|
|
GDT_SET_IMPL_(setStr, detail::SetterTraits<const char*>)
|
|
GDT_SET_IMPL_(setStr64, detail::SetterTraits<const char*>)
|
|
GDT_SET_IMPL_(setStr256, detail::SetterTraits<const char*>)
|
|
GDT_SET_IMPL_(setVec2f, detail::SetterTraits<sead::Vector2f>)
|
|
GDT_SET_IMPL_(setVec3f, detail::SetterTraits<sead::Vector3f>)
|
|
GDT_SET_IMPL_(setVec4f, detail::SetterTraits<sead::Vector4f>)
|
|
|
|
#undef GDT_SET_IMPL_
|
|
|
|
#define GDT_RESET_IMPL_(NAME) \
|
|
bool Manager::NAME(const sead::SafeString& name) { \
|
|
if (mBitFlags.isOn(BitFlag::_40000)) \
|
|
return false; \
|
|
return getParam().get1().NAME(name); \
|
|
} \
|
|
bool Manager::NAME##_(const sead::SafeString& name) { return NAME(name); } \
|
|
bool Manager::NAME(const sead::SafeString& name, int sub_idx) { \
|
|
if (mBitFlags.isOn(BitFlag::_40000)) \
|
|
return false; \
|
|
return getParam().get1().NAME(name, sub_idx); \
|
|
}
|
|
|
|
GDT_RESET_IMPL_(resetBool)
|
|
GDT_RESET_IMPL_(resetS32)
|
|
GDT_RESET_IMPL_(resetF32)
|
|
GDT_RESET_IMPL_(resetStr)
|
|
GDT_RESET_IMPL_(resetStr64)
|
|
GDT_RESET_IMPL_(resetStr256)
|
|
GDT_RESET_IMPL_(resetVec2f)
|
|
GDT_RESET_IMPL_(resetVec3f)
|
|
GDT_RESET_IMPL_(resetVec4f)
|
|
|
|
#undef GDT_RESET_IMPL_
|
|
|
|
void Manager::incrementS32NoCheck(s32 value, const sead::SafeString& name) {
|
|
if (mBitFlags.isOn(BitFlag::_40000))
|
|
return;
|
|
|
|
if (mBitFlags.isOn(BitFlag::_10000)) {
|
|
s32 current = 0;
|
|
if (getParamBypassPerm().get().getS32(¤t, name))
|
|
setS32NoCheck(current + value, name);
|
|
} else if (mIncreaseLogger) {
|
|
mIncreaseLogger->addRecord(value, name, -1, true);
|
|
}
|
|
}
|
|
|
|
void Manager::incrementS32(s32 value, const sead::SafeString& name) {
|
|
if (mBitFlags.isOn(BitFlag::_40000))
|
|
return;
|
|
|
|
if (mBitFlags.isOn(BitFlag::_10000)) {
|
|
s32 current = 0;
|
|
if (getParam().get().getS32(¤t, name))
|
|
setS32(current + value, name);
|
|
} else if (mIncreaseLogger) {
|
|
mIncreaseLogger->addRecord(value, name, -1, false);
|
|
}
|
|
}
|
|
|
|
void Manager::IncreaseLogger::addRecord(s32 value, const sead::SafeString& name, s32 sub_idx,
|
|
bool debug) {
|
|
const u32 name_hash = sead::HashCRC32::calcStringHash(name);
|
|
const auto core = sead::CoreInfo::getCurrentCoreId();
|
|
const u32 platform_core_id = sead::CoreInfo::getPlatformCoreId(core);
|
|
|
|
Record record;
|
|
record.debug = debug;
|
|
record.name_hash = name_hash;
|
|
record.sub_idx = sub_idx;
|
|
record.value = value;
|
|
ring_buffers[0][platform_core_id].pushBack(record);
|
|
}
|
|
|
|
bool Manager::wasFlagCopied(const sead::SafeString& name) {
|
|
bool value;
|
|
return getParam().get().getBuffer()->getBoolIfCopied(&value, name, false, true) && value != 0;
|
|
}
|
|
|
|
bool Manager::wasFlagNotCopied(const sead::SafeString& name) {
|
|
bool value;
|
|
return getParam().get().getBuffer()->getBoolIfCopied(&value, name, false, true) && !value;
|
|
}
|
|
|
|
void Manager::copyParamToParam1() {
|
|
mFlagBuffer1->copyChangedFlags(*mFlagBuffer, true, false, false);
|
|
}
|
|
|
|
FlagHandle Manager::getRevivalFlagHandle(const sead::SafeString& object_name,
|
|
const map::MubinIter& iter) {
|
|
if (mBitFlags.isOn(BitFlag::_40000))
|
|
return InvalidHandle;
|
|
|
|
const sead::SafeString& map_name =
|
|
mGetMapNameDelegate ? mGetMapNameDelegate->invoke() : sead::SafeString::cEmptyString;
|
|
|
|
u32 hash_id = 0;
|
|
iter.tryGetParamUIntByKey(&hash_id, "HashId");
|
|
|
|
sead::FormatFixedSafeString<128> flag_name("%s_%s_%u", map_name.cstr(), object_name.cstr(),
|
|
hash_id);
|
|
if (mBitFlags.isOn(BitFlag::_2000))
|
|
return InvalidHandle;
|
|
return getBoolHandle(flag_name);
|
|
}
|
|
|
|
void Manager::allocParam1() {
|
|
auto* parent_heap = OverlayArenaSystem::instance()->getGameDataWorkHeap();
|
|
auto* heap = util::tryCreateDualHeap(0, "param1", parent_heap, nullptr,
|
|
sead::Heap::cHeapDirection_Forward, false);
|
|
mFlagBuffer1 = new (heap) TriggerParam;
|
|
mFlagBuffer1->copyAllFlags(*mFlagBuffer, heap, true);
|
|
heap->adjust();
|
|
}
|
|
|
|
bool Manager::getShopInfoIter(u32 hash, al::ByamlIter* out, const al::ByamlIter& iter,
|
|
const u32* hashes) {
|
|
int a = 0;
|
|
int b = iter.getSize();
|
|
while (a < b) {
|
|
const auto m = (a + b) / 2;
|
|
if (hashes[m] == hash)
|
|
return iter.tryGetIterByIndex(out, m);
|
|
if (hashes[m] < hash)
|
|
a = m + 1;
|
|
else
|
|
b = m;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Manager::allocRetryBuffer(sead::Heap* heap) {
|
|
if (mRetryBuffer)
|
|
return;
|
|
|
|
auto* buffer_heap = util::tryCreateDualHeap(0x100000, "RetryBuffer", heap, nullptr,
|
|
sead::Heap::cHeapDirection_Reverse, false);
|
|
mRetryBuffer = new (buffer_heap) TriggerParam;
|
|
mRetryBuffer->copyPermanentFlags(*mFlagBuffer1, buffer_heap);
|
|
buffer_heap->adjust();
|
|
}
|
|
|
|
void Manager::destroyRetryBuffer() {
|
|
if (mBitFlags.isOn(BitFlag::_80000))
|
|
return;
|
|
|
|
if (mRetryBuffer) {
|
|
mRetryBuffer->destroyHeap();
|
|
mRetryBuffer = nullptr;
|
|
}
|
|
}
|
|
|
|
void Manager::syncData(char* data) {
|
|
const sead::SafeString cmd = data;
|
|
if (cmd.compare("SyncStart") == 0) {
|
|
if (util::getDebugHeap()) {
|
|
if (mBitFlags.testAndClear(BitFlag::_100)) {
|
|
mSyncStep = 0;
|
|
}
|
|
mBitFlags.set(BitFlag::_200);
|
|
syncStart();
|
|
}
|
|
} else if (cmd.compare("SyncEnd") == 0) {
|
|
mSyncStep = 0;
|
|
mBitFlags.reset(BitFlag::_100);
|
|
mBitFlags.reset(BitFlag::_200);
|
|
} else {
|
|
syncUpdate(data);
|
|
onChangedByDebug();
|
|
}
|
|
}
|
|
|
|
constexpr size_t ComBufferSize = 0x1a000;
|
|
|
|
void Manager::syncStart() {
|
|
if (KingEditor::instance()->get88() == 0 || util::getDebugHeap() == nullptr)
|
|
return;
|
|
|
|
if (mGameDataComHeap) {
|
|
if (mGameDataComHeap->getFreeSize() < ComBufferSize)
|
|
return;
|
|
} else {
|
|
mGameDataComHeap =
|
|
sead::ExpHeap::tryCreate(ComBufferSize + 0x400, "GameDataCom", util::getDebugHeap(),
|
|
sizeof(void*), sead::Heap::cHeapDirection_Forward, false);
|
|
if (!mGameDataComHeap)
|
|
return;
|
|
}
|
|
|
|
u8* buffer = new (mGameDataComHeap) u8[ComBufferSize];
|
|
auto* flag_buffer = mFlagBuffer;
|
|
const int step = mSyncStep;
|
|
switch (mSyncStep) {
|
|
case 0:
|
|
doSyncArray<bool>(flag_buffer->mBoolFlags, buffer, "[SyncData][AllData][bool]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 1:
|
|
doSyncArray<s32>(flag_buffer->mS32Flags, buffer, "[SyncData][AllData][s32]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 2:
|
|
doSyncArray<f32>(flag_buffer->mF32Flags, buffer, "[SyncData][AllData][f32]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 3:
|
|
doSyncArrayStr<32>(flag_buffer->mStringFlags, buffer, "[SyncData][AllData][string]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 4:
|
|
doSyncArrayStr<64>(flag_buffer->mString64Flags, buffer, "[SyncData][AllData][string64]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 5:
|
|
doSyncArrayStr<256>(flag_buffer->mString256Flags, buffer, "[SyncData][AllData][string256]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 6:
|
|
doSyncArrayVec<sead::Vector2f>(flag_buffer->mVector2fFlags, buffer,
|
|
"[SyncData][AllData][vector2f]", 2);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 7:
|
|
doSyncArrayVec<sead::Vector3f>(flag_buffer->mVector3fFlags, buffer,
|
|
"[SyncData][AllData][vector3f]", 3);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 8:
|
|
doSyncArrayVec<sead::Vector4f>(flag_buffer->mVector4fFlags, buffer,
|
|
"[SyncData][AllData][vector4f]", 4);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 9:
|
|
doSyncArray<bool>(flag_buffer->mBoolArrayFlags, buffer, "[SyncData][AllData][boolarray]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 10:
|
|
doSyncArray<s32>(flag_buffer->mS32ArrayFlags, buffer, "[SyncData][AllData][s32array]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 11:
|
|
doSyncArray<f32>(flag_buffer->mF32ArrayFlags, buffer, "[SyncData][AllData][f32array]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 12:
|
|
doSyncArrayStr<32>(flag_buffer->mStringArrayFlags, buffer,
|
|
"[SyncData][AllData][stringarray]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 13:
|
|
doSyncArrayStr<64>(flag_buffer->mString64ArrayFlags, buffer,
|
|
"[SyncData][AllData][string64array]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 14:
|
|
doSyncArrayStr<256>(flag_buffer->mString256ArrayFlags, buffer,
|
|
"[SyncData][AllData][string256array]");
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 15:
|
|
doSyncArrayVec<sead::Vector2f>(flag_buffer->mVector2fArrayFlags, buffer,
|
|
"[SyncData][AllData][vector2farray]", 2);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 16:
|
|
doSyncArrayVec<sead::Vector3f>(flag_buffer->mVector3fArrayFlags, buffer,
|
|
"[SyncData][AllData][vector3farray]", 3);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
case 17:
|
|
doSyncArrayVec<sead::Vector4f>(flag_buffer->mVector4fArrayFlags, buffer,
|
|
"[SyncData][AllData][vector4farray]", 4);
|
|
mSyncStep = step + 1;
|
|
break;
|
|
default:
|
|
KingEditor::instance()->log(getName(), "[SendAllData]");
|
|
mBitFlags.reset(BitFlag::SyncFlags);
|
|
mBitFlags.set(BitFlag::_100);
|
|
break;
|
|
}
|
|
util::safeDeleteArray(buffer);
|
|
}
|
|
|
|
// recordFlagChange calls not being merged, or merged in the wrong way
|
|
#ifdef NON_MATCHING
|
|
void Manager::syncUpdate(const char* data) {
|
|
const sead::SafeString cmd = data;
|
|
auto it = cmd.tokenBegin("|");
|
|
const auto end = cmd.tokenEnd("|");
|
|
if (it == end)
|
|
return;
|
|
|
|
sead::FixedSafeString<256> name;
|
|
it.getAndForward(&name);
|
|
|
|
sead::FixedSafeString<256> type;
|
|
it.getAndForward(&type);
|
|
|
|
sead::FixedSafeString<256> value;
|
|
it.getAndForward(&value);
|
|
|
|
auto* tparam = mFlagBuffer1;
|
|
int idx = -1;
|
|
const u32 pl_core_id = sead::CoreInfo::getPlatformCoreId(sead::CoreInfo::getCurrentCoreId());
|
|
|
|
const auto calc_hash = [&] { return sead::HashCRC32::calcStringHash(name); };
|
|
|
|
if (type.compare("bool") == 0) {
|
|
auto* flag = tparam->getBoolFlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
bool v = false;
|
|
if (value == "true")
|
|
v = true;
|
|
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("s32") == 0) {
|
|
auto* flag = tparam->getS32FlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
s32 v = 0;
|
|
sead::StringUtil::tryParseS32(&v, value, sead::StringUtil::CardinalNumber::BaseAuto);
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("f32") == 0) {
|
|
auto* flag = tparam->getF32FlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
f32 v = 0;
|
|
sead::StringUtil::tryParseF32(&v, value);
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("string") == 0) {
|
|
auto* flag = tparam->getStrFlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("string64") == 0) {
|
|
auto* flag = tparam->getStr64FlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("string256") == 0) {
|
|
auto* flag = tparam->getStr256FlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector2f") == 0) {
|
|
auto* flag = tparam->getVec2fFlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector2f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector3f") == 0) {
|
|
auto* flag = tparam->getVec3fFlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector3f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector4f") == 0) {
|
|
auto* flag = tparam->getVec4fFlagAndIdx(&idx, calc_hash());
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector4f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx);
|
|
return;
|
|
}
|
|
|
|
sead::FixedSafeString<64> sub_idx_str{"-1"};
|
|
if (it != end)
|
|
it.getAndForward(&sub_idx_str);
|
|
const int sub_idx =
|
|
sead::StringUtil::parseS32(sub_idx_str, sead::StringUtil::CardinalNumber::BaseAuto);
|
|
|
|
if (type.compare("boolarray") == 0) {
|
|
auto* flag = tparam->getBoolFlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
bool v = false;
|
|
if (value == "true")
|
|
v = true;
|
|
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("s32array") == 0) {
|
|
auto* flag = tparam->getS32FlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
s32 v = 0;
|
|
sead::StringUtil::tryParseS32(&v, value, sead::StringUtil::CardinalNumber::BaseAuto);
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("f32array") == 0) {
|
|
auto* flag = tparam->getF32FlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
f32 v = 0;
|
|
sead::StringUtil::tryParseF32(&v, value);
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("stringarray") == 0) {
|
|
auto* flag = tparam->getStrFlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("string64array") == 0) {
|
|
auto* flag = tparam->getStr64FlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("string256array") == 0) {
|
|
auto* flag = tparam->getStr256FlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
flag->setValue(value);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector2farray") == 0) {
|
|
auto* flag = tparam->getVec2fFlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector2f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector3farray") == 0) {
|
|
auto* flag = tparam->getVec3fFlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector3f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
|
|
if (type.compare("vector4farray") == 0) {
|
|
auto* flag = tparam->getVec4fFlagAndIdx(&idx, calc_hash(), sub_idx);
|
|
if (!flag)
|
|
return;
|
|
|
|
sead::Vector4f v;
|
|
parseFloats(value, v.e.data(), v.e.size());
|
|
flag->setValue(v);
|
|
recordFlagChange(pl_core_id, tparam, flag->getType(), idx, sub_idx);
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Manager::recordFlagChange(u32 platform_core_id, TriggerParam* tparam, u8 type, const s32& idx,
|
|
const s32& sub_idx) {
|
|
auto& buffer = tparam->mFlagChangeRecords[platform_core_id].ref();
|
|
buffer[tparam->mFlagChangeRecordIndices[platform_core_id]].type.mValue = type;
|
|
buffer[tparam->mFlagChangeRecordIndices[platform_core_id]].index = idx;
|
|
buffer[tparam->mFlagChangeRecordIndices[platform_core_id]].sub_index = sub_idx;
|
|
++tparam->mFlagChangeRecordIndices[platform_core_id];
|
|
}
|
|
|
|
void Manager::startSyncOnLoadEnd() {
|
|
if (!mBitFlags.isOn(BitFlag::_100) || mBitFlags.isOn(BitFlag::_200))
|
|
return;
|
|
|
|
KingEditor::instance()->log(getName(), "[LoadEnd]");
|
|
mBitFlags.reset(BitFlag::SyncFlags);
|
|
mBitFlags.set(BitFlag::_200);
|
|
mSyncStep = 0;
|
|
syncStart();
|
|
}
|
|
|
|
void Manager::parseFloats(const sead::SafeString& str, f32* values, u32 n) {
|
|
auto it = str.tokenBegin(" ");
|
|
const auto end = str.tokenEnd(" ");
|
|
u32 i = 0;
|
|
while (end != it) {
|
|
sead::FixedSafeString<256> part;
|
|
it.getAndForward(&part);
|
|
|
|
f32 value;
|
|
if (!sead::StringUtil::tryParseF32(&value, part))
|
|
value = 0.0;
|
|
|
|
values[i++] = value;
|
|
if (i == n)
|
|
break;
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
template <typename T>
|
|
void writeToBuffer(u8* buffer, u32* written, const T& value) {
|
|
static_assert(std::is_trivially_copyable<T>());
|
|
std::memcpy(buffer + *written, &value, sizeof(value));
|
|
*written += u32(sizeof(value));
|
|
}
|
|
} // namespace
|
|
|
|
template <typename T>
|
|
void Manager::doSyncArray(const sead::PtrArray<FlagBase>& array, u8* buffer,
|
|
const char* description) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
u32 offset = 0;
|
|
const auto flush = [&] {
|
|
KingEditor::instance()->log(getName(), description, buffer, offset);
|
|
offset = 0;
|
|
};
|
|
for (FlagBase& flag : array) {
|
|
u32 written = 0;
|
|
writeToBuffer(buffer + offset, &written, flag.getHash());
|
|
if constexpr (std::is_same<bool, T>()) {
|
|
writeToBuffer(buffer + offset, &written, static_cast<Flag<T>&>(flag).getValue());
|
|
} else {
|
|
writeToBuffer(buffer + offset, &written, static_cast<Flag<T>&>(flag).getValueRef());
|
|
}
|
|
offset += written;
|
|
if (offset >= ComBufferSize - written)
|
|
flush();
|
|
}
|
|
|
|
if (offset != 0)
|
|
flush();
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
template <int N>
|
|
void Manager::doSyncArrayStr(const sead::PtrArray<FlagBase>& array, u8* buffer,
|
|
const char* description, u32 n) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
u32 offset = 0;
|
|
const auto flush = [&] {
|
|
KingEditor::instance()->log(getName(), description, buffer, offset);
|
|
offset = 0;
|
|
};
|
|
for (FlagBase& flag : array) {
|
|
const auto& flag_ = static_cast<const Flag<sead::FixedSafeString<N>>&>(flag);
|
|
u8* entry = buffer + offset;
|
|
|
|
const u32 hash = flag.getHash();
|
|
std::memcpy(entry, &hash, sizeof(hash));
|
|
|
|
const auto len = flag_.getValueRef().calcLength();
|
|
sead::MemUtil::copy(entry + sizeof(hash), flag_.getValueRef().cstr(), len);
|
|
sead::MemUtil::fillZero(entry + u32(sizeof(hash) + len), n - len);
|
|
|
|
offset += u32(sizeof(hash) + n);
|
|
if (offset >= ComBufferSize - sizeof(hash) - n)
|
|
flush();
|
|
}
|
|
|
|
if (offset != 0)
|
|
flush();
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
template <typename T>
|
|
void Manager::doSyncArrayVec(const sead::PtrArray<FlagBase>& array, u8* buffer,
|
|
const char* description, u32 n) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
u32 offset = 0;
|
|
const auto flush = [&] {
|
|
KingEditor::instance()->log(getName(), description, buffer, offset);
|
|
offset = 0;
|
|
};
|
|
for (FlagBase& flag : array) {
|
|
const auto& flag_ = static_cast<const Flag<T>&>(flag);
|
|
u32 written = 0;
|
|
writeToBuffer(buffer + offset, &written, flag.getHash());
|
|
|
|
for (u32 i = 0; i != n; ++i)
|
|
writeToBuffer(buffer + offset, &written, flag_.getValueRef().e[i]);
|
|
|
|
offset += written;
|
|
/// @bug "n" should be "sizeof(f32) * n" instead.
|
|
if (offset >= ComBufferSize - sizeof(u32) - n)
|
|
flush();
|
|
}
|
|
|
|
if (offset != 0)
|
|
flush();
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
template <typename T>
|
|
void Manager::doSyncArray(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer,
|
|
const char* description) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
for (auto& flags : array) {
|
|
u32 written = [&] {
|
|
u32 offset = 0;
|
|
|
|
auto it = flags.begin();
|
|
const auto end = flags.end();
|
|
writeToBuffer(buffer, &offset, flags[0]->getHash());
|
|
|
|
for (; it != end; ++it) {
|
|
writeToBuffer(buffer, &offset, static_cast<Flag<T>&>(*it).getValueRef());
|
|
if (offset >= ComBufferSize - sizeof(T))
|
|
break;
|
|
}
|
|
return offset;
|
|
}();
|
|
|
|
if (written != 0)
|
|
KingEditor::instance()->log(getName(), description, buffer, written);
|
|
}
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
template <int N>
|
|
void Manager::doSyncArrayStr(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer,
|
|
const char* description, u32 n) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
for (auto& flags : array) {
|
|
u32 written = [&] {
|
|
u32 offset = 0;
|
|
|
|
auto it = flags.begin();
|
|
const auto end = flags.end();
|
|
writeToBuffer(buffer, &offset, flags[0]->getHash());
|
|
|
|
for (; it != end; ++it) {
|
|
const auto& flag = static_cast<const Flag<sead::FixedSafeString<N>>&>(*it);
|
|
|
|
const auto len = flag.getValueRef().calcLength();
|
|
sead::MemUtil::copy(buffer + offset, flag.getValueRef().cstr(), len);
|
|
sead::MemUtil::fillZero(buffer + u32(offset + len), n - len);
|
|
offset += n;
|
|
|
|
if (offset >= u32(ComBufferSize) - n)
|
|
break;
|
|
}
|
|
return offset;
|
|
}();
|
|
|
|
if (written != 0)
|
|
KingEditor::instance()->log(getName(), description, buffer, written);
|
|
}
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
template <typename T>
|
|
static u32 syncOneVec(Manager*, u8* buffer, const sead::PtrArray<FlagBase>& flags, u32 n) {
|
|
u32 offset = 0;
|
|
|
|
auto it = flags.begin();
|
|
const auto end = flags.end();
|
|
writeToBuffer(buffer, &offset, flags[0]->getHash());
|
|
|
|
for (; it != end; ++it) {
|
|
for (u32 i = 0; i < n; ++i)
|
|
writeToBuffer(buffer, &offset, static_cast<const Flag<T>&>(*it).getValueRef().e[i]);
|
|
|
|
if (offset >= u32(ComBufferSize) - n)
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
template <typename T>
|
|
void Manager::doSyncArrayVec(const sead::PtrArray<sead::PtrArray<FlagBase>>& array, u8* buffer,
|
|
const char* description, u32 n) {
|
|
KingEditor::instance()->log(getName(), "[ArrayStart]");
|
|
|
|
for (auto& flags : array) {
|
|
u32 written = syncOneVec<T>(this, buffer, flags, n);
|
|
if (written != 0)
|
|
KingEditor::instance()->log(getName(), description, buffer, written);
|
|
}
|
|
|
|
KingEditor::instance()->log(getName(), "[ArrayEnd]");
|
|
}
|
|
|
|
} // namespace ksys::gdt
|