Reload the active resource pack in Minecraft Bedrock without leaving the world. An mcpelauncher mod for Linux and macOS.
Edit a texture or a JSON UI file, click a menu entry, see the change. No world reload, no game restart.
Needs the Android NDK. The mod is loaded by mcpelauncher's own bionic linker, so it must be an Android aarch64 ELF even when built on macOS.
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-21 \
-DMINECRAFT_SO=/path/to/versions/1.26.40.5/lib/arm64-v8a/libminecraftpe.so \
-DOFFSETS_HEADER=$PWD/generated/offsets_1.26.40.5.h
cmake --build buildCopy build/resload.so into the launcher's mods/ directory.
| OS | Path |
|---|---|
| Linux | ~/.local/share/mcpelauncher/mods/ |
| macOS | ~/Library/Application Support/mcpelauncher/mods/ |
Menu bar, under resload:
| Entry | What it reloads |
|---|---|
| Reload everything | Textures, atlases, models, and UI |
| Reload UI only | JSON UI definitions. Fastest. |
| Reload geometry + animation | Entity geometry and animations |
Changes to existing files are picked up. Files added or deleted while the game is running are not; the pack repository is not rescanned.
Every offset is specific to one build of libminecraftpe.so. On any other
version the mod checks what the vtable slots actually point at, refuses to
patch anything, and logs why:
[resload] handleReloadUIDefinitions: slot 13 holds 0x..., expected 0x...
That is a clean refusal, not a crash. Supporting a new version means adding a
header to generated/.
The engine already has a full reload path; it runs when you change the pack
selection in settings. Three MinecraftGame virtuals cover it:
onActiveResourcePacksChanged(ResourcePackManager&)
handleReloadUIDefinitions()
reloadAnimationAndGeometryData(bool sync)
All three are virtual, so the mod only writes vtable slots. No inline hooking, no code generation.
It needs two instance pointers. MinecraftGame* arrives as this in a
per-frame vtable slot the mod hooks to get onto the game thread.
ResourcePackManager* is captured from its own vtable, because the game hands
it to listeners through the ResourcePackListener subobject, whose slot holds
a this-adjusting thunk that branches straight to the implementation, so hooking
the primary vtable slot never sees the call.
Menu clicks arrive on ImGui's thread. They set a flag, and the per-frame hook performs the reload on the game thread.
Run the launcher from a terminal to see the log. All output is prefixed
[resload].
| Message | Meaning |
|---|---|
slot N holds 0x..., expected 0x... |
Wrong game version for this build |
no menu support in this launcher build |
Launcher was built without ImGui |
no MinecraftGame captured yet |
Per-frame hook never fired; see RESLOAD_TICK_SLOT below |
RESLOAD_TICK_SLOT overrides which vtable slot is hooked for the per-frame
callback. It is the one value not derived from the binary, so it is settable
without a rebuild.