From 7111d8308268e3d405736c5e499cce9fb6af5a56 Mon Sep 17 00:00:00 2001 From: Jacobwasbeast Date: Wed, 11 Mar 2026 22:39:02 -0500 Subject: [PATCH] fix(rotation): compute placement data before setTile --- WeaveLoaderRuntime/src/GameHooks.cpp | 73 ++++++++++++------- WeaveLoaderRuntime/src/GameHooks.h | 3 + WeaveLoaderRuntime/src/HookManager.cpp | 14 ++++ .../src/Symbols/SymbolGroups.cpp | 3 + WeaveLoaderRuntime/src/Symbols/SymbolGroups.h | 1 + 5 files changed, 67 insertions(+), 27 deletions(-) diff --git a/WeaveLoaderRuntime/src/GameHooks.cpp b/WeaveLoaderRuntime/src/GameHooks.cpp index 0d55dd4..d0e6aab 100644 --- a/WeaveLoaderRuntime/src/GameHooks.cpp +++ b/WeaveLoaderRuntime/src/GameHooks.cpp @@ -76,6 +76,7 @@ namespace GameHooks LevelGetData_fn Level_GetData = nullptr; ServerLevelTickPendingTicks_fn Original_ServerLevelTickPendingTicks = nullptr; TileGetResource_fn Original_TileGetResource = nullptr; + TileGetPlacedOnFaceDataValue_fn Original_TileGetPlacedOnFaceDataValue = nullptr; McRegionChunkStorageLoad_fn Original_McRegionChunkStorageLoad = nullptr; McRegionChunkStorageSave_fn Original_McRegionChunkStorageSave = nullptr; TileCloneTileId_fn Original_TileCloneTileId = nullptr; @@ -1909,21 +1910,8 @@ namespace GameHooks bool __fastcall Hooked_LevelSetTileAndData(void* thisPtr, int x, int y, int z, int tile, int data, int updateFlags) { const int oldBlockId = s_levelGetTile ? s_levelGetTile(thisPtr, x, y, z) : -1; - const bool result = Original_LevelSetTileAndData - ? Original_LevelSetTileAndData(thisPtr, x, y, z, tile, data, updateFlags) - : false; - - if (result && s_levelGetTile) - WorldIdRemap::MarkChunkDirtyByBlockUpdate(x, z, oldBlockId, tile); - - if (result && tile > 0) - DispatchManagedBlockById(tile, thisPtr, x, y, z, 0, 0); - - bool isClientSide = false; - if (thisPtr && IsReadableRange(static_cast(thisPtr) + kLevelIsClientSideOffset, sizeof(bool))) - isClientSide = *reinterpret_cast(static_cast(thisPtr) + kLevelIsClientSideOffset); - - if (result && tile > 0 && Original_LevelSetData && !isClientSide) + int effectiveData = data; + if (tile > 0) { const int profile = ModelRegistry::GetRotationProfile(tile); if (profile == 1 || profile == 3) @@ -1939,18 +1927,14 @@ namespace GameHooks float yaw = 0.0f; if (TryGetEntityYaw(playerPtr, yaw)) { - int newData = data; if (profile == 1) - newData = ComputeFacingDataFromYaw(yaw); + effectiveData = ComputeFacingDataFromYaw(yaw); else - newData = ComputeStandingSignDataFromYaw(yaw); - - if (newData != data) - Original_LevelSetData(thisPtr, x, y, z, newData, updateFlags, false); + effectiveData = ComputeStandingSignDataFromYaw(yaw); if (s_rotationLogCount < 20) { - LogUtil::Log("[WeaveLoader] Rotation: yaw=%.2f data=%d -> %d", yaw, data, newData); + LogUtil::Log("[WeaveLoader] Rotation: yaw=%.2f data=%d -> %d", yaw, data, effectiveData); s_rotationLogCount++; } } @@ -1968,6 +1952,16 @@ namespace GameHooks } } + const bool result = Original_LevelSetTileAndData + ? Original_LevelSetTileAndData(thisPtr, x, y, z, tile, effectiveData, updateFlags) + : false; + + if (result && s_levelGetTile) + WorldIdRemap::MarkChunkDirtyByBlockUpdate(x, z, oldBlockId, tile); + + if (result && tile > 0) + DispatchManagedBlockById(tile, thisPtr, x, y, z, 0, 0); + return result; } @@ -2068,6 +2062,35 @@ namespace GameHooks return Original_TileGetResource ? Original_TileGetResource(thisPtr, data, random, playerBonusLevel) : 0; } + int __fastcall Hooked_TileGetPlacedOnFaceDataValue(void* thisPtr, void* levelPtr, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue) + { + int result = Original_TileGetPlacedOnFaceDataValue + ? Original_TileGetPlacedOnFaceDataValue(thisPtr, levelPtr, x, y, z, face, clickX, clickY, clickZ, itemValue) + : itemValue; + + int tileId = GetTileId(thisPtr); + if (tileId < 0) + return result; + + const int profile = ModelRegistry::GetRotationProfile(tileId); + if (profile == 1 || profile == 3) + { + void* playerPtr = nullptr; + if (TryGetPlacementPlayer(levelPtr, playerPtr)) + { + float yaw = 0.0f; + if (TryGetEntityYaw(playerPtr, yaw)) + { + return profile == 1 + ? ComputeFacingDataFromYaw(yaw) + : ComputeStandingSignDataFromYaw(yaw); + } + } + } + + return result; + } + int __fastcall Hooked_TileCloneTileId(void* thisPtr, void* level, int x, int y, int z) { const ManagedBlockRegistry::Definition* def = ManagedBlockRegistry::Find(TryReadTileId(thisPtr)); @@ -2734,11 +2757,7 @@ namespace GameHooks bool __fastcall Hooked_ItemInstanceUseOn(void* thisPtr, void* playerSharedPtr, void* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly) { - bool isClientSide = false; - if (level && IsReadableRange(static_cast(level) + kLevelIsClientSideOffset, sizeof(bool))) - isClientSide = *reinterpret_cast(static_cast(level) + kLevelIsClientSideOffset); - - if (!bTestUseOnOnly && !isClientSide) + if (!bTestUseOnOnly) { void* playerPtr = DecodePlayerPtrFromSharedArg(playerSharedPtr); if (playerPtr) diff --git a/WeaveLoaderRuntime/src/GameHooks.h b/WeaveLoaderRuntime/src/GameHooks.h index e4448e9..fd45466 100644 --- a/WeaveLoaderRuntime/src/GameHooks.h +++ b/WeaveLoaderRuntime/src/GameHooks.h @@ -43,6 +43,7 @@ typedef int (__fastcall *LevelGetData_fn)(void* thisPtr, int x, int y, int z); typedef void* (__fastcall *McRegionChunkStorageLoad_fn)(void* thisPtr, void* level, int x, int z); typedef void (__fastcall *McRegionChunkStorageSave_fn)(void* thisPtr, void* level, void* levelChunk); typedef int (__fastcall *TileGetResource_fn)(void* thisPtr, int data, void* random, int playerBonusLevel); +typedef int (__fastcall *TileGetPlacedOnFaceDataValue_fn)(void* thisPtr, void* levelPtr, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue); typedef int (__fastcall *TileCloneTileId_fn)(void* thisPtr, void* level, int x, int y, int z); typedef void* (__fastcall *TileGetTextureFaceData_fn)(void* thisPtr, int face, int data); typedef unsigned int (__fastcall *TileGetDescriptionId_fn)(void* thisPtr, int data); @@ -137,6 +138,7 @@ namespace GameHooks extern LevelGetData_fn Level_GetData; extern ServerLevelTickPendingTicks_fn Original_ServerLevelTickPendingTicks; extern TileGetResource_fn Original_TileGetResource; + extern TileGetPlacedOnFaceDataValue_fn Original_TileGetPlacedOnFaceDataValue; extern McRegionChunkStorageLoad_fn Original_McRegionChunkStorageLoad; extern McRegionChunkStorageSave_fn Original_McRegionChunkStorageSave; extern TileCloneTileId_fn Original_TileCloneTileId; @@ -230,6 +232,7 @@ namespace GameHooks bool __fastcall Hooked_LevelSetData(void* thisPtr, int x, int y, int z, int data, int updateFlags, bool forceUpdate); void __fastcall Hooked_LevelUpdateNeighborsAt(void* thisPtr, int x, int y, int z, int type); bool __fastcall Hooked_ServerLevelTickPendingTicks(void* thisPtr, bool force); + int __fastcall Hooked_TileGetPlacedOnFaceDataValue(void* thisPtr, void* levelPtr, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue); void* __fastcall Hooked_McRegionChunkStorageLoad(void* thisPtr, void* level, int x, int z); void __fastcall Hooked_McRegionChunkStorageSave(void* thisPtr, void* level, void* levelChunk); int __fastcall Hooked_TileGetResource(void* thisPtr, int data, void* random, int playerBonusLevel); diff --git a/WeaveLoaderRuntime/src/HookManager.cpp b/WeaveLoaderRuntime/src/HookManager.cpp index 06b2031..f45a601 100644 --- a/WeaveLoaderRuntime/src/HookManager.cpp +++ b/WeaveLoaderRuntime/src/HookManager.cpp @@ -492,6 +492,20 @@ bool HookManager::Install(const SymbolResolver& symbols) } } + if (symbols.Tile.pTileGetPlacedOnFaceDataValue) + { + if (MH_CreateHook(symbols.Tile.pTileGetPlacedOnFaceDataValue, + reinterpret_cast(&GameHooks::Hooked_TileGetPlacedOnFaceDataValue), + reinterpret_cast(&GameHooks::Original_TileGetPlacedOnFaceDataValue)) != MH_OK) + { + LogUtil::Log("[WeaveLoader] Warning: Failed to hook Tile::getPlacedOnFaceDataValue"); + } + else + { + LogUtil::Log("[WeaveLoader] Hooked Tile::getPlacedOnFaceDataValue (rotation placement)"); + } + } + if (symbols.Tile.pTileCloneTileId) { if (MH_CreateHook(symbols.Tile.pTileCloneTileId, diff --git a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp index 5f9ac66..3699ad0 100644 --- a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp +++ b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.cpp @@ -78,6 +78,7 @@ namespace static const char* SYM_TILE_NEIGHBORCHANGED = "?neighborChanged@Tile@@UEAAXPEAVLevel@@HHHH@Z"; static const char* SYM_TILE_TICK = "?tick@Tile@@UEAAXPEAVLevel@@HHHPEAVRandom@@@Z"; static const char* SYM_TILE_GETRESOURCE = "?getResource@Tile@@UEAAHHPEAVRandom@@H@Z"; + static const char* SYM_TILE_GETPLACEDONFACEDATAVALUE = "?getPlacedOnFaceDataValue@Tile@@UEAAHPEAVLevel@@HHHHMMMH@Z"; static const char* SYM_TILE_CLONETILEID = "?cloneTileId@Tile@@UEAAHPEAVLevel@@HHH@Z"; static const char* SYM_TILE_GETTEXTURE_FACEDATA = "?getTexture@Tile@@UEAAPEAVIcon@@HH@Z"; static const char* SYM_STONESLAB_GETTEXTURE = "?getTexture@StoneSlabTile@@UEAAPEAVIcon@@HH@Z"; @@ -339,6 +340,7 @@ bool TileSymbols::Resolve(SymbolResolver& resolver) pTileNeighborChanged = resolver.Resolve(SYM_TILE_NEIGHBORCHANGED); pTileTick = resolver.Resolve(SYM_TILE_TICK); pTileGetResource = resolver.Resolve(SYM_TILE_GETRESOURCE); + pTileGetPlacedOnFaceDataValue = resolver.Resolve(SYM_TILE_GETPLACEDONFACEDATAVALUE); pTileCloneTileId = resolver.Resolve(SYM_TILE_CLONETILEID); pTileGetTextureFaceData = resolver.Resolve(SYM_TILE_GETTEXTURE_FACEDATA); pStoneSlabGetTexture = resolver.Resolve(SYM_STONESLAB_GETTEXTURE); @@ -390,6 +392,7 @@ void TileSymbols::Log() const LogSym("Tile::neighborChanged", pTileNeighborChanged); LogSym("Tile::tick", pTileTick); LogSym("Tile::getResource", pTileGetResource); + LogSym("Tile::getPlacedOnFaceDataValue", pTileGetPlacedOnFaceDataValue); LogSym("Tile::cloneTileId", pTileCloneTileId); LogSym("Tile::getTexture(face,data)", pTileGetTextureFaceData); LogSym("StoneSlabTile::getTexture", pStoneSlabGetTexture); diff --git a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h index ad8da28..8a3d138 100644 --- a/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h +++ b/WeaveLoaderRuntime/src/Symbols/SymbolGroups.h @@ -98,6 +98,7 @@ struct TileSymbols void* pTileNeighborChanged = nullptr; void* pTileTick = nullptr; void* pTileGetResource = nullptr; + void* pTileGetPlacedOnFaceDataValue = nullptr; void* pTileCloneTileId = nullptr; void* pTileGetTextureFaceData = nullptr; void* pStoneSlabGetTexture = nullptr;