From ace6b7fc7e5933389a7dfd4aef1692b1c6cdbb2b Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 1 Sep 2025 11:56:25 -0700 Subject: [PATCH] (SiLoader) Start actions attached to world startup when world is ready (#704) --- LEGO1/lego/legoomni/src/main/legomain.cpp | 2 ++ extensions/include/extensions/siloader.h | 4 +++ extensions/src/siloader.cpp | 40 ++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp index 604701eb..666cd35d 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -407,6 +407,8 @@ LegoOmni* LegoOmni::GetInstance() void LegoOmni::AddWorld(LegoWorld* p_world) { m_worldList->Append(p_world); + + Extension::Call(HandleWorld, p_world); } // FUNCTION: LEGO1 0x1005adb0 diff --git a/extensions/include/extensions/siloader.h b/extensions/include/extensions/siloader.h index 2a82bd3b..eb61521d 100644 --- a/extensions/include/extensions/siloader.h +++ b/extensions/include/extensions/siloader.h @@ -23,6 +23,7 @@ class SiLoader { static bool Load(); static std::optional HandleFind(StreamObject p_object, LegoWorld* world); static std::optional HandleStart(MxDSAction& p_action); + static MxBool HandleWorld(LegoWorld* p_world); static std::optional HandleRemove(StreamObject p_object, LegoWorld* world); static std::optional HandleDelete(MxDSAction& p_action); static MxBool HandleEndAction(MxEndActionNotificationParam& p_param); @@ -47,6 +48,7 @@ class SiLoader { static bool LoadDirective(const char* p_directive); static MxStreamController* OpenStream(const char* p_file); static void ParseExtra(const MxAtomId& p_atom, si::Core* p_core, MxAtomId p_parentReplacedAtom = MxAtomId()); + static bool IsWorld(const StreamObject& p_object); }; #ifdef EXTENSIONS @@ -70,6 +72,7 @@ bool SiLoader::ReplacedIn(MxDSAction& p_action, Args... p_args) constexpr auto Load = &SiLoader::Load; constexpr auto HandleFind = &SiLoader::HandleFind; constexpr auto HandleStart = &SiLoader::HandleStart; +constexpr auto HandleWorld = &SiLoader::HandleWorld; constexpr auto HandleRemove = &SiLoader::HandleRemove; constexpr auto HandleDelete = &SiLoader::HandleDelete; constexpr auto HandleEndAction = &SiLoader::HandleEndAction; @@ -78,6 +81,7 @@ constexpr auto ReplacedIn = [](auto&&... args) { return SiLoader::ReplacedIn(std constexpr decltype(&SiLoader::Load) Load = nullptr; constexpr decltype(&SiLoader::HandleFind) HandleFind = nullptr; constexpr decltype(&SiLoader::HandleStart) HandleStart = nullptr; +constexpr decltype(&SiLoader::HandleWorld) HandleWorld = nullptr; constexpr decltype(&SiLoader::HandleRemove) HandleRemove = nullptr; constexpr decltype(&SiLoader::HandleDelete) HandleDelete = nullptr; constexpr decltype(&SiLoader::HandleEndAction) HandleEndAction = nullptr; diff --git a/extensions/src/siloader.cpp b/extensions/src/siloader.cpp index 3acb667e..9e11edd5 100644 --- a/extensions/src/siloader.cpp +++ b/extensions/src/siloader.cpp @@ -83,7 +83,7 @@ std::optional SiLoader::HandleStart(MxDSAction& p_action) }; for (const auto& key : startWith) { - if (key.first == object) { + if (key.first == object && !IsWorld(key.first)) { MxDSAction action; start(key.second, p_action, action); } @@ -128,6 +128,30 @@ std::optional SiLoader::HandleStart(MxDSAction& p_action) return std::nullopt; } +MxBool SiLoader::HandleWorld(LegoWorld* p_world) +{ + StreamObject object{p_world->GetAtomId(), p_world->GetEntityId()}; + auto start = [](const StreamObject& p_object, MxDSAction& p_out) { + if (!OpenStream(p_object.first.GetInternal())) { + return; + } + + p_out.SetAtomId(p_object.first); + p_out.SetObjectId(p_object.second); + p_out.SetUnknown24(-1); + Start(&p_out); + }; + + for (const auto& key : startWith) { + if (key.first == object) { + MxDSAction action; + start(key.second, action); + } + } + + return TRUE; +} + std::optional SiLoader::HandleRemove(StreamObject p_object, LegoWorld* world) { for (const auto& key : removeWith) { @@ -362,3 +386,17 @@ void SiLoader::ParseExtra(const MxAtomId& p_atom, si::Core* p_core, MxAtomId p_p ParseExtra(p_atom, child, replacedAtom); } } + +bool SiLoader::IsWorld(const StreamObject& p_object) +{ + // The convention in LEGO Island is that world objects are always at ID 0 + if (p_object.second == 0) { + for (int i = 0; i < LegoOmni::e_numWorlds; i++) { + if (p_object.first == *Lego()->GetWorldAtom((LegoOmni::World) i)) { + return true; + } + } + } + + return false; +}