GeckoLib

GeckoLib

146M Downloads

[1.16.5 Forge] Custom instructions cause the game to crash even if JSON is fixed

rbasamoyai opened this issue ยท 1 comments

commented

Today I was trying to use custom instruction keyframes. They constantly crash the game, and editing each timeline entry to be a JSON array instead of a string, e.g.

"timeline": {
    "0.5": "[\"hide_bullet\", \"true\"]",
    "1.0": "[\"hide_bullet\", \"false\"]",
}

to:

"timeline": {
    "0.5": ["hide_bullet", "true"],
    "1.0": ["hide_bullet", "false"],
}

still causes the game to crash.
The following error log is produced when trying to play an animation with custom instruction keyframes:

java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
	at software.bernie.geckolib3.core.controller.AnimationController.processCurrentAnimation(AnimationController.java:634) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at software.bernie.geckolib3.core.controller.AnimationController.process(AnimationController.java:481) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at software.bernie.geckolib3.core.processor.AnimationProcessor.tickAnimation(AnimationProcessor.java:65) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at software.bernie.geckolib3.model.AnimatedGeoModel.setLivingAnimations(AnimatedGeoModel.java:76) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at software.bernie.geckolib3.renderers.geo.GeoItemRenderer.render(GeoItemRenderer.java:84) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at software.bernie.geckolib3.renderers.geo.GeoItemRenderer.renderByItem(GeoItemRenderer.java:68) ~[geckolib-forge-1.16.5-3.0.56_mapped_official_1.16.5.jar:3.0.56] {re:classloading}
	at net.minecraft.client.renderer.ItemRenderer.render(ItemRenderer.java:137) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.renderer.ItemRenderer.renderGuiItem(ItemRenderer.java:236) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.renderer.ItemRenderer.tryRenderGuiItem(ItemRenderer.java:265) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.renderer.ItemRenderer.renderAndDecorateItem(ItemRenderer.java:257) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.gui.IngameGui.renderSlot(IngameGui.java:1038) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.gui.IngameGui.renderHotbar(IngameGui.java:496) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraftforge.client.gui.ForgeIngameGui.renderHotbar(ForgeIngameGui.java:362) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
	at net.minecraftforge.client.gui.ForgeIngameGui.render(ForgeIngameGui.java:149) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
	at net.minecraft.client.renderer.GameRenderer.render(GameRenderer.java:472) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.Minecraft.runTick(Minecraft.java:977) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.Minecraft.run(Minecraft.java:607) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A}
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_292] {}
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_292] {}
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_292] {}
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_292] {}
	at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.0.9.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.0.9.jar:?] {}
	at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.0.9.jar:?] {}
	at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.0.9.jar:?] {}
	at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.0.9.jar:?] {}
	at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:108) [forge-1.16.5-36.2.19_mapped_official_1.16.5-recomp.jar:?] {}

As the code in question used Animation#customInstructionKeyframes, I looked into where it was filled, which led me to here.

When I stepped through the code, keyFrame.getValue() returned a JsonPrimitive, so

keyFrame.getValue() instanceof JsonArray

returned false.

keyFrame.getValue().getAsString())

was evaluated instead of:

convertJsonArrayToList(keyFrame.getValue().getAsJsonArray())

, the former returning a String whereas the latter returns a List<IValue>. The String result is then put into an EventKeyFrame, which itself is put into Animation#customInstructionKeyframes. Later on in AnimationController, when trying to play an animation, the generic method EventKeyFrame#getData returns said String. An attempt is made to cast the String to a List<String> when passing it to instructions in CustomInstructionKeyframeEvent(T entity, double animationTick, List<String> instructions, AnimationController controller), causing the ClassCastException.

This issue occurs in 3.0.57.

commented

dupe of #197