mirror of
https://github.com/Jacobwasbeast/LegacyWeaveLoader.git
synced 2026-06-16 09:44:55 +00:00
fix(runtime): guard animated texture crashes
This commit is contained in:
@@ -88,6 +88,24 @@ static bool IsFatalException(DWORD code)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ShouldWriteVectoredReport(EXCEPTION_RECORD* er)
|
||||
{
|
||||
if (!er)
|
||||
return false;
|
||||
|
||||
switch (er->ExceptionCode)
|
||||
{
|
||||
case STATUS_STACK_BUFFER_OVERRUN:
|
||||
case STATUS_INVALID_CRUNTIME_PARAMETER:
|
||||
case STATUS_FAIL_FAST_EXCEPTION:
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void GetModuleForAddr(DWORD64 addr, char* nameBuf, size_t nameBufSize, DWORD64* outBase)
|
||||
{
|
||||
*outBase = 0;
|
||||
@@ -353,7 +371,16 @@ static LONG WINAPI VectoredHandler(EXCEPTION_POINTERS* ep)
|
||||
if (!IsFatalException(code))
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
WriteCrashReport("VectoredExceptionHandler", ep->ExceptionRecord, ep->ContextRecord);
|
||||
// TODO: Remove this suppression once the animated texture pack fault is fixed
|
||||
// at the source. For now, a vectored handler sees first-chance exceptions
|
||||
// before local __try/__except blocks run, and logging those handled faults
|
||||
// as crashes causes severe log spam and stalls under Windows.
|
||||
//
|
||||
// Keep vectored reporting only for fail-fast/noncontinuable cases that will
|
||||
// not normally make it to the top-level unhandled filter.
|
||||
if (ShouldWriteVectoredReport(ep->ExceptionRecord))
|
||||
WriteCrashReport("VectoredExceptionHandler", ep->ExceptionRecord, ep->ContextRecord);
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,12 @@ namespace GameHooks
|
||||
ItemInstanceGetIcon_fn Original_ItemInstanceGetIcon = nullptr;
|
||||
EntityRendererBindTextureResource_fn Original_EntityRendererBindTextureResource = nullptr;
|
||||
ItemRendererRenderItemBillboard_fn Original_ItemRendererRenderItemBillboard = nullptr;
|
||||
AnimatedTextureCycleFrames_fn Original_CompassTextureCycleFrames = nullptr;
|
||||
AnimatedTextureCycleFrames_fn Original_ClockTextureCycleFrames = nullptr;
|
||||
TextureGetSourceDim_fn Original_CompassTextureGetSourceWidth = nullptr;
|
||||
TextureGetSourceDim_fn Original_CompassTextureGetSourceHeight = nullptr;
|
||||
TextureGetSourceDim_fn Original_ClockTextureGetSourceWidth = nullptr;
|
||||
TextureGetSourceDim_fn Original_ClockTextureGetSourceHeight = nullptr;
|
||||
ItemInstanceMineBlock_fn Original_ItemInstanceMineBlock = nullptr;
|
||||
ItemMineBlock_fn Original_ItemMineBlock = nullptr;
|
||||
ItemMineBlock_fn Original_DiggerItemMineBlock = nullptr;
|
||||
@@ -76,6 +82,7 @@ namespace GameHooks
|
||||
static thread_local bool s_hasForcedBillboardRoute = false;
|
||||
static thread_local int s_forcedBillboardAtlas = -1;
|
||||
static thread_local int s_forcedBillboardPage = 0;
|
||||
static int s_animatedTextureGuardLogCount = 0;
|
||||
|
||||
struct TextureNameArrayNative
|
||||
{
|
||||
@@ -1062,6 +1069,102 @@ namespace GameHooks
|
||||
s_forcedBillboardPage = prevPage;
|
||||
}
|
||||
|
||||
static void LogAnimatedTextureGuard(const char* what, void* thisPtr)
|
||||
{
|
||||
if (s_animatedTextureGuardLogCount >= 12)
|
||||
return;
|
||||
LogUtil::Log("[WeaveLoader] AnimatedTextureGuard: %s fallback for %p", what, thisPtr);
|
||||
s_animatedTextureGuardLogCount++;
|
||||
}
|
||||
|
||||
void __fastcall Hooked_CompassTextureCycleFrames(void* thisPtr)
|
||||
{
|
||||
if (!Original_CompassTextureCycleFrames)
|
||||
return;
|
||||
__try
|
||||
{
|
||||
Original_CompassTextureCycleFrames(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("CompassTexture::cycleFrames", thisPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall Hooked_ClockTextureCycleFrames(void* thisPtr)
|
||||
{
|
||||
if (!Original_ClockTextureCycleFrames)
|
||||
return;
|
||||
__try
|
||||
{
|
||||
Original_ClockTextureCycleFrames(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("ClockTexture::cycleFrames", thisPtr);
|
||||
}
|
||||
}
|
||||
|
||||
int __fastcall Hooked_CompassTextureGetSourceWidth(void* thisPtr)
|
||||
{
|
||||
if (!Original_CompassTextureGetSourceWidth)
|
||||
return 16;
|
||||
__try
|
||||
{
|
||||
return Original_CompassTextureGetSourceWidth(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("CompassTexture::getSourceWidth", thisPtr);
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
int __fastcall Hooked_CompassTextureGetSourceHeight(void* thisPtr)
|
||||
{
|
||||
if (!Original_CompassTextureGetSourceHeight)
|
||||
return 16;
|
||||
__try
|
||||
{
|
||||
return Original_CompassTextureGetSourceHeight(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("CompassTexture::getSourceHeight", thisPtr);
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
int __fastcall Hooked_ClockTextureGetSourceWidth(void* thisPtr)
|
||||
{
|
||||
if (!Original_ClockTextureGetSourceWidth)
|
||||
return 16;
|
||||
__try
|
||||
{
|
||||
return Original_ClockTextureGetSourceWidth(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("ClockTexture::getSourceWidth", thisPtr);
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
int __fastcall Hooked_ClockTextureGetSourceHeight(void* thisPtr)
|
||||
{
|
||||
if (!Original_ClockTextureGetSourceHeight)
|
||||
return 16;
|
||||
__try
|
||||
{
|
||||
return Original_ClockTextureGetSourceHeight(thisPtr);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LogAnimatedTextureGuard("ClockTexture::getSourceHeight", thisPtr);
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall Hooked_ItemInstanceMineBlock(void* thisPtr, void* level, int tile, int x, int y, int z, void* ownerSharedPtr)
|
||||
{
|
||||
s_itemMineBlockHookCalls++;
|
||||
|
||||
@@ -21,6 +21,8 @@ typedef void* (__fastcall *RegisterIcon_fn)(void* thisPtr, const std::wstring& n
|
||||
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 *AnimatedTextureCycleFrames_fn)(void* thisPtr);
|
||||
typedef int (__fastcall *TextureGetSourceDim_fn)(void* thisPtr);
|
||||
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);
|
||||
@@ -57,6 +59,12 @@ namespace GameHooks
|
||||
extern ItemInstanceGetIcon_fn Original_ItemInstanceGetIcon;
|
||||
extern EntityRendererBindTextureResource_fn Original_EntityRendererBindTextureResource;
|
||||
extern ItemRendererRenderItemBillboard_fn Original_ItemRendererRenderItemBillboard;
|
||||
extern AnimatedTextureCycleFrames_fn Original_CompassTextureCycleFrames;
|
||||
extern AnimatedTextureCycleFrames_fn Original_ClockTextureCycleFrames;
|
||||
extern TextureGetSourceDim_fn Original_CompassTextureGetSourceWidth;
|
||||
extern TextureGetSourceDim_fn Original_CompassTextureGetSourceHeight;
|
||||
extern TextureGetSourceDim_fn Original_ClockTextureGetSourceWidth;
|
||||
extern TextureGetSourceDim_fn Original_ClockTextureGetSourceHeight;
|
||||
extern ItemInstanceMineBlock_fn Original_ItemInstanceMineBlock;
|
||||
extern ItemMineBlock_fn Original_ItemMineBlock;
|
||||
extern ItemMineBlock_fn Original_DiggerItemMineBlock;
|
||||
@@ -86,6 +94,12 @@ namespace GameHooks
|
||||
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_CompassTextureCycleFrames(void* thisPtr);
|
||||
void __fastcall Hooked_ClockTextureCycleFrames(void* thisPtr);
|
||||
int __fastcall Hooked_CompassTextureGetSourceWidth(void* thisPtr);
|
||||
int __fastcall Hooked_CompassTextureGetSourceHeight(void* thisPtr);
|
||||
int __fastcall Hooked_ClockTextureGetSourceWidth(void* thisPtr);
|
||||
int __fastcall Hooked_ClockTextureGetSourceHeight(void* thisPtr);
|
||||
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);
|
||||
|
||||
@@ -124,6 +124,90 @@ bool HookManager::Install(const SymbolResolver& symbols)
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pCompassTextureCycleFrames)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pCompassTextureCycleFrames,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_CompassTextureCycleFrames),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_CompassTextureCycleFrames)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook CompassTexture::cycleFrames");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked CompassTexture::cycleFrames (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pClockTextureCycleFrames)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pClockTextureCycleFrames,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_ClockTextureCycleFrames),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_ClockTextureCycleFrames)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook ClockTexture::cycleFrames");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked ClockTexture::cycleFrames (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pCompassTextureGetSourceWidth)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pCompassTextureGetSourceWidth,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_CompassTextureGetSourceWidth),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_CompassTextureGetSourceWidth)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook CompassTexture::getSourceWidth");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked CompassTexture::getSourceWidth (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pCompassTextureGetSourceHeight)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pCompassTextureGetSourceHeight,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_CompassTextureGetSourceHeight),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_CompassTextureGetSourceHeight)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook CompassTexture::getSourceHeight");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked CompassTexture::getSourceHeight (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pClockTextureGetSourceWidth)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pClockTextureGetSourceWidth,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_ClockTextureGetSourceWidth),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_ClockTextureGetSourceWidth)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook ClockTexture::getSourceWidth");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked ClockTexture::getSourceWidth (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pClockTextureGetSourceHeight)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pClockTextureGetSourceHeight,
|
||||
reinterpret_cast<void*>(&GameHooks::Hooked_ClockTextureGetSourceHeight),
|
||||
reinterpret_cast<void**>(&GameHooks::Original_ClockTextureGetSourceHeight)) != MH_OK)
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Warning: Failed to hook ClockTexture::getSourceHeight");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil::Log("[WeaveLoader] Hooked ClockTexture::getSourceHeight (texture pack crash guard)");
|
||||
}
|
||||
}
|
||||
|
||||
if (symbols.pItemMineBlock)
|
||||
{
|
||||
if (MH_CreateHook(symbols.pItemMineBlock,
|
||||
|
||||
@@ -21,6 +21,12 @@ static const char* SYM_REGISTER_ICON = "?registerIcon@PreStitchedTextureMap@@UEA
|
||||
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_COMPASS_CYCLEFRAMES = "?cycleFrames@CompassTexture@@UEAAXXZ";
|
||||
static const char* SYM_CLOCK_CYCLEFRAMES = "?cycleFrames@ClockTexture@@UEAAXXZ";
|
||||
static const char* SYM_COMPASS_GETSOURCEWIDTH = "?getSourceWidth@CompassTexture@@UEBAHXZ";
|
||||
static const char* SYM_COMPASS_GETSOURCEHEIGHT = "?getSourceHeight@CompassTexture@@UEBAHXZ";
|
||||
static const char* SYM_CLOCK_GETSOURCEWIDTH = "?getSourceWidth@ClockTexture@@UEBAHXZ";
|
||||
static const char* SYM_CLOCK_GETSOURCEHEIGHT = "?getSourceHeight@ClockTexture@@UEBAHXZ";
|
||||
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";
|
||||
@@ -122,6 +128,12 @@ bool SymbolResolver::ResolveGameFunctions()
|
||||
pItemInstanceGetIcon = Resolve(SYM_ITEMINSTANCE_GETICON);
|
||||
pEntityRendererBindTextureResource = Resolve(SYM_ENTITYRENDERER_BINDTEXTURE_RESOURCE);
|
||||
pItemRendererRenderItemBillboard = Resolve(SYM_ITEMRENDERER_RENDERITEMBILLBOARD);
|
||||
pCompassTextureCycleFrames = Resolve(SYM_COMPASS_CYCLEFRAMES);
|
||||
pClockTextureCycleFrames = Resolve(SYM_CLOCK_CYCLEFRAMES);
|
||||
pCompassTextureGetSourceWidth = Resolve(SYM_COMPASS_GETSOURCEWIDTH);
|
||||
pCompassTextureGetSourceHeight = Resolve(SYM_COMPASS_GETSOURCEHEIGHT);
|
||||
pClockTextureGetSourceWidth = Resolve(SYM_CLOCK_GETSOURCEWIDTH);
|
||||
pClockTextureGetSourceHeight = Resolve(SYM_CLOCK_GETSOURCEHEIGHT);
|
||||
pItemInstanceMineBlock = Resolve(SYM_ITEMINSTANCE_MINEBLOCK);
|
||||
pItemMineBlock = Resolve(SYM_ITEM_MINEBLOCK);
|
||||
pDiggerItemMineBlock = Resolve(SYM_DIGGERITEM_MINEBLOCK);
|
||||
@@ -181,6 +193,12 @@ bool SymbolResolver::ResolveGameFunctions()
|
||||
logSym("ItemInstance::getIcon", pItemInstanceGetIcon);
|
||||
logSym("EntityRenderer::bindTexture(ResourceLocation)", pEntityRendererBindTextureResource);
|
||||
logSym("ItemRenderer::renderItemBillboard", pItemRendererRenderItemBillboard);
|
||||
logSym("CompassTexture::cycleFrames", pCompassTextureCycleFrames);
|
||||
logSym("ClockTexture::cycleFrames", pClockTextureCycleFrames);
|
||||
logSym("CompassTexture::getSourceWidth", pCompassTextureGetSourceWidth);
|
||||
logSym("CompassTexture::getSourceHeight", pCompassTextureGetSourceHeight);
|
||||
logSym("ClockTexture::getSourceWidth", pClockTextureGetSourceWidth);
|
||||
logSym("ClockTexture::getSourceHeight", pClockTextureGetSourceHeight);
|
||||
logSym("ItemInstance::mineBlock", pItemInstanceMineBlock);
|
||||
logSym("Item::mineBlock", pItemMineBlock);
|
||||
logSym("DiggerItem::mineBlock", pDiggerItemMineBlock);
|
||||
|
||||
@@ -26,6 +26,12 @@ public:
|
||||
void* pItemInstanceGetIcon = nullptr; // ItemInstance::getIcon()
|
||||
void* pEntityRendererBindTextureResource = nullptr; // EntityRenderer::bindTexture(ResourceLocation*)
|
||||
void* pItemRendererRenderItemBillboard = nullptr; // ItemRenderer::renderItemBillboard(shared_ptr<ItemEntity>,Icon*,...)
|
||||
void* pCompassTextureCycleFrames = nullptr; // CompassTexture::cycleFrames()
|
||||
void* pClockTextureCycleFrames = nullptr; // ClockTexture::cycleFrames()
|
||||
void* pCompassTextureGetSourceWidth = nullptr; // CompassTexture::getSourceWidth() const
|
||||
void* pCompassTextureGetSourceHeight = nullptr; // CompassTexture::getSourceHeight() const
|
||||
void* pClockTextureGetSourceWidth = nullptr; // ClockTexture::getSourceWidth() const
|
||||
void* pClockTextureGetSourceHeight = nullptr; // ClockTexture::getSourceHeight() const
|
||||
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>)
|
||||
|
||||
Reference in New Issue
Block a user