Skip to content

Commit 0aefc60

Browse files
committed
Hook AwakeFromLoad and automatically spawn teapots
Create a hook directly into libunity to detect when any GameObject comes into existence. Check the name and spawn a teapot if necessary. This forms the basis of prefabs being spawned on any GameObject that matches a set of conditions.
1 parent b337ed6 commit 0aefc60

1 file changed

Lines changed: 40 additions & 7 deletions

File tree

src/main.cpp

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,39 @@ void spawnToyota() {
5454
toyotaGO->get_transform()->set_localScale(::UnityEngine::Vector3(0.4, 0.4, 0.4));
5555
}
5656

57-
void spawnTeapotOnNotes() {
57+
UnityW<UnityEngine::GameObject> getTeapotGO() {
5858
static UnityW<UnityEngine::GameObject> teapotGO;
59+
5960
if(!teapotGO) {
6061
teapotGO = Flair::Assets::loadModel("/storage/emulated/0/ModData/com.beatgames.beatsaber/Mods/Flair/teapot.glb");
61-
if(!teapotGO) return;
62+
if(!teapotGO) return nullptr;
6263
teapotGO->set_name("Teapot");
6364
teapotGO->SetActive(false);
6465
UnityEngine::GameObject::DontDestroyOnLoad(teapotGO);
6566
}
66-
67+
68+
return teapotGO;
69+
}
70+
71+
void spawnTeapotOnGameObject(UnityEngine::GameObject* go) {
72+
UnityW<UnityEngine::GameObject> teapotGO = getTeapotGO();
73+
if(!teapotGO) return;
74+
75+
if(go->get_transform()->Find("Teapot(Clone)")) return;
76+
77+
PaperLogger.info("Instantiating teapot on '{}'", go->get_name());
78+
UnityW<UnityEngine::GameObject> teapotCloneGO = UnityEngine::GameObject::Instantiate(teapotGO, go->get_transform(), false);
79+
if(!teapotCloneGO) {PaperLogger.error("Failed instantiating teapot"); return;}
80+
teapotCloneGO->SetActive(true);
81+
}
82+
83+
void spawnTeapotOnNotes() {
6784
float startTime = UnityEngine::Time::get_realtimeSinceStartup();
6885

6986
ArrayW<UnityEngine::GameObject*> everyGO = UnityEngine::GameObject::FindObjectsOfType<UnityEngine::GameObject*>();
7087
for(UnityEngine::GameObject* go : everyGO) {
7188
if(!(go->get_name()->StartsWith("Note ") || go->get_name() == "NoteCube")) continue;
72-
if(go->get_transform()->Find("Teapot(Clone)")) continue;
73-
PaperLogger.info("Instancing teapot onto '{}'", go->get_name());
74-
UnityEngine::GameObject* teapotCloneGO = UnityEngine::GameObject::Instantiate(teapotGO, go->get_transform(), false);
75-
teapotCloneGO->SetActive(true);
89+
spawnTeapotOnGameObject(go);
7690
}
7791

7892
float endTime = UnityEngine::Time::get_realtimeSinceStartup();
@@ -156,6 +170,17 @@ MAKE_HOOK_MATCH(SillyHook, &UnityEngine::GameObject::set_name, void, UnityEngine
156170
PaperLogger.info("Set GameObject name to '{}'", string);
157171
}
158172

173+
MAKE_HOOK_NO_CATCH(AwakeFromLoad_Hook, 0x0, void,
174+
void* GameObjectPtr_this, uint32_t AwakeFromLoadMode_param_1
175+
) {
176+
AwakeFromLoad_Hook(GameObjectPtr_this, AwakeFromLoadMode_param_1);
177+
UnityEngine::GameObject* self = (UnityEngine::GameObject*)UnityEngine::Object::FindObjectFromInstanceID(*(int*)( (char*)GameObjectPtr_this + 8 )).ptr();
178+
179+
if(UnityEngine::Object::IsPersistent(self)) return; // Can't instantiate on Unity prefabs
180+
if(!(self->get_name()->StartsWith("Note ") || self->get_name() == "NoteCube")) return;
181+
BSML::MainThreadScheduler::ScheduleAfterTime(1, [self](){spawnTeapotOnGameObject(self);}); // Game doesn't really like it when you start doing complicated things in the AwakeFromLoad method
182+
}
183+
159184
// Called at the early stages of game loading
160185
MOD_EXTERN_FUNC void setup(CModInfo *info) noexcept {
161186
*info = modInfo.to_c();
@@ -183,5 +208,13 @@ MOD_EXTERN_FUNC void late_load() noexcept {
183208
INSTALL_HOOK(PaperLogger, AssimpTestHook);
184209
INSTALL_HOOK(PaperLogger, SillyHook);
185210

211+
uintptr_t libunity = baseAddr("libunity.so");
212+
PaperLogger.info("Found libunity: {}", libunity);
213+
if(!libunity) {PaperLogger.error("Could not find libunity"); return;}
214+
uintptr_t AwakeFromLoad = findPattern(libunity, "fe 0f 1e f8 f4 4f 01 a9 f4 03 01 2a 3f 0c 00 71 f3 03 00 aa 61 00 00 54 e8 1f 80 52 68 de 01 39 e0 03 13 aa 0f 00 00 94 e0 03 13 aa 2b 00 00 94 9f 0e 00 71 00 01 00 54 e8 9c 00 f0 01 9d 44 f9");
215+
PaperLogger.info("Found AwakeFromLoad: {}", AwakeFromLoad);
216+
if(!AwakeFromLoad) {PaperLogger.error("Could not find AwakeFromLoad"); return;}
217+
INSTALL_HOOK_DIRECT(PaperLogger, AwakeFromLoad_Hook, reinterpret_cast<void*>(AwakeFromLoad));
218+
186219
PaperLogger.info("Installed all hooks!");
187220
}

0 commit comments

Comments
 (0)