EnderTurret / PatchedMod

A Minecraft mod that adds the ability to patch Json files for resource and data packs.
GNU Lesser General Public License v2.1
2 stars 0 forks source link

[Crash][1.20.1] Incompatibility with Tiny Skeletons v8.0.1 #18

Open Lumnyl opened 6 days ago

Lumnyl commented 6 days ago

Whenever a Baby Skeleton or Baby Wither Skeleton spawns, the game crashes. Using the Fabric modloader.

Crash logs : https://paste.ee/p/CPomi (regular skeleton) https://paste.ee/p/h6NF5 (wither skeleton) Link to mod : https://modrinth.com/mod/tiny-skeletons I also reported the bug to the mod's author.

EnderTurret commented 6 days ago

I've managed to reproduce this crash on both Fabric and Forge. I was initially very confused about the cause, since this crash should not ordinarily be possible.

Normally, Patched tries to capture the FallbackResourceManager instance since its inject is in a static method. This is fine because no one calls wrapForDebug and all the vanilla ones that do are already handled. The instance is also stored in a ThreadLocal so there can't in theory be any concurrency issues. This of course means that under normal circumstances this crash is impossible.

However, these aren't normal circumstances, and the stacktrace is very misleading about this. I believe what's happened is the following:

  1. A tiny skeleton tries to render itself
  2. The skeleton then renders its held item
  3. This flushes the render buffer, causing Minecraft to render the skeleton itself (so it can setup the state for the item)
  4. To do this, it must grab the skeleton's texture
  5. The MultiPackResourceManager invokes the corresponding FallbackResourceManager to grab the texture
  6. Patched captures the FallbackResourceManager instance
  7. The FallbackResourceManager asks the PackResources for the resource

And now this is where things get interesting:

  1. The BabySkeletonPackResources asks the MultiPackResourceManager for the vanilla skeleton texture
  2. The MultiPackResourceManager invokes the corresponding FallbackResourceManager to grab the texture
  3. Patched captures the FallbackResourceManager instance
  4. The FallbackResourceManager asks the PackResources for the resource
  5. Patched releases the FallbackResourceManager instance (!!!)
  6. The resource is returned to the BabySkeletonPackResources
  7. The BabySkeletonPackResources returns the raw IoSupplier

And here's the actual crash part:

  1. The FallbackResourceManager receives the IoSupplier and calls wrapForDebug on it
  2. Patched panics because it no longer has a FallbackResourceManager instance to work with (since this was released in step 12)

In summary, the problem is that the MultiPackResourceManager is queried twice when retrieving a resource, which causes Patched to become confused and crash.

Right now, I can see two options for addressing this problem:

I can attempt to fix this at some point soon for 1.21.1 (since I'm sure it's still an issue there), but I'm not sure when I'll end up backporting it to 1.20.1. I've had a backport planned for the forty some other features added since then but haven't gotten around to actually backporting them yet.