From c017dc5ba5595deda8599e88e87a3d759fea9e3c Mon Sep 17 00:00:00 2001 From: Amelia <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 24 Nov 2025 08:51:33 +0000 Subject: [PATCH 01/64] Add contributors to CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..de38604 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,2 @@ +AmeliaCute +EltyDev From 34b601ab346322858b5524b392f6be5632679dfe Mon Sep 17 00:00:00 2001 From: Amelia <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 24 Nov 2025 08:55:13 +0000 Subject: [PATCH 02/64] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..49bc779 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,43 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG REPORT] " +labels: bug +assignees: AmeliaCute, EltyDev + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +``` + + + +``` + + +**Expected behavior** +``` + + + +``` + +**Screenshots / Videos** +If applicable, add screenshots to help explain your problem. + +FLiAPI Version: `1.10` + +Mod list: +``` +- +- + +``` + + +**Additional context** +Add any other context about the problem here. From da5766f175d8a8dc8afefd801e6cb99c56305fbb Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:49:51 +0000 Subject: [PATCH 03/64] WIP --- include | 2 +- src/API/Skill/SkillData.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include b/include index 9183e5a..6698453 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 9183e5ac82d7e1ecf46e69cdac4337c9449484bb +Subproject commit 6698453ddc9fabb9976e287bcc4794194c7f648f diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index b325204..b8691db 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,5 +1,4 @@ #include "API/Skill/SkillData.hpp" -#include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" void SkillData::SetName(LANG lang, FString string) From b2a4dc5cf04e11e4bd4975be001de33fa4c9f924 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:56:33 +0000 Subject: [PATCH 04/64] EXPERIMENTAL: add GameRegistries --- CMakeLists.txt | 4 ++-- include | 2 +- src/GameRegistries.cpp | 26 ++++++++++++++++++++++++++ src/ModLoader.cpp | 5 +++++ 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/GameRegistries.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b73f02..a951148 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") -target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file +target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file diff --git a/include b/include index 6698453..a6c98f2 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 6698453ddc9fabb9976e287bcc4794194c7f648f +Subproject commit a6c98f27169b3f68441bd881f001735835f150f2 diff --git a/src/GameRegistries.cpp b/src/GameRegistries.cpp new file mode 100644 index 0000000..a7deeae --- /dev/null +++ b/src/GameRegistries.cpp @@ -0,0 +1,26 @@ +#include "GameRegistries.hpp" +#include "GameData.hpp" +#include "ModLoader.hpp" +#include "SDK/DP1Project.h" + +WrappedRegistry* GameRegistries::ITEM_MATERIAL = nullptr; + +void GameRegistries::init(GameData* gameData) +{ + ModLoader::logger->verbose("Initialize Game Registries"); + auto* sdm = gameData->getStaticDataManager(); + + bindItem(sdm); +} + +void GameRegistries::bindItem(UStaticDataManager* sdm) +{ + ModLoader::gameData->waitObject(&sdm->m_ItemMaterialData); + ITEM_MATERIAL = new WrappedRegistry(); + ITEM_MATERIAL->Bind(&sdm->m_ItemMaterialData->m_dataMap); + ITEM_MATERIAL->BuildIndex(); + ModLoader::logger->verbose("Binded Material Item Registry!"); + +} + + \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 49ab4f7..78c5583 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,6 +1,7 @@ #include "ModLoader.hpp" #include "GameCache.hpp" #include "GameData.hpp" +#include "GameRegistries.hpp" #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" @@ -29,6 +30,10 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) gameData->init(); gameCache = new GameCache(); + + GameRegistries* gameReg = new GameRegistries(); + gameReg->init(gameData); + configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); From 327c9c5f39c304100ab801eb308732c0c3ccd1ea Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 12:51:56 +0000 Subject: [PATCH 05/64] WIP --- include | 2 +- src/ModLoader.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/include b/include index 9183e5a..820aa20 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 9183e5ac82d7e1ecf46e69cdac4337c9449484bb +Subproject commit 820aa2019b270afa5f8c2fe1a3497ef70d7fe1d2 diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 49ab4f7..e898d9c 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -17,10 +17,7 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); - // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? - std::this_thread::sleep_for(std::chrono::milliseconds(200)); Patcher patcher; - logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); From 8e04408ee2e498346a404fe4410d8b41501fc639 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:10:16 +0000 Subject: [PATCH 06/64] Update offsets for GObjects, GNames, and GWorld in Offset.h --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index 0eff87d..9a00f65 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 0eff87d9f0c2983260666c366173018925dcef96 +Subproject commit 9a00f65bd1c8ef365956078fc5c0afe04ec0dbfd From ba838b0260550191f5fdaa8da0a88ae90fec0119 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 24 Dec 2025 13:11:08 +0000 Subject: [PATCH 07/64] [skip ci] update include submodule to latest main --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index 9a00f65..0eff87d 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 9a00f65bd1c8ef365956078fc5c0afe04ec0dbfd +Subproject commit 0eff87d9f0c2983260666c366173018925dcef96 From ff5bd77a94d24dc2e7b2ae231bc00f4a89ce418d Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:15:48 +0000 Subject: [PATCH 08/64] update submodule to latest commit --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index 0eff87d..9a9aac2 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 0eff87d9f0c2983260666c366173018925dcef96 +Subproject commit 9a9aac298dc96e87bf250a26aa722e30bd685377 From a2bd4c388c26540427cd57ba2ea85a7e216f1065 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:17:58 +0000 Subject: [PATCH 09/64] MAIS LAISSE MOI PR --- src/ModLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 2a193a5..8625c73 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -22,6 +22,7 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache->PostLoadCache(); gameData->initOthersData(); modEnvironnement->PostLoad(); + return 0; } From 0be4bccba413feb2d5197354cbf39169ddbcf6ca Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 14:07:47 +0000 Subject: [PATCH 10/64] AAAAAAAAAAA --- CMakeLists.txt | 2 +- include | 2 +- src/ModLoader.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9989f2c..58c45a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(FantasyLifeI-ModLoader LANGUAGES CXX C) set(VERSION 1.00) -option(MLDEBUG "Enable ModLoader debug code" OFF) +option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED src/ModLoader.cpp) diff --git a/include b/include index 9a9aac2..dc60be9 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 9a9aac298dc96e87bf250a26aa722e30bd685377 +Subproject commit dc60be9af0aecda7ac92f091dd4ae3035b7d1e07 diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 8625c73..3284072 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -11,8 +11,8 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { logger->info("Mod loader has been started"); Patcher patcher; uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); - patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); - patcher.applyPatches(baseAddress); + // patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); broken????? + // patcher.applyPatches(baseAddress); gameData = new GameData(reinterpret_cast(GetModuleHandle(nullptr))); gameCache = new GameCache(); @@ -22,7 +22,7 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache->PostLoadCache(); gameData->initOthersData(); modEnvironnement->PostLoad(); - + return 0; } From 7242e37eaaf48c44f19762d22cbcf2b869dae2c2 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:37:28 +0000 Subject: [PATCH 11/64] Update includes --- include | 2 +- src/ModLoader.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include b/include index 820aa20..425d7d1 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 820aa2019b270afa5f8c2fe1a3497ef70d7fe1d2 +Subproject commit 425d7d148bd4b4b1757d27887c4c7fb477fd17cb diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index e898d9c..96663ec 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -17,11 +17,13 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + Patcher patcher; logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); - patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); - patcher.applyPatches(baseAddress); + // patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); + // patcher.applyPatches(baseAddress); gameData = new GameData(baseAddress, moduleInfo->SizeOfImage); gameData->init(); From e43d96dff5401cc98da24ccff55657ffa39277d3 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 17 Sep 2025 09:22:18 +0100 Subject: [PATCH 12/64] WIP --- src/API/Common/CommonItemEffectParam.cpp | 13 +++++++++++++ src/API/Entities/Player/Player.cpp | 20 ++++++++++---------- src/API/Item/ItemData.cpp | 6 +++--- 3 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 src/API/Common/CommonItemEffectParam.cpp diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp new file mode 100644 index 0000000..ab2b83b --- /dev/null +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -0,0 +1,13 @@ +#include "API/Common/CommonItemEffectParam.hpp" +#include "Utils.hpp" +#include "Common.hpp" + +std::string CommonItemEffectParam::getDescIdentifier() +{ + return Utils::FNameToString(this->_object.effDescId); +} + +std::string CommonItemEffectParam::GetDescription(LANG lang) +{ + return DESC_GET(lang, getDescIdentifier()); +} diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index 664748b..c817c61 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -5,30 +5,30 @@ Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} -ELifeType Player::getLifeType() { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.getPermanentStatus()); +ELifeType Player::GetLifeType() { + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; return static_cast(std::stoi(lifeId.c_str() + 4)); } -void Player::setExp(ELifeType life, uint32_t exp) { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.getPermanentStatus()); +void Player::SetExp(ELifeType life, uint32_t exp) { + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); avatarStatus->m_exp.Data[static_cast(life) - 1].Value.Second = exp; } -uint32_t Player::getExp(ELifeType life) { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.getPermanentStatus()); +uint32_t Player::GetExp(ELifeType life) { + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); return avatarStatus->m_exp.Data[static_cast(life) - 1].Value.Second; } -void Player::setLevel(ELifeType life, uint16_t lvl) { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.getPermanentStatus()); +void Player::SetLevel(ELifeType life, uint16_t lvl) { + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); avatarStatus->m_lv.Data[static_cast(life) - 1].Value.Second = lvl; } -uint16_t Player::getLevel(ELifeType life) { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.getPermanentStatus()); +uint16_t Player::GetLevel(ELifeType life) { + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); return avatarStatus->m_lv.Data[static_cast(life) - 1].Value.Second; } \ No newline at end of file diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index 87d136a..63c6bcd 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -8,7 +8,7 @@ std::string ItemData::GetIdentifier() return Utils::FNameToString(this->_object.ID); } -std::string ItemData::GetNameIdentifier() +std::string ItemData::getNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } @@ -20,12 +20,12 @@ std::string ItemData::GetDescIdentifier() std::string ItemData::GetName(LANG lang) { - return NAME_GET(lang, GetNameIdentifier()); + return NAME_GET(lang, getNameIdentifier()); } void ItemData::SetName(LANG lang, FString string) { - NAME_SET(lang, GetNameIdentifier(), string); + NAME_SET(lang, getNameIdentifier(), string); } std::string ItemData::GetDescription(LANG lang) From b9a2f9a7d1d0671db513b63708fdcb57235aaee9 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Fri, 19 Sep 2025 06:15:11 +0100 Subject: [PATCH 13/64] Cleaning and Adding functions --- src/API/Entities/EntityStats.cpp | 42 +++++++++++++++---------------- src/API/Entities/EntityStatus.cpp | 12 ++++----- src/API/Item/ItemEquipData.cpp | 19 ++++++++++++-- src/GameCache.cpp | 13 ++++++++++ 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/API/Entities/EntityStats.cpp b/src/API/Entities/EntityStats.cpp index ab55cb4..1365b1a 100644 --- a/src/API/Entities/EntityStats.cpp +++ b/src/API/Entities/EntityStats.cpp @@ -1,58 +1,58 @@ #include "API/Entities/EntityStats.hpp" -void EntityStats::setPhysicalAttack(ELifeType life, int32_t physicalAttack) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +void EntityStats::SetPhysicalAttack(ELifeType life, int32_t physicalAttack) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); param.baseParamMin.physicalOffense = physicalAttack; } -void EntityStats::setMagicalAttack(ELifeType life, int32_t magicalAttack) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +void EntityStats::SetMagicalAttack(ELifeType life, int32_t magicalAttack) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); param.baseParamMin.magicOffense = magicalAttack; } -void EntityStats::setPhysicalDefense(ELifeType life, int32_t physicalDefense) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +void EntityStats::SetPhysicalDefense(ELifeType life, int32_t physicalDefense) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); param.baseParamMin.physicalDefense = physicalDefense; } -void EntityStats::setMagicalDefense(ELifeType life, int32_t magicalDefense) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +void EntityStats::SetMagicalDefense(ELifeType life, int32_t magicalDefense) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); param.baseParamMin.magicDefense = magicalDefense; } -FGDCharaParameter_CharaStatusParam &EntityStats::_getParamFrom(ELifeType life) { +FGDCharaParameter_CharaStatusParam &EntityStats::getParamFrom(ELifeType life) { int index = static_cast(life) - 1; if (!this->_object.charaStatusParamList.Data.IsValidIndex(index)) throw std::out_of_range("Invalid index"); return this->_object.charaStatusParamList.Data[index].Value.Second; } -int32_t EntityStats::getPhysicalAttack(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetPhysicalAttack(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.physicalOffense; } -int32_t EntityStats::getMagicalAttack(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetMagicalAttack(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.magicOffense; } -int32_t EntityStats::getPhysicalDefense(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetPhysicalDefense(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.physicalDefense; } -int32_t EntityStats::getMagicalDefense(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetMagicalDefense(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.magicDefense; } -int32_t EntityStats::getCriticalRate(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetCriticalRate(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.criticalRate; } -int32_t EntityStats::getCriticalRateEvasion(ELifeType life) { - FGDCharaParameter_CharaStatusParam ¶m = this->_getParamFrom(life); +int32_t EntityStats::GetCriticalRateEvasion(ELifeType life) { + FGDCharaParameter_CharaStatusParam ¶m = this->getParamFrom(life); return param.baseParamMin.criticalRateEvasion; } \ No newline at end of file diff --git a/src/API/Entities/EntityStatus.cpp b/src/API/Entities/EntityStatus.cpp index bd345cd..5846d1d 100644 --- a/src/API/Entities/EntityStatus.cpp +++ b/src/API/Entities/EntityStatus.cpp @@ -1,27 +1,27 @@ #include "API/Entities/EntityStatus.hpp" -void EntityStatus::setHP(uint32_t hp) { +void EntityStatus::SetHP(uint32_t hp) { this->_permanentStatus.m_nowHp = hp; this->_volatileStatus.m_maxHP = hp; } -void EntityStatus::setSP(uint32_t sp) { +void EntityStatus::SetSP(uint32_t sp) { this->_permanentStatus.m_nowSp = sp; this->_volatileStatus.m_maxSP = sp; } -uint32_t EntityStatus::getHP() { +uint32_t EntityStatus::GetHP() { return this->_permanentStatus.m_nowHp; } -uint32_t EntityStatus::getSP() { +uint32_t EntityStatus::GetSP() { return this->_permanentStatus.m_nowSp; } -FCharaStatusP &EntityStatus::getPermanentStatus() { +FCharaStatusP &EntityStatus::GetPermanentStatus() { return this->_permanentStatus; } -FAvatarCharaStatusV &EntityStatus::getVolatileStatus() { +FAvatarCharaStatusV &EntityStatus::GetVolatileStatus() { return this->_volatileStatus; } \ No newline at end of file diff --git a/src/API/Item/ItemEquipData.cpp b/src/API/Item/ItemEquipData.cpp index c2584a8..e2994eb 100644 --- a/src/API/Item/ItemEquipData.cpp +++ b/src/API/Item/ItemEquipData.cpp @@ -1,12 +1,27 @@ #include "API/Item/ItemEquipData.hpp" +#include "API/Engine/TArrayHelper.hpp" #include "Utils.hpp" +#include "ModLoader.hpp" std::string ItemEquipData::GetModelIdentifier() { - return Utils::FNameToString(reinterpret_cast(&this->_object)->modelID); + return Utils::FNameToString(static_cast(this->_object).modelID); } void ItemEquipData::SetModel(ItemEquipData item) { - reinterpret_cast(&this->_object)->modelID = reinterpret_cast(&item.getObject())->modelID; + static_cast(this->_object).modelID = static_cast(this->_object).modelID; } + +TArray& ItemEquipData::GetAddSkillLot(int rarity) +{ + auto skillIdRaw = TArrayHelper::Get(static_cast(this->_object).addSkillLotTableList, rarity); + std::string skillId = Utils::FNameToString(skillIdRaw); + + return ModLoader::gameCache->GetAddSkillTable(skillId); +} + +void ItemEquipData::SetAddSkillTable(int rarity, FName value) +{ + TArrayHelper::Set(static_cast(this->_object).addSkillLotTableList, rarity, value); +} \ No newline at end of file diff --git a/src/GameCache.cpp b/src/GameCache.cpp index 1808500..0858779 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -36,6 +36,9 @@ GameCache::GameCache() initChara(gmd, sdm); ModLoader::logger->verbose("Cached: Basic Chara Registries"); + + initAddSkillTable(gmd, sdm); + ModLoader::logger->verbose("Cached: AddSkillTable Registries"); } void GameCache::PostLoadCache() @@ -531,4 +534,14 @@ void GameCache::initMap(GameData* gmd, UStaticDataManager* sdm) _cacheMap.emplace(map.GetIdentifier(), std::make_unique(map)); } +} + +void GameCache::initAddSkillTable(GameData* gmd, UStaticDataManager* sdm) +{ + gmd->waitObject(&sdm->m_AddSkillLotTable); + for (int i = 0; i < sdm->m_AddSkillLotTable->m_dataMap.Data.Count; i++) + { + std::string key = Utils::FNameToString(sdm->m_AddSkillLotTable->m_dataMap.Data[i].Value.First); + this->_cacheAddSkillLotTable.emplace(key, &sdm->m_AddSkillLotTable->m_dataMap.Data[i].Value.Second.addSkillInfoList); + } } \ No newline at end of file From 818c6adc88981d71addc0e032329375d31c5b908 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:29:40 +0100 Subject: [PATCH 14/64] Include fixes --- src/API/Common/CommonItemEffectParam.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index ab2b83b..83c4809 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -1,6 +1,7 @@ #include "API/Common/CommonItemEffectParam.hpp" +#include "API/Common/Common.hpp" + #include "Utils.hpp" -#include "Common.hpp" std::string CommonItemEffectParam::getDescIdentifier() { From c37626307db3dfee9a999648274422001c4670da Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:38:48 +0100 Subject: [PATCH 15/64] Switching to CLANG --- .clangd | 7 +++++++ .gitignore | 18 +++++++++++++++--- CMakeLists.txt | 13 +++++++------ DllProxy/CMakeLists.txt | 11 ++++------- DllProxy/src/dllmain.cpp | 4 ---- README.md | 15 ++++++++++++++- src/API/Common/Common.cpp | 10 +++++----- src/API/Common/CommonItemEffectParam.cpp | 2 +- src/API/Common/CommonItemTableSetting.cpp | 2 +- src/API/Common/CommonPickParamData.cpp | 4 ++-- src/API/Entities/CharaData.cpp | 7 +++---- src/API/Entities/Player/Player.cpp | 2 -- src/API/Item/ItemData.cpp | 11 +++++------ src/API/Life/LifeData.cpp | 7 ++----- src/API/Life/ULifeData.cpp | 4 ++-- src/API/Recipe/RecipeData.cpp | 5 ++--- src/API/Skill/SkillData.cpp | 8 +++----- src/API/Skill/SkillEffectInfo.cpp | 2 -- src/API/Table/ItemTableDetail.cpp | 2 +- src/API/World/MapData.cpp | 14 ++++++-------- src/API/World/MapDataSubMapData.cpp | 4 ++-- src/API/World/MapSubLevel.cpp | 6 +++--- src/Hook/EventHandler.cpp | 3 --- src/Hook/MemoryHelper.cpp | 1 + src/ModEnvironnement.cpp | 11 +++++------ src/ModLoader.cpp | 4 +++- src/Utils.cpp | 2 ++ 27 files changed, 96 insertions(+), 83 deletions(-) create mode 100644 .clangd diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..1f41e26 --- /dev/null +++ b/.clangd @@ -0,0 +1,7 @@ +CompileFlags: + Add: [-std=c++20] + +If: + PathMatch: include/SDK.h +Diagnostics: + UnusedIncludes: None \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5145fdc..4713cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,22 @@ +#Exclude ALL FILES * +#Except : + +# Dll Proxy +!DllProxy +!DllProxy/**/* + +# Source codes !include/ !include/**/* !src/ !src/**/* -#!CMakeLists.txt + +# Configuration and documentation +!CMakeLists.txt +!.clangd !README.md + +# Git Action !.github/ -!.github/**/* -!version_proxy.def \ No newline at end of file +!.github/**/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 58c45a0..00d01ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,15 +16,18 @@ set_target_properties(${PROJECT_NAME} PROPERTIES target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED) target_compile_definitions(${PROJECT_NAME} PRIVATE MLVERSION=${VERSION}) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(${PROJECT_NAME} PRIVATE + "-Wno-inconsistent-dllimport" + "-Wno-dllimport-static-field-def" + ) +endif() + if(MLDEBUG) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") - - if(MSVC) - target_compile_options(FantasyLifeI-ModLoader PRIVATE /wd4369 /wd4309) - endif() endif() target_include_directories(${PROJECT_NAME} PUBLIC @@ -37,8 +40,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC ) target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c) -target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/miniz) -target_compile_definitions(${PROJECT_NAME} PRIVATE MZ_ZIP_READER_ONLY) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") target_sources(${PROJECT_NAME} PUBLIC diff --git a/DllProxy/CMakeLists.txt b/DllProxy/CMakeLists.txt index bfbe086..bb2b2b7 100644 --- a/DllProxy/CMakeLists.txt +++ b/DllProxy/CMakeLists.txt @@ -5,22 +5,19 @@ add_library(${PROJECT_NAME} SHARED src/dllmain.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "version" - CXX_STANDARD 17 + CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES + LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/version_proxy.def" ) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) - -if(MSVC) - target_compile_options(${PROJECT_NAME} PRIVATE /MT /EHsc /DWIN32_LEAN_AND_MEAN) - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/version_proxy.def") -endif() - +target_compile_definitions(${PROJECT_NAME} PRIVATE WIN32_LEAN_AND_MEAN) target_link_libraries(${PROJECT_NAME} PUBLIC user32 kernel32 + shlwapi ) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") diff --git a/DllProxy/src/dllmain.cpp b/DllProxy/src/dllmain.cpp index 91a1157..0c97efb 100644 --- a/DllProxy/src/dllmain.cpp +++ b/DllProxy/src/dllmain.cpp @@ -1,9 +1,5 @@ -#define WIN32_LEAN_AND_MEAN #include #include -#pragma comment(lib, "Shlwapi.lib") -#pragma comment(linker, "/DLL") - static HMODULE hOriginal = NULL; // If needed we can load multiple DLLs diff --git a/README.md b/README.md index 9bf3e42..aa84962 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Fantasy Life I Mod Loader > [!IMPORTANT] -> HEY!!! This mod loader is currently under development.. Somes features work (about 20%-30%??) but some things might break if you try weird stuff, that said, if you take your time and experiment a little you can already pull off some pretty cool things +> HEY!!! This mod loader is currently under development.. Somes features work (about 25%-35%??) but some things might break if you try weird stuff, that said, if you take your time and experiment a little you can already pull off some pretty cool things > If you're interested in supporting the project, contributions are welcome! Feel free to open a Pull Request!! ### How to install the Mod Loader @@ -53,3 +53,16 @@ Fantasy Life I/ ├── MyMod.fliarchive └── OtherMod.fliarchive ``` + +### Build the ModLoader + +```bash + $ cmake -B build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DMLDEBUG=OFF +``` +> [!NOTE] +> For debugging u might need to set MLDEBUG to ON: `-DMLDEBUG=OFF` +> But it's only if you need the pdb, otherwise let the option off. + +```bash + $ cmake --build build --config Release +``` \ No newline at end of file diff --git a/src/API/Common/Common.cpp b/src/API/Common/Common.cpp index 0556a6f..1f10028 100644 --- a/src/API/Common/Common.cpp +++ b/src/API/Common/Common.cpp @@ -2,9 +2,9 @@ #include "ModLoader.hpp" #include "GameCache.hpp" -std::string Common::NounSingular(LANG lang, std::string identifier) +std::string Common::NounSingular(LANG lang, std::string& identifier) { - if(identifier == "None") return "NO_NAME"; + if(identifier == "None") return nullptr; auto text = ModLoader::gameCache->GetNoun(identifier); switch(lang) { @@ -22,7 +22,7 @@ std::string Common::NounSingular(LANG lang, std::string identifier) return text->nounSingularForm.ToString(); } -void Common::NounSingularSet(LANG lang, std::string identifier, FString value) +void Common::NounSingularSet(LANG lang, std::string& identifier, FString value) { if(identifier == "None") { @@ -45,7 +45,7 @@ void Common::NounSingularSet(LANG lang, std::string identifier, FString value) } } -std::string Common::Description(LANG lang, std::string identifier) +std::string Common::Description(LANG lang, std::string& identifier) { auto text = ModLoader::gameCache->GetText(identifier); switch(lang) @@ -64,7 +64,7 @@ std::string Common::Description(LANG lang, std::string identifier) return text->Text.ToString(); } -void Common::DescriptionSet(LANG lang, std::string identifier, FString value) +void Common::DescriptionSet(LANG lang, std::string &identifier, FString value) { if(identifier == "desc_itm_common") { diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 83c4809..4e35d66 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -3,7 +3,7 @@ #include "Utils.hpp" -std::string CommonItemEffectParam::getDescIdentifier() +std::string& CommonItemEffectParam::getDescIdentifier() { return Utils::FNameToString(this->_object.effDescId); } diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index d5c2351..a730092 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -2,7 +2,7 @@ #include "Utils.hpp" #include "API/Engine/TArrayHelper.hpp" -std::string CommonItemTableSetting::GetIdentifier() +std::string& CommonItemTableSetting::GetIdentifier() { return Utils::FNameToString(this->_object.tableId); } diff --git a/src/API/Common/CommonPickParamData.cpp b/src/API/Common/CommonPickParamData.cpp index f57d706..aba585f 100644 --- a/src/API/Common/CommonPickParamData.cpp +++ b/src/API/Common/CommonPickParamData.cpp @@ -1,12 +1,12 @@ #include "API/Common/CommonPickParamData.hpp" #include "Utils.hpp" -std::string CommonPickParamData::GetIdentifier() +std::string& CommonPickParamData::GetIdentifier() { return Utils::FNameToString(this->_object.ID); } -std::string CommonPickParamData::GetGotIdentifier() +std::string& CommonPickParamData::GetGotIdentifier() { return Utils::FNameToString(this->_object.gotId); } \ No newline at end of file diff --git a/src/API/Entities/CharaData.cpp b/src/API/Entities/CharaData.cpp index 7be32af..8ef5d39 100644 --- a/src/API/Entities/CharaData.cpp +++ b/src/API/Entities/CharaData.cpp @@ -1,14 +1,13 @@ #include "API/Entities/CharaData.hpp" -#include "GameCache.hpp" -#include "ModLoader.hpp" #include "API/Common/Common.hpp" +#include "Utils.hpp" -std::string CharaData::GetIdentifier() +std::string& CharaData::GetIdentifier() { return Utils::FNameToString(this->_object.ID); } -std::string CharaData::GetNameIdentifier() +std::string& CharaData::GetNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index c817c61..7c58850 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,7 +1,5 @@ - #include "API/Entities/Player/Player.hpp" #include "Utils.hpp" -#include "ModLoader.hpp" Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index 63c6bcd..3856e79 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -1,19 +1,18 @@ #include "API/Item/ItemData.hpp" -#include "ModLoader.hpp" -#include "GameCache.hpp" #include "API/Common/Common.hpp" +#include "Utils.hpp" -std::string ItemData::GetIdentifier() +std::string& ItemData::GetIdentifier() { return Utils::FNameToString(this->_object.ID); } -std::string ItemData::getNameIdentifier() +std::string& ItemData::getNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } -std::string ItemData::GetDescIdentifier() +std::string& ItemData::GetDescIdentifier() { return Utils::FNameToString(this->_object.DescId); } @@ -38,7 +37,7 @@ void ItemData::SetDescription(LANG lang, FString string) DESC_SET(lang, GetDescIdentifier(), string); } -std::string ItemData::GetOverwriteIcon() +std::string& ItemData::GetOverwriteIcon() { return Utils::FNameToString(this->_object.overwriteIconName); } \ No newline at end of file diff --git a/src/API/Life/LifeData.cpp b/src/API/Life/LifeData.cpp index 432a595..f6d3ece 100644 --- a/src/API/Life/LifeData.cpp +++ b/src/API/Life/LifeData.cpp @@ -1,16 +1,13 @@ #include "API/Life/LifeData.hpp" -#include "GameData.hpp" #include "Utils.hpp" -#include "ModLoader.hpp" -#include "GameCache.hpp" #include "API/Common/Common.hpp" -std::string LifeData::GetNameIdentifier() +std::string& LifeData::GetNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } -std::string LifeData::GetDescIdentifier() +std::string& LifeData::GetDescIdentifier() { return Utils::FNameToString(this->_object.DescId); } diff --git a/src/API/Life/ULifeData.cpp b/src/API/Life/ULifeData.cpp index f29c062..7195397 100644 --- a/src/API/Life/ULifeData.cpp +++ b/src/API/Life/ULifeData.cpp @@ -1,5 +1,5 @@ -#include "Api/Life/ULifeData.hpp" -#include "API/Engine/TArrayHelper.hpp" +#include "API/Life/ULifeData.hpp" +#include "API/Life/LifeData.hpp" LifeData ULifeData::GetLife(ELifeType life) { diff --git a/src/API/Recipe/RecipeData.cpp b/src/API/Recipe/RecipeData.cpp index a5cde6f..883cfc3 100644 --- a/src/API/Recipe/RecipeData.cpp +++ b/src/API/Recipe/RecipeData.cpp @@ -1,16 +1,15 @@ #include "API/Recipe/RecipeData.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -#include #include "API/Engine/TArrayHelper.hpp" -std::string RecipeData::GetIdentifier() +std::string& RecipeData::GetIdentifier() { return Utils::FNameToString(this->_object.recipeId); } -std::string RecipeData::GetItemIdentifier() +std::string& RecipeData::GetItemIdentifier() { return Utils::FNameToString(this->_object.ItemId); } diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index bac7103..7baa56c 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,16 +1,14 @@ #include "API/Skill/SkillData.hpp" -#include "ModLoader.hpp" -#include "GameCache.hpp" #include "Utils.hpp" #include "API/Common/Common.hpp" #include "API/Engine/TArrayHelper.hpp" -std::string SkillData::GetIdentifier() +std::string& SkillData::GetIdentifier() { return Utils::FNameToString(this->_object.ID.Name); } -std::string SkillData::GetNameIdentifier() +std::string& SkillData::GetNameIdentifier() { return Utils::FNameToString(this->_object.nameTextID); } @@ -25,7 +23,7 @@ void SkillData::SetName(LANG lang, FString string) NAME_SET(lang, GetNameIdentifier(), string); } -std::string SkillData::GetDescIdentifier() +std::string& SkillData::GetDescIdentifier() { return Utils::FNameToString(this->_object.dascTextId); } diff --git a/src/API/Skill/SkillEffectInfo.cpp b/src/API/Skill/SkillEffectInfo.cpp index 4fdc3a0..7a58db7 100644 --- a/src/API/Skill/SkillEffectInfo.cpp +++ b/src/API/Skill/SkillEffectInfo.cpp @@ -1,6 +1,4 @@ #include "API/Skill/SkillEffectInfo.hpp" -#include -#include "ModLoader.hpp" #include "API/Engine/TArrayHelper.hpp" EffectCondition SkillEffectInfo::GetEffectCondition(int index) diff --git a/src/API/Table/ItemTableDetail.cpp b/src/API/Table/ItemTableDetail.cpp index fc972ff..511f06e 100644 --- a/src/API/Table/ItemTableDetail.cpp +++ b/src/API/Table/ItemTableDetail.cpp @@ -2,7 +2,7 @@ #include "ModLoader.hpp" #include "GameCache.hpp" -std::string ItemTableDetail::GetItemIdentifier() +std::string& ItemTableDetail::GetItemIdentifier() { return Utils::FNameToString(this->_object.ItemId); } diff --git a/src/API/World/MapData.cpp b/src/API/World/MapData.cpp index 375c713..fa3cbe9 100644 --- a/src/API/World/MapData.cpp +++ b/src/API/World/MapData.cpp @@ -1,20 +1,18 @@ #include "API/World/MapData.hpp" -#include "ModLoader.hpp" -#include "GameCache.hpp" #include "Utils.hpp" #include "API/Common/Common.hpp" -std::string MapData::GetIdentifier() +std::string& MapData::GetIdentifier() { return Utils::FNameToString(this->_object.mapId); } -std::string MapData::GetPath() +std::string& MapData::GetPath() { return Utils::FNameToString(this->_object.MapPath); } -std::string MapData::GetMapViewCategory() +std::string& MapData::GetMapViewCategory() { return Utils::FNameToString(this->_object.MapViewCategory); } @@ -39,12 +37,12 @@ void MapData::SetMapViewName(int index, FString name) this->_object.MapViewDataArray.Data[index].mapName = name; } -std::string MapData::GetMapSubject() +std::string& MapData::GetMapSubject() { return Utils::FNameToString(this->_object.MapSubject); } -std::string MapData::GetNameIdentifier() +std::string& MapData::GetNameIdentifier() { return Utils::FNameToString(this->_object.MapNameID); } @@ -59,7 +57,7 @@ void MapData::SetName(LANG lang, FString string) NAME_SET(lang, GetNameIdentifier(), string); } -std::string MapData::GetWorldMap() +std::string& MapData::GetWorldMap() { return Utils::FNameToString(this->_object.WorldMapID); } diff --git a/src/API/World/MapDataSubMapData.cpp b/src/API/World/MapDataSubMapData.cpp index d222c04..b8f8c0f 100644 --- a/src/API/World/MapDataSubMapData.cpp +++ b/src/API/World/MapDataSubMapData.cpp @@ -3,7 +3,7 @@ #include "GameCache.hpp" #include "Utils.hpp" -std::string MapDataSubMapData::GetSubMapIdentifier() +std::string& MapDataSubMapData::GetSubMapIdentifier() { return Utils::FNameToString(this->_object.subMapId); } @@ -13,7 +13,7 @@ MapSubLevel MapDataSubMapData::GetSubMap() return ModLoader::gameCache->GetSubLevel(GetSubMapIdentifier()); } -std::string MapDataSubMapData::GetAreaID() +std::string& MapDataSubMapData::GetAreaID() { return Utils::FNameToString(this->_object.AreaID); } \ No newline at end of file diff --git a/src/API/World/MapSubLevel.cpp b/src/API/World/MapSubLevel.cpp index d2f057a..49a8a79 100644 --- a/src/API/World/MapSubLevel.cpp +++ b/src/API/World/MapSubLevel.cpp @@ -1,17 +1,17 @@ #include "API/World/MapSubLevel.hpp" #include "Utils.hpp" -std::string MapSubLevel::GetIdentifier() +std::string& MapSubLevel::GetIdentifier() { return Utils::FNameToString(this->_object.SubLevelID); } -std::string MapSubLevel::GetMapSubIdentifier() +std::string& MapSubLevel::GetMapSubIdentifier() { return Utils::FNameToString(this->_object.mapSubId); } -std::string MapSubLevel::GetPath() +std::string& MapSubLevel::GetPath() { return Utils::FNameToString(this->_object.SubLevelInfo.SubLevelPath); } \ No newline at end of file diff --git a/src/Hook/EventHandler.cpp b/src/Hook/EventHandler.cpp index 69aa9ec..32f7e60 100644 --- a/src/Hook/EventHandler.cpp +++ b/src/Hook/EventHandler.cpp @@ -1,10 +1,7 @@ #include "Hook/EventHandler.hpp" #include "Hook/MemoryHelper.hpp" -#include "ModLoader.hpp" #include "SDK.h" -#include - std::unordered_map)>>> EventHandler::_handlers; std::unordered_map EventHandler::_events; diff --git a/src/Hook/MemoryHelper.cpp b/src/Hook/MemoryHelper.cpp index 1ba9b8b..9a2ecb0 100644 --- a/src/Hook/MemoryHelper.cpp +++ b/src/Hook/MemoryHelper.cpp @@ -1,4 +1,5 @@ #include "Hook/MemoryHelper.hpp" +#include uintptr_t MemoryHelper::findFreeMemory(uintptr_t address, uint8_t length) { unsigned char *ptr = (unsigned char *) address; diff --git a/src/ModEnvironnement.cpp b/src/ModEnvironnement.cpp index 88580d5..d26e0de 100644 --- a/src/ModEnvironnement.cpp +++ b/src/ModEnvironnement.cpp @@ -1,10 +1,9 @@ #include "Mod/ModEnvironnement.hpp" #include "ModLoader.hpp" -#include #include "Mod/ThreadPool.hpp" #include -#include "Lib/Json.hpp" +#include "Lib/json.hpp" #include "Lib/miniz.h" @@ -120,7 +119,7 @@ bool ModEnvironnement::findModJsonInArchive(const std::filesystem::path& archive { mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; - if(!stat.m_filename) break; + //if(!stat.m_filename) break; std::string fname = stat.m_filename; if(fname.size() >= 8 && fname.substr(fname.size() - 8) == "Mod.json") @@ -145,7 +144,7 @@ bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archiveP for (mz_uint i = 0; i < num; ++i) { mz_zip_archive_file_stat st; if (!mz_zip_reader_file_stat(&archive, i, &st)) continue; - if (st.m_filename) { + //if (st.m_filename) { std::string fname = st.m_filename; if (fname.size() >= libName.size() && fname.compare(fname.size() - libName.size(), libName.size(), libName) == 0) @@ -154,7 +153,7 @@ bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archiveP mz_zip_reader_end(&archive); return true; } - } + //} } mz_zip_reader_end(&archive); @@ -178,7 +177,7 @@ bool ModEnvironnement::readContentFromArchive(const std::filesystem::path& archi { mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; - if(!stat.m_filename) break; + //if(stat.m_filename == "") break; std::string fname = stat.m_filename; if(fname.size() >= internalName.size() && fname.compare(fname.size() - internalName.size(), internalName.size(), internalName) == 0) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 3284072..4667df5 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,5 +1,8 @@ #include "ModLoader.hpp" #include "Hook/EventHandler.hpp" +#include "Patcher/Patcher.hpp" +#include "Patcher/Patches/EventHook.hpp" +#include "Utils.hpp" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -34,7 +37,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser case DLL_PROCESS_ATTACH: { AllocConsole(); - freopen_s(reinterpret_cast(stdout), "CONOUT$", "w", stdout); freopen_s(reinterpret_cast(stderr), "CONOUT$", "w", stderr); diff --git a/src/Utils.cpp b/src/Utils.cpp index 60db305..e3ed47d 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -2,6 +2,8 @@ #include "ModLoader.hpp" #include "GameData.hpp" #include "GameCache.hpp" +#include "Offset.h" + std::unordered_map Utils::_strings; From 923feb20f9b9cb96ba1b1194f550712f6df01e1b Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:41:29 +0100 Subject: [PATCH 16/64] Remove goofy readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aa84962..c97e92c 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,8 @@ Fantasy Life I/ $ cmake -B build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DMLDEBUG=OFF ``` > [!NOTE] -> For debugging u might need to set MLDEBUG to ON: `-DMLDEBUG=OFF` -> But it's only if you need the pdb, otherwise let the option off. +> For debugging you might need to set `MLDEBUG` to `ON`: `-DMLDEBUG=OFF` +> This is only needed if you require PDB files, otherwise keep this option off. ```bash $ cmake --build build --config Release From f7f775bcd0155cab7e725cff3e390dd072990b5a Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:52:23 +0100 Subject: [PATCH 17/64] Temp fix for issue #35 --- CMakeLists.txt | 1 + DllProxy/CMakeLists.txt | 1 + src/ModEnvironnement.cpp | 126 ++++++++++++++++++++------------------- src/ModLoader.cpp | 2 - 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00d01ed..e05ec27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() if(MLDEBUG) + add_compile_options(/EHsc) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG") diff --git a/DllProxy/CMakeLists.txt b/DllProxy/CMakeLists.txt index bb2b2b7..92efc93 100644 --- a/DllProxy/CMakeLists.txt +++ b/DllProxy/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.16) project(DllProxy LANGUAGES CXX C) +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") add_library(${PROJECT_NAME} SHARED src/dllmain.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/src/ModEnvironnement.cpp b/src/ModEnvironnement.cpp index d26e0de..c2d9497 100644 --- a/src/ModEnvironnement.cpp +++ b/src/ModEnvironnement.cpp @@ -283,6 +283,14 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) void ModEnvironnement::PreLoad() { + #ifdef MLDEBUG + ThreadPool podol{1}; + podol.enqueue([](){ + std::cerr << "[TEST1] pool task executed on " << std::this_thread::get_id() << "\n"; + ModLoader::logger->error("[TEST2] logger work"); + }); + #endif + const size_t modListSize = _modsList.size(); size_t numThreads = std::thread::hardware_concurrency(); if(numThreads == 0) numThreads = 1; @@ -297,74 +305,68 @@ void ModEnvironnement::PreLoad() std::vector buckets(numThreads); std::atomic nextBucket { 0 }; - std::latch done(static_cast(modListSize)); - + for (auto * mod : _modsList) { - pool.enqueue([this, &done, mod, &buckets, &nextBucket, numThreads] + pool.enqueue([this, &done, mod, &buckets, &nextBucket, numThreads]() + { + size_t index = nextBucket.fetch_add(1) % numThreads; + Bucket& bucket = buckets[index]; + + std::vector modBuf; + if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) + { + ModLoader::logger->error("Failed to decompressed content from archive from: ", mod->getMeta().identifier); + done.count_down(); + return; + } + + std::string suffix = ".mod"; + { + std::string intern = mod->getInternalPath(); + size_t pos = intern.find_last_of('.'); + if(pos != std::string::npos) suffix = intern.substr(pos); + } + + std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); + if(libOnDiskPath.empty()) + { + ModLoader::logger->error("Failed to writee temporary content for ", mod->getMeta().identifier); + done.count_down(); + return; + } + { - size_t index = nextBucket.fetch_add(1) % numThreads; - Bucket& bucket = buckets[index]; - - ModMetaData meta = mod->getMeta(); - std::string identifier = meta.identifier; - ModLoader::logger->info("Loading mod: ", identifier, " v", meta.version); - - std::vector modBuf; - if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) - { - ModLoader::logger->error("Failed to decompressed content from archive from: ", identifier); - done.count_down(); - return; - } - - std::string suffix = ".mod"; - { - std::string intern = mod->getInternalPath(); - size_t pos = intern.find_last_of('.'); - if(pos != std::string::npos) suffix = intern.substr(pos); - } - - std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); - if(libOnDiskPath.empty()) - { - ModLoader::logger->error("Failed to writee temporary content for ", identifier); - done.count_down(); - return; - } - - { - std::lock_guard lg(_mergeMutex); - _tempFilesToRemove.push_back(libOnDiskPath); - } - - LibHandle lib = LoadLib(libOnDiskPath.string()); - if(!lib) - { - ModLoader::logger->error("Failed to load: ", identifier); - done.count_down(); - return; - } - - using GetModFunc = ModBase *(*)(); - auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); - if(!getter) - { - ModLoader::logger->error("Missing CraftMod in ", identifier); - CloseLib(lib); - done.count_down(); - return; - } - - auto modPtr = std::unique_ptr(getter()); - modPtr->OnPreLoad(); - - bucket.libs.push_back(lib); - bucket.mods.push_back(std::move(modPtr)); + std::lock_guard lg(_mergeMutex); + _tempFilesToRemove.push_back(libOnDiskPath); + } + + LibHandle lib = LoadLib(libOnDiskPath.string()); + if(!lib) + { + ModLoader::logger->error("Failed to load: ", mod->getMeta().identifier); done.count_down(); + return; } - ); + + using GetModFunc = ModBase *(*)(); + auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); + if(!getter) + { + ModLoader::logger->error("Missing CraftMod in ", mod->getMeta().identifier); + CloseLib(lib); + done.count_down(); + return; + } + + auto modPtr = std::unique_ptr(getter()); + modPtr->OnPreLoad(); + + bucket.libs.push_back(lib); + bucket.mods.push_back(std::move(modPtr)); + done.count_down(); + }); } done.wait(); diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 4667df5..f2bf54a 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -45,8 +45,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser Utils::EnableAnsiColors(); LoaderThread = CreateThread(nullptr, 0, ModLoader::init, nullptr, 0, nullptr); - if (LoaderThread) - CloseHandle(LoaderThread); break; } case DLL_PROCESS_DETACH: From c9afe8aa3f2c69e10b2b1a7271989e23bdcc8824 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:33:49 +0100 Subject: [PATCH 18/64] Wip fixing API --- CMakeLists.txt | 3 ++- src/API/Entities/Player/Player.cpp | 12 ++++++++++-- src/ModEnvironnement.cpp | 31 ++++++++++++++++-------------- src/ModLoader.cpp | 1 + 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e05ec27..b952d27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,10 +21,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") "-Wno-inconsistent-dllimport" "-Wno-dllimport-static-field-def" ) + + add_compile_options(${PROJECT_NAME} PRIVATE /EHsc /GS /MD) endif() if(MLDEBUG) - add_compile_options(/EHsc) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG") diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index 7c58850..5a17afd 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,16 +1,24 @@ #include "API/Entities/Player/Player.hpp" #include "Utils.hpp" +#include "ModLoader.hpp" + Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} +// FIXME: Invalid return value ELifeType Player::GetLifeType() { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); + std::string &lifeId = GetLifeId(); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; return static_cast(std::stoi(lifeId.c_str() + 4)); } +std::string& Player::GetLifeId() +{ + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); + return Utils::FNameToString(avatarStatus->m_lifeId); +} + void Player::SetExp(ELifeType life, uint32_t exp) { FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); avatarStatus->m_exp.Data[static_cast(life) - 1].Value.Second = exp; diff --git a/src/ModEnvironnement.cpp b/src/ModEnvironnement.cpp index c2d9497..88bd1a1 100644 --- a/src/ModEnvironnement.cpp +++ b/src/ModEnvironnement.cpp @@ -3,6 +3,7 @@ #include "ModLoader.hpp" #include "Mod/ThreadPool.hpp" #include +#include #include "Lib/json.hpp" #include "Lib/miniz.h" @@ -283,14 +284,6 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) void ModEnvironnement::PreLoad() { - #ifdef MLDEBUG - ThreadPool podol{1}; - podol.enqueue([](){ - std::cerr << "[TEST1] pool task executed on " << std::this_thread::get_id() << "\n"; - ModLoader::logger->error("[TEST2] logger work"); - }); - #endif - const size_t modListSize = _modsList.size(); size_t numThreads = std::thread::hardware_concurrency(); if(numThreads == 0) numThreads = 1; @@ -299,8 +292,9 @@ void ModEnvironnement::PreLoad() ThreadPool pool{numThreads}; struct Bucket { - std::vector libs; - std::vector> mods; + std::mutex mutex; + std::vector libs; + std::vector> mods; }; std::vector buckets(numThreads); @@ -332,7 +326,7 @@ void ModEnvironnement::PreLoad() std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); if(libOnDiskPath.empty()) { - ModLoader::logger->error("Failed to writee temporary content for ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to write temporary content for ", mod->getMeta().identifier); done.count_down(); return; } @@ -363,8 +357,11 @@ void ModEnvironnement::PreLoad() auto modPtr = std::unique_ptr(getter()); modPtr->OnPreLoad(); - bucket.libs.push_back(lib); - bucket.mods.push_back(std::move(modPtr)); + { + std::lock_guard lg(bucket.mutex); + bucket.libs.push_back(lib); + bucket.mods.push_back(std::move(modPtr)); + } done.count_down(); }); } @@ -372,13 +369,19 @@ void ModEnvironnement::PreLoad() done.wait(); { + _modLibList.reserve(buckets.size()); std::lock_guard lg(_mergeMutex); for(auto& bucket : buckets) { + _modPtrList.reserve(bucket.mods.size()); _modLibList.insert(_modLibList.end(), bucket.libs.begin(), bucket.libs.end()); - for(auto& modPtr : bucket.mods) _modPtrList.push_back(std::move(modPtr)); + for(auto& modPtr : bucket.mods) + { + _modPtrList.push_back(std::move(modPtr)); + } } } + ModLoader::logger->verbose("MENV Preload finished.\n Total size of modPtr: ", _modPtrList.size()); } void ModEnvironnement::PostLoad() diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index f2bf54a..d69cd16 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,4 +1,5 @@ #include "ModLoader.hpp" +#include "GameData.hpp" #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" From 80e4f6667824161b5f8f16a03d38592bd40bf876 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:38:03 +0100 Subject: [PATCH 19/64] Fixing Player::GetLifeType --- src/API/Entities/Player/Player.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index 5a17afd..efa7222 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -2,21 +2,18 @@ #include "Utils.hpp" #include "ModLoader.hpp" +#include Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} -// FIXME: Invalid return value ELifeType Player::GetLifeType() { - std::string &lifeId = GetLifeId(); + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); + std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; - return static_cast(std::stoi(lifeId.c_str() + 4)); -} -std::string& Player::GetLifeId() -{ - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - return Utils::FNameToString(avatarStatus->m_lifeId); + uint8_t life = std::stoi(lifeId.c_str() + 4); + return static_cast(life + 1); } void Player::SetExp(ELifeType life, uint32_t exp) { From 496ff0bd688a5afe3d0b777db1ba4806b1158e22 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 08:44:49 +0000 Subject: [PATCH 20/64] Cleaning a little bit the CMake --- CMakeLists.txt | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b952d27..b60366c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,45 +5,36 @@ set(VERSION 1.00) option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) -add_library(${PROJECT_NAME} SHARED src/ModLoader.cpp) +add_library(${PROJECT_NAME} SHARED) -set_target_properties(${PROJECT_NAME} PROPERTIES - OUTPUT_NAME "ModLoader" - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES -) +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) +target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) -target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED) -target_compile_definitions(${PROJECT_NAME} PRIVATE MLVERSION=${VERSION}) +if(MLDEBUG) + target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") +endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(${PROJECT_NAME} PRIVATE "-Wno-inconsistent-dllimport" "-Wno-dllimport-static-field-def" + /EHsc /GS /MD ) - - add_compile_options(${PROJECT_NAME} PRIVATE /EHsc /GS /MD) -endif() - -if(MLDEBUG) - target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") endif() target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) -target_link_libraries(${PROJECT_NAME} PUBLIC +target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32 ) -target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c) - file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") target_sources(${PROJECT_NAME} PUBLIC + src/Lib/miniz.c ${PROJECT_SOURCE} ) \ No newline at end of file From c3802a5799703376ecce75b8e5d65a3fca9c5f77 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:31:40 +0000 Subject: [PATCH 21/64] Adding config --- .github/doc/Mod/ConfigurationFiles.md | 84 ++++++++++++++++ CMakeLists.txt | 15 +-- src/Mod/Configuration/ConfigManager.cpp | 34 +++++++ src/Mod/Configuration/ModConfig.cpp | 122 ++++++++++++++++++++++++ src/{ => Mod}/ModEnvironnement.cpp | 5 + src/ModLoader.cpp | 8 +- 6 files changed, 255 insertions(+), 13 deletions(-) create mode 100644 .github/doc/Mod/ConfigurationFiles.md create mode 100644 src/Mod/Configuration/ConfigManager.cpp create mode 100644 src/Mod/Configuration/ModConfig.cpp rename src/{ => Mod}/ModEnvironnement.cpp (99%) diff --git a/.github/doc/Mod/ConfigurationFiles.md b/.github/doc/Mod/ConfigurationFiles.md new file mode 100644 index 0000000..e8c0a68 --- /dev/null +++ b/.github/doc/Mod/ConfigurationFiles.md @@ -0,0 +1,84 @@ +# Mod configs +Mod configuration files are an important part of mods, they allow you to define settings that can be easily changed by user or other mods. + +To register configuration values, use the [Config Manager](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigManager.hpp) provided by the [Mod Loader](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/ModLoader.hpp) class. + +## Basic example: +```cpp +ConfigValue setting1; +ConfigValue setting2; +ConfigValue setting3; + +void YourMod::OnPreLoad() +{ + ... + + // The config manager is a part of ModLoader + // To register a configuration, call PushConfig() + // It takes two arguments: + // 1. A string ID that uniquely identifies your configuration file + // 2. A function (or lambda) that performs the registration + ModLoader::configManager->PushConfig("YourModID", [&](ModConfig& config) + { + // Register() requires three arguments: + // 1. The path used inside the JSON file + // 2. A Pointer to your ConfigValue variable + // 3. The default value to use if the config file doesn't exit + + config.Register("setting1", &setting1, true); + config.Register("setting2", &setting2, std::string("HRT :3")); + config.Register("setting3", &setting3, 543653); + }); + ... +} +``` + +## Accessing and using your config values: +```cpp +bool test = YourMod::setting1.Get(); // Retrieve current value +YourMod::setting1.Set(false); // Change value +``` +> [!NOTE] +> `Get()` blocks until the value is initialized +> Use `GetOrThrow()` if you are impatient or if you want a exception instead of waiting + +## Cleaner way to use the ConfigManager: + +Instead of defining all the config values directly in you main mod file, you can group them neatly inside a `Config` class + +`Config.hpp` +```cpp +... + +class Config +{ + public: + inline static ConfigValue setting1; + inline static ConfigValue setting2; + inline static ConfigValue setting3; + + inline static void configRegister(ModConfig& config) + { + config.Register("setting1", &setting1, true); + config.Register("setting2", &setting2, std::string("HRT :3")); + config.Register("setting3", &setting3, 543653); + } +} +``` + +`Mod.cpp` +```cpp + +void YourMod::OnPreload() +{ + ... + ModLoader::configManager->PushConfig("YourModID", Config::configRegister); + ... +} +``` + +## References: +- [Mod Base](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/ModBase.hpp) +- [Config Manager](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigManager.hpp) +- [Mod Config](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ModConfig.hpp) +- [Config value](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigValue.hpp) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b60366c..54081b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,17 +24,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -target_link_libraries(${PROJECT_NAME} PRIVATE - user32 - kernel32 -) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") -target_sources(${PROJECT_NAME} PUBLIC - src/Lib/miniz.c - ${PROJECT_SOURCE} -) \ No newline at end of file +target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file diff --git a/src/Mod/Configuration/ConfigManager.cpp b/src/Mod/Configuration/ConfigManager.cpp new file mode 100644 index 0000000..cfe6c82 --- /dev/null +++ b/src/Mod/Configuration/ConfigManager.cpp @@ -0,0 +1,34 @@ +#include "Mod/Configuration/ConfigManager.hpp" +#include +#include + +ConfigManager::ConfigManager(const std::filesystem::path& configPath) : _configPath(configPath) +{ + std::filesystem::create_directories(_configPath); +} + +void ConfigManager::PushConfig(std::string name, std::function registerFunction) +{ + std::lock_guard lock(_mutex); + auto configPath = _configPath / (name + ".json"); + auto config = std::make_shared(name, configPath); + + registerFunction(*config); + + config->Load(); + _configs[name] = config; +} + +void ConfigManager::SaveAll() +{ + std::lock_guard lock(_mutex); + for(const auto& [name, config] : _configs) + config->Save(); +} + +void ConfigManager::ReloadAll() +{ + std::lock_guard lock(_mutex); + for(const auto& [name, config] : _configs) + config->Reload(); +} diff --git a/src/Mod/Configuration/ModConfig.cpp b/src/Mod/Configuration/ModConfig.cpp new file mode 100644 index 0000000..925906a --- /dev/null +++ b/src/Mod/Configuration/ModConfig.cpp @@ -0,0 +1,122 @@ +#include "Mod/Configuration/ModConfig.hpp" +#include +#include +#include +#include +#include +#include +#include "Lib/json.hpp" +#include "ModLoader.hpp" + + +void ModConfig::Load() +{ + std::lock_guard lock(_mutex); + + if(!std::filesystem::exists(_configPath)) + { + FinalizeIntialization(); + return; + } + + try + { + std::ifstream file(_configPath); + if(!file.is_open()) + { + ModLoader::logger->error("Failed to open config file: ", _configPath.string()); + + FinalizeIntialization(); + return; + } + + json Json; + file >> Json; + file.close(); + + for(const auto& [path, value] : Json.items()) + { + ApplyLoadedValue(path, value); + } + + FinalizeIntialization(); + } + catch(const json::exception& e) + { + ModLoader::logger->error("JSON parse error in ", _configPath, " ", e.what()); + FinalizeIntialization(); + } +} + +void ModConfig::Save() +{ + std::lock_guard lock(_mutex); + + try + { + std::filesystem::create_directories(_configPath.parent_path()); + json Json = GetAllValues(); + + std::ofstream file(_configPath); + if(!file.is_open()) throw std::runtime_error("Failed to open config file for writing: " + _configPath.string()); + + file << Json.dump(4); + file.close(); + } catch (const std::exception& e) + { + ModLoader::logger->error("Failed to save config ", _configPath, " : ", e.what()); + } +} + +void ModConfig::Reload() +{ + { + std::lock_guard lock(_mutex); + for(auto& [path, reg] : _registration) + { + _pending.insert(path); + // TODO: Reset the config value and adding a reset method in reg + } + } + + Load(); +} + +void ModConfig::ApplyLoadedValue(const std::string& path, const json& value) +{ + auto it = _registration.find(path); + if(it != _registration.end()) + { + try + { + it->second.setter(value); + } catch(const json::exception& e) + { + ModLoader::logger->error("Error loading config value '", path, "': ", e.what()); + it->second.setter(it->second.defaultValue); + } + + _pending.erase(path); + } +} + +void ModConfig::FinalizeIntialization() +{ + // Praying on the fact that the mutex is already locked by caller, if not, ngl we are cook + + for(const auto& path : _pending) + { + auto it = _registration.find(path); + if(it != _registration.end()) it->second.setter(it->second.defaultValue); + } + + _pending.clear(); +} + +json ModConfig::GetAllValues() +{ + json Json; + for(const auto& [path, reg] : _registration) Json[path] = reg.getter(); + + return Json; +} \ No newline at end of file diff --git a/src/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp similarity index 99% rename from src/ModEnvironnement.cpp rename to src/Mod/ModEnvironnement.cpp index 88bd1a1..4cfc307 100644 --- a/src/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -403,10 +403,15 @@ void ModEnvironnement::Free() delete mod; _modsList.clear(); + + for(auto& modPtr : _modPtrList) + modPtr->OnExit(); + _modPtrList.clear(); for(auto lib : _modLibList) CloseLib(lib); + _modLibList.clear(); for(const std::filesystem::path& p : _tempFilesToRemove) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index d69cd16..8e65ce9 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -9,6 +9,7 @@ GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; Logger *ModLoader::logger = nullptr; ModEnvironnement *ModLoader::modEnvironnement = nullptr; +ConfigManager *ModLoader::configManager = nullptr; DWORD WINAPI ModLoader::init(LPVOID lpParam) { logger = new Logger("ModLoader"); @@ -20,8 +21,10 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameData = new GameData(reinterpret_cast(GetModuleHandle(nullptr))); gameCache = new GameCache(); + configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); - modEnvironnement->PreLoad(); + +// modEnvironnement->PreLoad(); gameCache->PostLoadCache(); gameData->initOthersData(); @@ -70,6 +73,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser delete ModLoader::modEnvironnement; } + if(ModLoader::configManager != nullptr) + delete ModLoader::configManager; + break; } } From 20a50f69e6a87c09db4b82f523e4672bc0937cf7 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:34:17 +0000 Subject: [PATCH 22/64] Revert ModLoader unnecessary code --- src/ModLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 8e65ce9..85e55bd 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -23,11 +23,11 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache = new GameCache(); configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); - -// modEnvironnement->PreLoad(); + modEnvironnement->PreLoad(); gameCache->PostLoadCache(); gameData->initOthersData(); + modEnvironnement->PostLoad(); return 0; From 2d95cc20981aa4425c23bbf3349dfc5be9970c20 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 4 Nov 2025 08:05:26 +0000 Subject: [PATCH 23/64] Fixing logger deadlock #35 --- src/Mod/ModEnvironnement.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 4cfc307..a517ce6 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -307,11 +307,14 @@ void ModEnvironnement::PreLoad() { size_t index = nextBucket.fetch_add(1) % numThreads; Bucket& bucket = buckets[index]; + + ModMetaData meta = mod->getMeta(); + std::string identifier = meta.identifier; std::vector modBuf; if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) { - ModLoader::logger->error("Failed to decompressed content from archive from: ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to decompressed content from archive from: ", identifier); done.count_down(); return; } @@ -326,7 +329,7 @@ void ModEnvironnement::PreLoad() std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); if(libOnDiskPath.empty()) { - ModLoader::logger->error("Failed to write temporary content for ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to write temporary content for ", identifier); done.count_down(); return; } @@ -339,7 +342,7 @@ void ModEnvironnement::PreLoad() LibHandle lib = LoadLib(libOnDiskPath.string()); if(!lib) { - ModLoader::logger->error("Failed to load: ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to load: ", identifier); done.count_down(); return; } @@ -348,12 +351,13 @@ void ModEnvironnement::PreLoad() auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); if(!getter) { - ModLoader::logger->error("Missing CraftMod in ", mod->getMeta().identifier); + ModLoader::logger->error("Missing CraftMod in ", identifier); CloseLib(lib); done.count_down(); return; } + ModLoader::logger->info("Loading ", identifier, " v", meta.version); auto modPtr = std::unique_ptr(getter()); modPtr->OnPreLoad(); @@ -367,7 +371,6 @@ void ModEnvironnement::PreLoad() } done.wait(); - { _modLibList.reserve(buckets.size()); std::lock_guard lg(_mergeMutex); @@ -381,7 +384,7 @@ void ModEnvironnement::PreLoad() } } } - ModLoader::logger->verbose("MENV Preload finished.\n Total size of modPtr: ", _modPtrList.size()); + ModLoader::logger->verbose("MENV Preload finished. [size of modPtr: ", _modPtrList.size(),"]"); } void ModEnvironnement::PostLoad() @@ -411,7 +414,7 @@ void ModEnvironnement::Free() for(auto lib : _modLibList) CloseLib(lib); - + _modLibList.clear(); for(const std::filesystem::path& p : _tempFilesToRemove) From a154eb79947f95ac3f948c41e667841e097482cc Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 4 Nov 2025 08:49:02 +0000 Subject: [PATCH 24/64] Update to latest include branch commit --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index dc60be9..425d7d1 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit dc60be9af0aecda7ac92f091dd4ae3035b7d1e07 +Subproject commit 425d7d148bd4b4b1757d27887c4c7fb477fd17cb From c343a83107aa570bf5cfb543982e897790ed8fc9 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 17 Sep 2025 09:22:18 +0100 Subject: [PATCH 25/64] WIP --- src/API/Common/CommonItemEffectParam.cpp | 5 ++--- src/API/Item/ItemData.cpp | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 4e35d66..ab2b83b 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -1,9 +1,8 @@ #include "API/Common/CommonItemEffectParam.hpp" -#include "API/Common/Common.hpp" - #include "Utils.hpp" +#include "Common.hpp" -std::string& CommonItemEffectParam::getDescIdentifier() +std::string CommonItemEffectParam::getDescIdentifier() { return Utils::FNameToString(this->_object.effDescId); } diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index 3856e79..cbf34df 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -7,7 +7,7 @@ std::string& ItemData::GetIdentifier() return Utils::FNameToString(this->_object.ID); } -std::string& ItemData::getNameIdentifier() +std::string ItemData::getNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } @@ -20,11 +20,13 @@ std::string& ItemData::GetDescIdentifier() std::string ItemData::GetName(LANG lang) { return NAME_GET(lang, getNameIdentifier()); + return NAME_GET(lang, getNameIdentifier()); } void ItemData::SetName(LANG lang, FString string) { NAME_SET(lang, getNameIdentifier(), string); + NAME_SET(lang, getNameIdentifier(), string); } std::string ItemData::GetDescription(LANG lang) From 0d42af08bf64cb261f4ca32c5d84a590478b1c67 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:29:40 +0100 Subject: [PATCH 26/64] Include fixes --- src/API/Common/CommonItemEffectParam.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index ab2b83b..83c4809 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -1,6 +1,7 @@ #include "API/Common/CommonItemEffectParam.hpp" +#include "API/Common/Common.hpp" + #include "Utils.hpp" -#include "Common.hpp" std::string CommonItemEffectParam::getDescIdentifier() { From 723b778baf9db05e98f3144629574baf30a239e1 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:38:48 +0100 Subject: [PATCH 27/64] Switching to CLANG --- CMakeLists.txt | 33 +++++++++++++++++------- README.md | 5 ++-- src/API/Common/CommonItemEffectParam.cpp | 2 +- src/API/Entities/Player/Player.cpp | 3 --- src/API/Item/ItemData.cpp | 2 +- src/Mod/ModEnvironnement.cpp | 5 +++- src/ModLoader.cpp | 3 +++ 7 files changed, 35 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54081b5..4a5cbed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,25 +7,38 @@ option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED) -set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) -target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) +set_target_properties(${PROJECT_NAME} PROPERTIES + OUTPUT_NAME "ModLoader" + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES +) -if(MLDEBUG) - target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") -endif() +target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED) +target_compile_definitions(${PROJECT_NAME} PRIVATE MLVERSION=${VERSION}) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(${PROJECT_NAME} PRIVATE "-Wno-inconsistent-dllimport" "-Wno-dllimport-static-field-def" - /EHsc /GS /MD ) endif() -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) +if(MLDEBUG) + target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") +endif() + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_link_libraries(${PROJECT_NAME} PUBLIC + user32 + kernel32 +) + +target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file diff --git a/README.md b/README.md index c97e92c..9e3cf72 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Fantasy Life I Mod Loader > [!IMPORTANT] > HEY!!! This mod loader is currently under development.. Somes features work (about 25%-35%??) but some things might break if you try weird stuff, that said, if you take your time and experiment a little you can already pull off some pretty cool things +> HEY!!! This mod loader is currently under development.. Somes features work (about 25%-35%??) but some things might break if you try weird stuff, that said, if you take your time and experiment a little you can already pull off some pretty cool things > If you're interested in supporting the project, contributions are welcome! Feel free to open a Pull Request!! ### How to install the Mod Loader @@ -60,8 +61,8 @@ Fantasy Life I/ $ cmake -B build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DMLDEBUG=OFF ``` > [!NOTE] -> For debugging you might need to set `MLDEBUG` to `ON`: `-DMLDEBUG=OFF` -> This is only needed if you require PDB files, otherwise keep this option off. +> For debugging u might need to set MLDEBUG to ON: `-DMLDEBUG=OFF` +> But it's only if you need the pdb, otherwise let the option off. ```bash $ cmake --build build --config Release diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 83c4809..4e35d66 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -3,7 +3,7 @@ #include "Utils.hpp" -std::string CommonItemEffectParam::getDescIdentifier() +std::string& CommonItemEffectParam::getDescIdentifier() { return Utils::FNameToString(this->_object.effDescId); } diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index efa7222..fba672c 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,9 +1,6 @@ #include "API/Entities/Player/Player.hpp" #include "Utils.hpp" -#include "ModLoader.hpp" -#include - Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} ELifeType Player::GetLifeType() { diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index cbf34df..c3ee003 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -7,7 +7,7 @@ std::string& ItemData::GetIdentifier() return Utils::FNameToString(this->_object.ID); } -std::string ItemData::getNameIdentifier() +std::string& ItemData::getNameIdentifier() { return Utils::FNameToString(this->_object.nameId); } diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index a517ce6..556a741 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -3,7 +3,6 @@ #include "ModLoader.hpp" #include "Mod/ThreadPool.hpp" #include -#include #include "Lib/json.hpp" #include "Lib/miniz.h" @@ -121,6 +120,7 @@ bool ModEnvironnement::findModJsonInArchive(const std::filesystem::path& archive mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; //if(!stat.m_filename) break; + //if(!stat.m_filename) break; std::string fname = stat.m_filename; if(fname.size() >= 8 && fname.substr(fname.size() - 8) == "Mod.json") @@ -145,6 +145,7 @@ bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archiveP for (mz_uint i = 0; i < num; ++i) { mz_zip_archive_file_stat st; if (!mz_zip_reader_file_stat(&archive, i, &st)) continue; + //if (st.m_filename) { //if (st.m_filename) { std::string fname = st.m_filename; if (fname.size() >= libName.size() && @@ -155,6 +156,7 @@ bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archiveP return true; } //} + //} } mz_zip_reader_end(&archive); @@ -179,6 +181,7 @@ bool ModEnvironnement::readContentFromArchive(const std::filesystem::path& archi mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; //if(stat.m_filename == "") break; + //if(stat.m_filename == "") break; std::string fname = stat.m_filename; if(fname.size() >= internalName.size() && fname.compare(fname.size() - internalName.size(), internalName.size(), internalName) == 0) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 85e55bd..c42928c 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -4,6 +4,9 @@ #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" #include "Utils.hpp" +#include "Patcher/Patcher.hpp" +#include "Patcher/Patches/EventHook.hpp" +#include "Utils.hpp" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; From d72394c7bbfba80d3ce13af03bb9d1b22a4eefc3 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:41:29 +0100 Subject: [PATCH 28/64] Remove goofy readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e3cf72..fa7be6f 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ Fantasy Life I/ $ cmake -B build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DMLDEBUG=OFF ``` > [!NOTE] -> For debugging u might need to set MLDEBUG to ON: `-DMLDEBUG=OFF` -> But it's only if you need the pdb, otherwise let the option off. +> For debugging you might need to set `MLDEBUG` to `ON`: `-DMLDEBUG=OFF` +> This is only needed if you require PDB files, otherwise keep this option off. ```bash $ cmake --build build --config Release From b4c852c407685b9104dffa02537be082bb2a914f Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:52:23 +0100 Subject: [PATCH 29/64] Temp fix for issue #35 --- CMakeLists.txt | 2 ++ src/Mod/ModEnvironnement.cpp | 38 ++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5cbed..846236e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(FantasyLifeI-ModLoader LANGUAGES CXX C) set(VERSION 1.00) +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) @@ -24,6 +25,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() if(MLDEBUG) + add_compile_options(/EHsc) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 556a741..d17870b 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -287,6 +287,14 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) void ModEnvironnement::PreLoad() { + #ifdef MLDEBUG + ThreadPool podol{1}; + podol.enqueue([](){ + std::cerr << "[TEST1] pool task executed on " << std::this_thread::get_id() << "\n"; + ModLoader::logger->error("[TEST2] logger work"); + }); + #endif + const size_t modListSize = _modsList.size(); size_t numThreads = std::thread::hardware_concurrency(); if(numThreads == 0) numThreads = 1; @@ -304,24 +312,28 @@ void ModEnvironnement::PreLoad() std::atomic nextBucket { 0 }; std::latch done(static_cast(modListSize)); + for (auto * mod : _modsList) { pool.enqueue([this, &done, mod, &buckets, &nextBucket, numThreads]() { size_t index = nextBucket.fetch_add(1) % numThreads; Bucket& bucket = buckets[index]; - - ModMetaData meta = mod->getMeta(); - std::string identifier = meta.identifier; std::vector modBuf; if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) { - ModLoader::logger->error("Failed to decompressed content from archive from: ", identifier); + ModLoader::logger->error("Failed to decompressed content from archive from: ", mod->getMeta().identifier); done.count_down(); return; } + std::string suffix = ".mod"; + { + std::string intern = mod->getInternalPath(); + size_t pos = intern.find_last_of('.'); + if(pos != std::string::npos) suffix = intern.substr(pos); + } std::string suffix = ".mod"; { std::string intern = mod->getInternalPath(); @@ -332,11 +344,15 @@ void ModEnvironnement::PreLoad() std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); if(libOnDiskPath.empty()) { - ModLoader::logger->error("Failed to write temporary content for ", identifier); + ModLoader::logger->error("Failed to writee temporary content for ", mod->getMeta().identifier); done.count_down(); return; } + { + std::lock_guard lg(_mergeMutex); + _tempFilesToRemove.push_back(libOnDiskPath); + } { std::lock_guard lg(_mergeMutex); _tempFilesToRemove.push_back(libOnDiskPath); @@ -345,7 +361,7 @@ void ModEnvironnement::PreLoad() LibHandle lib = LoadLib(libOnDiskPath.string()); if(!lib) { - ModLoader::logger->error("Failed to load: ", identifier); + ModLoader::logger->error("Failed to load: ", mod->getMeta().identifier); done.count_down(); return; } @@ -354,21 +370,17 @@ void ModEnvironnement::PreLoad() auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); if(!getter) { - ModLoader::logger->error("Missing CraftMod in ", identifier); + ModLoader::logger->error("Missing CraftMod in ", mod->getMeta().identifier); CloseLib(lib); done.count_down(); return; } - ModLoader::logger->info("Loading ", identifier, " v", meta.version); auto modPtr = std::unique_ptr(getter()); modPtr->OnPreLoad(); - { - std::lock_guard lg(bucket.mutex); - bucket.libs.push_back(lib); - bucket.mods.push_back(std::move(modPtr)); - } + bucket.libs.push_back(lib); + bucket.mods.push_back(std::move(modPtr)); done.count_down(); }); } From bf2b938f731f502b3091924573abd34d546f7de8 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:33:49 +0100 Subject: [PATCH 30/64] Wip fixing API --- CMakeLists.txt | 3 ++- src/API/Entities/Player/Player.cpp | 12 ++++++++++-- src/Mod/ModEnvironnement.cpp | 29 +++++++++++++++++------------ 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 846236e..b78fc8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") "-Wno-inconsistent-dllimport" "-Wno-dllimport-static-field-def" ) + + add_compile_options(${PROJECT_NAME} PRIVATE /EHsc /GS /MD) endif() if(MLDEBUG) - add_compile_options(/EHsc) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index fba672c..5aed823 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,11 +1,13 @@ #include "API/Entities/Player/Player.hpp" #include "Utils.hpp" +#include "ModLoader.hpp" + Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} +// FIXME: Invalid return value ELifeType Player::GetLifeType() { - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); + std::string &lifeId = GetLifeId(); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; @@ -13,6 +15,12 @@ ELifeType Player::GetLifeType() { return static_cast(life + 1); } +std::string& Player::GetLifeId() +{ + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); + return Utils::FNameToString(avatarStatus->m_lifeId); +} + void Player::SetExp(ELifeType life, uint32_t exp) { FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); avatarStatus->m_exp.Data[static_cast(life) - 1].Value.Second = exp; diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index d17870b..44f1797 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -3,6 +3,7 @@ #include "ModLoader.hpp" #include "Mod/ThreadPool.hpp" #include +#include #include "Lib/json.hpp" #include "Lib/miniz.h" @@ -287,14 +288,6 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) void ModEnvironnement::PreLoad() { - #ifdef MLDEBUG - ThreadPool podol{1}; - podol.enqueue([](){ - std::cerr << "[TEST1] pool task executed on " << std::this_thread::get_id() << "\n"; - ModLoader::logger->error("[TEST2] logger work"); - }); - #endif - const size_t modListSize = _modsList.size(); size_t numThreads = std::thread::hardware_concurrency(); if(numThreads == 0) numThreads = 1; @@ -306,6 +299,9 @@ void ModEnvironnement::PreLoad() std::mutex mutex; std::vector libs; std::vector> mods; + std::mutex mutex; + std::vector libs; + std::vector> mods; }; std::vector buckets(numThreads); @@ -344,7 +340,7 @@ void ModEnvironnement::PreLoad() std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); if(libOnDiskPath.empty()) { - ModLoader::logger->error("Failed to writee temporary content for ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to write temporary content for ", mod->getMeta().identifier); done.count_down(); return; } @@ -379,27 +375,36 @@ void ModEnvironnement::PreLoad() auto modPtr = std::unique_ptr(getter()); modPtr->OnPreLoad(); - bucket.libs.push_back(lib); - bucket.mods.push_back(std::move(modPtr)); + { + std::lock_guard lg(bucket.mutex); + bucket.libs.push_back(lib); + bucket.mods.push_back(std::move(modPtr)); + } done.count_down(); }); } done.wait(); { + _modLibList.reserve(buckets.size()); _modLibList.reserve(buckets.size()); std::lock_guard lg(_mergeMutex); for(auto& bucket : buckets) { + _modPtrList.reserve(bucket.mods.size()); _modPtrList.reserve(bucket.mods.size()); _modLibList.insert(_modLibList.end(), bucket.libs.begin(), bucket.libs.end()); for(auto& modPtr : bucket.mods) { _modPtrList.push_back(std::move(modPtr)); } + for(auto& modPtr : bucket.mods) + { + _modPtrList.push_back(std::move(modPtr)); + } } } - ModLoader::logger->verbose("MENV Preload finished. [size of modPtr: ", _modPtrList.size(),"]"); + ModLoader::logger->verbose("MENV Preload finished.\n Total size of modPtr: ", _modPtrList.size()); } void ModEnvironnement::PostLoad() From f6507842bc042369d9542e583e81f3b9b5ba212b Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:38:03 +0100 Subject: [PATCH 31/64] Fixing Player::GetLifeType --- src/API/Entities/Player/Player.cpp | 11 +++-------- src/ModLoader.cpp | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index 5aed823..efa7222 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -2,12 +2,13 @@ #include "Utils.hpp" #include "ModLoader.hpp" +#include Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} -// FIXME: Invalid return value ELifeType Player::GetLifeType() { - std::string &lifeId = GetLifeId(); + FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); + std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; @@ -15,12 +16,6 @@ ELifeType Player::GetLifeType() { return static_cast(life + 1); } -std::string& Player::GetLifeId() -{ - FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - return Utils::FNameToString(avatarStatus->m_lifeId); -} - void Player::SetExp(ELifeType life, uint32_t exp) { FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); avatarStatus->m_exp.Data[static_cast(life) - 1].Value.Second = exp; diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index c42928c..9979e70 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -30,7 +30,7 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache->PostLoadCache(); gameData->initOthersData(); - + modEnvironnement->PostLoad(); return 0; From a677bb3c488982e3e5a02d0e1703efb5d7ca76e4 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 08:44:49 +0000 Subject: [PATCH 32/64] Cleaning a little bit the CMake --- CMakeLists.txt | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b78fc8d..ee605ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,41 +7,36 @@ option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED) +add_library(${PROJECT_NAME} SHARED) -set_target_properties(${PROJECT_NAME} PROPERTIES - OUTPUT_NAME "ModLoader" - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES -) +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) +target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) -target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED) -target_compile_definitions(${PROJECT_NAME} PRIVATE MLVERSION=${VERSION}) +if(MLDEBUG) + target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") +endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(${PROJECT_NAME} PRIVATE "-Wno-inconsistent-dllimport" "-Wno-dllimport-static-field-def" + /EHsc /GS /MD ) - - add_compile_options(${PROJECT_NAME} PRIVATE /EHsc /GS /MD) -endif() - -if(MLDEBUG) - target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG") endif() target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) -target_link_libraries(${PROJECT_NAME} PUBLIC +target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32 ) -target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c) - file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") -target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file +target_sources(${PROJECT_NAME} PUBLIC + src/Lib/miniz.c + ${PROJECT_SOURCE} +) \ No newline at end of file From fd8c321fbfd386c49adef483775f266c3811ee21 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:31:40 +0000 Subject: [PATCH 33/64] Adding config --- CMakeLists.txt | 15 +++------------ src/Mod/ModEnvironnement.cpp | 2 +- src/ModLoader.cpp | 11 +++++++++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee605ae..132fe79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,17 +26,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -target_link_libraries(${PROJECT_NAME} PRIVATE - user32 - kernel32 -) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") -target_sources(${PROJECT_NAME} PUBLIC - src/Lib/miniz.c - ${PROJECT_SOURCE} -) \ No newline at end of file +target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 44f1797..1863f69 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -434,7 +434,7 @@ void ModEnvironnement::Free() for(auto lib : _modLibList) CloseLib(lib); - + _modLibList.clear(); for(const std::filesystem::path& p : _tempFilesToRemove) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 9979e70..0fc44c3 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -26,12 +26,19 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache = new GameCache(); configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); - modEnvironnement->PreLoad(); + + + + + +// modEnvironnement->PreLoad(); gameCache->PostLoadCache(); gameData->initOthersData(); + + logger->info(test1.Get(), " > ", test2.Get(), " ? ", test3.Get()); - modEnvironnement->PostLoad(); +// modEnvironnement->PostLoad(); return 0; } From e6041d46c6e6492d3bf42da4bfa3db28aa6c1a43 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:34:17 +0000 Subject: [PATCH 34/64] Revert ModLoader unnecessary code --- src/ModLoader.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 0fc44c3..c42928c 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -26,19 +26,12 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { gameCache = new GameCache(); configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); - - - - - -// modEnvironnement->PreLoad(); + modEnvironnement->PreLoad(); gameCache->PostLoadCache(); gameData->initOthersData(); - logger->info(test1.Get(), " > ", test2.Get(), " ? ", test3.Get()); - -// modEnvironnement->PostLoad(); + modEnvironnement->PostLoad(); return 0; } From 5eade0f27b4c0e24d938e56677ee8f3a834639bb Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Tue, 4 Nov 2025 08:05:26 +0000 Subject: [PATCH 35/64] Fixing logger deadlock #35 --- src/Mod/ModEnvironnement.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 1863f69..79876b7 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -315,11 +315,14 @@ void ModEnvironnement::PreLoad() { size_t index = nextBucket.fetch_add(1) % numThreads; Bucket& bucket = buckets[index]; + + ModMetaData meta = mod->getMeta(); + std::string identifier = meta.identifier; std::vector modBuf; if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) { - ModLoader::logger->error("Failed to decompressed content from archive from: ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to decompressed content from archive from: ", identifier); done.count_down(); return; } @@ -340,7 +343,7 @@ void ModEnvironnement::PreLoad() std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); if(libOnDiskPath.empty()) { - ModLoader::logger->error("Failed to write temporary content for ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to write temporary content for ", identifier); done.count_down(); return; } @@ -357,7 +360,7 @@ void ModEnvironnement::PreLoad() LibHandle lib = LoadLib(libOnDiskPath.string()); if(!lib) { - ModLoader::logger->error("Failed to load: ", mod->getMeta().identifier); + ModLoader::logger->error("Failed to load: ", identifier); done.count_down(); return; } @@ -366,12 +369,13 @@ void ModEnvironnement::PreLoad() auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); if(!getter) { - ModLoader::logger->error("Missing CraftMod in ", mod->getMeta().identifier); + ModLoader::logger->error("Missing CraftMod in ", identifier); CloseLib(lib); done.count_down(); return; } + ModLoader::logger->info("Loading ", identifier, " v", meta.version); auto modPtr = std::unique_ptr(getter()); modPtr->OnPreLoad(); @@ -404,7 +408,7 @@ void ModEnvironnement::PreLoad() } } } - ModLoader::logger->verbose("MENV Preload finished.\n Total size of modPtr: ", _modPtrList.size()); + ModLoader::logger->verbose("MENV Preload finished. [size of modPtr: ", _modPtrList.size(),"]"); } void ModEnvironnement::PostLoad() @@ -434,7 +438,7 @@ void ModEnvironnement::Free() for(auto lib : _modLibList) CloseLib(lib); - + _modLibList.clear(); for(const std::filesystem::path& p : _tempFilesToRemove) From 7da81b32e2b2919f2774a55585d3b909097347a7 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 12 Nov 2025 03:15:19 +0000 Subject: [PATCH 36/64] WIP + Clean --- .clangd | 11 +++- .github/doc/Mod/ConfigurationFiles.md | 84 --------------------------- src/GameData.cpp | 11 +++- src/Hook/MemoryHelper.cpp | 19 ++++++ src/Hook/Pattern.cpp | 21 +++++++ src/ModLoader.cpp | 28 ++++++--- 6 files changed, 80 insertions(+), 94 deletions(-) delete mode 100644 .github/doc/Mod/ConfigurationFiles.md create mode 100644 src/Hook/Pattern.cpp diff --git a/.clangd b/.clangd index 1f41e26..e69d464 100644 --- a/.clangd +++ b/.clangd @@ -1,7 +1,16 @@ CompileFlags: Add: [-std=c++20] +--- + If: PathMatch: include/SDK.h Diagnostics: - UnusedIncludes: None \ No newline at end of file + UnusedIncludes: None + +--- + +If: + PathMatch: .* +Diagnostics: + Suppress: [-Wunused-include:include/SDK.h] \ No newline at end of file diff --git a/.github/doc/Mod/ConfigurationFiles.md b/.github/doc/Mod/ConfigurationFiles.md deleted file mode 100644 index e8c0a68..0000000 --- a/.github/doc/Mod/ConfigurationFiles.md +++ /dev/null @@ -1,84 +0,0 @@ -# Mod configs -Mod configuration files are an important part of mods, they allow you to define settings that can be easily changed by user or other mods. - -To register configuration values, use the [Config Manager](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigManager.hpp) provided by the [Mod Loader](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/ModLoader.hpp) class. - -## Basic example: -```cpp -ConfigValue setting1; -ConfigValue setting2; -ConfigValue setting3; - -void YourMod::OnPreLoad() -{ - ... - - // The config manager is a part of ModLoader - // To register a configuration, call PushConfig() - // It takes two arguments: - // 1. A string ID that uniquely identifies your configuration file - // 2. A function (or lambda) that performs the registration - ModLoader::configManager->PushConfig("YourModID", [&](ModConfig& config) - { - // Register() requires three arguments: - // 1. The path used inside the JSON file - // 2. A Pointer to your ConfigValue variable - // 3. The default value to use if the config file doesn't exit - - config.Register("setting1", &setting1, true); - config.Register("setting2", &setting2, std::string("HRT :3")); - config.Register("setting3", &setting3, 543653); - }); - ... -} -``` - -## Accessing and using your config values: -```cpp -bool test = YourMod::setting1.Get(); // Retrieve current value -YourMod::setting1.Set(false); // Change value -``` -> [!NOTE] -> `Get()` blocks until the value is initialized -> Use `GetOrThrow()` if you are impatient or if you want a exception instead of waiting - -## Cleaner way to use the ConfigManager: - -Instead of defining all the config values directly in you main mod file, you can group them neatly inside a `Config` class - -`Config.hpp` -```cpp -... - -class Config -{ - public: - inline static ConfigValue setting1; - inline static ConfigValue setting2; - inline static ConfigValue setting3; - - inline static void configRegister(ModConfig& config) - { - config.Register("setting1", &setting1, true); - config.Register("setting2", &setting2, std::string("HRT :3")); - config.Register("setting3", &setting3, 543653); - } -} -``` - -`Mod.cpp` -```cpp - -void YourMod::OnPreload() -{ - ... - ModLoader::configManager->PushConfig("YourModID", Config::configRegister); - ... -} -``` - -## References: -- [Mod Base](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/ModBase.hpp) -- [Config Manager](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigManager.hpp) -- [Mod Config](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ModConfig.hpp) -- [Config value](https://github.com/ReDevCafe/FantasyLifeI-ModLoader-Headers/Mod/Configuration/ConfigValue.hpp) \ No newline at end of file diff --git a/src/GameData.cpp b/src/GameData.cpp index 8829e4d..e8a527d 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -3,9 +3,13 @@ #include "ModLoader.hpp" #include "Offset.h" -GameData::GameData(uintptr_t baseAddress) : _staticDataManager(nullptr), _dynamicDataManager(nullptr) { +GameData::GameData(uintptr_t baseAddress, uint32_t imageSize) : + _staticDataManager(nullptr), + _dynamicDataManager(nullptr) +{ ModLoader::logger->verbose("Initialize GameData"); this->_baseAddress = baseAddress; + this->_imageSize = imageSize; this->_gObjects = reinterpret_cast(this->_baseAddress + GOBJECTS_OFFSET); this->_gWorld = reinterpret_cast(this->_baseAddress + GWORLD_OFFSET); this->_gNames = reinterpret_cast(this->_baseAddress + GNAMES_OFFSET); @@ -36,6 +40,11 @@ uintptr_t GameData::getBaseAddress() { return _baseAddress; } +uint32_t GameData::getImageSize() +{ + return _imageSize; +} + FUObjectArray *GameData::getGObjects() { return _gObjects; } diff --git a/src/Hook/MemoryHelper.cpp b/src/Hook/MemoryHelper.cpp index 9a2ecb0..5bd9bdc 100644 --- a/src/Hook/MemoryHelper.cpp +++ b/src/Hook/MemoryHelper.cpp @@ -23,6 +23,25 @@ bool MemoryHelper::isFree(uintptr_t address, uint8_t length) { return true; } +uintptr_t MemoryHelper::findPattern(uintptr_t start, size_t rangeSize, const uint8_t* pattern, const char* mask) { + size_t patternLength = std::strlen(mask); + for (size_t i = 0; i <= rangeSize - patternLength; ++i) { + uintptr_t currentAddress = start + i; + uint8_t* memory = reinterpret_cast(currentAddress); + bool match = true; + for (size_t j = 0; j < patternLength; ++j) { + if (mask[j] == '?') continue; + if (memory[j] != pattern[j]) { + match = false; + break; + } + } + if (match) + return currentAddress; + } + throw std::out_of_range("Pattern not found"); +} + CONTEXT MemoryHelper::getPreviousFrame(CONTEXT originalCtx, uint8_t nth) { DWORD64 imageBase = 0; CONTEXT newContext = originalCtx; diff --git a/src/Hook/Pattern.cpp b/src/Hook/Pattern.cpp new file mode 100644 index 0000000..8d1e4df --- /dev/null +++ b/src/Hook/Pattern.cpp @@ -0,0 +1,21 @@ +#include "Hook/Pattern.hpp" +#include "Hook/MemoryHelper.hpp" + +Pattern::Pattern(uint8_t *pattern, const char *mask) : _pattern(pattern), _mask(mask) {} + +size_t Pattern::getSize() { + return strlen(_mask); +} + +uint8_t *Pattern::getPattern() { + return _pattern; +} + +const char *Pattern::getMask() { + return _mask; +} + +uintptr_t Pattern::find(uintptr_t baseAddress, uint32_t range) +{ + return MemoryHelper::findPattern(baseAddress, range, this->_pattern, this->_mask); +} \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index c42928c..bf84a63 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,12 +1,13 @@ #include "ModLoader.hpp" +#include "GameCache.hpp" #include "GameData.hpp" #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" #include "Utils.hpp" -#include "Patcher/Patcher.hpp" -#include "Patcher/Patches/EventHook.hpp" -#include "Utils.hpp" +#include "Psapi.h" + +#include "API/Function/Engine/FnameToString.hpp" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -14,20 +15,29 @@ Logger *ModLoader::logger = nullptr; ModEnvironnement *ModLoader::modEnvironnement = nullptr; ConfigManager *ModLoader::configManager = nullptr; -DWORD WINAPI ModLoader::init(LPVOID lpParam) { + +DWORD WINAPI ModLoader::init(LPVOID lpParam) +{ logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); Patcher patcher; uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); - // patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); broken????? - // patcher.applyPatches(baseAddress); - gameData = new GameData(reinterpret_cast(GetModuleHandle(nullptr))); + patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); + patcher.applyPatches(baseAddress); + gameData = new GameData(baseAddress, reinterpret_cast(lpParam)->SizeOfImage); gameCache = new GameCache(); configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); + FName test = gameCache->GetItem("imt01004480").getObject().nameId; + FString fstrtest; + FNameToString::call(&test, &fstrtest); + + std::string res = fstrtest.IsValid() ? fstrtest.ToString() : "Value invalid sorry.."; + ModLoader::logger->info("Returned: ", res); + gameCache->PostLoadCache(); gameData->initOthersData(); @@ -51,7 +61,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser std::cerr.clear(); Utils::EnableAnsiColors(); - LoaderThread = CreateThread(nullptr, 0, ModLoader::init, nullptr, 0, nullptr); + MODULEINFO moduleInfo{}; + GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &moduleInfo, sizeof(MODULEINFO)); + LoaderThread = CreateThread(nullptr, 0, ModLoader::init, &moduleInfo, 0, nullptr); break; } case DLL_PROCESS_DETACH: From d50f324cb25649fc4e0d038d59bda4a7f86712dd Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 12 Nov 2025 18:26:37 +0000 Subject: [PATCH 37/64] Engine FNames (CTor + ToString Class) --- src/ModLoader.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index bf84a63..1c940da 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -7,7 +7,7 @@ #include "Utils.hpp" #include "Psapi.h" -#include "API/Function/Engine/FnameToString.hpp" +#include "API/Engine/FName.hpp" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -30,13 +30,10 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); + + FName test("Cute:3"); + ModLoader::logger->info("Returned: ", test.ToString()); - FName test = gameCache->GetItem("imt01004480").getObject().nameId; - FString fstrtest; - FNameToString::call(&test, &fstrtest); - - std::string res = fstrtest.IsValid() ? fstrtest.ToString() : "Value invalid sorry.."; - ModLoader::logger->info("Returned: ", res); gameCache->PostLoadCache(); gameData->initOthersData(); From 7096e872470ded4523e9249081eccd5532467123 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Fri, 21 Nov 2025 02:29:21 +0000 Subject: [PATCH 38/64] Full FName Conversion --- CMakeLists.txt | 5 + src/API/Common/Common.cpp | 16 +- src/API/Common/CommonItemEffectParam.cpp | 7 +- src/API/Common/CommonItemTableSetting.cpp | 6 +- src/API/Common/CommonPickParamData.cpp | 10 +- src/API/Entities/CharaData.cpp | 15 +- src/API/Entities/Player/Player.cpp | 3 +- src/API/Item/ItemData.cpp | 18 +- src/API/Item/ItemEquipData.cpp | 6 +- src/API/Item/ItemLifeToolsData.cpp | 4 +- src/API/Life/LifeData.cpp | 11 +- src/API/Recipe/RecipeData.cpp | 9 +- src/API/Recipe/RecipeDataItemInfo.cpp | 4 +- src/API/Recipe/RecipeDataRewardData.cpp | 9 +- src/API/Skill/SkillData.cpp | 13 +- src/API/Table/ItemTableDetail.cpp | 5 +- src/API/World/MapData.cpp | 26 +-- src/API/World/MapDataSubMapData.cpp | 10 +- src/API/World/MapSubLevel.cpp | 14 +- src/GameCache.cpp | 257 +++++++++++----------- src/GameData.cpp | 25 +++ src/ModLoader.cpp | 5 +- 22 files changed, 262 insertions(+), 216 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 132fe79..00781ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(FantasyLifeI-ModLoader LANGUAGES CXX C) set(VERSION 1.00) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") option(MLDEBUG "Enable ModLoader debug code" ON) +option(USE_CUSTOM_UE_CLASS "Use custom Unreal Engine class instead of inheriting UE classes" OFF) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED) @@ -12,6 +13,10 @@ add_library(${PROJECT_NAME} SHARED) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) +if(USE_CUSTOM_UE_CLASS) + target_compile_definitions(${PROJECT_NAME} PRIVATE USE_CUSTOM_UE_CLASS) +endif() + if(MLDEBUG) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") diff --git a/src/API/Common/Common.cpp b/src/API/Common/Common.cpp index 1f10028..7ea19c3 100644 --- a/src/API/Common/Common.cpp +++ b/src/API/Common/Common.cpp @@ -2,10 +2,10 @@ #include "ModLoader.hpp" #include "GameCache.hpp" -std::string Common::NounSingular(LANG lang, std::string& identifier) +std::string Common::NounSingular(LANG lang, std::string_view identifier) { if(identifier == "None") return nullptr; - auto text = ModLoader::gameCache->GetNoun(identifier); + auto text = ModLoader::gameCache->GetNoun(identifier.data()); switch(lang) { case LANG::JAPANESE: return text->nounSingularForm.ToString(); @@ -22,7 +22,7 @@ std::string Common::NounSingular(LANG lang, std::string& identifier) return text->nounSingularForm.ToString(); } -void Common::NounSingularSet(LANG lang, std::string& identifier, FString value) +void Common::NounSingularSet(LANG lang, std::string_view identifier, FString value) { if(identifier == "None") { @@ -30,7 +30,7 @@ void Common::NounSingularSet(LANG lang, std::string& identifier, FString value) return; } - auto text = ModLoader::gameCache->GetNoun(identifier); + auto text = ModLoader::gameCache->GetNoun(identifier.data()); switch(lang) { case LANG::JAPANESE: text->nounSingularForm = value; @@ -45,9 +45,9 @@ void Common::NounSingularSet(LANG lang, std::string& identifier, FString value) } } -std::string Common::Description(LANG lang, std::string& identifier) +std::string Common::Description(LANG lang, std::string_view identifier) { - auto text = ModLoader::gameCache->GetText(identifier); + auto text = ModLoader::gameCache->GetText(identifier.data()); switch(lang) { case LANG::JAPANESE: return text->Text.ToString(); @@ -64,7 +64,7 @@ std::string Common::Description(LANG lang, std::string& identifier) return text->Text.ToString(); } -void Common::DescriptionSet(LANG lang, std::string &identifier, FString value) +void Common::DescriptionSet(LANG lang, std::string_view identifier, FString value) { if(identifier == "desc_itm_common") { @@ -72,7 +72,7 @@ void Common::DescriptionSet(LANG lang, std::string &identifier, FString value) return; } - auto text = ModLoader::gameCache->GetText(identifier); + auto text = ModLoader::gameCache->GetText(identifier.data()); switch(lang) { case LANG::JAPANESE: text->Text = value; diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 4e35d66..967ba38 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -1,11 +1,10 @@ #include "API/Common/CommonItemEffectParam.hpp" #include "API/Common/Common.hpp" +#include "API/Engine/FName.hpp" -#include "Utils.hpp" - -std::string& CommonItemEffectParam::getDescIdentifier() +std::string CommonItemEffectParam::getDescIdentifier() { - return Utils::FNameToString(this->_object.effDescId); + return static_cast(this->_object.effDescId).ToString(); } std::string CommonItemEffectParam::GetDescription(LANG lang) diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index a730092..c475e44 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -1,10 +1,10 @@ #include "API/Common/CommonItemTableSetting.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" #include "API/Engine/TArrayHelper.hpp" -std::string& CommonItemTableSetting::GetIdentifier() +std::string CommonItemTableSetting::GetIdentifier() { - return Utils::FNameToString(this->_object.tableId); + return static_cast(this->_object.tableId).ToString(); } ItemTableDetail CommonItemTableSetting::GetData(int index) diff --git a/src/API/Common/CommonPickParamData.cpp b/src/API/Common/CommonPickParamData.cpp index aba585f..221d420 100644 --- a/src/API/Common/CommonPickParamData.cpp +++ b/src/API/Common/CommonPickParamData.cpp @@ -1,12 +1,12 @@ #include "API/Common/CommonPickParamData.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" -std::string& CommonPickParamData::GetIdentifier() +std::string CommonPickParamData::GetIdentifier() { - return Utils::FNameToString(this->_object.ID); + return static_cast(this->_object.ID).ToString(); } -std::string& CommonPickParamData::GetGotIdentifier() +std::string CommonPickParamData::GetGotIdentifier() { - return Utils::FNameToString(this->_object.gotId); + return static_cast(this->_object.gotId).ToString(); } \ No newline at end of file diff --git a/src/API/Entities/CharaData.cpp b/src/API/Entities/CharaData.cpp index 8ef5d39..2d925af 100644 --- a/src/API/Entities/CharaData.cpp +++ b/src/API/Entities/CharaData.cpp @@ -1,15 +1,20 @@ #include "API/Entities/CharaData.hpp" #include "API/Common/Common.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" -std::string& CharaData::GetIdentifier() +std::string CharaData::GetIdentifier() { - return Utils::FNameToString(this->_object.ID); + return static_cast(this->_object.ID).ToString(); } -std::string& CharaData::GetNameIdentifier() +std::string CharaData::GetNameIdentifier() { - return Utils::FNameToString(this->_object.nameId); + return static_cast(this->_object.nameId).ToString(); +} + +std::string CharaData::GetFlag() +{ + return static_cast(this->_object.Flag).ToString(); } std::string CharaData::GetName(LANG lang) diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index efa7222..1f74dc1 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,4 +1,5 @@ #include "API/Entities/Player/Player.hpp" +#include "API/Engine/FName.hpp" #include "Utils.hpp" #include "ModLoader.hpp" @@ -8,7 +9,7 @@ Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, F ELifeType Player::GetLifeType() { FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - std::string &lifeId = Utils::FNameToString(avatarStatus->m_lifeId); + std::string lifeId = static_cast(avatarStatus->m_lifeId).ToString(); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index c3ee003..b5f6bf2 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -1,20 +1,20 @@ #include "API/Item/ItemData.hpp" #include "API/Common/Common.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" -std::string& ItemData::GetIdentifier() +std::string ItemData::GetIdentifier() { - return Utils::FNameToString(this->_object.ID); + return static_cast(this->_object.ID).ToString(); } -std::string& ItemData::getNameIdentifier() +std::string ItemData::getNameIdentifier() { - return Utils::FNameToString(this->_object.nameId); + return static_cast(this->_object.nameId).ToString(); } -std::string& ItemData::GetDescIdentifier() +std::string ItemData::GetDescIdentifier() { - return Utils::FNameToString(this->_object.DescId); + return static_cast(this->_object.DescId).ToString(); } std::string ItemData::GetName(LANG lang) @@ -39,7 +39,7 @@ void ItemData::SetDescription(LANG lang, FString string) DESC_SET(lang, GetDescIdentifier(), string); } -std::string& ItemData::GetOverwriteIcon() +std::string ItemData::GetOverwriteIcon() { - return Utils::FNameToString(this->_object.overwriteIconName); + return static_cast(this->_object.overwriteIconName).ToString(); } \ No newline at end of file diff --git a/src/API/Item/ItemEquipData.cpp b/src/API/Item/ItemEquipData.cpp index e2994eb..9b708e4 100644 --- a/src/API/Item/ItemEquipData.cpp +++ b/src/API/Item/ItemEquipData.cpp @@ -1,11 +1,12 @@ #include "API/Item/ItemEquipData.hpp" +#include "API/Engine/FName.hpp" #include "API/Engine/TArrayHelper.hpp" #include "Utils.hpp" #include "ModLoader.hpp" std::string ItemEquipData::GetModelIdentifier() { - return Utils::FNameToString(static_cast(this->_object).modelID); + return static_cast(static_cast(this->_object).modelID).ToString(); } void ItemEquipData::SetModel(ItemEquipData item) @@ -16,8 +17,7 @@ void ItemEquipData::SetModel(ItemEquipData item) TArray& ItemEquipData::GetAddSkillLot(int rarity) { auto skillIdRaw = TArrayHelper::Get(static_cast(this->_object).addSkillLotTableList, rarity); - std::string skillId = Utils::FNameToString(skillIdRaw); - + std::string skillId = static_cast(skillIdRaw).ToString(); return ModLoader::gameCache->GetAddSkillTable(skillId); } diff --git a/src/API/Item/ItemLifeToolsData.cpp b/src/API/Item/ItemLifeToolsData.cpp index ef1fddd..43041d4 100644 --- a/src/API/Item/ItemLifeToolsData.cpp +++ b/src/API/Item/ItemLifeToolsData.cpp @@ -1,7 +1,7 @@ #include "API/Item/ItemLifeToolsData.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" std::string ItemLifeToolsData::GetSecondModel() { - return Utils::FNameToString(reinterpret_cast(&this->_object)->ModelId2); + return static_cast(reinterpret_cast(&this->_object)->ModelId2).ToString(); } \ No newline at end of file diff --git a/src/API/Life/LifeData.cpp b/src/API/Life/LifeData.cpp index f6d3ece..327c9cc 100644 --- a/src/API/Life/LifeData.cpp +++ b/src/API/Life/LifeData.cpp @@ -1,17 +1,16 @@ #include "API/Life/LifeData.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -std::string& LifeData::GetNameIdentifier() +std::string LifeData::GetNameIdentifier() { - return Utils::FNameToString(this->_object.nameId); + return static_cast(this->_object.nameId).ToString(); } -std::string& LifeData::GetDescIdentifier() +std::string LifeData::GetDescIdentifier() { - return Utils::FNameToString(this->_object.DescId); + return static_cast(this->_object.DescId).ToString(); } - std::string LifeData::GetName(LANG lang) { return NAME_GET(lang, GetNameIdentifier()); diff --git a/src/API/Recipe/RecipeData.cpp b/src/API/Recipe/RecipeData.cpp index 883cfc3..7e7472c 100644 --- a/src/API/Recipe/RecipeData.cpp +++ b/src/API/Recipe/RecipeData.cpp @@ -1,17 +1,18 @@ #include "API/Recipe/RecipeData.hpp" +#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" #include "API/Engine/TArrayHelper.hpp" -std::string& RecipeData::GetIdentifier() +std::string RecipeData::GetIdentifier() { - return Utils::FNameToString(this->_object.recipeId); + return static_cast(this->_object.recipeId).ToString(); } -std::string& RecipeData::GetItemIdentifier() +std::string RecipeData::GetItemIdentifier() { - return Utils::FNameToString(this->_object.ItemId); + return static_cast(this->_object.ItemId).ToString(); } ItemData RecipeData::GetItem() diff --git a/src/API/Recipe/RecipeDataItemInfo.cpp b/src/API/Recipe/RecipeDataItemInfo.cpp index 9de1f11..3c2016e 100644 --- a/src/API/Recipe/RecipeDataItemInfo.cpp +++ b/src/API/Recipe/RecipeDataItemInfo.cpp @@ -1,8 +1,10 @@ #include "API/Recipe/RecipeDataItemInfo.hpp" +#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" +#include "Utils.hpp" ItemData RecipeDataItemInfo::GetItem() { - return ModLoader::gameCache->GetItem(Utils::FNameToString(this->_object.ItemId)); + return ModLoader::gameCache->GetItem(static_cast(this->_object.ItemId).ToString()); } \ No newline at end of file diff --git a/src/API/Recipe/RecipeDataRewardData.cpp b/src/API/Recipe/RecipeDataRewardData.cpp index df99e1c..e722525 100644 --- a/src/API/Recipe/RecipeDataRewardData.cpp +++ b/src/API/Recipe/RecipeDataRewardData.cpp @@ -1,24 +1,25 @@ #include "API/Recipe/RecipeDataRewardData.hpp" +#include "API/Engine/FName.hpp" #include "GameCache.hpp" #include "ModLoader.hpp" ItemData RecipeDataRewardData::GetRank0Item() { - return ModLoader::gameCache->GetItem(Utils::FNameToString(this->_object.rank0_itemId)); + return ModLoader::gameCache->GetItem(static_cast(this->_object.rank0_itemId).ToString()); } ItemData RecipeDataRewardData::GetRank1Item() { - return ModLoader::gameCache->GetItem(Utils::FNameToString(this->_object.rank1_itemId)); + return ModLoader::gameCache->GetItem(static_cast(this->_object.rank1_itemId).ToString()); } ItemData RecipeDataRewardData::GetRank2Item() { - return ModLoader::gameCache->GetItem(Utils::FNameToString(this->_object.rank2_itemId)); + return ModLoader::gameCache->GetItem(static_cast(this->_object.rank2_itemId).ToString()); } ItemData RecipeDataRewardData::GetRank3Item() { - return ModLoader::gameCache->GetItem(Utils::FNameToString(this->_object.rank3_itemId)); + return ModLoader::gameCache->GetItem(static_cast(this->_object.rank3_itemId).ToString()); } diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index 7baa56c..6bcb21f 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,16 +1,17 @@ #include "API/Skill/SkillData.hpp" +#include "API/Engine/FName.hpp" #include "Utils.hpp" #include "API/Common/Common.hpp" #include "API/Engine/TArrayHelper.hpp" -std::string& SkillData::GetIdentifier() +std::string SkillData::GetIdentifier() { - return Utils::FNameToString(this->_object.ID.Name); + return static_cast(this->_object.ID.Name).ToString(); } -std::string& SkillData::GetNameIdentifier() +std::string SkillData::GetNameIdentifier() { - return Utils::FNameToString(this->_object.nameTextID); + return static_cast(this->_object.nameTextID).ToString(); } std::string SkillData::GetName(LANG lang) @@ -23,9 +24,9 @@ void SkillData::SetName(LANG lang, FString string) NAME_SET(lang, GetNameIdentifier(), string); } -std::string& SkillData::GetDescIdentifier() +std::string SkillData::GetDescIdentifier() { - return Utils::FNameToString(this->_object.dascTextId); + return static_cast(this->_object.descTextID).ToString(); } std::string SkillData::GetDescription(LANG lang) diff --git a/src/API/Table/ItemTableDetail.cpp b/src/API/Table/ItemTableDetail.cpp index 511f06e..5340a49 100644 --- a/src/API/Table/ItemTableDetail.cpp +++ b/src/API/Table/ItemTableDetail.cpp @@ -1,10 +1,11 @@ #include "API/Table/ItemTableDetail.hpp" +#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -std::string& ItemTableDetail::GetItemIdentifier() +std::string ItemTableDetail::GetItemIdentifier() { - return Utils::FNameToString(this->_object.ItemId); + return static_cast(this->_object.ItemId).ToString(); } ItemData ItemTableDetail::GetItem() diff --git a/src/API/World/MapData.cpp b/src/API/World/MapData.cpp index fa3cbe9..caba423 100644 --- a/src/API/World/MapData.cpp +++ b/src/API/World/MapData.cpp @@ -1,20 +1,20 @@ #include "API/World/MapData.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -std::string& MapData::GetIdentifier() +std::string MapData::GetIdentifier() { - return Utils::FNameToString(this->_object.mapId); + return static_cast(this->_object.mapId).ToString(); } -std::string& MapData::GetPath() +std::string MapData::GetPath() { - return Utils::FNameToString(this->_object.MapPath); + return static_cast(this->_object.MapPath).ToString(); } -std::string& MapData::GetMapViewCategory() +std::string MapData::GetMapViewCategory() { - return Utils::FNameToString(this->_object.MapViewCategory); + return static_cast(this->_object.MapViewCategory).ToString(); } std::string MapData::GetMapViewName(int index) @@ -37,14 +37,14 @@ void MapData::SetMapViewName(int index, FString name) this->_object.MapViewDataArray.Data[index].mapName = name; } -std::string& MapData::GetMapSubject() +std::string MapData::GetMapSubject() { - return Utils::FNameToString(this->_object.MapSubject); + return static_cast(this->_object.MapSubject).ToString(); } -std::string& MapData::GetNameIdentifier() +std::string MapData::GetNameIdentifier() { - return Utils::FNameToString(this->_object.MapNameID); + return static_cast(this->_object.MapNameID).ToString(); } std::string MapData::GetName(LANG lang) @@ -57,9 +57,9 @@ void MapData::SetName(LANG lang, FString string) NAME_SET(lang, GetNameIdentifier(), string); } -std::string& MapData::GetWorldMap() +std::string MapData::GetWorldMap() { - return Utils::FNameToString(this->_object.WorldMapID); + return static_cast(this->_object.WorldMapID).ToString(); } MapDataSubMapData MapData::GetSubMap(int index) diff --git a/src/API/World/MapDataSubMapData.cpp b/src/API/World/MapDataSubMapData.cpp index b8f8c0f..99e3843 100644 --- a/src/API/World/MapDataSubMapData.cpp +++ b/src/API/World/MapDataSubMapData.cpp @@ -1,11 +1,11 @@ #include "API/World/MapDataSubMapData.hpp" +#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -#include "Utils.hpp" -std::string& MapDataSubMapData::GetSubMapIdentifier() +std::string MapDataSubMapData::GetSubMapIdentifier() { - return Utils::FNameToString(this->_object.subMapId); + return static_cast(this->_object.subMapId).ToString(); } MapSubLevel MapDataSubMapData::GetSubMap() @@ -13,7 +13,7 @@ MapSubLevel MapDataSubMapData::GetSubMap() return ModLoader::gameCache->GetSubLevel(GetSubMapIdentifier()); } -std::string& MapDataSubMapData::GetAreaID() +std::string MapDataSubMapData::GetAreaID() { - return Utils::FNameToString(this->_object.AreaID); + return static_cast(this->_object.AreaID).ToString(); } \ No newline at end of file diff --git a/src/API/World/MapSubLevel.cpp b/src/API/World/MapSubLevel.cpp index 49a8a79..0d094db 100644 --- a/src/API/World/MapSubLevel.cpp +++ b/src/API/World/MapSubLevel.cpp @@ -1,17 +1,17 @@ #include "API/World/MapSubLevel.hpp" -#include "Utils.hpp" +#include "API/Engine/FName.hpp" -std::string& MapSubLevel::GetIdentifier() +std::string MapSubLevel::GetIdentifier() { - return Utils::FNameToString(this->_object.SubLevelID); + return static_cast(this->_object.SubLevelID).ToString(); } -std::string& MapSubLevel::GetMapSubIdentifier() +std::string MapSubLevel::GetMapSubIdentifier() { - return Utils::FNameToString(this->_object.mapSubId); + return static_cast(this->_object.mapSubId).ToString(); } -std::string& MapSubLevel::GetPath() +std::string MapSubLevel::GetPath() { - return Utils::FNameToString(this->_object.SubLevelInfo.SubLevelPath); + return static_cast(this->_object.SubLevelInfo.SubLevelPath).ToString(); } \ No newline at end of file diff --git a/src/GameCache.cpp b/src/GameCache.cpp index 0858779..e247fe2 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -1,4 +1,6 @@ #include "GameCache.hpp" + +#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameData.hpp" @@ -61,111 +63,111 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) gmd->waitObject(&sdm->m_BattleCommandNameNoun); for (int i = 0; i < sdm->m_BattleCommandNameNoun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_BattleCommandNameNoun->m_dataMap.Data[i].Value.Second.nounInfoArray.Data; + auto textInfo = sdm->m_BattleCommandNameNoun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_BattleCommandNameNoun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_PlantDungeonText_Noun); for (int i = 0; i < sdm->m_PlantDungeonText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_PlantDungeonText_Noun->m_dataMap.Data[i].Value.Second.nounInfoArray.Data; + auto textInfo = sdm->m_PlantDungeonText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_PlantDungeonText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_ItemText_Noun); for (int i = 0; i < sdm->m_ItemText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_ItemText_Noun->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_ItemText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_ItemText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_LifeText_Noun); for (int i = 0; i < sdm->m_LifeText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_LifeText_Noun->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_LifeText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_LifeText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_SkillText_Noun); for (int i = 0; i < sdm->m_SkillText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_SkillText_Noun->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_SkillText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_SkillText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_QuestRequestMapText_Noun); for (int i = 0; i < sdm->m_QuestRequestMapText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_QuestRequestMapText_Noun->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_QuestRequestMapText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_QuestRequestMapText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_QuestTitleText); for (int i = 0; i < sdm->m_QuestTitleText->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_QuestTitleText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_QuestTitleText->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.Text.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_QuestTitleText->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_MapText_Noun); for (int i = 0; i < sdm->m_MapText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_MapText_Noun->m_dataMap.Data[i].Value.Second.nounInfo.Data; + auto textInfo = sdm->m_MapText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.nounInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_MapText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_MenuText_Noun); for (int i = 0; i < sdm->m_MenuText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_MenuText_Noun->m_dataMap.Data[i].Value.Second.nounInfoArray.Data; + auto textInfo = sdm->m_MenuText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_MenuText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_CharaText_Noun); for (int i = 0; i < sdm->m_CharaText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_CharaText_Noun->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_CharaText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_CharaText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } gmd->waitObject(&sdm->m_SystemText_Noun); for (int i = 0; i < sdm->m_SystemText_Noun->m_dataMap.Data.Count; i++) { - auto noun = sdm->m_SystemText_Noun->m_dataMap.Data[i].Value.Second.nounInfoArray.Data; + auto textInfo = sdm->m_SystemText_Noun->m_dataMap.Data[i]; + auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_SystemText_Noun->m_dataMap.Data[i].Value.First); - - this->_cacheNounInfo.emplace(key, noun); + + this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); } } @@ -174,192 +176,192 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) gmd->waitObject(&sdm->m_AchievementText); for (int i = 0; i < sdm->m_AchievementText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_AchievementText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_AchievementText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_AchievementText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); - } + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + } gmd->waitObject(&sdm->m_CharacterFlavorText); for (int i = 0; i < sdm->m_CharacterFlavorText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_CharacterFlavorText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_CharacterFlavorText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_CharacterFlavorText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_CharamakeText); for (int i = 0; i < sdm->m_CharamakeText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_CharamakeText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_CharamakeText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_CharamakeText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_DailyMissionCompleteNotificationText); for (int i = 0; i < sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_DailyMissionTitleText); for (int i = 0; i < sdm->m_DailyMissionTitleText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_DailyMissionTitleText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_DailyMissionTitleText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_DailyMissionTitleText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_GuildRewardText); for (int i = 0; i < sdm->m_GuildRewardText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_GuildRewardText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_GuildRewardText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_GuildRewardText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_ItemText); for (int i = 0; i < sdm->m_ItemText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_ItemText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_ItemText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_ItemText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_LifeText); for (int i = 0; i < sdm->m_LifeText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_LifeText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_LifeText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_LifeText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_MapText); for (int i = 0; i < sdm->m_MapText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_MapText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_MapText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_MapText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_MenuText); for (int i = 0; i < sdm->m_MenuText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_MenuText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_MenuText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_MenuText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_MultiText); for (int i = 0; i < sdm->m_MultiText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_MultiText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_MultiText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_MultiText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_PhaseTitleText); for (int i = 0; i < sdm->m_PhaseTitleText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_PhaseTitleText->m_dataMap.Data[i].Value.Second.textInfoArray.Data; + auto textInfo = sdm->m_PhaseTitleText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfoArray.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_PhaseTitleText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_PlantDungeonText); for (int i = 0; i < sdm->m_PlantDungeonText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_PlantDungeonText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_PlantDungeonText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_PlantDungeonText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_QuestDetailText); for (int i = 0; i < sdm->m_QuestDetailText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_QuestDetailText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_QuestDetailText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_QuestDetailText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_QuestPurposeText); for (int i = 0; i < sdm->m_QuestPurposeText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_QuestPurposeText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_QuestPurposeText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_QuestPurposeText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_QuestReportNotificationText); for (int i = 0; i < sdm->m_QuestReportNotificationText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_QuestReportNotificationText->m_dataMap.Data[i].Value.Second.Text.Data; + auto textInfo = sdm->m_QuestReportNotificationText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_QuestReportNotificationText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_SkillText); for (int i = 0; i < sdm->m_SkillText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_SkillText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_SkillText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_SkillText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_SystemText); for (int i = 0; i < sdm->m_SystemText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_SystemText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_SystemText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_SystemText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_TipsText); for (int i = 0; i < sdm->m_TipsText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_TipsText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_TipsText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_TipsText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } } @@ -368,21 +370,21 @@ void GameCache::postInitText(GameData* gmd, UStaticDataManager* sdm) gmd->waitObject(&sdm->m_PhasePurposeText); for (int i = 0; i < sdm->m_PhasePurposeText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_PhasePurposeText->m_dataMap.Data[i].Value.Second.textInfoArray.Data; + auto textInfo = sdm->m_PhasePurposeText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfoArray.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_PhasePurposeText->m_dataMap.Data[i].Value.First); - this->_cacheTextInfo.emplace(key, text); + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } gmd->waitObject(&sdm->m_BattleCommandDescText); for (int i = 0; i < sdm->m_BattleCommandDescText->m_dataMap.Data.Count; i++) { - auto text = sdm->m_BattleCommandDescText->m_dataMap.Data[i].Value.Second.textInfo.Data; + auto textInfo = sdm->m_BattleCommandDescText->m_dataMap.Data[i]; + auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - std::string key = Utils::FNameToString(sdm->m_BattleCommandDescText->m_dataMap.Data[i].Value.First); - - this->_cacheTextInfo.emplace(key, text); + + this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); } } @@ -391,12 +393,11 @@ void GameCache::initSkill(GameData* gmd, UStaticDataManager* sdm) gmd->waitObject(&sdm->m_SkillData); for (int i = 0; i < sdm->m_SkillData->m_dataMap.Data.Count; i++) { - std::string key = Utils::FNameToString(sdm->m_SkillData->m_dataMap.Data[i].Value.First.Name); + auto skillInfo = sdm->m_SkillData->m_dataMap.Data[i]; + std::string key = static_cast(skillInfo.Value.First.Name).ToString(); if(key == "ps_just_avoid" || key == "ps_just_guard") continue; - SkillData skill{ sdm->m_SkillData->m_dataMap.Data[i].Value.Second }; - - this->_cacheSkillData.emplace(key, std::make_unique(skill)); + this->_cacheSkillData.emplace(key, std::make_unique(skillInfo.Value.Second)); } } @@ -541,7 +542,9 @@ void GameCache::initAddSkillTable(GameData* gmd, UStaticDataManager* sdm) gmd->waitObject(&sdm->m_AddSkillLotTable); for (int i = 0; i < sdm->m_AddSkillLotTable->m_dataMap.Data.Count; i++) { - std::string key = Utils::FNameToString(sdm->m_AddSkillLotTable->m_dataMap.Data[i].Value.First); - this->_cacheAddSkillLotTable.emplace(key, &sdm->m_AddSkillLotTable->m_dataMap.Data[i].Value.Second.addSkillInfoList); + auto addSkillInfo = sdm->m_AddSkillLotTable->m_dataMap.Data[i]; + this->_cacheAddSkillLotTable.emplace( + static_cast(addSkillInfo.Value.First).ToString(), + &addSkillInfo.Value.Second.addSkillInfoList); } } \ No newline at end of file diff --git a/src/GameData.cpp b/src/GameData.cpp index e8a527d..5cddc51 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -1,4 +1,5 @@ #include "GameData.hpp" +#include "API/Engine/FName.hpp" #include "API/Entities/Player/Player.hpp" #include "ModLoader.hpp" #include "Offset.h" @@ -10,6 +11,10 @@ GameData::GameData(uintptr_t baseAddress, uint32_t imageSize) : ModLoader::logger->verbose("Initialize GameData"); this->_baseAddress = baseAddress; this->_imageSize = imageSize; +} + +void GameData::init() +{ this->_gObjects = reinterpret_cast(this->_baseAddress + GOBJECTS_OFFSET); this->_gWorld = reinterpret_cast(this->_baseAddress + GWORLD_OFFSET); this->_gNames = reinterpret_cast(this->_baseAddress + GNAMES_OFFSET); @@ -32,6 +37,26 @@ void GameData::initOthersData() { ModLoader::logger->info("OK: GameData has been initialized"); } +UObject* GameData::_getUObject(std::string_view name, bool safe, int nth = 0) +{ + API_FName apiName(name); + + UObject *object = nullptr; + uint32_t counter = 0; + if (safe) + _gObjects->lock(); + for (int i = 0; i < _gObjects->ObjObjects.NumElements; ++i) { + object = _gObjects->getObject(i); + if (object == nullptr) continue; + if (static_cast(object->NamePrivate) == apiName && ++counter > nth) break; + object = nullptr; + } + if (safe) + _gObjects->unlock(); + + return object; +} + Player *GameData::getPlayer() { return _player.get(); } diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 1c940da..dcdacf6 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -25,15 +25,18 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); patcher.applyPatches(baseAddress); gameData = new GameData(baseAddress, reinterpret_cast(lpParam)->SizeOfImage); + gameData->init(); gameCache = new GameCache(); configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); - FName test("Cute:3"); + API_FName test("Cute:3"); ModLoader::logger->info("Returned: ", test.ToString()); + API_FName name(gameCache->GetItem("imt01000430").getObject().nameId); + ModLoader::logger->info("Item name: ", name.ToString()); gameCache->PostLoadCache(); gameData->initOthersData(); From 6c0a23bf83144c1ed573513480c4b2d27e0917cc Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Fri, 21 Nov 2025 03:54:57 +0000 Subject: [PATCH 39/64] I guess everything is good for FNames --- CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00781ff..132fe79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,6 @@ project(FantasyLifeI-ModLoader LANGUAGES CXX C) set(VERSION 1.00) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") option(MLDEBUG "Enable ModLoader debug code" ON) -option(USE_CUSTOM_UE_CLASS "Use custom Unreal Engine class instead of inheriting UE classes" OFF) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED) @@ -13,10 +12,6 @@ add_library(${PROJECT_NAME} SHARED) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) -if(USE_CUSTOM_UE_CLASS) - target_compile_definitions(${PROJECT_NAME} PRIVATE USE_CUSTOM_UE_CLASS) -endif() - if(MLDEBUG) target_compile_definitions(${PROJECT_NAME} PRIVATE MLDEBUG) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") From f8113b232122e680fcf2d2b98caa29bdc7bb4ba1 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 24 Nov 2025 08:08:07 +0000 Subject: [PATCH 40/64] Replace FName with API_FName --- src/API/Common/CommonItemEffectParam.cpp | 2 +- src/API/Common/CommonItemTableSetting.cpp | 2 +- src/API/Common/CommonPickParamData.cpp | 4 +- src/API/Entities/CharaData.cpp | 6 +- src/API/Entities/Player/Player.cpp | 5 +- src/API/Item/ItemData.cpp | 8 +-- src/API/Item/ItemEquipData.cpp | 6 +- src/API/Item/ItemLifeToolsData.cpp | 2 +- src/API/Life/LifeData.cpp | 4 +- src/API/Recipe/RecipeData.cpp | 4 +- src/API/Recipe/RecipeDataItemInfo.cpp | 3 +- src/API/Recipe/RecipeDataRewardData.cpp | 8 +-- src/API/Skill/SkillData.cpp | 7 +-- src/API/Table/ItemTableDetail.cpp | 2 +- src/API/World/MapData.cpp | 12 ++-- src/API/World/MapDataSubMapData.cpp | 4 +- src/API/World/MapSubLevel.cpp | 6 +- src/GameCache.cpp | 71 ++++++++++++----------- src/GameData.cpp | 9 ++- src/Hook/Pattern.cpp | 7 +++ src/ModLoader.cpp | 19 ++++-- src/Utils.cpp | 63 -------------------- 22 files changed, 104 insertions(+), 150 deletions(-) delete mode 100644 src/Utils.cpp diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 967ba38..8353655 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -4,7 +4,7 @@ std::string CommonItemEffectParam::getDescIdentifier() { - return static_cast(this->_object.effDescId).ToString(); + return this->_object.effDescId.ToString(); } std::string CommonItemEffectParam::GetDescription(LANG lang) diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index c475e44..6f62cb9 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -4,7 +4,7 @@ std::string CommonItemTableSetting::GetIdentifier() { - return static_cast(this->_object.tableId).ToString(); + return this->_object.tableId.ToString(); } ItemTableDetail CommonItemTableSetting::GetData(int index) diff --git a/src/API/Common/CommonPickParamData.cpp b/src/API/Common/CommonPickParamData.cpp index 221d420..7123181 100644 --- a/src/API/Common/CommonPickParamData.cpp +++ b/src/API/Common/CommonPickParamData.cpp @@ -3,10 +3,10 @@ std::string CommonPickParamData::GetIdentifier() { - return static_cast(this->_object.ID).ToString(); + return this->_object.ID.ToString(); } std::string CommonPickParamData::GetGotIdentifier() { - return static_cast(this->_object.gotId).ToString(); + return this->_object.gotId.ToString(); } \ No newline at end of file diff --git a/src/API/Entities/CharaData.cpp b/src/API/Entities/CharaData.cpp index 2d925af..8b3173c 100644 --- a/src/API/Entities/CharaData.cpp +++ b/src/API/Entities/CharaData.cpp @@ -4,17 +4,17 @@ std::string CharaData::GetIdentifier() { - return static_cast(this->_object.ID).ToString(); + return this->_object.ID.ToString(); } std::string CharaData::GetNameIdentifier() { - return static_cast(this->_object.nameId).ToString(); + return this->_object.nameId.ToString(); } std::string CharaData::GetFlag() { - return static_cast(this->_object.Flag).ToString(); + return this->_object.Flag.ToString(); } std::string CharaData::GetName(LANG lang) diff --git a/src/API/Entities/Player/Player.cpp b/src/API/Entities/Player/Player.cpp index 1f74dc1..62543ef 100644 --- a/src/API/Entities/Player/Player.cpp +++ b/src/API/Entities/Player/Player.cpp @@ -1,15 +1,12 @@ #include "API/Entities/Player/Player.hpp" #include "API/Engine/FName.hpp" -#include "Utils.hpp" - -#include "ModLoader.hpp" #include Player::Player(FGDCharaParameter &charaParameter, FCharaStatusP *charaStatusP, FAvatarCharaStatusV &charaStatusV) : stats(charaParameter), status(*charaStatusP, charaStatusV) {} ELifeType Player::GetLifeType() { FAvatarCharaStatusP *avatarStatus = reinterpret_cast(&this->status.GetPermanentStatus()); - std::string lifeId = static_cast(avatarStatus->m_lifeId).ToString(); + std::string lifeId = avatarStatus->m_lifeId.ToString(); if (lifeId.empty() || lifeId.size() <= 4) return ELifeType::ELifeType__None; diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index b5f6bf2..3caa659 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -4,17 +4,17 @@ std::string ItemData::GetIdentifier() { - return static_cast(this->_object.ID).ToString(); + return this->_object.ID.ToString(); } std::string ItemData::getNameIdentifier() { - return static_cast(this->_object.nameId).ToString(); + return this->_object.nameId.ToString(); } std::string ItemData::GetDescIdentifier() { - return static_cast(this->_object.DescId).ToString(); + return this->_object.DescId.ToString(); } std::string ItemData::GetName(LANG lang) @@ -41,5 +41,5 @@ void ItemData::SetDescription(LANG lang, FString string) std::string ItemData::GetOverwriteIcon() { - return static_cast(this->_object.overwriteIconName).ToString(); + return this->_object.overwriteIconName.ToString(); } \ No newline at end of file diff --git a/src/API/Item/ItemEquipData.cpp b/src/API/Item/ItemEquipData.cpp index 9b708e4..ab28e1b 100644 --- a/src/API/Item/ItemEquipData.cpp +++ b/src/API/Item/ItemEquipData.cpp @@ -1,12 +1,11 @@ #include "API/Item/ItemEquipData.hpp" #include "API/Engine/FName.hpp" #include "API/Engine/TArrayHelper.hpp" -#include "Utils.hpp" #include "ModLoader.hpp" std::string ItemEquipData::GetModelIdentifier() { - return static_cast(static_cast(this->_object).modelID).ToString(); + return static_cast(this->_object).modelID.ToString(); } void ItemEquipData::SetModel(ItemEquipData item) @@ -17,8 +16,7 @@ void ItemEquipData::SetModel(ItemEquipData item) TArray& ItemEquipData::GetAddSkillLot(int rarity) { auto skillIdRaw = TArrayHelper::Get(static_cast(this->_object).addSkillLotTableList, rarity); - std::string skillId = static_cast(skillIdRaw).ToString(); - return ModLoader::gameCache->GetAddSkillTable(skillId); + return ModLoader::gameCache->GetAddSkillTable(skillIdRaw.ToString()); } void ItemEquipData::SetAddSkillTable(int rarity, FName value) diff --git a/src/API/Item/ItemLifeToolsData.cpp b/src/API/Item/ItemLifeToolsData.cpp index 43041d4..09a9a55 100644 --- a/src/API/Item/ItemLifeToolsData.cpp +++ b/src/API/Item/ItemLifeToolsData.cpp @@ -3,5 +3,5 @@ std::string ItemLifeToolsData::GetSecondModel() { - return static_cast(reinterpret_cast(&this->_object)->ModelId2).ToString(); + return reinterpret_cast(&this->_object)->ModelId2.ToString(); } \ No newline at end of file diff --git a/src/API/Life/LifeData.cpp b/src/API/Life/LifeData.cpp index 327c9cc..b24a1b3 100644 --- a/src/API/Life/LifeData.cpp +++ b/src/API/Life/LifeData.cpp @@ -4,12 +4,12 @@ std::string LifeData::GetNameIdentifier() { - return static_cast(this->_object.nameId).ToString(); + return this->_object.nameId.ToString(); } std::string LifeData::GetDescIdentifier() { - return static_cast(this->_object.DescId).ToString(); + return this->_object.DescId.ToString(); } std::string LifeData::GetName(LANG lang) { diff --git a/src/API/Recipe/RecipeData.cpp b/src/API/Recipe/RecipeData.cpp index 7e7472c..aa59e2a 100644 --- a/src/API/Recipe/RecipeData.cpp +++ b/src/API/Recipe/RecipeData.cpp @@ -7,12 +7,12 @@ std::string RecipeData::GetIdentifier() { - return static_cast(this->_object.recipeId).ToString(); + return this->_object.recipeId.ToString(); } std::string RecipeData::GetItemIdentifier() { - return static_cast(this->_object.ItemId).ToString(); + return this->_object.ItemId.ToString(); } ItemData RecipeData::GetItem() diff --git a/src/API/Recipe/RecipeDataItemInfo.cpp b/src/API/Recipe/RecipeDataItemInfo.cpp index 3c2016e..7160f87 100644 --- a/src/API/Recipe/RecipeDataItemInfo.cpp +++ b/src/API/Recipe/RecipeDataItemInfo.cpp @@ -2,9 +2,8 @@ #include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -#include "Utils.hpp" ItemData RecipeDataItemInfo::GetItem() { - return ModLoader::gameCache->GetItem(static_cast(this->_object.ItemId).ToString()); + return ModLoader::gameCache->GetItem(this->_object.ItemId.ToString()); } \ No newline at end of file diff --git a/src/API/Recipe/RecipeDataRewardData.cpp b/src/API/Recipe/RecipeDataRewardData.cpp index e722525..f63158b 100644 --- a/src/API/Recipe/RecipeDataRewardData.cpp +++ b/src/API/Recipe/RecipeDataRewardData.cpp @@ -5,21 +5,21 @@ ItemData RecipeDataRewardData::GetRank0Item() { - return ModLoader::gameCache->GetItem(static_cast(this->_object.rank0_itemId).ToString()); + return ModLoader::gameCache->GetItem(this->_object.rank0_itemId.ToString()); } ItemData RecipeDataRewardData::GetRank1Item() { - return ModLoader::gameCache->GetItem(static_cast(this->_object.rank1_itemId).ToString()); + return ModLoader::gameCache->GetItem(this->_object.rank1_itemId.ToString()); } ItemData RecipeDataRewardData::GetRank2Item() { - return ModLoader::gameCache->GetItem(static_cast(this->_object.rank2_itemId).ToString()); + return ModLoader::gameCache->GetItem(this->_object.rank2_itemId.ToString()); } ItemData RecipeDataRewardData::GetRank3Item() { - return ModLoader::gameCache->GetItem(static_cast(this->_object.rank3_itemId).ToString()); + return ModLoader::gameCache->GetItem(this->_object.rank3_itemId.ToString()); } diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index 6bcb21f..3639c27 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,17 +1,16 @@ #include "API/Skill/SkillData.hpp" #include "API/Engine/FName.hpp" -#include "Utils.hpp" #include "API/Common/Common.hpp" #include "API/Engine/TArrayHelper.hpp" std::string SkillData::GetIdentifier() { - return static_cast(this->_object.ID.Name).ToString(); + return this->_object.ID.Name.ToString(); } std::string SkillData::GetNameIdentifier() { - return static_cast(this->_object.nameTextID).ToString(); + return this->_object.nameTextID.ToString(); } std::string SkillData::GetName(LANG lang) @@ -26,7 +25,7 @@ void SkillData::SetName(LANG lang, FString string) std::string SkillData::GetDescIdentifier() { - return static_cast(this->_object.descTextID).ToString(); + return this->_object.descTextID.ToString(); } std::string SkillData::GetDescription(LANG lang) diff --git a/src/API/Table/ItemTableDetail.cpp b/src/API/Table/ItemTableDetail.cpp index 5340a49..c5ecb50 100644 --- a/src/API/Table/ItemTableDetail.cpp +++ b/src/API/Table/ItemTableDetail.cpp @@ -5,7 +5,7 @@ std::string ItemTableDetail::GetItemIdentifier() { - return static_cast(this->_object.ItemId).ToString(); + return this->_object.ItemId.ToString(); } ItemData ItemTableDetail::GetItem() diff --git a/src/API/World/MapData.cpp b/src/API/World/MapData.cpp index caba423..bb7b245 100644 --- a/src/API/World/MapData.cpp +++ b/src/API/World/MapData.cpp @@ -4,17 +4,17 @@ std::string MapData::GetIdentifier() { - return static_cast(this->_object.mapId).ToString(); + return this->_object.mapId.ToString(); } std::string MapData::GetPath() { - return static_cast(this->_object.MapPath).ToString(); + return this->_object.MapPath.ToString(); } std::string MapData::GetMapViewCategory() { - return static_cast(this->_object.MapViewCategory).ToString(); + return this->_object.MapViewCategory.ToString(); } std::string MapData::GetMapViewName(int index) @@ -39,12 +39,12 @@ void MapData::SetMapViewName(int index, FString name) std::string MapData::GetMapSubject() { - return static_cast(this->_object.MapSubject).ToString(); + return this->_object.MapSubject.ToString(); } std::string MapData::GetNameIdentifier() { - return static_cast(this->_object.MapNameID).ToString(); + return this->_object.MapNameID.ToString(); } std::string MapData::GetName(LANG lang) @@ -59,7 +59,7 @@ void MapData::SetName(LANG lang, FString string) std::string MapData::GetWorldMap() { - return static_cast(this->_object.WorldMapID).ToString(); + return this->_object.WorldMapID.ToString(); } MapDataSubMapData MapData::GetSubMap(int index) diff --git a/src/API/World/MapDataSubMapData.cpp b/src/API/World/MapDataSubMapData.cpp index 99e3843..e578e21 100644 --- a/src/API/World/MapDataSubMapData.cpp +++ b/src/API/World/MapDataSubMapData.cpp @@ -5,7 +5,7 @@ std::string MapDataSubMapData::GetSubMapIdentifier() { - return static_cast(this->_object.subMapId).ToString(); + return this->_object.subMapId.ToString(); } MapSubLevel MapDataSubMapData::GetSubMap() @@ -15,5 +15,5 @@ MapSubLevel MapDataSubMapData::GetSubMap() std::string MapDataSubMapData::GetAreaID() { - return static_cast(this->_object.AreaID).ToString(); + return this->_object.AreaID.ToString(); } \ No newline at end of file diff --git a/src/API/World/MapSubLevel.cpp b/src/API/World/MapSubLevel.cpp index 0d094db..996aec4 100644 --- a/src/API/World/MapSubLevel.cpp +++ b/src/API/World/MapSubLevel.cpp @@ -3,15 +3,15 @@ std::string MapSubLevel::GetIdentifier() { - return static_cast(this->_object.SubLevelID).ToString(); + return this->_object.SubLevelID.ToString(); } std::string MapSubLevel::GetMapSubIdentifier() { - return static_cast(this->_object.mapSubId).ToString(); + return this->_object.mapSubId.ToString(); } std::string MapSubLevel::GetPath() { - return static_cast(this->_object.SubLevelInfo.SubLevelPath).ToString(); + return this->_object.SubLevelInfo.SubLevelPath.ToString(); } \ No newline at end of file diff --git a/src/GameCache.cpp b/src/GameCache.cpp index e247fe2..45afa12 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -67,7 +67,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_PlantDungeonText_Noun); @@ -77,7 +77,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_ItemText_Noun); @@ -87,7 +87,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_LifeText_Noun); @@ -97,7 +97,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_SkillText_Noun); @@ -107,7 +107,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_QuestRequestMapText_Noun); @@ -117,7 +117,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_QuestTitleText); @@ -127,7 +127,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.Text.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_MapText_Noun); @@ -137,7 +137,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.nounInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_MenuText_Noun); @@ -147,7 +147,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_CharaText_Noun); @@ -157,7 +157,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.textInfo.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } gmd->waitObject(&sdm->m_SystemText_Noun); @@ -167,7 +167,7 @@ void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) auto noun = textInfo.Value.Second.nounInfoArray.Data; if (noun == nullptr) continue; - this->_cacheNounInfo.emplace(static_cast(textInfo.Value.First).ToString(), noun); + this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); } } @@ -180,7 +180,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_CharacterFlavorText); @@ -190,7 +190,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_CharamakeText); @@ -200,7 +200,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_DailyMissionCompleteNotificationText); @@ -210,7 +210,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_DailyMissionTitleText); @@ -220,7 +220,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_GuildRewardText); @@ -230,7 +230,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_ItemText); @@ -240,7 +240,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_LifeText); @@ -250,7 +250,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_MapText); @@ -260,7 +260,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_MenuText); @@ -270,7 +270,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_MultiText); @@ -280,7 +280,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } @@ -291,7 +291,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfoArray.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_PlantDungeonText); @@ -301,7 +301,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_QuestDetailText); @@ -311,7 +311,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_QuestPurposeText); @@ -321,7 +321,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_QuestReportNotificationText); @@ -331,7 +331,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.Text.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_SkillText); @@ -341,7 +341,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_SystemText); @@ -351,7 +351,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_TipsText); @@ -361,7 +361,7 @@ void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } } @@ -374,7 +374,7 @@ void GameCache::postInitText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfoArray.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } gmd->waitObject(&sdm->m_BattleCommandDescText); @@ -384,7 +384,7 @@ void GameCache::postInitText(GameData* gmd, UStaticDataManager* sdm) auto text = textInfo.Value.Second.textInfo.Data; if (text == nullptr) continue; - this->_cacheTextInfo.emplace(static_cast(textInfo.Value.First).ToString(), text); + this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); } } @@ -394,7 +394,7 @@ void GameCache::initSkill(GameData* gmd, UStaticDataManager* sdm) for (int i = 0; i < sdm->m_SkillData->m_dataMap.Data.Count; i++) { auto skillInfo = sdm->m_SkillData->m_dataMap.Data[i]; - std::string key = static_cast(skillInfo.Value.First.Name).ToString(); + std::string key = skillInfo.Value.First.Name.ToString(); if(key == "ps_just_avoid" || key == "ps_just_guard") continue; this->_cacheSkillData.emplace(key, std::make_unique(skillInfo.Value.Second)); @@ -544,7 +544,8 @@ void GameCache::initAddSkillTable(GameData* gmd, UStaticDataManager* sdm) { auto addSkillInfo = sdm->m_AddSkillLotTable->m_dataMap.Data[i]; this->_cacheAddSkillLotTable.emplace( - static_cast(addSkillInfo.Value.First).ToString(), - &addSkillInfo.Value.Second.addSkillInfoList); + addSkillInfo.Value.First.ToString(), + &addSkillInfo.Value.Second.addSkillInfoList + ); } } \ No newline at end of file diff --git a/src/GameData.cpp b/src/GameData.cpp index 5cddc51..0a7f7de 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -4,6 +4,11 @@ #include "ModLoader.hpp" #include "Offset.h" +#ifdef _WIN32 + #include +#else +#endif + GameData::GameData(uintptr_t baseAddress, uint32_t imageSize) : _staticDataManager(nullptr), _dynamicDataManager(nullptr) @@ -39,7 +44,7 @@ void GameData::initOthersData() { UObject* GameData::_getUObject(std::string_view name, bool safe, int nth = 0) { - API_FName apiName(name); + FName apiName(name); UObject *object = nullptr; uint32_t counter = 0; @@ -48,7 +53,7 @@ UObject* GameData::_getUObject(std::string_view name, bool safe, int nth = 0) for (int i = 0; i < _gObjects->ObjObjects.NumElements; ++i) { object = _gObjects->getObject(i); if (object == nullptr) continue; - if (static_cast(object->NamePrivate) == apiName && ++counter > nth) break; + if (object->NamePrivate == apiName && ++counter > nth) break; object = nullptr; } if (safe) diff --git a/src/Hook/Pattern.cpp b/src/Hook/Pattern.cpp index 8d1e4df..7d5dc9f 100644 --- a/src/Hook/Pattern.cpp +++ b/src/Hook/Pattern.cpp @@ -1,5 +1,7 @@ #include "Hook/Pattern.hpp" +#include "GameData.hpp" #include "Hook/MemoryHelper.hpp" +#include "ModLoader.hpp" Pattern::Pattern(uint8_t *pattern, const char *mask) : _pattern(pattern), _mask(mask) {} @@ -18,4 +20,9 @@ const char *Pattern::getMask() { uintptr_t Pattern::find(uintptr_t baseAddress, uint32_t range) { return MemoryHelper::findPattern(baseAddress, range, this->_pattern, this->_mask); +} + +uintptr_t Pattern::find(uintptr_t startOffset) +{ + return MemoryHelper::findPattern(ModLoader::gameData->getBaseAddress() + startOffset, ModLoader::gameData->getImageSize(), this->_pattern, this->_mask); } \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index dcdacf6..17732f1 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -4,7 +4,6 @@ #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" -#include "Utils.hpp" #include "Psapi.h" #include "API/Engine/FName.hpp" @@ -21,6 +20,9 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); Patcher patcher; + + Sleep(200); // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? + logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); patcher.applyPatches(baseAddress); @@ -31,11 +33,12 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); + logger->verbose("All loader preparations done"); - API_FName test("Cute:3"); + FName test("Cute:3"); ModLoader::logger->info("Returned: ", test.ToString()); - API_FName name(gameCache->GetItem("imt01000430").getObject().nameId); + FName name(gameCache->GetItem("imt01000430").getObject().nameId); ModLoader::logger->info("Item name: ", name.ToString()); gameCache->PostLoadCache(); @@ -43,6 +46,7 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) modEnvironnement->PostLoad(); + logger->verbose("Mod loader initialization complete"); return 0; } @@ -60,7 +64,14 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser std::cout.clear(); std::cerr.clear(); - Utils::EnableAnsiColors(); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + if(GetConsoleMode(hConsole, &dwMode)) + { + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(hConsole, dwMode); + } + MODULEINFO moduleInfo{}; GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &moduleInfo, sizeof(MODULEINFO)); LoaderThread = CreateThread(nullptr, 0, ModLoader::init, &moduleInfo, 0, nullptr); diff --git a/src/Utils.cpp b/src/Utils.cpp deleted file mode 100644 index e3ed47d..0000000 --- a/src/Utils.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "Utils.hpp" -#include "ModLoader.hpp" -#include "GameData.hpp" -#include "GameCache.hpp" -#include "Offset.h" - - -std::unordered_map Utils::_strings; - -std::string &Utils::FNameToString(uintptr_t baseAddress, FName fname) { - if (_strings.contains(fname.ComparisonIndex)) - return _strings.at(fname.ComparisonIndex); - char name[NAME_BUFFER + 1] = {0}; - const unsigned int chunkOffset = fname.ComparisonIndex >> 16; - const unsigned short nameOffset = fname.ComparisonIndex; - uintptr_t namePoolChunk = *(uintptr_t *) (baseAddress + GNAMES_OFFSET + 8 * (chunkOffset + 2)) + 2 * nameOffset; - const uint16_t nameLength = *(uint16_t *) (namePoolChunk) >> 6; - if (reinterpret_cast(namePoolChunk + 2) == nullptr) - throw std::invalid_argument("namePoolChunk is null."); - memcpy(name, (void *) (namePoolChunk + 2), nameLength < NAME_BUFFER ? nameLength : NAME_BUFFER); - auto result = _strings.emplace(fname.ComparisonIndex, std::string(name)); - return result.first->second; -} - -std::string &Utils::FNameToString(FName fname) { - return FNameToString(ModLoader::gameData->getBaseAddress(), fname); -} - -std::string &Utils::PC_FNameToString(uintptr_t baseAdress, FName fname) -{ - if(_strings.contains(fname.ComparisonIndex)) - return _strings.at(fname.ComparisonIndex); - - char name[NAME_BUFFER + 1] = { 0 }; - const unsigned int chunkOffset = fname.ComparisonIndex >> 16; - const unsigned short nameOffset = fname.ComparisonIndex; - - uintptr_t namePoolChunk = *(uintptr_t *) (baseAdress + GNAMES_OFFSET + 8 * (chunkOffset +2 )) + 4 * nameOffset; - const uint16_t nameLength = (*(uint16_t *) (namePoolChunk) + 4) >> 1; - if(reinterpret_cast(namePoolChunk + 6) == nullptr) - throw std::invalid_argument("namePoolChunk is null..."); - - memcpy(name, (void*) (namePoolChunk + 6), nameLength < NAME_BUFFER ? nameLength : NAME_BUFFER); - auto result = _strings.emplace(fname.ComparisonIndex, std::string(name)); - return result.first->second; -} - -std::string &Utils::PC_FNameToString(FName fname) -{ - return PC_FNameToString(ModLoader::gameData->getBaseAddress(), fname); -} - -void Utils::EnableAnsiColors() -{ - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - if(hConsole == INVALID_HANDLE_VALUE) return; - - DWORD dwMode = 0; - if(!GetConsoleMode(hConsole, &dwMode)) return; - - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - SetConsoleMode(hConsole, dwMode); -} \ No newline at end of file From 3dffab110fe08b2c22c2fbec7389a9c9813dbac7 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 24 Nov 2025 12:36:49 +0000 Subject: [PATCH 41/64] TMap Iterator --- src/API/Common/CommonItemTableSetting.cpp | 7 +- src/API/Item/ItemEquipData.cpp | 5 +- src/API/Item/ItemUniqueSkillEquipData.cpp | 4 +- src/API/Recipe/RecipeData.cpp | 8 +- src/API/Skill/SkillData.cpp | 7 +- src/API/Skill/SkillEffectInfo.cpp | 7 +- src/GameCache.cpp | 479 ++++++---------------- src/ModLoader.cpp | 13 +- 8 files changed, 149 insertions(+), 381 deletions(-) diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index 6f62cb9..410a19f 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -1,6 +1,5 @@ #include "API/Common/CommonItemTableSetting.hpp" #include "API/Engine/FName.hpp" -#include "API/Engine/TArrayHelper.hpp" std::string CommonItemTableSetting::GetIdentifier() { @@ -9,16 +8,16 @@ std::string CommonItemTableSetting::GetIdentifier() ItemTableDetail CommonItemTableSetting::GetData(int index) { - auto raw = TArrayHelper::Get(this->_object.tableData, index); + auto raw = this->_object.tableData.Get(index); return ItemTableDetail(raw); } void CommonItemTableSetting::SetData(int index, ItemTableDetail value) { - TArrayHelper::Set(this->_object.tableData, index, value.getObject()); + this->_object.tableData.Set(index, value.getObject()); } void CommonItemTableSetting::AddData(ItemTableDetail value) { - TArrayHelper::Add(this->_object.tableData, value.getObject()); + this->_object.tableData.Add(value.getObject()); } \ No newline at end of file diff --git a/src/API/Item/ItemEquipData.cpp b/src/API/Item/ItemEquipData.cpp index ab28e1b..45781b2 100644 --- a/src/API/Item/ItemEquipData.cpp +++ b/src/API/Item/ItemEquipData.cpp @@ -1,6 +1,5 @@ #include "API/Item/ItemEquipData.hpp" #include "API/Engine/FName.hpp" -#include "API/Engine/TArrayHelper.hpp" #include "ModLoader.hpp" std::string ItemEquipData::GetModelIdentifier() @@ -15,11 +14,11 @@ void ItemEquipData::SetModel(ItemEquipData item) TArray& ItemEquipData::GetAddSkillLot(int rarity) { - auto skillIdRaw = TArrayHelper::Get(static_cast(this->_object).addSkillLotTableList, rarity); + auto skillIdRaw = static_cast(this->_object).addSkillLotTableList.Get(rarity); return ModLoader::gameCache->GetAddSkillTable(skillIdRaw.ToString()); } void ItemEquipData::SetAddSkillTable(int rarity, FName value) { - TArrayHelper::Set(static_cast(this->_object).addSkillLotTableList, rarity, value); + static_cast(this->_object).addSkillLotTableList.Set(rarity, value); } \ No newline at end of file diff --git a/src/API/Item/ItemUniqueSkillEquipData.cpp b/src/API/Item/ItemUniqueSkillEquipData.cpp index f69a684..8161dea 100644 --- a/src/API/Item/ItemUniqueSkillEquipData.cpp +++ b/src/API/Item/ItemUniqueSkillEquipData.cpp @@ -1,8 +1,6 @@ #include "API/Item/ItemUniqueSkillEquipData.hpp" -#include "API/Engine/TArrayHelper.hpp" void ItemUniqueSkillEquipData::AddSkill(SkillData skill) { - auto data = reinterpret_cast(&this->_object); - TArrayHelper::Add(data->SkillID, skill.getObject().ID.Name); + reinterpret_cast(&this->_object)->SkillID.Add(skill.getObject().ID.Name); } \ No newline at end of file diff --git a/src/API/Recipe/RecipeData.cpp b/src/API/Recipe/RecipeData.cpp index aa59e2a..e32213b 100644 --- a/src/API/Recipe/RecipeData.cpp +++ b/src/API/Recipe/RecipeData.cpp @@ -2,8 +2,6 @@ #include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -#include "API/Engine/TArrayHelper.hpp" - std::string RecipeData::GetIdentifier() { @@ -22,16 +20,16 @@ ItemData RecipeData::GetItem() RecipeDataItemInfo RecipeData::GetRecipeItem(int index) { - auto raw = TArrayHelper::Get(this->_object.itemList, index); + auto raw = this->_object.itemList.Get(index); return RecipeDataItemInfo(raw); } void RecipeData::SetRecipeItem(ItemData value, int index, int32_t quantity) { - TArrayHelper::Set(this->_object.itemList, index, FGDRecipeData_ItemInfo{value.getObject().ID, quantity}); + this->_object.itemList.Set(index, FGDRecipeData_ItemInfo{value.getObject().ID, quantity}); } void RecipeData::AddRecipeItem(ItemData data, int32_t quantity) { - TArrayHelper::Add(this->_object.itemList, FGDRecipeData_ItemInfo{data.getObject().ID, quantity}); + this->_object.itemList.Add(FGDRecipeData_ItemInfo{data.getObject().ID, quantity}); } \ No newline at end of file diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index 3639c27..bd7c113 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,7 +1,6 @@ #include "API/Skill/SkillData.hpp" #include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -#include "API/Engine/TArrayHelper.hpp" std::string SkillData::GetIdentifier() { @@ -40,16 +39,16 @@ void SkillData::SetDescription(LANG lang, FString string) SkillEffectInfo SkillData::GetSkillEffect(int index) { - auto raw = TArrayHelper::Get(this->_object.skillEffectInfoList, index); + auto raw = this->_object.skillEffectInfoList.Get(index); return SkillEffectInfo(raw); } void SkillData::SetSkillEffect(int index, SkillEffectInfo value) { - TArrayHelper::Set(this->_object.skillEffectInfoList, index, value.getObject()); + this->_object.skillEffectInfoList.Set(index, value.getObject()); } void SkillData::AddSkillEffect(SkillEffectInfo data) { - TArrayHelper::Add(this->_object.skillEffectInfoList, data.getObject()); + this->_object.skillEffectInfoList.Add(data.getObject()); } \ No newline at end of file diff --git a/src/API/Skill/SkillEffectInfo.cpp b/src/API/Skill/SkillEffectInfo.cpp index 7a58db7..afbd8bf 100644 --- a/src/API/Skill/SkillEffectInfo.cpp +++ b/src/API/Skill/SkillEffectInfo.cpp @@ -1,18 +1,17 @@ #include "API/Skill/SkillEffectInfo.hpp" -#include "API/Engine/TArrayHelper.hpp" EffectCondition SkillEffectInfo::GetEffectCondition(int index) { - auto raw = TArrayHelper::Get(this->_object.effCondList, index); + auto raw = this->_object.effCondList.Get(index); return EffectCondition(raw); } void SkillEffectInfo::SetEffectCondition(int index, EffectCondition value) { - TArrayHelper::Set(this->_object.effCondList, index, value.getObject()); + this->_object.effCondList.Set(index, value.getObject()); } void SkillEffectInfo::AddEffectCondition(EffectCondition value) { - TArrayHelper::Add(this->_object.effCondList, value.getObject()); + this->_object.effCondList.Add(value.getObject()); } \ No newline at end of file diff --git a/src/GameCache.cpp b/src/GameCache.cpp index 45afa12..11540c8 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -14,6 +14,8 @@ #include "API/Item/ItemKitData.hpp" #include "API/Item/ItemVehicleData.hpp" #include "API/Item/ItemPowerUpData.hpp" +#include +#include GameCache::GameCache() { @@ -41,6 +43,17 @@ GameCache::GameCache() initAddSkillTable(gmd, sdm); ModLoader::logger->verbose("Cached: AddSkillTable Registries"); + + uint32_t totalSize = + (this->_cacheNounInfo.size() * sizeof(void*)) + + (this->_cacheTextInfo.size() * sizeof(void*)) + + (this->_cacheItemData.size() * sizeof(void*)) + + (this->_cacheRecipeData.size() * sizeof(void*)) + + (this->_cacheCommonPickParam.size() * sizeof(void*)) + + (this->_cacheCharaData.size() * sizeof(void*)) + + (this->_cacheAddSkillLotTable.size() * sizeof(TArray*)); + + ModLoader::logger->verbose("Total cached size: ", totalSize / 1024, " KB"); } void GameCache::PostLoadCache() @@ -61,491 +74,253 @@ void GameCache::PostLoadCache() void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_BattleCommandNameNoun); - for (int i = 0; i < sdm->m_BattleCommandNameNoun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_BattleCommandNameNoun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.nounInfoArray.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& noun : sdm->m_BattleCommandNameNoun->m_dataMap) + this->_cacheNounInfo.emplace(noun.ID.ToString(), noun.nounInfoArray.GetData()); gmd->waitObject(&sdm->m_PlantDungeonText_Noun); - for (int i = 0; i < sdm->m_PlantDungeonText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_PlantDungeonText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.nounInfoArray.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& noun : sdm->m_PlantDungeonText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(noun.ID.ToString(), noun.nounInfoArray.GetData()); gmd->waitObject(&sdm->m_ItemText_Noun); - for (int i = 0; i < sdm->m_ItemText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_ItemText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.textInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& noun : sdm->m_ItemText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(noun.ID.ToString(), noun.textInfo.GetData()); // WHY IS THIS FUCKING NAMED TEXTINFO WTF LEVEL 5 PLEASE BE CONSISTENT gmd->waitObject(&sdm->m_LifeText_Noun); - for (int i = 0; i < sdm->m_LifeText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_LifeText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.textInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_LifeText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_SkillText_Noun); - for (int i = 0; i < sdm->m_SkillText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_SkillText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.textInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_SkillText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_QuestRequestMapText_Noun); - for (int i = 0; i < sdm->m_QuestRequestMapText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_QuestRequestMapText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.textInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_QuestRequestMapText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_QuestTitleText); - for (int i = 0; i < sdm->m_QuestTitleText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_QuestTitleText->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.Text.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_QuestTitleText->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_MapText_Noun); - for (int i = 0; i < sdm->m_MapText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_MapText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.nounInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_MapText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.nounInfo.GetData()); gmd->waitObject(&sdm->m_MenuText_Noun); - for (int i = 0; i < sdm->m_MenuText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_MenuText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.nounInfoArray.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_MenuText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.nounInfoArray.GetData()); gmd->waitObject(&sdm->m_CharaText_Noun); - for (int i = 0; i < sdm->m_CharaText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_CharaText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.textInfo.Data; - if (noun == nullptr) continue; - - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + for (auto& textInfo : sdm->m_CharaText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_SystemText_Noun); - for (int i = 0; i < sdm->m_SystemText_Noun->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_SystemText_Noun->m_dataMap.Data[i]; - auto noun = textInfo.Value.Second.nounInfoArray.Data; - if (noun == nullptr) continue; + for (auto& textInfo : sdm->m_SystemText_Noun->m_dataMap) + this->_cacheNounInfo.emplace(textInfo.ID.ToString(), textInfo.nounInfoArray.GetData()); - this->_cacheNounInfo.emplace(textInfo.Value.First.ToString(), noun); - } + ModLoader::logger->verbose("GameCache: NounInfo size: ", this->_cacheNounInfo.size()); } void GameCache::initText(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_AchievementText); - for (int i = 0; i < sdm->m_AchievementText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_AchievementText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_AchievementText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_CharacterFlavorText); - for (int i = 0; i < sdm->m_CharacterFlavorText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_CharacterFlavorText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_CharacterFlavorText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_CharamakeText); - for (int i = 0; i < sdm->m_CharamakeText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_CharamakeText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_CharamakeText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_DailyMissionCompleteNotificationText); - for (int i = 0; i < sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_DailyMissionCompleteNotificationText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_DailyMissionCompleteNotificationText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_DailyMissionTitleText); - for (int i = 0; i < sdm->m_DailyMissionTitleText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_DailyMissionTitleText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_DailyMissionTitleText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_GuildRewardText); - for (int i = 0; i < sdm->m_GuildRewardText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_GuildRewardText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_GuildRewardText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_ItemText); - for (int i = 0; i < sdm->m_ItemText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_ItemText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_ItemText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_LifeText); - for (int i = 0; i < sdm->m_LifeText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_LifeText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_LifeText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_MapText); - for (int i = 0; i < sdm->m_MapText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_MapText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_MapText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_MenuText); - for (int i = 0; i < sdm->m_MenuText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_MenuText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_MenuText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_MultiText); - for (int i = 0; i < sdm->m_MultiText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_MultiText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } - + for (auto& textInfo : sdm->m_MultiText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_PhaseTitleText); - for (int i = 0; i < sdm->m_PhaseTitleText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_PhaseTitleText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfoArray.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_PhaseTitleText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfoArray.GetData()); gmd->waitObject(&sdm->m_PlantDungeonText); - for (int i = 0; i < sdm->m_PlantDungeonText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_PlantDungeonText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_PlantDungeonText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_QuestDetailText); - for (int i = 0; i < sdm->m_QuestDetailText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_QuestDetailText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_QuestDetailText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_QuestPurposeText); - for (int i = 0; i < sdm->m_QuestPurposeText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_QuestPurposeText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_QuestPurposeText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_QuestReportNotificationText); - for (int i = 0; i < sdm->m_QuestReportNotificationText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_QuestReportNotificationText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.Text.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_QuestReportNotificationText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.Text.GetData()); gmd->waitObject(&sdm->m_SkillText); - for (int i = 0; i < sdm->m_SkillText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_SkillText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_SkillText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_SystemText); - for (int i = 0; i < sdm->m_SystemText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_SystemText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_SystemText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); gmd->waitObject(&sdm->m_TipsText); - for (int i = 0; i < sdm->m_TipsText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_TipsText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; + for (auto& textInfo : sdm->m_TipsText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + ModLoader::logger->verbose("GameCache: TextInfo size: ", this->_cacheTextInfo.size()); } void GameCache::postInitText(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_PhasePurposeText); - for (int i = 0; i < sdm->m_PhasePurposeText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_PhasePurposeText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfoArray.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_PhasePurposeText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfoArray.GetData()); gmd->waitObject(&sdm->m_BattleCommandDescText); - for (int i = 0; i < sdm->m_BattleCommandDescText->m_dataMap.Data.Count; i++) - { - auto textInfo = sdm->m_BattleCommandDescText->m_dataMap.Data[i]; - auto text = textInfo.Value.Second.textInfo.Data; - if (text == nullptr) continue; - - this->_cacheTextInfo.emplace(textInfo.Value.First.ToString(), text); - } + for (auto& textInfo : sdm->m_BattleCommandDescText->m_dataMap) + this->_cacheTextInfo.emplace(textInfo.ID.ToString(), textInfo.textInfo.GetData()); + } void GameCache::initSkill(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_SkillData); - for (int i = 0; i < sdm->m_SkillData->m_dataMap.Data.Count; i++) + for (auto& skillInfo : sdm->m_SkillData->m_dataMap) { - auto skillInfo = sdm->m_SkillData->m_dataMap.Data[i]; - std::string key = skillInfo.Value.First.Name.ToString(); + std::string key = skillInfo.ID.Name.ToString(); if(key == "ps_just_avoid" || key == "ps_just_guard") continue; - this->_cacheSkillData.emplace(key, std::make_unique(skillInfo.Value.Second)); + this->_cacheSkillData.emplace(key, std::make_unique(skillInfo)); } + ModLoader::logger->verbose("GameCache: SkillData size: ", this->_cacheSkillData.size()); } void GameCache::initCommonPickParam(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_CommonPickParamData); - for (int i = 0; i < sdm->m_CommonPickParamData->m_dataMap.Data.Count; i++) - { - CommonPickParamData param{ sdm->m_CommonPickParamData->m_dataMap.Data[i].Value.Second }; - this->_cacheCommonPickParam.emplace(param.GetIdentifier(), std::make_unique(param)); - } + for (auto& paramInfo : sdm->m_CommonPickParamData->m_dataMap) + this->_cacheCommonPickParam.emplace(paramInfo.ID.ToString(), std::make_unique(paramInfo)); + + ModLoader::logger->verbose("GameCache: CommonPickParamData size: ", this->_cacheCommonPickParam.size()); } void GameCache::initItem(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_ItemMaterialData); - for (int i = 0; i < sdm->m_ItemMaterialData->m_dataMap.Data.Count; i++) - { - ItemMaterialData citem{ sdm->m_ItemMaterialData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - - } - + for (auto& itemInfo : sdm->m_ItemMaterialData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); + gmd->waitObject(&sdm->m_ItemConsumeData); - for (int i = 0; i < sdm->m_ItemConsumeData->m_dataMap.Data.Count; i++) - { - ItemConsumeData citem{ sdm->m_ItemConsumeData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemConsumeData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemImportantData); - for (int i = 0; i < sdm->m_ItemImportantData->m_dataMap.Data.Count; i++) - { - ItemImportantData citem{ sdm->m_ItemImportantData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemImportantData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemWeaponData); - for (int i = 0; i < sdm->m_ItemWeaponData->m_dataMap.Data.Count; i++) - { - ItemWeaponData citem{ sdm->m_ItemWeaponData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemWeaponData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemLifeToolsData); - for (int i = 0; i < sdm->m_ItemLifeToolsData->m_dataMap.Data.Count; i++) - { - ItemLifeToolsData citem{ sdm->m_ItemLifeToolsData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemLifeToolsData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemArmorData); - for (int i = 0; i < sdm->m_ItemArmorData->m_dataMap.Data.Count; i++) - { - ItemArmorData citem{ sdm->m_ItemArmorData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemArmorData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); + gmd->waitObject(&sdm->m_ItemCraftData); - for (int i = 0; i < sdm->m_ItemCraftData->m_dataMap.Data.Count; i++) - { - ItemCraftData citem{ sdm->m_ItemCraftData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemCraftData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemKitData); - for (int i = 0; i < sdm->m_ItemKitData->m_dataMap.Data.Count; i++) - { - ItemKitData citem{ sdm->m_ItemKitData->m_dataMap.Data[i].Value.Second }; + for (auto& itemInfo : sdm->m_ItemKitData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } gmd->waitObject(&sdm->m_ItemVehicleData); - for (int i = 0; i < sdm->m_ItemVehicleData->m_dataMap.Data.Count; i++) - { - ItemVehicleData citem{ sdm->m_ItemVehicleData->m_dataMap.Data[i].Value.Second }; - - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + for (auto& itemInfo : sdm->m_ItemVehicleData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); gmd->waitObject(&sdm->m_ItemPowerUpData); - for (int i = 0; i < sdm->m_ItemPowerUpData->m_dataMap.Data.Count; i++) - { - ItemPowerUpData citem{ sdm->m_ItemPowerUpData->m_dataMap.Data[i].Value.Second }; + for (auto& itemInfo : sdm->m_ItemPowerUpData->m_dataMap) + this->_cacheItemData.emplace(itemInfo.ID.ToString(), std::make_unique(itemInfo)); - _cacheItemData.emplace(citem.GetIdentifier(), std::make_unique(citem)); - } + ModLoader::logger->verbose("GameCache: ItemData size: ", this->_cacheItemData.size()); } void GameCache::initRecipe(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_RecipeData); - for (int i = 0; i < sdm->m_RecipeData->m_dataMap.Data.Count; i++) - { - RecipeData recipe{ sdm->m_RecipeData->m_dataMap.Data[i].Value.Second }; + for (auto& recipeInfo : sdm->m_RecipeData->m_dataMap) + this->_cacheRecipeData.emplace(recipeInfo.recipeId.ToString(), std::make_unique(recipeInfo)); - _cacheRecipeData.emplace(recipe.GetIdentifier(), std::make_unique(recipe)); - } + ModLoader::logger->verbose("GameCache: RecipeData size: ", this->_cacheRecipeData.size()); } void GameCache::initChara(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_CharaData); - for (int i = 0; i < sdm->m_CharaData->m_dataMap.Data.Count; i++) - { - CharaData chara{ sdm->m_CharaData->m_dataMap.Data[i].Value.Second }; + for (auto& charaInfo : sdm->m_CharaData->m_dataMap) + this->_cacheCharaData.emplace(charaInfo.ID.ToString(), std::make_unique(charaInfo)); - _cacheCharaData.emplace(chara.GetIdentifier(), std::make_unique(chara)); - } + ModLoader::logger->verbose("GameCache: CharaData size: ", this->_cacheCharaData.size()); } void GameCache::initSubLevel(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_MapSubLevel); - for (int i = 0; i < sdm->m_MapSubLevel->m_dataMap.Data.Count; i++) - { - MapSubLevel level{ sdm->m_MapSubLevel->m_dataMap.Data[i].Value.Second }; + for (auto& levelInfo : sdm->m_MapSubLevel->m_dataMap) + this->_cacheSubLevel.emplace(levelInfo.SubLevelID.ToString(), std::make_unique(levelInfo)); - _cacheSubLevel.emplace(level.GetIdentifier(), std::make_unique(level)); - } + ModLoader::logger->verbose("GameCache: SubLevel size: ", this->_cacheSubLevel.size()); } void GameCache::initMap(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_MapData); - for (int i = 0; i < sdm->m_MapData->m_dataMap.Data.Count; ++i) - { - MapData map{ sdm->m_MapData->m_dataMap.Data[i].Value.Second }; + for (auto& mapInfo : sdm->m_MapData->m_dataMap) + this->_cacheMap.emplace(mapInfo.mapId.ToString(), std::make_unique(mapInfo)); - _cacheMap.emplace(map.GetIdentifier(), std::make_unique(map)); - } + ModLoader::logger->verbose("GameCache: MapData size: ", this->_cacheMap.size()); } void GameCache::initAddSkillTable(GameData* gmd, UStaticDataManager* sdm) { gmd->waitObject(&sdm->m_AddSkillLotTable); - for (int i = 0; i < sdm->m_AddSkillLotTable->m_dataMap.Data.Count; i++) - { - auto addSkillInfo = sdm->m_AddSkillLotTable->m_dataMap.Data[i]; - this->_cacheAddSkillLotTable.emplace( - addSkillInfo.Value.First.ToString(), - &addSkillInfo.Value.Second.addSkillInfoList - ); - } + for (auto& addSkillInfo : sdm->m_AddSkillLotTable->m_dataMap) + this->_cacheAddSkillLotTable.emplace(addSkillInfo.ID.ToString(), &addSkillInfo.addSkillInfoList); + + ModLoader::logger->verbose("GameCache: AddSkillLotTable size: ", this->_cacheAddSkillLotTable.size()); } \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 17732f1..8034827 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -19,9 +19,10 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) { logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); - Patcher patcher; Sleep(200); // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? + Patcher patcher; + logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); @@ -84,22 +85,22 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser CloseHandle(LoaderThread); FreeConsole(); - if (ModLoader::gameData != nullptr) + if (!ModLoader::gameData) delete ModLoader::gameData; - if(ModLoader::gameCache != nullptr) + if (!ModLoader::gameCache) delete ModLoader::gameCache; - if(ModLoader::logger != nullptr) + if (!ModLoader::logger) delete ModLoader::logger; - if(ModLoader::modEnvironnement != nullptr) + if (!ModLoader::modEnvironnement) { ModLoader::modEnvironnement->Free(); delete ModLoader::modEnvironnement; } - if(ModLoader::configManager != nullptr) + if (!ModLoader::configManager) delete ModLoader::configManager; break; From fa8e0b87d7da910bf1dd3a9dc631c838213ae73b Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:19:17 +0000 Subject: [PATCH 42/64] WIP --- CMakeLists.txt | 1 + README.md | 3 +++ src/ModLoader.cpp | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 132fe79..294d573 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() + target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) diff --git a/README.md b/README.md index fa7be6f..578221e 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,9 @@ Fantasy Life I/ ### Build the ModLoader +>[!WARNING] +> Use LLVM 21.1.3 OR HIGHER + ```bash $ cmake -B build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DMLDEBUG=OFF ``` diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 8034827..f10ea43 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,4 +1,6 @@ #include "ModLoader.hpp" +#include "API/Engine/TArray.hpp" +#include "API/Engine/TMap.hpp" #include "GameCache.hpp" #include "GameData.hpp" #include "Hook/EventHandler.hpp" @@ -7,6 +9,7 @@ #include "Psapi.h" #include "API/Engine/FName.hpp" +#include "SDK/DP1Project.h" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -39,9 +42,22 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) FName test("Cute:3"); ModLoader::logger->info("Returned: ", test.ToString()); - FName name(gameCache->GetItem("imt01000430").getObject().nameId); + FName name(gameCache->GetItem("imt01000430").GetDescIdentifier()); ModLoader::logger->info("Item name: ", name.ToString()); + TArray textInfoArray; + auto tdfest = gameCache->GetText(name.ToString()); + textInfoArray.Add(*tdfest); + + FGDItemText itemText + { + .ID = test, + .textInfo = textInfoArray + }; + TPair newItemElement{test, itemText}; + newItemElement.First = test; + gameData->getStaticDataManager()->m_ItemText->m_dataMap.Data.Add(TSetElement>{newItemElement, -1, -1}); + gameCache->PostLoadCache(); gameData->initOthersData(); From 7918357084e973a2f3888a63bd1827eb2fd902f1 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 22:21:22 +0000 Subject: [PATCH 43/64] TMap reallocation --- src/Mod/ModEnvironnement.cpp | 2 +- src/ModLoader.cpp | 40 +++++++++--------------------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 79876b7..b42a6dc 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -408,7 +408,7 @@ void ModEnvironnement::PreLoad() } } } - ModLoader::logger->verbose("MENV Preload finished. [size of modPtr: ", _modPtrList.size(),"]"); + ModLoader::logger->verbose("MENV Preload finished (size of modPtr: ", _modPtrList.size(), ")"); } void ModEnvironnement::PostLoad() diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index f10ea43..fa59e54 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -37,27 +37,7 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); - logger->verbose("All loader preparations done"); - FName test("Cute:3"); - ModLoader::logger->info("Returned: ", test.ToString()); - - FName name(gameCache->GetItem("imt01000430").GetDescIdentifier()); - ModLoader::logger->info("Item name: ", name.ToString()); - - TArray textInfoArray; - auto tdfest = gameCache->GetText(name.ToString()); - textInfoArray.Add(*tdfest); - - FGDItemText itemText - { - .ID = test, - .textInfo = textInfoArray - }; - TPair newItemElement{test, itemText}; - newItemElement.First = test; - gameData->getStaticDataManager()->m_ItemText->m_dataMap.Data.Add(TSetElement>{newItemElement, -1, -1}); - gameCache->PostLoadCache(); gameData->initOthersData(); @@ -101,23 +81,23 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser CloseHandle(LoaderThread); FreeConsole(); - if (!ModLoader::gameData) - delete ModLoader::gameData; - - if (!ModLoader::gameCache) - delete ModLoader::gameCache; - - if (!ModLoader::logger) - delete ModLoader::logger; + if (!ModLoader::configManager) + delete ModLoader::configManager; if (!ModLoader::modEnvironnement) { ModLoader::modEnvironnement->Free(); delete ModLoader::modEnvironnement; } + + if (!ModLoader::logger) + delete ModLoader::logger; - if (!ModLoader::configManager) - delete ModLoader::configManager; + if (!ModLoader::gameCache) + delete ModLoader::gameCache; + + if (!ModLoader::gameData) + delete ModLoader::gameData; break; } From 1f9d73820c0b554017415a0305e834bb2fb13a8e Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:25:49 +0000 Subject: [PATCH 44/64] TEST --- .github/workflows/build-check.yml | 32 ++++++++++++++++++ .github/workflows/cd.yml | 54 +++++++++++-------------------- 2 files changed, 50 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/build-check.yml diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml new file mode 100644 index 0000000..3ce880b --- /dev/null +++ b/.github/workflows/build-check.yml @@ -0,0 +1,32 @@ +name: "Build Check" + +on: + push: + branches-ignore: + - master + pull_request: + branches: + - master + +env: + BUILD_TYPE: Release + +jobs: + build-check: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v2 + with: + version: "21.1.3" + + - name: Pull submodule + run: git submodule update --init + + - name: Configure CMake with Clang-CL + run: cmake -B ${{github.workspace}}/build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMLDEBUG=OFF + + - name: Build project + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} \ No newline at end of file diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 953bbd7..fb720c9 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -13,11 +13,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v2 + with: + version: "21.1.3" + - name: Pull submodule run: git submodule update --init - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + - name: Configure CMake with Clang-CL + run: cmake -B ${{github.workspace}}/build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMLDEBUG=OFF - name: Build project run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} @@ -27,9 +32,10 @@ jobs: with: name: fli-modloader path: | - ./build/Release/ModLoader.dll - ./build/Release/ModLoader.lib - ./build/DllProxy/Release/version.dll + ./build/ModLoader.dll + ./build/ModLoader.lib + ./build/DllProxy/version.dll + release: needs: build runs-on: ubuntu-latest @@ -38,9 +44,11 @@ jobs: run: | DATE_TAG="v$(date +'%Y%m%d.%H%M')" echo "TAG_NAME=$DATE_TAG" >> $GITHUB_ENV - echo "{tag}=$DATE_TAG" + echo "tag=$DATE_TAG" + - name: Download Artifacts uses: actions/download-artifact@v4 + - name: Create GitHub Release id: create_release uses: softprops/action-gh-release@v2 @@ -49,33 +57,7 @@ jobs: body: "Automated release of ${{ github.ref_name }}." generate_release_notes: true token: ${{ secrets.RELEASE_CD_TOKEN }} - - - name: Upload ModLoader.dll - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_CD_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: "./fli-modloader/Release/ModLoader.dll" - asset_name: ModLoader.dll - asset_content_type: application/octet-stream - - - name: Upload version.dll - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_CD_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: "./fli-modloader/DllProxy/Release/version.dll" - asset_name: version.dll - asset_content_type: application/octet-stream - - - name: Upload ModLoader.lib - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_CD_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: "./fli-modloader/Release/ModLoader.lib" - asset_name: ModLoader.lib - asset_content_type: application/octet-stream \ No newline at end of file + files: | + ./fli-modloader/ModLoader.dll + ./fli-modloader/ModLoader.lib + ./fli-modloader/DllProxy/version.dll \ No newline at end of file From 2ebfda8f9878426b86803129cc614092d6539230 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:29:59 +0000 Subject: [PATCH 45/64] test 2 --- .github/workflows/build-check.yml | 11 +++++++---- .github/workflows/cd.yml | 13 ++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml index 3ce880b..c24167b 100644 --- a/.github/workflows/build-check.yml +++ b/.github/workflows/build-check.yml @@ -17,10 +17,13 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install LLVM and Clang - uses: KyleMayes/install-llvm-action@v2 - with: - version: "21.1.3" + - name: Install LLVM 21.1.3 + run: choco install llvm --version=21.1.3 -y + shell: powershell + + - name: Add LLVM to PATH + run: echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + shell: powershell - name: Pull submodule run: git submodule update --init diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index fb720c9..b10ad7c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -13,15 +13,18 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install LLVM and Clang - uses: KyleMayes/install-llvm-action@v2 - with: - version: "21.1.3" + - name: Install LLVM 21.1.3 + run: choco install llvm --version=21.1.3 -y + shell: powershell + + - name: Add LLVM to PATH + run: echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + shell: powershell - name: Pull submodule run: git submodule update --init - - name: Configure CMake with Clang-CL + - name: Configure CMake with Clang-CL run: cmake -B ${{github.workspace}}/build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMLDEBUG=OFF - name: Build project From e327b6431a12ed61490e31b967331bc5c92715ac Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:31:51 +0000 Subject: [PATCH 46/64] LLVM LLVM 21.1.0 instead of 21.1.3 --- .github/workflows/build-check.yml | 4 ++-- .github/workflows/cd.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml index c24167b..bfcdb68 100644 --- a/.github/workflows/build-check.yml +++ b/.github/workflows/build-check.yml @@ -17,8 +17,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install LLVM 21.1.3 - run: choco install llvm --version=21.1.3 -y + - name: Install LLVM 21.1.0 + run: choco install llvm --version=21.1.0 -y shell: powershell - name: Add LLVM to PATH diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index b10ad7c..03da1ce 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -13,8 +13,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install LLVM 21.1.3 - run: choco install llvm --version=21.1.3 -y + - name: Install LLVM 21.1.0 + run: choco install llvm --version=21.1.0 -y shell: powershell - name: Add LLVM to PATH From 85bbc8599d0236fc3f1b49fb2e58a26c2bab8731 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:37:11 +0000 Subject: [PATCH 47/64] fucking cache --- .github/workflows/build-check.yml | 8 ++++++++ .github/workflows/cd.yml | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml index bfcdb68..250a27c 100644 --- a/.github/workflows/build-check.yml +++ b/.github/workflows/build-check.yml @@ -17,7 +17,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache LLVM + id: cache-llvm + uses: actions/cache@v4 + with: + path: C:\Program Files\LLVM + key: llvm-21.1.0-windows + - name: Install LLVM 21.1.0 + if: steps.cache-llvm.outputs.cache-hit != 'true' run: choco install llvm --version=21.1.0 -y shell: powershell diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 03da1ce..1d6611c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -13,7 +13,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache LLVM + id: cache-llvm + uses: actions/cache@v4 + with: + path: C:\Program Files\LLVM + key: llvm-21.1.0-windows + - name: Install LLVM 21.1.0 + if: steps.cache-llvm.outputs.cache-hit != 'true' run: choco install llvm --version=21.1.0 -y shell: powershell @@ -24,7 +32,7 @@ jobs: - name: Pull submodule run: git submodule update --init - - name: Configure CMake with Clang-CL + - name: Configure CMake with Clang-CL run: cmake -B ${{github.workspace}}/build -G "Ninja" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMLDEBUG=OFF - name: Build project From 83a6133c01daad6728aed7bf9a1b8ae6e8247611 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:04:18 +0000 Subject: [PATCH 48/64] Fixing my own complaints --- src/API/Common/Common.cpp | 74 +++++++++++------------ src/API/Common/CommonItemTableSetting.cpp | 5 -- src/API/Common/CommonPickParamData.cpp | 12 ---- src/API/Entities/CharaData.cpp | 16 ----- src/API/Item/ItemData.cpp | 25 +------- src/API/Recipe/RecipeData.cpp | 10 --- src/API/Skill/SkillData.cpp | 25 -------- src/API/World/MapData.cpp | 29 --------- src/API/World/MapSubLevel.cpp | 17 ------ src/ModLoader.cpp | 10 +-- 10 files changed, 44 insertions(+), 179 deletions(-) delete mode 100644 src/API/Common/CommonPickParamData.cpp delete mode 100644 src/API/World/MapSubLevel.cpp diff --git a/src/API/Common/Common.cpp b/src/API/Common/Common.cpp index 7ea19c3..55accac 100644 --- a/src/API/Common/Common.cpp +++ b/src/API/Common/Common.cpp @@ -4,19 +4,19 @@ std::string Common::NounSingular(LANG lang, std::string_view identifier) { - if(identifier == "None") return nullptr; + if(identifier == "None") return "nullptr"; auto text = ModLoader::gameCache->GetNoun(identifier.data()); switch(lang) { - case LANG::JAPANESE: return text->nounSingularForm.ToString(); - case LANG::ENGLISH: return text->nounSingularForm_en.ToString(); - case LANG::FRENCH: return text->nounSingularForm_fr.ToString(); - case LANG::ESPAGNOL: return text->nounSingularForm_es.ToString(); - case LANG::DEUTSCH: return text->nounSingularForm_de.ToString(); - case LANG::ITALIAN: return text->nounSingularForm_it.ToString(); - case LANG::TZH: return text->nounSingularForm_tzh.ToString(); - case LANG::CZH: return text->nounSingularForm_czh.ToString(); - case LANG::KO: return text->nounSingularForm_ko.ToString(); + case LANG::JAPANESE: return text->nounSingularForm.ToString(); break; + case LANG::ENGLISH: return text->nounSingularForm_en.ToString(); break; + case LANG::FRENCH: return text->nounSingularForm_fr.ToString(); break; + case LANG::ESPAGNOL: return text->nounSingularForm_es.ToString(); break; + case LANG::DEUTSCH: return text->nounSingularForm_de.ToString(); break; + case LANG::ITALIAN: return text->nounSingularForm_it.ToString(); break; + case LANG::TZH: return text->nounSingularForm_tzh.ToString(); break; + case LANG::CZH: return text->nounSingularForm_czh.ToString(); break; + case LANG::KO: return text->nounSingularForm_ko.ToString(); break; } return text->nounSingularForm.ToString(); @@ -33,15 +33,15 @@ void Common::NounSingularSet(LANG lang, std::string_view identifier, FString val auto text = ModLoader::gameCache->GetNoun(identifier.data()); switch(lang) { - case LANG::JAPANESE: text->nounSingularForm = value; - case LANG::ENGLISH: text->nounSingularForm_en = value; - case LANG::FRENCH: text->nounSingularForm_fr = value; - case LANG::ESPAGNOL: text->nounSingularForm_es = value; - case LANG::DEUTSCH: text->nounSingularForm_de = value; - case LANG::ITALIAN: text->nounSingularForm_it = value; - case LANG::TZH: text->nounSingularForm_tzh = value; - case LANG::CZH: text->nounSingularForm_czh = value; - case LANG::KO: text->nounSingularForm_ko = value; + case LANG::JAPANESE: text->nounSingularForm = value; break; + case LANG::ENGLISH: text->nounSingularForm_en = value; break; + case LANG::FRENCH: text->nounSingularForm_fr = value; break; + case LANG::ESPAGNOL: text->nounSingularForm_es = value; break; + case LANG::DEUTSCH: text->nounSingularForm_de = value; break; + case LANG::ITALIAN: text->nounSingularForm_it = value; break; + case LANG::TZH: text->nounSingularForm_tzh = value; break; + case LANG::CZH: text->nounSingularForm_czh = value; break; + case LANG::KO: text->nounSingularForm_ko = value; break; } } @@ -50,15 +50,15 @@ std::string Common::Description(LANG lang, std::string_view identifier) auto text = ModLoader::gameCache->GetText(identifier.data()); switch(lang) { - case LANG::JAPANESE: return text->Text.ToString(); - case LANG::ENGLISH: return text->text_en.ToString(); - case LANG::FRENCH: return text->text_fr.ToString(); - case LANG::ESPAGNOL: return text->text_es.ToString(); - case LANG::DEUTSCH: return text->text_de.ToString(); - case LANG::ITALIAN: return text->text_de.ToString(); - case LANG::TZH: return text->text_tzh.ToString(); - case LANG::CZH: return text->text_czh.ToString(); - case LANG::KO : return text->text_ko.ToString(); + case LANG::JAPANESE: return text->Text.ToString(); break; + case LANG::ENGLISH: return text->text_en.ToString(); break; + case LANG::FRENCH: return text->text_fr.ToString(); break; + case LANG::ESPAGNOL: return text->text_es.ToString(); break; + case LANG::DEUTSCH: return text->text_de.ToString(); break; + case LANG::ITALIAN: return text->text_de.ToString(); break; + case LANG::TZH: return text->text_tzh.ToString(); break; + case LANG::CZH: return text->text_czh.ToString(); break; + case LANG::KO: return text->text_ko.ToString(); break; } return text->Text.ToString(); @@ -75,14 +75,14 @@ void Common::DescriptionSet(LANG lang, std::string_view identifier, FString valu auto text = ModLoader::gameCache->GetText(identifier.data()); switch(lang) { - case LANG::JAPANESE: text->Text = value; - case LANG::ENGLISH: text->text_en = value; - case LANG::FRENCH: text->text_fr = value; - case LANG::ESPAGNOL: text->text_es = value; - case LANG::DEUTSCH: text->text_de = value; - case LANG::ITALIAN: text->text_de = value; - case LANG::TZH: text->text_tzh = value; - case LANG::CZH: text->text_czh = value; - case LANG::KO : text->text_ko = value; + case LANG::JAPANESE: text->Text = value; break; + case LANG::ENGLISH: text->text_en = value; break; + case LANG::FRENCH: text->text_fr = value; break; + case LANG::ESPAGNOL: text->text_es = value; break; + case LANG::DEUTSCH: text->text_de = value; break; + case LANG::ITALIAN: text->text_de = value; break; + case LANG::TZH: text->text_tzh = value; break; + case LANG::CZH: text->text_czh = value; break; + case LANG::KO: text->text_ko = value; break; } } \ No newline at end of file diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index 410a19f..c5992c2 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -1,11 +1,6 @@ #include "API/Common/CommonItemTableSetting.hpp" #include "API/Engine/FName.hpp" -std::string CommonItemTableSetting::GetIdentifier() -{ - return this->_object.tableId.ToString(); -} - ItemTableDetail CommonItemTableSetting::GetData(int index) { auto raw = this->_object.tableData.Get(index); diff --git a/src/API/Common/CommonPickParamData.cpp b/src/API/Common/CommonPickParamData.cpp deleted file mode 100644 index 7123181..0000000 --- a/src/API/Common/CommonPickParamData.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "API/Common/CommonPickParamData.hpp" -#include "API/Engine/FName.hpp" - -std::string CommonPickParamData::GetIdentifier() -{ - return this->_object.ID.ToString(); -} - -std::string CommonPickParamData::GetGotIdentifier() -{ - return this->_object.gotId.ToString(); -} \ No newline at end of file diff --git a/src/API/Entities/CharaData.cpp b/src/API/Entities/CharaData.cpp index 8b3173c..74bcf79 100644 --- a/src/API/Entities/CharaData.cpp +++ b/src/API/Entities/CharaData.cpp @@ -1,21 +1,5 @@ #include "API/Entities/CharaData.hpp" #include "API/Common/Common.hpp" -#include "API/Engine/FName.hpp" - -std::string CharaData::GetIdentifier() -{ - return this->_object.ID.ToString(); -} - -std::string CharaData::GetNameIdentifier() -{ - return this->_object.nameId.ToString(); -} - -std::string CharaData::GetFlag() -{ - return this->_object.Flag.ToString(); -} std::string CharaData::GetName(LANG lang) { diff --git a/src/API/Item/ItemData.cpp b/src/API/Item/ItemData.cpp index 3caa659..3e037af 100644 --- a/src/API/Item/ItemData.cpp +++ b/src/API/Item/ItemData.cpp @@ -2,31 +2,15 @@ #include "API/Common/Common.hpp" #include "API/Engine/FName.hpp" -std::string ItemData::GetIdentifier() -{ - return this->_object.ID.ToString(); -} - -std::string ItemData::getNameIdentifier() -{ - return this->_object.nameId.ToString(); -} - -std::string ItemData::GetDescIdentifier() -{ - return this->_object.DescId.ToString(); -} std::string ItemData::GetName(LANG lang) { - return NAME_GET(lang, getNameIdentifier()); - return NAME_GET(lang, getNameIdentifier()); + return NAME_GET(lang, GetNameIdentifier()); } void ItemData::SetName(LANG lang, FString string) { - NAME_SET(lang, getNameIdentifier(), string); - NAME_SET(lang, getNameIdentifier(), string); + NAME_SET(lang, GetNameIdentifier(), string); } std::string ItemData::GetDescription(LANG lang) @@ -37,9 +21,4 @@ std::string ItemData::GetDescription(LANG lang) void ItemData::SetDescription(LANG lang, FString string) { DESC_SET(lang, GetDescIdentifier(), string); -} - -std::string ItemData::GetOverwriteIcon() -{ - return this->_object.overwriteIconName.ToString(); } \ No newline at end of file diff --git a/src/API/Recipe/RecipeData.cpp b/src/API/Recipe/RecipeData.cpp index e32213b..a31dfb5 100644 --- a/src/API/Recipe/RecipeData.cpp +++ b/src/API/Recipe/RecipeData.cpp @@ -3,16 +3,6 @@ #include "ModLoader.hpp" #include "GameCache.hpp" -std::string RecipeData::GetIdentifier() -{ - return this->_object.recipeId.ToString(); -} - -std::string RecipeData::GetItemIdentifier() -{ - return this->_object.ItemId.ToString(); -} - ItemData RecipeData::GetItem() { return ModLoader::gameCache->GetItem(GetItemIdentifier()); diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index bd7c113..b325204 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -2,36 +2,11 @@ #include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -std::string SkillData::GetIdentifier() -{ - return this->_object.ID.Name.ToString(); -} - -std::string SkillData::GetNameIdentifier() -{ - return this->_object.nameTextID.ToString(); -} - -std::string SkillData::GetName(LANG lang) -{ - return NAME_GET(lang, GetNameIdentifier()); -} - void SkillData::SetName(LANG lang, FString string) { NAME_SET(lang, GetNameIdentifier(), string); } -std::string SkillData::GetDescIdentifier() -{ - return this->_object.descTextID.ToString(); -} - -std::string SkillData::GetDescription(LANG lang) -{ - return DESC_GET(lang, GetDescIdentifier()); -} - void SkillData::SetDescription(LANG lang, FString string) { DESC_SET(lang, GetDescIdentifier(), string); diff --git a/src/API/World/MapData.cpp b/src/API/World/MapData.cpp index bb7b245..fd31397 100644 --- a/src/API/World/MapData.cpp +++ b/src/API/World/MapData.cpp @@ -2,21 +2,6 @@ #include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -std::string MapData::GetIdentifier() -{ - return this->_object.mapId.ToString(); -} - -std::string MapData::GetPath() -{ - return this->_object.MapPath.ToString(); -} - -std::string MapData::GetMapViewCategory() -{ - return this->_object.MapViewCategory.ToString(); -} - std::string MapData::GetMapViewName(int index) { if(index < 0 || index >= this->_object.MapViewDataArray.Count) @@ -37,15 +22,6 @@ void MapData::SetMapViewName(int index, FString name) this->_object.MapViewDataArray.Data[index].mapName = name; } -std::string MapData::GetMapSubject() -{ - return this->_object.MapSubject.ToString(); -} - -std::string MapData::GetNameIdentifier() -{ - return this->_object.MapNameID.ToString(); -} std::string MapData::GetName(LANG lang) { @@ -57,11 +33,6 @@ void MapData::SetName(LANG lang, FString string) NAME_SET(lang, GetNameIdentifier(), string); } -std::string MapData::GetWorldMap() -{ - return this->_object.WorldMapID.ToString(); -} - MapDataSubMapData MapData::GetSubMap(int index) { if(index < 0 || index >= this->_object.subMapDataList.Data.Count) diff --git a/src/API/World/MapSubLevel.cpp b/src/API/World/MapSubLevel.cpp deleted file mode 100644 index 996aec4..0000000 --- a/src/API/World/MapSubLevel.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "API/World/MapSubLevel.hpp" -#include "API/Engine/FName.hpp" - -std::string MapSubLevel::GetIdentifier() -{ - return this->_object.SubLevelID.ToString(); -} - -std::string MapSubLevel::GetMapSubIdentifier() -{ - return this->_object.mapSubId.ToString(); -} - -std::string MapSubLevel::GetPath() -{ - return this->_object.SubLevelInfo.SubLevelPath.ToString(); -} \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index fa59e54..90093f1 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -81,22 +81,22 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser CloseHandle(LoaderThread); FreeConsole(); - if (!ModLoader::configManager) + if (ModLoader::configManager) delete ModLoader::configManager; - if (!ModLoader::modEnvironnement) + if (ModLoader::modEnvironnement) { ModLoader::modEnvironnement->Free(); delete ModLoader::modEnvironnement; } - if (!ModLoader::logger) + if (ModLoader::logger) delete ModLoader::logger; - if (!ModLoader::gameCache) + if (ModLoader::gameCache) delete ModLoader::gameCache; - if (!ModLoader::gameData) + if (ModLoader::gameData) delete ModLoader::gameData; break; From 7758e77d0896ede5340f23817b40e319bdba44e1 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:05:09 +0000 Subject: [PATCH 49/64] duh --- src/ModLoader.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 90093f1..0529678 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,6 +1,4 @@ #include "ModLoader.hpp" -#include "API/Engine/TArray.hpp" -#include "API/Engine/TMap.hpp" #include "GameCache.hpp" #include "GameData.hpp" #include "Hook/EventHandler.hpp" @@ -8,9 +6,6 @@ #include "Patcher/Patches/EventHook.hpp" #include "Psapi.h" -#include "API/Engine/FName.hpp" -#include "SDK/DP1Project.h" - GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; Logger *ModLoader::logger = nullptr; From fcb5214257cba50700543103c499eae8777b544a Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 1 Dec 2025 05:16:38 +0000 Subject: [PATCH 50/64] Fixing my own complaints v2 --- src/API/Common/CommonItemEffectParam.cpp | 6 ------ src/API/Life/LifeData.cpp | 10 ---------- src/API/Table/ItemTableDetail.cpp | 6 ------ src/API/World/MapDataSubMapData.cpp | 11 ----------- src/GameCache.cpp | 1 - 5 files changed, 34 deletions(-) diff --git a/src/API/Common/CommonItemEffectParam.cpp b/src/API/Common/CommonItemEffectParam.cpp index 8353655..e31f59e 100644 --- a/src/API/Common/CommonItemEffectParam.cpp +++ b/src/API/Common/CommonItemEffectParam.cpp @@ -1,11 +1,5 @@ #include "API/Common/CommonItemEffectParam.hpp" #include "API/Common/Common.hpp" -#include "API/Engine/FName.hpp" - -std::string CommonItemEffectParam::getDescIdentifier() -{ - return this->_object.effDescId.ToString(); -} std::string CommonItemEffectParam::GetDescription(LANG lang) { diff --git a/src/API/Life/LifeData.cpp b/src/API/Life/LifeData.cpp index b24a1b3..a7837be 100644 --- a/src/API/Life/LifeData.cpp +++ b/src/API/Life/LifeData.cpp @@ -1,16 +1,6 @@ #include "API/Life/LifeData.hpp" -#include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" -std::string LifeData::GetNameIdentifier() -{ - return this->_object.nameId.ToString(); -} - -std::string LifeData::GetDescIdentifier() -{ - return this->_object.DescId.ToString(); -} std::string LifeData::GetName(LANG lang) { return NAME_GET(lang, GetNameIdentifier()); diff --git a/src/API/Table/ItemTableDetail.cpp b/src/API/Table/ItemTableDetail.cpp index c5ecb50..45b18fe 100644 --- a/src/API/Table/ItemTableDetail.cpp +++ b/src/API/Table/ItemTableDetail.cpp @@ -1,13 +1,7 @@ #include "API/Table/ItemTableDetail.hpp" -#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -std::string ItemTableDetail::GetItemIdentifier() -{ - return this->_object.ItemId.ToString(); -} - ItemData ItemTableDetail::GetItem() { return ModLoader::gameCache->GetItem(GetItemIdentifier()); diff --git a/src/API/World/MapDataSubMapData.cpp b/src/API/World/MapDataSubMapData.cpp index e578e21..b703d20 100644 --- a/src/API/World/MapDataSubMapData.cpp +++ b/src/API/World/MapDataSubMapData.cpp @@ -1,19 +1,8 @@ #include "API/World/MapDataSubMapData.hpp" -#include "API/Engine/FName.hpp" #include "ModLoader.hpp" #include "GameCache.hpp" -std::string MapDataSubMapData::GetSubMapIdentifier() -{ - return this->_object.subMapId.ToString(); -} - MapSubLevel MapDataSubMapData::GetSubMap() { return ModLoader::gameCache->GetSubLevel(GetSubMapIdentifier()); } - -std::string MapDataSubMapData::GetAreaID() -{ - return this->_object.AreaID.ToString(); -} \ No newline at end of file diff --git a/src/GameCache.cpp b/src/GameCache.cpp index 11540c8..791caee 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -14,7 +14,6 @@ #include "API/Item/ItemKitData.hpp" #include "API/Item/ItemVehicleData.hpp" #include "API/Item/ItemPowerUpData.hpp" -#include #include GameCache::GameCache() From 84fb16d1c10101f7690d2fbd928b3bf4a939327e Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:13:38 +0000 Subject: [PATCH 51/64] TCHOUPI --- src/API/Common/CommonItemTableSetting.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/API/Common/CommonItemTableSetting.cpp b/src/API/Common/CommonItemTableSetting.cpp index c5992c2..68d38cd 100644 --- a/src/API/Common/CommonItemTableSetting.cpp +++ b/src/API/Common/CommonItemTableSetting.cpp @@ -1,5 +1,4 @@ #include "API/Common/CommonItemTableSetting.hpp" -#include "API/Engine/FName.hpp" ItemTableDetail CommonItemTableSetting::GetData(int index) { From 67336b4cf0118f5969ae6176c3c3230139e349de Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:43:42 +0000 Subject: [PATCH 52/64] Windows Threads to Standard Threads and other fixes.. --- src/GameCache.cpp | 24 +++++---- src/Mod/Configuration/ConfigManager.cpp | 2 - src/Mod/Configuration/ModConfig.cpp | 11 ++-- src/Mod/ModEnvironnement.cpp | 72 ++++++++++++++++--------- src/ModLoader.cpp | 30 +++++------ 5 files changed, 79 insertions(+), 60 deletions(-) diff --git a/src/GameCache.cpp b/src/GameCache.cpp index 791caee..a3ef752 100644 --- a/src/GameCache.cpp +++ b/src/GameCache.cpp @@ -42,17 +42,6 @@ GameCache::GameCache() initAddSkillTable(gmd, sdm); ModLoader::logger->verbose("Cached: AddSkillTable Registries"); - - uint32_t totalSize = - (this->_cacheNounInfo.size() * sizeof(void*)) + - (this->_cacheTextInfo.size() * sizeof(void*)) + - (this->_cacheItemData.size() * sizeof(void*)) + - (this->_cacheRecipeData.size() * sizeof(void*)) + - (this->_cacheCommonPickParam.size() * sizeof(void*)) + - (this->_cacheCharaData.size() * sizeof(void*)) + - (this->_cacheAddSkillLotTable.size() * sizeof(TArray*)); - - ModLoader::logger->verbose("Total cached size: ", totalSize / 1024, " KB"); } void GameCache::PostLoadCache() @@ -68,6 +57,19 @@ void GameCache::PostLoadCache() ModLoader::logger->info("OK: GameCache has been initialized"); + + uint32_t totalSize = + (this->_cacheNounInfo.size() * sizeof(void*)) + + (this->_cacheTextInfo.size() * sizeof(void*)) + + (this->_cacheItemData.size() * sizeof(void*)) + + (this->_cacheRecipeData.size() * sizeof(void*)) + + (this->_cacheCommonPickParam.size() * sizeof(void*)) + + (this->_cacheCharaData.size() * sizeof(void*)) + + (this->_cacheAddSkillLotTable.size() * sizeof(TArray*)) + + (this->_cacheSubLevel.size() * sizeof(void*)) + + (this->_cacheMap.size() * sizeof(void*)); + + ModLoader::logger->verbose("Total cached size: ", totalSize / 1024, " KB"); } void GameCache::initNoun(GameData* gmd, UStaticDataManager* sdm) diff --git a/src/Mod/Configuration/ConfigManager.cpp b/src/Mod/Configuration/ConfigManager.cpp index cfe6c82..9d0f698 100644 --- a/src/Mod/Configuration/ConfigManager.cpp +++ b/src/Mod/Configuration/ConfigManager.cpp @@ -21,14 +21,12 @@ void ConfigManager::PushConfig(std::string name, std::function void ConfigManager::SaveAll() { - std::lock_guard lock(_mutex); for(const auto& [name, config] : _configs) config->Save(); } void ConfigManager::ReloadAll() { - std::lock_guard lock(_mutex); for(const auto& [name, config] : _configs) config->Reload(); } diff --git a/src/Mod/Configuration/ModConfig.cpp b/src/Mod/Configuration/ModConfig.cpp index 925906a..71ed9a2 100644 --- a/src/Mod/Configuration/ModConfig.cpp +++ b/src/Mod/Configuration/ModConfig.cpp @@ -1,5 +1,4 @@ #include "Mod/Configuration/ModConfig.hpp" -#include #include #include #include @@ -70,13 +69,11 @@ void ModConfig::Save() void ModConfig::Reload() { + std::lock_guard lock(_mutex); + for(auto& [path, reg] : _registration) { - std::lock_guard lock(_mutex); - for(auto& [path, reg] : _registration) - { - _pending.insert(path); - // TODO: Reset the config value and adding a reset method in reg - } + _pending.insert(path); + // TODO: Reset the config value and adding a reset method in reg } Load(); diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index b42a6dc..39770ed 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -2,8 +2,6 @@ #include "ModLoader.hpp" #include "Mod/ThreadPool.hpp" -#include -#include #include "Lib/json.hpp" #include "Lib/miniz.h" @@ -120,8 +118,6 @@ bool ModEnvironnement::findModJsonInArchive(const std::filesystem::path& archive { mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; - //if(!stat.m_filename) break; - //if(!stat.m_filename) break; std::string fname = stat.m_filename; if(fname.size() >= 8 && fname.substr(fname.size() - 8) == "Mod.json") @@ -143,21 +139,18 @@ bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archiveP if(!mz_zip_reader_init_file(&archive, archivePath.string().c_str(), 0)) return false; mz_uint num = mz_zip_reader_get_num_files(&archive); - for (mz_uint i = 0; i < num; ++i) { + for (mz_uint i = 0; i < num; ++i) + { mz_zip_archive_file_stat st; if (!mz_zip_reader_file_stat(&archive, i, &st)) continue; - //if (st.m_filename) { - //if (st.m_filename) { - std::string fname = st.m_filename; - if (fname.size() >= libName.size() && - fname.compare(fname.size() - libName.size(), libName.size(), libName) == 0) - { - foundPath = fname; - mz_zip_reader_end(&archive); - return true; - } - //} - //} + std::string fname = st.m_filename; + + if (fname.size() >= libName.size() && fname.compare(fname.size() - libName.size(), libName.size(), libName) == 0) + { + foundPath = fname; + mz_zip_reader_end(&archive); + return true; + } } mz_zip_reader_end(&archive); @@ -288,13 +281,10 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) void ModEnvironnement::PreLoad() { - const size_t modListSize = _modsList.size(); - size_t numThreads = std::thread::hardware_concurrency(); - if(numThreads == 0) numThreads = 1; - if(numThreads > modListSize) numThreads = modListSize; + _modLibList.reserve(_modsList.size()); + _modPtrList.reserve(_modsList.size()); - ThreadPool pool{numThreads}; - struct Bucket + for (auto* mod : _modsList) { std::mutex mutex; std::vector libs; @@ -407,8 +397,39 @@ void ModEnvironnement::PreLoad() _modPtrList.push_back(std::move(modPtr)); } } + + std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, ".mod"); + if(libOnDiskPath.empty()) + { + ModLoader::logger->error("Failed to write temporary content for ", identifier); + continue; + } + + _tempFilesToRemove.push_back(libOnDiskPath); + + LibHandle lib = LoadLib(libOnDiskPath.string()); + if(!lib) + { + ModLoader::logger->error("Failed to load: ", identifier); + continue; + } + + using GetModFunc = ModBase *(*)(); + auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); + if(!getter) + { + ModLoader::logger->error("Missing CraftMod in ", identifier); + CloseLib(lib); + continue; + } + + ModLoader::logger->info("Loading ", identifier, " v", meta.version); + auto modPtr = std::unique_ptr(getter()); + modPtr->OnPreLoad(); + + _modLibList.push_back(lib); + _modPtrList.push_back(std::move(modPtr)); } - ModLoader::logger->verbose("MENV Preload finished (size of modPtr: ", _modPtrList.size(), ")"); } void ModEnvironnement::PostLoad() @@ -421,7 +442,8 @@ void ModEnvironnement::PostLoad() ThreadPool pool{numThreads}; for(auto& modPtr : _modPtrList) - pool.enqueue([&modPtr]{modPtr->OnPostLoad();}); + + pool.enqueue([&modPtr]{modPtr->OnPostLoad();}); } void ModEnvironnement::Free() diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 0529678..49ab4f7 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -4,7 +4,7 @@ #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" -#include "Psapi.h" +#include GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -12,20 +12,20 @@ Logger *ModLoader::logger = nullptr; ModEnvironnement *ModLoader::modEnvironnement = nullptr; ConfigManager *ModLoader::configManager = nullptr; - -DWORD WINAPI ModLoader::init(LPVOID lpParam) +void WINAPI ModLoader::init(MODULEINFO* moduleInfo) { logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); - Sleep(200); // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? + // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? + std::this_thread::sleep_for(std::chrono::milliseconds(200)); Patcher patcher; logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); patcher.applyPatches(baseAddress); - gameData = new GameData(baseAddress, reinterpret_cast(lpParam)->SizeOfImage); + gameData = new GameData(baseAddress, moduleInfo->SizeOfImage); gameData->init(); gameCache = new GameCache(); @@ -37,14 +37,12 @@ DWORD WINAPI ModLoader::init(LPVOID lpParam) gameData->initOthersData(); modEnvironnement->PostLoad(); - logger->verbose("Mod loader initialization complete"); - return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - HANDLE LoaderThread = nullptr; + std::thread* loaderThread; switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: @@ -66,15 +64,12 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser MODULEINFO moduleInfo{}; GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &moduleInfo, sizeof(MODULEINFO)); - LoaderThread = CreateThread(nullptr, 0, ModLoader::init, &moduleInfo, 0, nullptr); + loaderThread = new std::thread(ModLoader::init, &moduleInfo); break; } case DLL_PROCESS_DETACH: { ModLoader::logger->verbose("Mod loader detached from process"); - if (LoaderThread) - CloseHandle(LoaderThread); - FreeConsole(); if (ModLoader::configManager) delete ModLoader::configManager; @@ -84,9 +79,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser ModLoader::modEnvironnement->Free(); delete ModLoader::modEnvironnement; } - - if (ModLoader::logger) - delete ModLoader::logger; if (ModLoader::gameCache) delete ModLoader::gameCache; @@ -94,6 +86,14 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser if (ModLoader::gameData) delete ModLoader::gameData; + if (ModLoader::logger) + delete ModLoader::logger; + + if (loaderThread) + loaderThread->join(); + + FreeConsole(); + break; } } From 88c0b4b44a2e9b32fee4dcb45f71a64dd6e52096 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 12:51:56 +0000 Subject: [PATCH 53/64] WIP --- src/ModLoader.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 49ab4f7..e898d9c 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -17,10 +17,7 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); - // TODO: Remove this hacky sleep, but it's needed, maybe check if the memory is ready next time? - std::this_thread::sleep_for(std::chrono::milliseconds(200)); Patcher patcher; - logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); From b36a43f48db48543230612ba560becba72c52be0 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 17:37:28 +0000 Subject: [PATCH 54/64] Update includes --- src/ModLoader.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index e898d9c..96663ec 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -17,11 +17,13 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) logger = new Logger("ModLoader"); logger->info("Mod loader has been started"); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + Patcher patcher; logger->verbose("Dll module is loaded"); uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); - patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); - patcher.applyPatches(baseAddress); + // patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); + // patcher.applyPatches(baseAddress); gameData = new GameData(baseAddress, moduleInfo->SizeOfImage); gameData->init(); From b73a3beba8d398c1a4a87d714f5bb190bff29415 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 18:07:48 +0000 Subject: [PATCH 55/64] OPTIQUE 2000 --- CMakeLists.txt | 2 - src/Mod/ModEnvironnement.cpp | 116 ++--------------------------------- 2 files changed, 6 insertions(+), 112 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 294d573..6ab9dfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,12 +2,10 @@ cmake_minimum_required(VERSION 3.16) project(FantasyLifeI-ModLoader LANGUAGES CXX C) set(VERSION 1.00) -set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") option(MLDEBUG "Enable ModLoader debug code" ON) add_subdirectory(DllProxy) add_library(${PROJECT_NAME} SHARED) -add_library(${PROJECT_NAME} SHARED) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "ModLoader" CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES) target_compile_definitions(${PROJECT_NAME} PRIVATE MLCOMPILED MLVERSION=${VERSION}) diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 39770ed..2b0311f 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -174,8 +174,6 @@ bool ModEnvironnement::readContentFromArchive(const std::filesystem::path& archi { mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; - //if(stat.m_filename == "") break; - //if(stat.m_filename == "") break; std::string fname = stat.m_filename; if(fname.size() >= internalName.size() && fname.compare(fname.size() - internalName.size(), internalName.size(), internalName) == 0) @@ -286,116 +284,14 @@ void ModEnvironnement::PreLoad() for (auto* mod : _modsList) { - std::mutex mutex; - std::vector libs; - std::vector> mods; - std::mutex mutex; - std::vector libs; - std::vector> mods; - }; - - std::vector buckets(numThreads); - std::atomic nextBucket { 0 }; - std::latch done(static_cast(modListSize)); - - - for (auto * mod : _modsList) - { - pool.enqueue([this, &done, mod, &buckets, &nextBucket, numThreads]() - { - size_t index = nextBucket.fetch_add(1) % numThreads; - Bucket& bucket = buckets[index]; - - ModMetaData meta = mod->getMeta(); - std::string identifier = meta.identifier; - - std::vector modBuf; - if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) - { - ModLoader::logger->error("Failed to decompressed content from archive from: ", identifier); - done.count_down(); - return; - } - - std::string suffix = ".mod"; - { - std::string intern = mod->getInternalPath(); - size_t pos = intern.find_last_of('.'); - if(pos != std::string::npos) suffix = intern.substr(pos); - } - std::string suffix = ".mod"; - { - std::string intern = mod->getInternalPath(); - size_t pos = intern.find_last_of('.'); - if(pos != std::string::npos) suffix = intern.substr(pos); - } - - std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, suffix); - if(libOnDiskPath.empty()) - { - ModLoader::logger->error("Failed to write temporary content for ", identifier); - done.count_down(); - return; - } - - { - std::lock_guard lg(_mergeMutex); - _tempFilesToRemove.push_back(libOnDiskPath); - } - { - std::lock_guard lg(_mergeMutex); - _tempFilesToRemove.push_back(libOnDiskPath); - } - - LibHandle lib = LoadLib(libOnDiskPath.string()); - if(!lib) - { - ModLoader::logger->error("Failed to load: ", identifier); - done.count_down(); - return; - } - - using GetModFunc = ModBase *(*)(); - auto getter = reinterpret_cast(GetFunction(lib, "CraftMod")); - if(!getter) - { - ModLoader::logger->error("Missing CraftMod in ", identifier); - CloseLib(lib); - done.count_down(); - return; - } - - ModLoader::logger->info("Loading ", identifier, " v", meta.version); - auto modPtr = std::unique_ptr(getter()); - modPtr->OnPreLoad(); - - { - std::lock_guard lg(bucket.mutex); - bucket.libs.push_back(lib); - bucket.mods.push_back(std::move(modPtr)); - } - done.count_down(); - }); - } + ModMetaData meta = mod->getMeta(); + std::string identifier = meta.identifier; - done.wait(); - { - _modLibList.reserve(buckets.size()); - _modLibList.reserve(buckets.size()); - std::lock_guard lg(_mergeMutex); - for(auto& bucket : buckets) + std::vector modBuf; + if(!readContentFromArchive(mod->getContainerPath(), mod->getInternalPath(), modBuf)) { - _modPtrList.reserve(bucket.mods.size()); - _modPtrList.reserve(bucket.mods.size()); - _modLibList.insert(_modLibList.end(), bucket.libs.begin(), bucket.libs.end()); - for(auto& modPtr : bucket.mods) - { - _modPtrList.push_back(std::move(modPtr)); - } - for(auto& modPtr : bucket.mods) - { - _modPtrList.push_back(std::move(modPtr)); - } + ModLoader::logger->error("Failed to decompress content from: ", identifier); + continue; } std::filesystem::path libOnDiskPath = writeBufferToTemp(modBuf, ".mod"); From 49cdcc282bacfb3bec3b8741c60dab2606c3ad5b Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 19:11:50 +0000 Subject: [PATCH 56/64] Refactor archive file handling methods in ModEnvironnement --- src/Mod/ModEnvironnement.cpp | 42 ++++++++++-------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/src/Mod/ModEnvironnement.cpp b/src/Mod/ModEnvironnement.cpp index 3a0047f..20c2da9 100644 --- a/src/Mod/ModEnvironnement.cpp +++ b/src/Mod/ModEnvironnement.cpp @@ -106,46 +106,26 @@ void ModEnvironnement::resolveOrder(std::vector mods) _modsList = std::move(sorted); } -bool ModEnvironnement::findModJsonInArchive(const std::filesystem::path& archivePath, std::string& foundPath) +bool ModEnvironnement::findFileInArchive(const std::filesystem::path& archivePath, const std::string& suffix, std::string& foundPath) { mz_zip_archive archive; memset(&archive, 0, sizeof(archive)); - if(!mz_zip_reader_init_file(&archive, archivePath.string().c_str(), 0)) return false; + if(!mz_zip_reader_init_file(&archive, archivePath.string().c_str(), 0)) + return false; mz_uint num = mz_zip_reader_get_num_files(&archive); + const size_t suffixLen = suffix.size(); + for(mz_uint i = 0; i < num; ++i) { mz_zip_archive_file_stat stat; if(!mz_zip_reader_file_stat(&archive, i, &stat)) continue; - std::string fname = stat.m_filename; - if(fname.size() >= 8 && fname.substr(fname.size() - 8) == "Mod.json") - { - foundPath = fname; - mz_zip_reader_end(&archive); - return true; - } - } - - mz_zip_reader_end(&archive); - return false; -} - -bool ModEnvironnement::findModLibInArchive(const std::filesystem::path& archivePath, const std::string& libName, std::string& foundPath) -{ - mz_zip_archive archive; - memset(&archive, 0, sizeof(archive)); - - if(!mz_zip_reader_init_file(&archive, archivePath.string().c_str(), 0)) return false; - mz_uint num = mz_zip_reader_get_num_files(&archive); - for (mz_uint i = 0; i < num; ++i) - { - mz_zip_archive_file_stat st; - if (!mz_zip_reader_file_stat(&archive, i, &st)) continue; - std::string fname = st.m_filename; - - if (fname.size() >= libName.size() && fname.compare(fname.size() - libName.size(), libName.size(), libName) == 0) + const char* fname = stat.m_filename; + size_t fnameLen = strlen(fname); + + if(fnameLen >= suffixLen && strncmp(fname + fnameLen - suffixLen, suffix.c_str(), suffixLen) == 0) { foundPath = fname; mz_zip_reader_end(&archive); @@ -240,7 +220,7 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) if(entryPath.extension() == ".fliarchive") { std::string modJsonInternal; - if(!findModJsonInArchive(entryPath, modJsonInternal)) + if(!findFileInArchive(entryPath, "Mod.json", modJsonInternal)) { ModLoader::logger->warn("Invalid mod (no metadata) ", entryPath); continue; @@ -263,7 +243,7 @@ void ModEnvironnement::SetupEnvironnnement(std::string modDirs) std::string internalModPath; std::string modLibIdentifier = "CompiledBin.bin"; - if(!findModLibInArchive(entryPath, modLibIdentifier, internalModPath)) + if(!findFileInArchive(entryPath, modLibIdentifier, internalModPath)) { ModLoader::logger->warn("Invalid mod (no content) ", entryPath); continue; From 7b748e1a29fdca521e1c9d6d5127081f3365f989 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 24 Dec 2025 19:11:54 +0000 Subject: [PATCH 57/64] Update subproject commit reference in include --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index 425d7d1..deac430 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 425d7d148bd4b4b1757d27887c4c7fb477fd17cb +Subproject commit deac430ec0fbcce30d960ead055bbd57bf79309b From 28ed1e6daecb779cf4d3acf325d6c428eefcd6cb Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 4 Jan 2026 18:32:11 +0000 Subject: [PATCH 58/64] Rebase de con pour la 2.0.3 --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index deac430..e924542 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit deac430ec0fbcce30d960ead055bbd57bf79309b +Subproject commit e9245427b98f60a819bac365db3fd4468b3399b3 From 3dc80452cf0574c9a96b51f6221969a96953557c Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Sun, 4 Jan 2026 18:40:47 +0000 Subject: [PATCH 59/64] fix vscode merge editor shit --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index e924542..0f48943 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit e9245427b98f60a819bac365db3fd4468b3399b3 +Subproject commit 0f48943493bcaed945f6ab690d071a12042a9cff From c089af26bb51ab2174416de2a1c0ecdd236019d0 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:25:42 +0000 Subject: [PATCH 60/64] Refactor GameData and Pattern classes to utilize CommonData for base address and image size management --- include | 2 +- src/CommonData.cpp | 6 ++++++ src/GameData.cpp | 20 +++++--------------- src/Hook/Pattern.cpp | 12 ++++++++---- src/ModLoader.cpp | 7 +++++-- 5 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 src/CommonData.cpp diff --git a/include b/include index 0f48943..887bbf2 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 0f48943493bcaed945f6ab690d071a12042a9cff +Subproject commit 887bbf28a873a9756ebd4c2a95cda25ec9a012ad diff --git a/src/CommonData.cpp b/src/CommonData.cpp new file mode 100644 index 0000000..de5b6ac --- /dev/null +++ b/src/CommonData.cpp @@ -0,0 +1,6 @@ +#include "CommonData.hpp" + +#ifdef _WIN32 +int64_t CommonData::sizeImage = 0; +uintptr_t CommonData::baseAddress = 0; +#endif \ No newline at end of file diff --git a/src/GameData.cpp b/src/GameData.cpp index 0a7f7de..052d8d2 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -3,26 +3,25 @@ #include "API/Entities/Player/Player.hpp" #include "ModLoader.hpp" #include "Offset.h" +#include "CommonData.hpp" #ifdef _WIN32 #include #else #endif -GameData::GameData(uintptr_t baseAddress, uint32_t imageSize) : +GameData::GameData() : _staticDataManager(nullptr), _dynamicDataManager(nullptr) { ModLoader::logger->verbose("Initialize GameData"); - this->_baseAddress = baseAddress; - this->_imageSize = imageSize; } void GameData::init() { - this->_gObjects = reinterpret_cast(this->_baseAddress + GOBJECTS_OFFSET); - this->_gWorld = reinterpret_cast(this->_baseAddress + GWORLD_OFFSET); - this->_gNames = reinterpret_cast(this->_baseAddress + GNAMES_OFFSET); + this->_gObjects = reinterpret_cast(CommonData::GetBaseAddress() + GOBJECTS_OFFSET); + this->_gWorld = reinterpret_cast(CommonData::GetBaseAddress() + GWORLD_OFFSET); + this->_gNames = reinterpret_cast(CommonData::GetBaseAddress() + GNAMES_OFFSET); this->waitObject(&this->_gObjects); this->waitObject(&this->_staticDataManager, "StaticDataManager", 1); ModLoader::logger->verbose("Found StaticDataManager => ", std::hex, this->_staticDataManager); @@ -66,15 +65,6 @@ Player *GameData::getPlayer() { return _player.get(); } -uintptr_t GameData::getBaseAddress() { - return _baseAddress; -} - -uint32_t GameData::getImageSize() -{ - return _imageSize; -} - FUObjectArray *GameData::getGObjects() { return _gObjects; } diff --git a/src/Hook/Pattern.cpp b/src/Hook/Pattern.cpp index 7d5dc9f..30d8147 100644 --- a/src/Hook/Pattern.cpp +++ b/src/Hook/Pattern.cpp @@ -1,19 +1,23 @@ #include "Hook/Pattern.hpp" +#include "CommonData.hpp" #include "GameData.hpp" #include "Hook/MemoryHelper.hpp" #include "ModLoader.hpp" Pattern::Pattern(uint8_t *pattern, const char *mask) : _pattern(pattern), _mask(mask) {} -size_t Pattern::getSize() { +size_t Pattern::getSize() +{ return strlen(_mask); } -uint8_t *Pattern::getPattern() { +uint8_t *Pattern::getPattern() +{ return _pattern; } -const char *Pattern::getMask() { +const char *Pattern::getMask() +{ return _mask; } @@ -24,5 +28,5 @@ uintptr_t Pattern::find(uintptr_t baseAddress, uint32_t range) uintptr_t Pattern::find(uintptr_t startOffset) { - return MemoryHelper::findPattern(ModLoader::gameData->getBaseAddress() + startOffset, ModLoader::gameData->getImageSize(), this->_pattern, this->_mask); + return MemoryHelper::findPattern(CommonData::GetBaseAddress() + startOffset, CommonData::GetSizeImage(), this->_pattern, this->_mask); } \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 96663ec..f870ab2 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -5,6 +5,7 @@ #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" #include +#include "CommonData.hpp" GameData *ModLoader::gameData = nullptr; GameCache *ModLoader::gameCache = nullptr; @@ -21,10 +22,12 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) Patcher patcher; logger->verbose("Dll module is loaded"); - uintptr_t baseAddress = (uintptr_t) GetModuleHandle(nullptr); + CommonData::init(moduleInfo->SizeOfImage, (uintptr_t) GetModuleHandle(nullptr)); + // Patcher is crashing the game for unknown reasons - disabling for now, waiting @EltyDev to investigate // patcher.add(new EventHook(EventType::ClickEvent, 0x657DC32)); // patcher.applyPatches(baseAddress); - gameData = new GameData(baseAddress, moduleInfo->SizeOfImage); + + gameData = new GameData(); gameData->init(); gameCache = new GameCache(); From 58d057c028b8072163d9a482a912362b8a570f62 Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:49:51 +0000 Subject: [PATCH 61/64] WIP --- include | 2 +- src/API/Skill/SkillData.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include b/include index 887bbf2..438a401 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 887bbf28a873a9756ebd4c2a95cda25ec9a012ad +Subproject commit 438a4016f10400dfa1e4f8dfc4842df4a0794c29 diff --git a/src/API/Skill/SkillData.cpp b/src/API/Skill/SkillData.cpp index b325204..b8691db 100644 --- a/src/API/Skill/SkillData.cpp +++ b/src/API/Skill/SkillData.cpp @@ -1,5 +1,4 @@ #include "API/Skill/SkillData.hpp" -#include "API/Engine/FName.hpp" #include "API/Common/Common.hpp" void SkillData::SetName(LANG lang, FString string) From 60c9435420248a71e99d2184c04bbd93b8dad3be Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:56:33 +0000 Subject: [PATCH 62/64] EXPERIMENTAL: add GameRegistries --- CMakeLists.txt | 4 ++-- src/GameRegistries.cpp | 26 ++++++++++++++++++++++++++ src/ModLoader.cpp | 5 +++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/GameRegistries.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ab9dfa..772243e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(${PROJECT_NAME} PRIVATE user32 kernel32) file(GLOB_RECURSE PROJECT_SOURCE "src/*.cpp") -target_sources(${PROJECT_NAME} PUBLIC src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file +target_sources(${PROJECT_NAME} PRIVATE src/Lib/miniz.c ${PROJECT_SOURCE}) \ No newline at end of file diff --git a/src/GameRegistries.cpp b/src/GameRegistries.cpp new file mode 100644 index 0000000..a7deeae --- /dev/null +++ b/src/GameRegistries.cpp @@ -0,0 +1,26 @@ +#include "GameRegistries.hpp" +#include "GameData.hpp" +#include "ModLoader.hpp" +#include "SDK/DP1Project.h" + +WrappedRegistry* GameRegistries::ITEM_MATERIAL = nullptr; + +void GameRegistries::init(GameData* gameData) +{ + ModLoader::logger->verbose("Initialize Game Registries"); + auto* sdm = gameData->getStaticDataManager(); + + bindItem(sdm); +} + +void GameRegistries::bindItem(UStaticDataManager* sdm) +{ + ModLoader::gameData->waitObject(&sdm->m_ItemMaterialData); + ITEM_MATERIAL = new WrappedRegistry(); + ITEM_MATERIAL->Bind(&sdm->m_ItemMaterialData->m_dataMap); + ITEM_MATERIAL->BuildIndex(); + ModLoader::logger->verbose("Binded Material Item Registry!"); + +} + + \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index f870ab2..508b449 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -1,6 +1,7 @@ #include "ModLoader.hpp" #include "GameCache.hpp" #include "GameData.hpp" +#include "GameRegistries.hpp" #include "Hook/EventHandler.hpp" #include "Patcher/Patcher.hpp" #include "Patcher/Patches/EventHook.hpp" @@ -31,6 +32,10 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) gameData->init(); gameCache = new GameCache(); + + GameRegistries* gameReg = new GameRegistries(); + gameReg->init(gameData); + configManager = new ConfigManager("../../Content/Settings"); modEnvironnement = new ModEnvironnement("../../Content/Mods"); modEnvironnement->PreLoad(); From 62cf6df165e553ece3fb870e2adfd5f59d5beccd Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Thu, 8 Jan 2026 15:38:06 +0000 Subject: [PATCH 63/64] WIP NEED LOT OF CLEANING --- include | 2 +- src/GameRegistries.cpp | 122 ++++++++++++++++++++++++++++++++++++++--- src/ModLoader.cpp | 5 ++ 3 files changed, 120 insertions(+), 9 deletions(-) diff --git a/include b/include index 438a401..52981c7 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 438a4016f10400dfa1e4f8dfc4842df4a0794c29 +Subproject commit 52981c7f130db814ee0551c8fc65a707ae93352e diff --git a/src/GameRegistries.cpp b/src/GameRegistries.cpp index a7deeae..12b8774 100644 --- a/src/GameRegistries.cpp +++ b/src/GameRegistries.cpp @@ -3,24 +3,130 @@ #include "ModLoader.hpp" #include "SDK/DP1Project.h" -WrappedRegistry* GameRegistries::ITEM_MATERIAL = nullptr; +// Initialize merged registries +std::shared_ptr> GameRegistries::BATTLE_COMMAND_NOUN = nullptr; +std::shared_ptr> GameRegistries::PLANT_DUNGEON_NOUN = nullptr; +std::shared_ptr> GameRegistries::ITEM_NOUN = nullptr; +std::shared_ptr> GameRegistries::LIFE_NOUN = nullptr; +std::shared_ptr> GameRegistries::SKILL_NOUN = nullptr; +std::shared_ptr> GameRegistries::QUEST_REQUEST_NOUN = nullptr; +std::shared_ptr> GameRegistries::QUEST_TITLE_NOUN = nullptr; +std::shared_ptr> GameRegistries::MAP_NOUN = nullptr; +std::shared_ptr> GameRegistries::MENU_NOUN = nullptr; +std::shared_ptr> GameRegistries::CHARA_NOUN = nullptr; +std::shared_ptr> GameRegistries::SYSTEM_NOUN = nullptr; +std::shared_ptr> GameRegistries::ITEM_MATERIAL = nullptr; + +// Game source IDs +uint16_t GameRegistries::_battleCommandNounSourceId = 0; +uint16_t GameRegistries::_plantDungeonNounSourceId = 0; +uint16_t GameRegistries::_itemNounSourceId = 0; +uint16_t GameRegistries::_lifeNounSourceId = 0; +uint16_t GameRegistries::_skillNounSourceId = 0; +uint16_t GameRegistries::_questRequestNounSourceId = 0; +uint16_t GameRegistries::_questTitleNounSourceId = 0; +uint16_t GameRegistries::_mapNounSourceId = 0; +uint16_t GameRegistries::_menuNounSourceId = 0; +uint16_t GameRegistries::_charaNounSourceId = 0; +uint16_t GameRegistries::_systemNounSourceId = 0; +uint16_t GameRegistries::_itemMaterialSourceId = 0; void GameRegistries::init(GameData* gameData) { ModLoader::logger->verbose("Initialize Game Registries"); auto* sdm = gameData->getStaticDataManager(); + bindNounPRE(sdm); bindItem(sdm); } +void GameRegistries::bindNounPRE(UStaticDataManager* sdm) +{ + ModLoader::gameData->waitObject(&sdm->m_BattleCommandNameNoun); + BATTLE_COMMAND_NOUN = std::make_shared>(); + auto battleCommandSource = std::make_shared>("BattleCommandNoun", 0, &sdm->m_BattleCommandNameNoun->m_dataMap); + battleCommandSource->BuildIndex(); + _battleCommandNounSourceId = BATTLE_COMMAND_NOUN->AddSource(battleCommandSource); + ModLoader::logger->verbose("Binded Battle Command Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_PlantDungeonText_Noun); + PLANT_DUNGEON_NOUN = std::make_shared>(); + auto plantDungeonSource = std::make_shared>("PlantDungeonNoun", 0, &sdm->m_PlantDungeonText_Noun->m_dataMap); + plantDungeonSource->BuildIndex(); + _plantDungeonNounSourceId = PLANT_DUNGEON_NOUN->AddSource(plantDungeonSource); + ModLoader::logger->verbose("Binded Plant Dungeon Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_ItemText_Noun); + ITEM_NOUN = std::make_shared>(); + auto itemNounSource = std::make_shared>("ItemNoun", 0, &sdm->m_ItemText_Noun->m_dataMap); + itemNounSource->BuildIndex(); + _itemNounSourceId = ITEM_NOUN->AddSource(itemNounSource); + ModLoader::logger->verbose("Binded Item Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_LifeText_Noun); + LIFE_NOUN = std::make_shared>(); + auto lifeNounSource = std::make_shared>("LifeNoun", 0, &sdm->m_LifeText_Noun->m_dataMap); + lifeNounSource->BuildIndex(); + _lifeNounSourceId = LIFE_NOUN->AddSource(lifeNounSource); + ModLoader::logger->verbose("Binded Life Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_SkillText); + SKILL_NOUN = std::make_shared>(); + auto skillNounSource = std::make_shared>("SkillNoun", 0, &sdm->m_SkillText->m_dataMap); + skillNounSource->BuildIndex(); + _skillNounSourceId = SKILL_NOUN->AddSource(skillNounSource); + ModLoader::logger->verbose("Binded Skill Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_QuestRequestMapText_Noun); + QUEST_REQUEST_NOUN = std::make_shared>(); + auto questRequestSource = std::make_shared>("QuestRequestNoun", 0, &sdm->m_QuestRequestMapText_Noun->m_dataMap); + questRequestSource->BuildIndex(); + _questRequestNounSourceId = QUEST_REQUEST_NOUN->AddSource(questRequestSource); + ModLoader::logger->verbose("Binded Quest Request Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_QuestTitleText); + QUEST_TITLE_NOUN = std::make_shared>(); + auto questTitleSource = std::make_shared>("QuestTitleNoun", 0, &sdm->m_QuestTitleText->m_dataMap); + questTitleSource->BuildIndex(); + _questTitleNounSourceId = QUEST_TITLE_NOUN->AddSource(questTitleSource); + ModLoader::logger->verbose("Binded Quest Title Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_MapText_Noun); + MAP_NOUN = std::make_shared>(); + auto mapNounSource = std::make_shared>("MapNoun", 0, &sdm->m_MapText_Noun->m_dataMap); + mapNounSource->BuildIndex(); + _mapNounSourceId = MAP_NOUN->AddSource(mapNounSource); + ModLoader::logger->verbose("Binded Map Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_MenuText_Noun); + MENU_NOUN = std::make_shared>(); + auto menuNounSource = std::make_shared>("MenuNoun", 0, &sdm->m_MenuText_Noun->m_dataMap); + menuNounSource->BuildIndex(); + _menuNounSourceId = MENU_NOUN->AddSource(menuNounSource); + ModLoader::logger->verbose("Binded Menu Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_CharaText_Noun); + CHARA_NOUN = std::make_shared>(); + auto charaNounSource = std::make_shared>("CharaNoun", 0, &sdm->m_CharaText_Noun->m_dataMap); + charaNounSource->BuildIndex(); + _charaNounSourceId = CHARA_NOUN->AddSource(charaNounSource); + ModLoader::logger->verbose("Binded Chara Noun Registry!"); + + ModLoader::gameData->waitObject(&sdm->m_SystemText_Noun); + SYSTEM_NOUN = std::make_shared>(); + auto systemNounSource = std::make_shared>("SystemNoun", 0, &sdm->m_SystemText_Noun->m_dataMap); + systemNounSource->BuildIndex(); + _systemNounSourceId = SYSTEM_NOUN->AddSource(systemNounSource); + ModLoader::logger->verbose("Binded System Noun Registry!"); +} + void GameRegistries::bindItem(UStaticDataManager* sdm) { ModLoader::gameData->waitObject(&sdm->m_ItemMaterialData); - ITEM_MATERIAL = new WrappedRegistry(); - ITEM_MATERIAL->Bind(&sdm->m_ItemMaterialData->m_dataMap); - ITEM_MATERIAL->BuildIndex(); - ModLoader::logger->verbose("Binded Material Item Registry!"); + ITEM_MATERIAL = std::make_shared>(); + auto itemMaterialSource = std::make_shared>("ItemMaterial", 0, &sdm->m_ItemMaterialData->m_dataMap); -} - - \ No newline at end of file + itemMaterialSource->BuildIndex(); + _itemMaterialSourceId = ITEM_MATERIAL->AddSource(itemMaterialSource); + ModLoader::logger->verbose("Binded Material Item Registry!"); +} \ No newline at end of file diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index 508b449..8c75030 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -45,6 +45,11 @@ void WINAPI ModLoader::init(MODULEINFO* moduleInfo) modEnvironnement->PostLoad(); logger->verbose("Mod loader initialization complete"); + + for(auto text : GameRegistries::LIFE_NOUN->GetAll()) + { + logger->verbose("Life Noun: ", text->ID.ToString()); + } } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) From 05948c2b7905379c60e74117afb19aed95227c0e Mon Sep 17 00:00:00 2001 From: AmeliaCute <48628282+AmeliaCute@users.noreply.github.com> Date: Wed, 14 Jan 2026 03:28:50 +0000 Subject: [PATCH 64/64] update include --- include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include b/include index 52981c7..d662472 160000 --- a/include +++ b/include @@ -1 +1 @@ -Subproject commit 52981c7f130db814ee0551c8fc65a707ae93352e +Subproject commit d662472a920a977557fc258744ac520ee73097b4