Hi Blackdrag,
thank you for your reply. I have created a minimal IntelliJ 2017.1.2
Groovy project that exhibits the problem (without the Groovy lib it is
only 16KB, so I can mail it to you or upload it somewhere).
It contains just 4 simple classes:
public abstract class MicraEntityMinimalJava {
public boolean preventEntitySpawning;
}
@CompileStatic class MicramodEntityMinimalCompileStaticGroovyextends
MicraEntityMinimalJava {
MicramodEntityMinimalCompileStaticGroovy() {this.preventEntitySpawning =true }
}
class MicramodEntityMinimalGroovyextends MicraEntityMinimalJava {
MicramodEntityMinimalGroovy() {this.preventEntitySpawning =true }
}
class MicramodEntityMinimalJavaextends MicraEntityMinimalJava {
MicramodEntityMinimalJava() {
this.preventEntitySpawning =true;
}
}
Which, when compiled in IntelliJ using groovy-2.4.11 under Java
1.8.0_131, give the following class files (decompiled using IntelliJ):
public abstract class MicraEntityMinimalJava {
public boolean preventEntitySpawning;
public MicraEntityMinimalJava() {}
}
public class MicramodEntityMinimalCompileStaticGroovyextends
MicraEntityMinimalJavaimplements GroovyObject {
public MicramodEntityMinimalCompileStaticGroovy() {
MetaClass var1 =this.$getStaticMetaClass();
this.metaClass = var1;
boolean var2 =true;
ScriptBytecodeAdapter.setGroovyObjectProperty(Boolean.valueOf(var2),
MicramodEntityMinimalCompileStaticGroovy.class,this,
(String)"preventEntitySpawning");
}
}
public class MicramodEntityMinimalGroovyextends
MicraEntityMinimalJavaimplements GroovyObject {
public MicramodEntityMinimalGroovy() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 =this.$getStaticMetaClass();
this.metaClass = var2;
boolean var3 =true;
ScriptBytecodeAdapter.setGroovyObjectProperty(Boolean.valueOf(var3),
MicramodEntityMinimalGroovy.class,this, (String)"preventEntitySpawning");
}
}
class MicramodEntityMinimalJavaextends MicraEntityMinimalJava {
MicramodEntityMinimalJava() {
this.preventEntitySpawning =true;
}
}
The way I see it, the MicramodEntityMinimalJava.class file has the form
that works with Mineforge, since it contains a preventEntitySpawning
field access which the Mineforge obfuscator finds. The two Groovy class
files access the field through setGroovyObjectProperty with the String
argument "preventEntitySpawning", which the Mineforge obfuscator does
not replace, since it has no explicit Groovy support. If I understand
you correctly, the class file coming from
MicramodEntityMinimalCompileStaticGroovy does not have the form you
would have expected, and it should look like the one coming from
MicramodEntityMinimalJava ? I hope this helps, Ahm
Am 12.06.2017 um 10:19 schrieb Jochen Theodorou:
On 10.06.2017 21:52, Ahm Avoby wrote:
Hi, I am a Groovy developer at work, and am trying to switch my sons
Minecraft 1.11.2 project (Forge based) from Java to Groovy 2.4.11.
Since the generated class files need to be obfuscated to work with
Minecraft, I am using @CompileStatic, as suggested by another
Minecraft developer, so that the Forge obfuscator finds the
field/method names in the class files. This works in some cases, but
when trying to access fields of the base class (e.g.
net.minecraft.entity.Entity) I am encountering
groovy.lang.MissingPropertyException|s.
you need the obfuscation to be able to call into the obfuscated
minecraft code I assume. It sounds very much like a bug if calling to
a accessible super class field ends up in a MissingPropertyException.
Is it possible for you to make a small example? Though I had assumed,
that if you use forge, you do not need to do that anymore. Well,
modding on minecraft is not unknown to me, but I never tried to mod
myself. So of course I have no idea about the details.
I don't have much experience using @CompileStatic (nor with Minecraft
modding), but looking at the generated class files, it seems as if
property (same for fields) access is not compiled statically, but
remains a call to ScriptBytecodeAdapter.setProperty, with the
property name given as a string literal (ergo the obfuscator won't
see it, and the call in Minecraft will fail). I have explained this
more in-depth with code samples on minecraftforum.net, but did not
get a reply (
http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/modification-development/2828852-groovy-compilestatic-solution-not-working-when).
Frankly, about every setProperty/getProperty call in @CompileStatic is
not right and needs fixing.
Can anyone confirm to me that what I am seeing is the excpected
@CompileStatic behavior - so using @CompileStatic on all Groovy
classes is not the solution to modding Minecraft with Groovy - or if
there is something I can do differently ?
That is not the expected behaviour, no. If you can provide samples,
especially a small script, that shows the problem but has no other
dependencies, you would help us to fix this. As for obfuscation in
Groovy in general... I think it can be done, but there are some
limitations, even with @CompileStatic. Our final goal for
@CompileStatic is to have a runtime, that has only the minimum
required dynamic elements, but right now we have a lot of methods,
that you usually call, that have more a naming convention, than
anything else. And such conventions do not translate to obfuscation
well. For example doCall in Closure, asBoolean, and iterator are very
central here, as they are called from the runtime dynamically even if
@CompileStatic is used. But excluding those few would then already do
the job.. well... in theory... if @CompileStatic does not fall back to
a dynamic setProperty for a reason it should not do that of course.
I would also be grateful for any other suggestion at a solution - I
really would like to avoid having to revert the project back to its
Java version :-)
depending on the problem we could fix it and ensure there is a speedy
2.4.12. Other solution my also require knowing the nature of the
problem first bye Jochen