diff --git a/WeaveLoaderRuntime/src/GameHooks.cpp b/WeaveLoaderRuntime/src/GameHooks.cpp index bc098c2..64da674 100644 --- a/WeaveLoaderRuntime/src/GameHooks.cpp +++ b/WeaveLoaderRuntime/src/GameHooks.cpp @@ -110,6 +110,7 @@ namespace GameHooks TileRendererTesselateBlockInWorld_fn TileRenderer_TesselateBlockInWorld = nullptr; TileRendererSetShape_fn TileRenderer_SetShape = nullptr; TileRendererSetShapeTile_fn TileRenderer_SetShapeTile = nullptr; + TileRendererRenderTile_fn Original_TileRendererRenderTile = nullptr; TileSetShape_fn Tile_SetShape = nullptr; AABBNewTemp_fn AABB_NewTemp = nullptr; AABBClip_fn AABB_Clip = nullptr; @@ -389,6 +390,7 @@ namespace GameHooks return rendered; } + } static int s_itemMineBlockHookCalls = 0; static void* s_currentLevel = nullptr; @@ -475,6 +477,9 @@ namespace GameHooks static bool s_preInitCalled = false; static bool s_initCalled = false; static bool s_postInitCalled = false; + static thread_local bool s_inventoryShapeOverrideActive = false; + static thread_local void* s_inventoryShapeOverrideTile = nullptr; + static thread_local ModelBox s_inventoryShapeOverrideBox{}; static void EnsurePageResourcesInitialized() { @@ -3033,6 +3038,32 @@ namespace GameHooks : false; } + void __fastcall Hooked_TileRendererRenderTile(void* thisPtr, void* tilePtr, int data, float brightness, float fAlpha, bool useCompiled) + { + const std::vector* boxes = nullptr; + int tileId = GetTileId(tilePtr); + if (tileId >= 0 && ModelRegistry::TryGetModel(tileId, boxes) && boxes && !boxes->empty()) + { + if (Original_TileRendererRenderTile && Tile_SetShape) + { + s_inventoryShapeOverrideTile = tilePtr; + s_inventoryShapeOverrideActive = true; + for (const auto& box : *boxes) + { + s_inventoryShapeOverrideBox = box; + Original_TileRendererRenderTile(thisPtr, tilePtr, data, brightness, fAlpha, useCompiled); + } + s_inventoryShapeOverrideActive = false; + s_inventoryShapeOverrideTile = nullptr; + Hooked_TileUpdateDefaultShape(tilePtr); + return; + } + } + + if (Original_TileRendererRenderTile) + Original_TileRendererRenderTile(thisPtr, tilePtr, data, brightness, fAlpha, useCompiled); + } + void __fastcall Hooked_TileAddAABBs(void* thisPtr, void* levelPtr, int x, int y, int z, void* boxPtr, void* boxesPtr, void* sourcePtr) { const std::vector* boxes = nullptr; @@ -3074,6 +3105,19 @@ namespace GameHooks void __fastcall Hooked_TileUpdateDefaultShape(void* thisPtr) { + if (s_inventoryShapeOverrideActive && s_inventoryShapeOverrideTile == thisPtr && Tile_SetShape) + { + const ModelBox& box = s_inventoryShapeOverrideBox; + const float bx0 = box.x0 < box.x1 ? box.x0 : box.x1; + const float by0 = box.y0 < box.y1 ? box.y0 : box.y1; + const float bz0 = box.z0 < box.z1 ? box.z0 : box.z1; + const float bx1 = box.x0 < box.x1 ? box.x1 : box.x0; + const float by1 = box.y0 < box.y1 ? box.y1 : box.y0; + const float bz1 = box.z0 < box.z1 ? box.z1 : box.z0; + Tile_SetShape(thisPtr, bx0, by0, bz0, bx1, by1, bz1); + return; + } + const std::vector* boxes = nullptr; int tileId = GetTileId(thisPtr); if (tileId >= 0 && ModelRegistry::TryGetModel(tileId, boxes) && boxes && !boxes->empty() && Tile_SetShape) diff --git a/WeaveLoaderRuntime/src/GameHooks.h b/WeaveLoaderRuntime/src/GameHooks.h index 275a142..d239bb2 100644 --- a/WeaveLoaderRuntime/src/GameHooks.h +++ b/WeaveLoaderRuntime/src/GameHooks.h @@ -75,6 +75,7 @@ typedef bool (__fastcall *TileRendererTesselateInWorld_fn)(void* thisPtr, void* typedef bool (__fastcall *TileRendererTesselateBlockInWorld_fn)(void* thisPtr, void* tilePtr, int x, int y, int z); typedef void (__fastcall *TileRendererSetShape_fn)(void* thisPtr, float x0, float y0, float z0, float x1, float y1, float z1); typedef void (__fastcall *TileRendererSetShapeTile_fn)(void* thisPtr, void* tilePtr); +typedef void (__fastcall *TileRendererRenderTile_fn)(void* thisPtr, void* tilePtr, int data, float brightness, float fAlpha, bool useCompiled); typedef void (__fastcall *TileSetShape_fn)(void* thisPtr, float x0, float y0, float z0, float x1, float y1, float z1); typedef void (__fastcall *TileAddAABBs_fn)(void* thisPtr, void* levelPtr, int x, int y, int z, void* boxPtr, void* boxesPtr, void* sourcePtr); typedef void (__fastcall *TileUpdateDefaultShape_fn)(void* thisPtr); @@ -168,6 +169,7 @@ namespace GameHooks extern TileRendererTesselateBlockInWorld_fn TileRenderer_TesselateBlockInWorld; extern TileRendererSetShape_fn TileRenderer_SetShape; extern TileRendererSetShapeTile_fn TileRenderer_SetShapeTile; + extern TileRendererRenderTile_fn Original_TileRendererRenderTile; extern TileSetShape_fn Tile_SetShape; extern AABBNewTemp_fn AABB_NewTemp; extern AABBClip_fn AABB_Clip; @@ -262,6 +264,7 @@ namespace GameHooks void* __fastcall Hooked_TileClip(void* thisPtr, void* levelPtr, int x, int y, int z, void* aPtr, void* bPtr); void* __fastcall Hooked_LevelClip(void* thisPtr, void* aPtr, void* bPtr, bool liquid, bool solidOnly); void* __fastcall Hooked_LivingEntityPick(void* thisPtr, double range, float partialTicks); + void __fastcall Hooked_TileRendererRenderTile(void* thisPtr, void* tilePtr, int data, float brightness, float fAlpha, bool useCompiled); void SetAtlasLocationPointers(void* blocksLocation, void* itemsLocation); void SetTileTilesArray(void* tilesArray); void SetSummonSymbols(void* levelAddEntity, diff --git a/WeaveLoaderRuntime/src/HookManager.cpp b/WeaveLoaderRuntime/src/HookManager.cpp index f6244ec..1764b73 100644 --- a/WeaveLoaderRuntime/src/HookManager.cpp +++ b/WeaveLoaderRuntime/src/HookManager.cpp @@ -562,6 +562,20 @@ bool HookManager::Install(const SymbolResolver& symbols) } } + if (symbols.Tile.pTileRendererRenderTile) + { + if (MH_CreateHook(symbols.Tile.pTileRendererRenderTile, + reinterpret_cast(&GameHooks::Hooked_TileRendererRenderTile), + reinterpret_cast(&GameHooks::Original_TileRendererRenderTile)) != MH_OK) + { + LogUtil::Log("[WeaveLoader] Warning: Failed to hook TileRenderer::renderTile"); + } + else + { + LogUtil::Log("[WeaveLoader] Hooked TileRenderer::renderTile (block models in inventory)"); + } + } + if (symbols.Tile.pStoneSlabGetTexture) { if (MH_CreateHook(symbols.Tile.pStoneSlabGetTexture, diff --git a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp index fa6d836..0c0001b 100644 --- a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp +++ b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp @@ -107,6 +107,7 @@ namespace static const char* SYM_TILERENDERER_TESSELLATE_BLOCK_IN_WORLD = "?tesselateBlockInWorld@TileRenderer@@QEAA_NPEAVTile@@HHH@Z"; static const char* SYM_TILERENDERER_SET_SHAPE = "?setShape@TileRenderer@@QEAAXMMMMMM@Z"; static const char* SYM_TILERENDERER_SET_SHAPE_TILE = "?setShape@TileRenderer@@QEAAXPEAVTile@@@Z"; + static const char* SYM_TILERENDERER_RENDER_TILE = "?renderTile@TileRenderer@@QEAAXPEAVTile@@HMM_N@Z"; static const char* SYM_LEVEL_UPDATE_NEIGHBORS_AT = "?updateNeighborsAt@Level@@QEAAXHHHH@Z"; static const char* SYM_SERVERLEVEL_TICKPENDINGTICKS = "?tickPendingTicks@ServerLevel@@UEAA_N_N@Z"; @@ -360,6 +361,7 @@ bool TileSymbols::Resolve(SymbolResolver& resolver) pTileRendererTesselateBlockInWorld = resolver.Resolve(SYM_TILERENDERER_TESSELLATE_BLOCK_IN_WORLD); pTileRendererSetShape = resolver.Resolve(SYM_TILERENDERER_SET_SHAPE); pTileRendererSetShapeTile = resolver.Resolve(SYM_TILERENDERER_SET_SHAPE_TILE); + pTileRendererRenderTile = resolver.Resolve(SYM_TILERENDERER_RENDER_TILE); if (resolver.IsStub(pTileOnPlace)) pTileOnPlace = resolver.ResolveExact("Tile::onPlace"); @@ -410,6 +412,7 @@ void TileSymbols::Log() const LogSym("TileRenderer::tesselateBlockInWorld", pTileRendererTesselateBlockInWorld); LogSym("TileRenderer::setShape(float)", pTileRendererSetShape); LogSym("TileRenderer::setShape(Tile)", pTileRendererSetShapeTile); + LogSym("TileRenderer::renderTile", pTileRendererRenderTile); } bool LevelSymbols::Resolve(SymbolResolver& resolver) diff --git a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h index ae46461..369a279 100644 --- a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h +++ b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h @@ -127,6 +127,7 @@ struct TileSymbols void* pTileRendererTesselateBlockInWorld = nullptr; void* pTileRendererSetShape = nullptr; void* pTileRendererSetShapeTile = nullptr; + void* pTileRendererRenderTile = nullptr; bool Resolve(SymbolResolver& resolver); void Log() const;