fix(runtime): route dropped item billboard atlas binds

This commit is contained in:
Jacobwasbeast
2026-03-07 20:54:17 -06:00
parent 0b4c87acbc
commit ed78317b96
5 changed files with 91 additions and 0 deletions

View File

@@ -29,6 +29,8 @@ namespace GameHooks
LoadUVs_fn Original_LoadUVs = nullptr;
RegisterIcon_fn Original_RegisterIcon = nullptr;
ItemInstanceGetIcon_fn Original_ItemInstanceGetIcon = nullptr;
EntityRendererBindTextureResource_fn Original_EntityRendererBindTextureResource = nullptr;
ItemRendererRenderItemBillboard_fn Original_ItemRendererRenderItemBillboard = nullptr;
ItemInstanceMineBlock_fn Original_ItemInstanceMineBlock = nullptr;
ItemMineBlock_fn Original_ItemMineBlock = nullptr;
ItemMineBlock_fn Original_DiggerItemMineBlock = nullptr;
@@ -71,6 +73,9 @@ namespace GameHooks
static int s_textureAtlasIdBlocks = -1;
static int s_textureAtlasIdItems = -1;
static thread_local bool s_inLoadTextureByNameHook = false;
static thread_local bool s_hasForcedBillboardRoute = false;
static thread_local int s_forcedBillboardAtlas = -1;
static thread_local int s_forcedBillboardPage = 0;
struct TextureNameArrayNative
{
@@ -1013,6 +1018,50 @@ namespace GameHooks
return icon;
}
void __fastcall Hooked_EntityRendererBindTextureResource(void* thisPtr, void* resourcePtr)
{
if (!Original_EntityRendererBindTextureResource)
return;
const int boundAtlas = DetectAtlasTypeFromResource(resourcePtr);
if (s_hasForcedBillboardRoute && resourcePtr && boundAtlas == s_forcedBillboardAtlas && s_forcedBillboardPage > 0)
{
EnsurePageResourcesInitialized();
const ResourceLocationNative* originalRes =
reinterpret_cast<const ResourceLocationNative*>(resourcePtr);
s_pageResource.textures = originalRes->textures;
s_pageResource.path = BuildVirtualAtlasPath(s_forcedBillboardAtlas, s_forcedBillboardPage);
s_pageResource.preloaded = false;
Original_EntityRendererBindTextureResource(thisPtr, &s_pageResource);
return;
}
Original_EntityRendererBindTextureResource(thisPtr, resourcePtr);
}
void __fastcall Hooked_ItemRendererRenderItemBillboard(void* thisPtr, void* entitySharedPtr, void* iconPtr, int count, float a, float red, float green, float blue)
{
const bool hadForcedRoute = s_hasForcedBillboardRoute;
const int prevAtlas = s_forcedBillboardAtlas;
const int prevPage = s_forcedBillboardPage;
int atlasType = -1;
int page = 0;
if (iconPtr && ModAtlas::TryGetIconRoute(iconPtr, atlasType, page) && page > 0)
{
s_hasForcedBillboardRoute = true;
s_forcedBillboardAtlas = atlasType;
s_forcedBillboardPage = page;
}
if (Original_ItemRendererRenderItemBillboard)
Original_ItemRendererRenderItemBillboard(thisPtr, entitySharedPtr, iconPtr, count, a, red, green, blue);
s_hasForcedBillboardRoute = hadForcedRoute;
s_forcedBillboardAtlas = prevAtlas;
s_forcedBillboardPage = prevPage;
}
void __fastcall Hooked_ItemInstanceMineBlock(void* thisPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr)
{
s_itemMineBlockHookCalls++;

View File

@@ -19,6 +19,8 @@ typedef void* (*GetResourceAsStream_fn)(const void* fileName);
typedef void (__fastcall *LoadUVs_fn)(void* thisPtr);
typedef void* (__fastcall *RegisterIcon_fn)(void* thisPtr, const std::wstring& name);
typedef void* (__fastcall *ItemInstanceGetIcon_fn)(void* thisPtr);
typedef void (__fastcall *EntityRendererBindTextureResource_fn)(void* thisPtr, void* resourcePtr);
typedef void (__fastcall *ItemRendererRenderItemBillboard_fn)(void* thisPtr, void* entitySharedPtr, void* iconPtr, int count, float a, float red, float green, float blue);
typedef void (__fastcall *ItemInstanceMineBlock_fn)(void* thisPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr);
typedef bool (__fastcall *ItemMineBlock_fn)(void* thisPtr, void* itemInstanceSharedPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr);
typedef bool (__fastcall *GameModeUseItem_fn)(void* thisPtr, void* playerSharedPtr, void* level, void* itemInstanceSharedPtr, bool bTestUseOnly);
@@ -53,6 +55,8 @@ namespace GameHooks
extern LoadUVs_fn Original_LoadUVs;
extern RegisterIcon_fn Original_RegisterIcon;
extern ItemInstanceGetIcon_fn Original_ItemInstanceGetIcon;
extern EntityRendererBindTextureResource_fn Original_EntityRendererBindTextureResource;
extern ItemRendererRenderItemBillboard_fn Original_ItemRendererRenderItemBillboard;
extern ItemInstanceMineBlock_fn Original_ItemInstanceMineBlock;
extern ItemMineBlock_fn Original_ItemMineBlock;
extern ItemMineBlock_fn Original_DiggerItemMineBlock;
@@ -80,6 +84,8 @@ namespace GameHooks
void __fastcall Hooked_LoadUVs(void* thisPtr);
void* __fastcall Hooked_RegisterIcon(void* thisPtr, const std::wstring& name);
void* __fastcall Hooked_ItemInstanceGetIcon(void* thisPtr);
void __fastcall Hooked_EntityRendererBindTextureResource(void* thisPtr, void* resourcePtr);
void __fastcall Hooked_ItemRendererRenderItemBillboard(void* thisPtr, void* entitySharedPtr, void* iconPtr, int count, float a, float red, float green, float blue);
void __fastcall Hooked_ItemInstanceMineBlock(void* thisPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr);
bool __fastcall Hooked_ItemMineBlock(void* thisPtr, void* itemInstanceSharedPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr);
bool __fastcall Hooked_DiggerItemMineBlock(void* thisPtr, void* itemInstanceSharedPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr);

View File

@@ -96,6 +96,34 @@ bool HookManager::Install(const SymbolResolver& symbols)
}
}
if (symbols.pEntityRendererBindTextureResource)
{
if (MH_CreateHook(symbols.pEntityRendererBindTextureResource,
reinterpret_cast<void*>(&GameHooks::Hooked_EntityRendererBindTextureResource),
reinterpret_cast<void**>(&GameHooks::Original_EntityRendererBindTextureResource)) != MH_OK)
{
LogUtil::Log("[WeaveLoader] Warning: Failed to hook EntityRenderer::bindTexture(ResourceLocation)");
}
else
{
LogUtil::Log("[WeaveLoader] Hooked EntityRenderer::bindTexture(ResourceLocation) (dropped item atlas routing)");
}
}
if (symbols.pItemRendererRenderItemBillboard)
{
if (MH_CreateHook(symbols.pItemRendererRenderItemBillboard,
reinterpret_cast<void*>(&GameHooks::Hooked_ItemRendererRenderItemBillboard),
reinterpret_cast<void**>(&GameHooks::Original_ItemRendererRenderItemBillboard)) != MH_OK)
{
LogUtil::Log("[WeaveLoader] Warning: Failed to hook ItemRenderer::renderItemBillboard");
}
else
{
LogUtil::Log("[WeaveLoader] Hooked ItemRenderer::renderItemBillboard (dropped item atlas routing)");
}
}
if (symbols.pItemMineBlock)
{
if (MH_CreateHook(symbols.pItemMineBlock,

View File

@@ -19,6 +19,8 @@ static const char* SYM_SIMPLE_ICON_CTOR = "??0SimpleIcon@@QEAA@AEBV?$basic_strin
static const char* SYM_OPERATOR_NEW = "??2@YAPEAX_K@Z";
static const char* SYM_REGISTER_ICON = "?registerIcon@PreStitchedTextureMap@@UEAAPEAVIcon@@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z";
static const char* SYM_ITEMINSTANCE_GETICON = "?getIcon@ItemInstance@@QEAAPEAVIcon@@XZ";
static const char* SYM_ENTITYRENDERER_BINDTEXTURE_RESOURCE = "?bindTexture@EntityRenderer@@MEAAXPEAVResourceLocation@@@Z";
static const char* SYM_ITEMRENDERER_RENDERITEMBILLBOARD = "?renderItemBillboard@ItemRenderer@@EEAAXV?$shared_ptr@VItemEntity@@@std@@PEAVIcon@@HMMMM@Z";
static const char* SYM_ITEMINSTANCE_MINEBLOCK = "?mineBlock@ItemInstance@@QEAAXPEAVLevel@@HHHHV?$shared_ptr@VPlayer@@@std@@@Z";
static const char* SYM_ITEM_MINEBLOCK = "?mineBlock@Item@@UEAA_NV?$shared_ptr@VItemInstance@@@std@@PEAVLevel@@HHHHV?$shared_ptr@VLivingEntity@@@3@@Z";
static const char* SYM_DIGGERITEM_MINEBLOCK = "?mineBlock@DiggerItem@@UEAA_NV?$shared_ptr@VItemInstance@@@std@@PEAVLevel@@HHHHV?$shared_ptr@VLivingEntity@@@3@@Z";
@@ -118,6 +120,8 @@ bool SymbolResolver::ResolveGameFunctions()
pOperatorNew = Resolve(SYM_OPERATOR_NEW);
pRegisterIcon = Resolve(SYM_REGISTER_ICON);
pItemInstanceGetIcon = Resolve(SYM_ITEMINSTANCE_GETICON);
pEntityRendererBindTextureResource = Resolve(SYM_ENTITYRENDERER_BINDTEXTURE_RESOURCE);
pItemRendererRenderItemBillboard = Resolve(SYM_ITEMRENDERER_RENDERITEMBILLBOARD);
pItemInstanceMineBlock = Resolve(SYM_ITEMINSTANCE_MINEBLOCK);
pItemMineBlock = Resolve(SYM_ITEM_MINEBLOCK);
pDiggerItemMineBlock = Resolve(SYM_DIGGERITEM_MINEBLOCK);
@@ -175,6 +179,8 @@ bool SymbolResolver::ResolveGameFunctions()
logSym("operator new", pOperatorNew);
logSym("registerIcon", pRegisterIcon);
logSym("ItemInstance::getIcon", pItemInstanceGetIcon);
logSym("EntityRenderer::bindTexture(ResourceLocation)", pEntityRendererBindTextureResource);
logSym("ItemRenderer::renderItemBillboard", pItemRendererRenderItemBillboard);
logSym("ItemInstance::mineBlock", pItemInstanceMineBlock);
logSym("Item::mineBlock", pItemMineBlock);
logSym("DiggerItem::mineBlock", pDiggerItemMineBlock);

View File

@@ -24,6 +24,8 @@ public:
void* pOperatorNew = nullptr; // global operator new(size_t) - for texture injection
void* pRegisterIcon = nullptr; // PreStitchedTextureMap::registerIcon(const wstring&)
void* pItemInstanceGetIcon = nullptr; // ItemInstance::getIcon()
void* pEntityRendererBindTextureResource = nullptr; // EntityRenderer::bindTexture(ResourceLocation*)
void* pItemRendererRenderItemBillboard = nullptr; // ItemRenderer::renderItemBillboard(shared_ptr<ItemEntity>,Icon*,...)
void* pItemInstanceMineBlock = nullptr; // ItemInstance::mineBlock(Level*,int,int,int,int,shared_ptr<Player>)
void* pItemMineBlock = nullptr; // Item::mineBlock(shared_ptr<ItemInstance>,Level*,int,int,int,int,shared_ptr<LivingEntity>)
void* pDiggerItemMineBlock = nullptr; // DiggerItem::mineBlock(shared_ptr<ItemInstance>,Level*,int,int,int,int,shared_ptr<LivingEntity>)