ZenScript
ZenScript copied to clipboard
Using a function as a parameter for a custom function causes ArrayIndexOutOfBoundsException
Creating a custom function that accepts a function causes a java.lang.ArrayIndexOutOfBoundsException
Example Script
function test(callback as function(int)bool)
{
if(callback(3))
{
print("callback success");
}
}
//Note: The below is unnecessary but provided for completeness
test(function(a as int) as bool
{
print("value was " ~ a);
return true;
} as function(int)bool);
Exception in crafttweaker.log
[INITIALIZATION][CLIENT][ERROR] [crafttweaker]: Error executing {[0:crafttweaker]: testFunction.zs}: 69
java.lang.ArrayIndexOutOfBoundsException: 69
at org.objectweb.asm.Type.getArgumentTypes(Unknown Source)
at org.objectweb.asm.commons.LocalVariablesSorter.<init>(Unknown Source)
at org.objectweb.asm.commons.LocalVariablesSorter.<init>(Unknown Source)
at stanhebben.zenscript.util.MethodOutput.<init>(MethodOutput.java:26)
at stanhebben.zenscript.ZenModule.compileScripts(ZenModule.java:114)
at crafttweaker.runtime.CrTTweaker.loadScript(CrTTweaker.java:211)
at crafttweaker.runtime.CrTTweaker.loadScript(CrTTweaker.java:101)
at crafttweaker.mc1120.events.CommonEventHandler.registerRecipes(CommonEventHandler.java:69)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_818_CommonEventHandler_registerRecipes_Register.invoke(.dynamic)
at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
at net.minecraftforge.fml.common.eventhandler.EventBus$1.invoke(EventBus.java:144)
at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:182)
at net.minecraftforge.registries.GameData.fireRegistryEvents(GameData.java:814)
at net.minecraftforge.common.crafting.CraftingHelper.loadRecipes(CraftingHelper.java:624)
at net.minecraftforge.fml.common.Loader.initializeMods(Loader.java:742)
at net.minecraftforge.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:336)
at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:535)
at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:3931)
at net.minecraft.client.main.Main.main(SourceFile:123)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
CraftTweaker version: CraftTweaker2-1.12-4.1.15
ZS does not allow for functions as parameters because internally it uses different types. This would only be possible if you were to use a function that is registered to ZS as a functional Interface (e.g. IItemCondition)
Short of forking CT, can we register a functional interface using ZenClasses?
Take this example (the 2nd function parameter for recipes)
So it's like using lambda needs an interface? If we are allowed to define interfaces or function signatures, it seems this is possible.
You can use lambdas when you have registered a functional interface using Java Code. You cannot create functional interfaces from within ZS, but you can implement them (that is what a lambda is)
Hey there,
I apologize for the late reply. Currently I have a rudimentary implementation for function types as parameters and members in my local dev environment.
var myTestFun as function(string)void = function(s as string) as void {print(s);};
myTestFun('Hello World');
function myAcceptFun(consumer as function(string)void) as void {
consumer('hello from inside myAcceptFun');
}
myAcceptFun(myTestFun);
myAcceptFun(function(s as string) as void {print('Another thing: ' ~ s);});
Would print
Hello World
hello from inside myAcceptFun
Another thing: hello from inside myAcceptFun
And
zenClass myClass {
var consumer as function(string)void;
zenConstructor(consumer as function(string)void) {
this.consumer = consumer;
}
function acceptString(x as string) as void {
consumer(x);
}
}
myClass(function(x as string) as void {print('inside fun: ' ~ x);}).acceptString('abc');
Would print
inside fun: abc