spongepowered / mixin Goto Github PK
View Code? Open in Web Editor NEWMixin is a trait/mixin and bytecode weaving framework for Java using ASM
License: MIT License
Mixin is a trait/mixin and bytecode weaving framework for Java using ASM
License: MIT License
There are a few cases where we want to replace some existing bytecode, but not all of it. By adding an optional @Inject type parameter to @overwrite along with a specifier for how many instructions we would want to overwrite, this situation can be handled without duplication of entire methods, or confusing blocks of code that null out other blocks of code to get the features of @Inject.
I'm planning to add this myself, but I figured I would see if there was some strong opposition before I got started with this.
This is especially useful should the environment change in such a way that a mixin patch should become incompatible with the enviroment for one reason or another, or for whatever reason a mixin should only be applied under special circumstances.
I am looking into implementing Mixin for ForgeEssentials, and thus need this functionality for a few reasons:
This could be done by including a special @Annotated method that the mixin finder uses to determine if the mixin class should be used or not. Alternatively, allowing mixins to be defined in code, so I can use a environment handler to determine if a mixin should be applied.
Currently, Mixin injects the bytecode from a method with the @Inject
annotation into the target method. While this is usually sufficient, there are some use cases where it isn't:
@Shadow
s) needs to be copied in. This could be solved by injecting a POP
instruction to remove the constant, then pushing the desired value onto the stack.JMP
instruction to the label node after the conditional.This has several uses in Sponge
. Many projectile-related classes, such as EntitySnowball
and EntityEgg
use a hardcoded value of 0.0
in the call to attackEntityFrom
. To implement the Projectile
interface, this value needs to be modified. If the ability to inject arbitrary instructions was added, this could easily be solved by the approach mentioned above.
I propose that the Target
of the @Inject
annotation be extended to include ElementType.FIELD
.
An array of AbstractInsnNode
s could then be annotation with @Inject
. Instead of injecting the body of an annotated method, the instructions contained in the array would be injected, following the normal rules for @At
.
Using an anonymous inner class for the predicate in the class linked in #49 caused https://gist.github.com/zml2008/6316871b8ebdd77ebc57 -- seems like references to the mixin class are not being stripped from the class properlfy, or there's some annotation I should be doing but am not.
Why does Mixin even require the use of the system class loader anyway?
I've been having to troubleshoot various compatibility issues between FE and various other coremods, and seem to keep running into the problem of ASM being split-loaded by the LaunchClassLoader before I get a chance to call MixinBootstrap.
@Aaron1011 and myself have been going back and forth in TS regarding this issue. He created a branch called "maybe fix" but the nature of Mixin's setup in SpongeCommon makes this surprisingly difficult as gradle refuses to use our changes (another issue altogether).
I'm not completely sure if this exists already, but it would be great if the annotation processor could validate the shadow fields and methods as well as injections at compile time and warn if they actually don't exist. While you'll notice it at runtime, it would be better if that could be reported already at compile time instead of only noticing once the mixin target class gets loaded.
For example, this commit by @gabizou in SpongeCommon compiles without any problems or warnings, but does actually add an injection on a method added by Forge which will fail when running in Vanilla.
It would be nice if we could have it fail the build, or at least warn about problems like this at compile time so we notice when adding Forge specific stuff to Common directly.
@Mumfrey ,
In updating Sponge for the unified multi-world implementation, I hit a brick wall here:
SpongePowered/Sponge@f8d57a5#diff-ef8a3be4b70089992a904af75dec8e5dR23
I need to proxy all of common's DimensionManager calls back to Forge's (to remain 100% compatible) but the Mixin transformer rejects it as it fails the safey check. Any chance of a way to override the check or a better way to do this?
As described in ForgeEssentials/ForgeEssentials#1333, some of my users have been encountering funny LinkageErrors when using Mixin-enabled versions of FE.
Sample log here, more in the linked issue: http://pastebin.com/WBUM0iLa
Is there any workaround I can use, or does any fixing have to be done on your part?
ASMTransformerWrapper (introduced in MinecraftForge/FML@43ec260 which is present as of Forge build 1310) breaks re-entrance detection.
An example of the impact this with the latest Biome O' Plenty (which uses Mixins) can be found here:
https://dl.dropboxusercontent.com/u/56679758/Crashes/Mixins/fml-client-latest.log
When you try to add an @Inject
at INVOKE
of methods called in the target class (but defined in a super class) they don't get reobfuscated by the annotation processor. For example, these 3 injections in a mixin for DedicatedServer
in Granite are failing to reobfuscate because the annotation processor can't find the method mappings. (See this Travis CI log)
While using the method of the super class as the target (e.g. MinecraftServer
instead of DedicatedServer
) reobfuscates fine, the injection doesn't seem to work anymore because it is actually calling the method on DedicatedServer
and not on MinecraftServer
.
At runtime, Forge is checking for the method mappings of the super classes so these methods are getting properly deobfuscated, but the methods are not explicitely listed for sub classes in the SRG mappings. We should probably either get the mappings for the super classes in the annotation processor as well or allow the original owner of the method to be used so these can be properly reobfuscated.
https://github.com/SpongePowered/Sponge/blob/master/build.gradle#L253
Can this be added to Mixin build.gradle? Currently, the latest Mixin master is failing in travis due to javadoc errors. Adding the fix above will ignore javadoc errors.
It seems the behavior of @Inject
is to actually call a method with the injected code. Which would make sense, it's a lot safer than just injecting the opcodes directly into the target class. However this makes captureLocals somewhat unhelpful when dealing with primitive types, namely int.
I need to increment an integer through an @Inject
is the basic problem.
Here is what travis is seeing
http://pastie.org/pastes/9886632/text
The problematic mixin is MixinBootstrap
https://github.com/SpongePowered/Sponge/blob/master/src/main/java/org/spongepowered/mod/mixin/MixinBootstrap.java
I don't have this issue in dev nor when building locally.
@Mumfrey let me know if you need any other info. Thanks!
The wiki doesn't seem to have any tutorials on how to create a mod that uses mixins. I'm not talking about writing the code (that's already added); I'm talking about setting up stuff like build.gradle
. Any plans to add this?
Yet another from the unified changes:
SpongePowered/Sponge@f8d57a5#diff-7935aaf1dc2aaf2359fbb6ef6905acf3L61
I need teleportEntity (the method changes that were added here) to exist up in Common. The correct code would be to keep that inection. Common's MixinEntity adds teleportEntity, Sponge's MixinEntity needs to inject into it.
Mixin throws an exception because its mixin into a mixin provided method.
MixinTweaker only supports the post-MC 1.8 FML CoreModManager (net.minecraftforge.fml namespace), whereas other parts of the mixin codebase support the cpw.mods.fml namespace used by FML before MC 1.8.
This "bug" has prevented me from being able to test FE, which employs mixins in a 1.7.10 environment, within a production workspace.
Will this be fixed?
When using asserts in mixin classes, the mixin applier fails with the following message:
Mixin classes cannot contain visible static methods or fields, found $assertionsDisabled
When the java compiler finds an assert, it adds a static variable to the class indicating whether or not the -ea argument is added. As this variable is not visible in source, it is safe to whitelist it.
The annotation processor currently requires a generic signature to be present, in order to be able to find the target of an injection-related annotation. compareElement
, called here, uses the generic signature of the Element
being checked, requiring the MemberInfo
to contain it as well.
However, MemberInfo
doesn't correctly parse the generic singnature, resulting in Mixin failing to apply the mixin at runtime.
Mixin is currently referencing Guava 18.0 as dependency while Minecraft 1.8.X only provides Guava 17.0. Therefore, using features of Guava 17.0 will fail on most implementations (and especially in Forge mods as Forge is using the Guava version provided by Vanilla).
Due to transitive dependencies, Guava gets also silently upgraded in projects referencing Mixin unless the Guava dependency gets explicitely excluded. That caused a few problems in Sponge for example where usages of Guava 18.0 were silently breaking running Sponge in production without noticing it at compile time. We should consider downgrading it in Mixin so unavailable features are not used and projects get the correct Guava dependency directly.
I noticed with trying to inject a callback after line 138 in Explosion (vanilla-only sources) that not only is Mixin not putting my callback there, the LVT printed from debug is wrong too.
Mixin:
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.vanilla.mixin.world;
import net.minecraft.util.Vec3;
import net.minecraft.world.Explosion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.HashSet;
@Mixin(value = Explosion.class, priority = 1001)
public abstract class MixinExplosion implements org.spongepowered.api.world.explosion.Explosion {
@Inject(method = "doExplosionA", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getEntitiesWithinAABBExcludingEntity"
+ "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/AxisAlignedBB;)Ljava/util/List;", shift = At.Shift.AFTER), locals = LocalCapture
.PRINT)
public void callWorldOnExplosionEvent(CallbackInfo ci, HashSet hashset, boolean flag, int j, int k, float f3, int j1, int l, int k1, int i1,
double d2, Vec3 vec3) {
}
}
LVT:
[23:41:05] [Server thread/ERROR] [ERR]: /************************************************************************************************************************************************************************/
[23:41:05] [Server thread/ERROR] [ERR]: /* Target Class : net.minecraft.world.Explosion */
[23:41:05] [Server thread/ERROR] [ERR]: /* Target Method : public void doExplosionA() */
[23:41:05] [Server thread/ERROR] [ERR]: /* Target Max LOCALS : 30 */
[23:41:05] [Server thread/ERROR] [ERR]: /* Initial Frame Size : 1 */
[23:41:05] [Server thread/ERROR] [ERR]: /* Callback Name : callWorldOnExplosionEvent */
[23:41:05] [Server thread/ERROR] [ERR]: /* Instruction : VarInsnNode ASTORE */
[23:41:05] [Server thread/ERROR] [ERR]: /************************************************************************************************************************************************************************/
[23:41:05] [Server thread/ERROR] [ERR]: /* LOCAL TYPE NAME */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 0] Explosion this */
[23:41:05] [Server thread/ERROR] [ERR]: /* > [ 1] HashSet hashset <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 2] boolean flag <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 3] int j <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 4] int k <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 5] float f3 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 6] int j1 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 7] int l <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 8] int k1 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 9] int i1 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 10] double d2 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 11] Vec3 vec3 <capture> */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 12] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 13] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 14] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 15] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 16] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 17] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 18] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 19] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 20] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 21] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 22] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 23] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 24] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 25] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 26] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 27] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 28] - */
[23:41:05] [Server thread/ERROR] [ERR]: /* [ 29] - */
[23:41:05] [Server thread/ERROR] [ERR]: /************************************************************************************************************************************************************************/
[23:41:05] [Server thread/ERROR] [ERR]: /* */
[23:41:05] [Server thread/ERROR] [ERR]: /* /** */
[23:41:05] [Server thread/ERROR] [ERR]: /* * Expected callback signature */
[23:41:05] [Server thread/ERROR] [ERR]: /* * / */
[23:41:05] [Server thread/ERROR] [ERR]: /* public void callWorldOnExplosionEvent(CallbackInfo ci, HashSet hashset, boolean flag, int j, int k, float f3, int j1, int l, int k1, int i1, double d2, Vec3 vec3) { */
[23:41:05] [Server thread/ERROR] [ERR]: /* // Method body */
[23:41:05] [Server thread/ERROR] [ERR]: /* } */
[23:41:05] [Server thread/ERROR] [ERR]: /* */
[23:41:05] [Server thread/ERROR] [ERR]: /************************************************************************************************************************************************************************/
I'm no bytecode expert but double d2 SHOULD be that List object (which I also need...). Thoughts @Mumfrey @Aaron1011 ?
Variables that are assigned globally in the class, specifically
private List patterns = Lists.newArrayList();
in MixinTileEntityBanner, do not actually set the variable.
As can be seen here, SpongePowered/Sponge@f985197
After setting up the annotation processor from the latest build of Mixin, I was pleased to find it worked well with Intellij IDEA. However when attempting to compile, my builds were failing at the AP because of @Inject
mapping failures.
Some of which were caused by spaces in the target method @At
others because of MixinToSubClass extends MixinToSuperClass wasn't being recognized properly, expecting MixinToSubClass extends SubClass.
All of these so-called "errors" from the AP during compile, will run and apply just fine during a test run of the server. In fact the code itself is fairly old (MixinLeafBlock in SpongeCommon). I see this as a failure in the provided annotation processor.
I'm writing a mixin for BiomeGenBase, similar as in sponge common. Applying of this mixin fails with:
[21:25:59] [Server thread/INFO] [mixin]: Mixing world.MixinBiomeGenBase into net.minecraft.world.biome.BiomeGenBase
[21:28:05] [Server thread/ERROR]: Encountered an unexpected exception
java.lang.NoClassDefFoundError: net/minecraft/world/biome/BiomeGenBase
at nl.jk_5.pumpkin.server.registry.PumpkinGameRegistry.setBiomeTypes(PumpkinGameRegistry.java:183) ~[PumpkinGameRegistry.class:?]
at nl.jk_5.pumpkin.server.registry.PumpkinGameRegistry.init(PumpkinGameRegistry.java:441) ~[PumpkinGameRegistry.class:?]
at nl.jk_5.pumpkin.server.Pumpkin.initialize(Pumpkin.java:81) ~[Pumpkin.class:?]
at net.minecraft.server.dedicated.DedicatedServer.onStartServer(SourceFile:119) ~[DedicatedServer.class:?]
at net.minecraft.server.dedicated.DedicatedServer.startServer(SourceFile:93) ~[DedicatedServer.class:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:417) [MinecraftServer.class:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_25]
Caused by: java.lang.ClassNotFoundException: net.minecraft.world.biome.BiomeGenBase
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_25]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_25]
... 7 more
Caused by: org.spongepowered.asm.mixin.transformer.MixinTransformerError: An unexpected critical error was encountered
at org.spongepowered.asm.mixin.transformer.MixinTransformer.transform(MixinTransformer.java:372) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at org.spongepowered.asm.mixin.transformer.MixinTransformer$Proxy.transform(MixinTransformer.java:101) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_25]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_25]
... 7 more
Caused by: java.lang.IllegalArgumentException: Invalid access flags: 16425
at org.objectweb.asm.util.CheckClassAdapter.checkAccess(CheckClassAdapter.java:599) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.util.CheckClassAdapter.visitInnerClass(CheckClassAdapter.java:460) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.InnerClassNode.accept(InnerClassNode.java:99) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:404) ~[asm-debug-all-5.0.3.jar:5.0.3]
at org.spongepowered.asm.mixin.transformer.MixinTransformerModuleCheckClass.postApply(MixinTransformerModuleCheckClass.java:56) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.postApply(MixinTransformer.java:560) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.applyMixins(MixinTransformer.java:521) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.transform(MixinTransformer.java:360) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at org.spongepowered.asm.mixin.transformer.MixinTransformer$Proxy.transform(MixinTransformer.java:101) ~[mixin-0.3.3-SNAPSHOT.jar:0.3.3-SNAPSHOT+unknown-b0.git-unknown]
at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.11.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_25]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_25]
... 7 more
Note that the stacktrace mentions the CheckClassAdapter's visitInnerClass. It fails with an invalid access flags error (16425). After some calculation, it turns out that the inner class has ACC_SUPER (32) where that is not allowed.
It fails on visiting inner class TempCategory in BiomeGenBase, which is an enum.
Mixin source code: http://pastebin.com/Ey52AWhG
Not sure if this is something i am overlooking or an actual issue. I'm totally out of ideas so having your vision on this would be nice.
Tried looking at the bytecode from the -Dmixin.dumpTargetOnFailure=true
option, but it doesn't actually dump the bytecode
I'm seeing in a couple of Sponge mixins the priority being set in the @mixin annotation (typically its set to 1001). Are we supposed to be setting Sponge's mixin priority in the json config? From my understanding, common's mixins should have the lowest priority and Sponge/SpongeVanilla's should have the higher priority. Otherwise, Mixin prints warning for duplicate overwrites.
Seems odd as that would mean that somehow the inner/outer class is null or the name is?
Stacktrace: https://gist.github.com/zml2008/0d935592484363d6c601
I'm thinking this is related to the switch statement -- those sometimes create inner classes for some reason, and is part of the hasPermission method, which is what was being invoked when this error occurred.
I am going to explain it with an example.
public void dostuff(){
for (int i = 0; i < 200; i++){
doOtherstuff(i);
}
}
Lets say I want a mixin like this:
//inject might be incorrect
@Inject(method = "dostuff()V", at = @At(value = "INVOKE", target = "Exampleclass.doOtherstuff(I)V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILSOFT, cancellable = true)
private void continueLoop(CallbackInfo callbackInfo, int i){
if (i == 50) {
continue; // Doesn't work because we aren't in a loop
callbackInfo.cancel(); //will stop the loop and return. does not continue to work on number 51
}
}
(Originally from #9)
There is currently no way for a mixin to have a super class that's not the direct super class of the target.
This is normally fine, but can become an issue when creating a mixin for targeting multiple classes.
Some of the target classes may have a different direct super class, but all have a class in common. However this common class is not the super class of all targets and so the mixin is not possible.
This issue requests that a mixin can have any super class that the target has, and allows for a common super class.
As described in ForgeEssentials/ForgeEssentials#1351 or Chicken-Bones/ForgeMultipart#313 (similar issue), the current(?) implementation incorrectly runs transformers multiple times, potentially causing unexpected internal state there.
Title says it all.
The annotation processor fails to compile against JDK 1.8 since dcd44b9. FakeElement and FakeType throw compilation errors on the basis that TypeMirror (indirectly implemented by the two classes) now extends AnnotatedConstruct, the methods of which are not currently implemented in Mixin.
Continuing the same code from SpongePowered/SpongeVanilla#167, I'm now positive of a correct signature and inject annotation and this source file breaks the server load with the provided error log only when capture locals using PRINT is enabled. If I remove that argument the injection works correctly. https://gist.github.com/modwizcode/98aa1686c643427b8b78
When building javadocs for mixin, the build fails with the following errors:
<redacted>\Mixin\src\main\java\org\spongepowered\asm\mixin\transformer\meta\MixinRenamed.java:37: error: reference not found
* {@link org.spongepowered.asm.mixin.transformer.meta.MixinInfo} and
<redacted>\Mixin\src\main\java\org\spongepowered\asm\mixin\transformer\meta\MixinRenamed.java:38: error: reference not found
* {@link org.spongepowered.asm.mixin.transformer.MixinPreProcessor} to mark
Am I doing something wrong, or is something that shouldn't be there happening?
My mod Almura is basically ready for primetime and while mixins are not 100% needed, it does let some of what we are doing work 100% correctly.
Are we any further with getting this working?
I propose that the Mixin project convert casts to a mixin class into casts to the class targeted by said mixin. This would allow mixins to be written much more cleanly, without needing to add in an interface for every mixin whose added methods need to be added.
Consider the following scenario (many such examples exist in the Sponge repository)
MixinEntity
adds a method - isTeleporting
.isTeleporting
method of an Entity
instance it has.Since mixin classes don't exist at runtime, it's impossible to cast the Entity
instance to MixinEntity
. Instead, this procedure must be followed:
IMixinEntity
) containing the method that you want to access - in this case, isTeleporting
isTeleporting
, it casts its Entity
instance to IMixinEntity
, then calls the method.This is quite common in the Sponge codebase.
This could be simplified greatly by having Mixin convert all such casts to casts to the target class. Since the mixin class doesn't exist at runtime, there's no scenario under which such a cast would lead to desired behavior, and would need to be left unchanged.
EDIT: After discussion on IRC, it's been proposed that this only apply to mixins - that is, only casts in mixin classes are transformed.
I currently have a situation where i would like to run a mixin on a mod, but the current setup seems to run mixins as they are loaded, so this causes a class not found because it runs before the class is actually loaded,
is there a way to run a mixin after a mod is loaded?
Currently, applying mixins requires that Mixin be started from a tweak class, invoked by launchwrapper. This means that a full server instance must be started just to see if a mixin will apply cleanly.
Allowing Mixin to be started without launchwrapper (with Forge on the classpath) would allow the actual application of mixins, not just their compilation, to be tested on a CI server, without the need to start a Minecraft server instance.
Normally, Mixin registers a classloader through launchwrapper. When a class is loaded, the class loader checks if there are any mixins for it. If so, it runs them on the class.
In the scenario I propose, Mixin would inspect that target(s) of each registed mixin, and load the class for it. The loaded class would then be processed as normal.
In the class at https://gist.github.com/zml2008/482eb91adf7f2b174165#file-mixinsubject-java-L86
the highlighted line is never reached. It seems like it should be possible to inject simple initializers with multi-target mixins, but this does not appear to happen currently
Currently, ASMHelper#getAnnotationValue
iterates over AnnotationNode.values
, assuming that the name of the value is followed by the value itself.
However, this isn't the case for Enum values. Instead of an Enum member, the value is a two-element array containing a descriptor for the enum, and the member name.
For example, this annotation: @At(value = "JUMP", shift = At.Shift.AFTER)
:
is stored like this: [value, JUMP, shift, [Lorg/spongepowered/asm/mixin/injection/At$Shift;, BY]
Because of this, using the shift
parameter to the At
annotation causes an error when the class is mixed it.
I'm trying to cast an instance of the target class to the Mixin itself so I can access a private field of it. Here is a small example:
@Mixin(SomeClass.class)
public abstract class MixinSomeClass {
@Shadow private List<SomeClass> children;
private boolean someValue;
private void findValues() {
for (SomeClass child : children) {
System.out.println(((MixinSomeClass) child).someValue);
}
}
}
Normally this should work in the feature/supermixin
branch but it doesn't because only methods of mixins extending another mixin get transformed. When I remove the check it works fine, but with this check it tries to find the mixin class at runtime because the cast doesn't get replaced.
Maybe we can also extend this to mixins not extending another mixin?
We discovered today that when gradle downloaded the newest snapshot of Mixin for Almura we could no longer perform a compilation due to missing the SRG or mappings.
Mixin should handle this without bombing on javac step.
Log:
Powered By MCP:
http://mcp.ocean-labs.de/
Searge, ProfMobius, Fesh0r,
R4wk, ZeuX, IngisKahn, bspkrs
MCP Data version : unknown
****************************
Found AccessTransformer in main resources: forgeessentials_at.cfg
:compileApiJava UP-TO-DATE
:processApiResources UP-TO-DATE
:apiClasses UP-TO-DATE
:compileUtilsJavawarning: [options] bootstrap class path not set in conjunction with -source 1.7
error: The reobfSrgFile argument was not supplied, obfuscation processing will not occur
warning: Supported source version 'RELEASE_6' from annotation processor 'org.spongepowered.tools.obfuscation.TargetObfuscationProcessor' less than -source '1.7'
warning: Supported source version 'RELEASE_6' from annotation processor 'org.spongepowered.tools.obfuscation.InjectionObfuscationProcessor' less than -source '1.7'
1 error
2 warnings
FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileUtilsJava'.
> Compilation failed; see the compiler error output for details.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 58.838 secs
Is there anything else I need to do? I need the files in the custom source sets (utils in this case) to be reobfed as well.
This isn't an issue so much as a question.
For Map implementation I can mix my interface into the vanilla MapColor, however I need to create instances of my interface to complete colors that aren't in the original enum (shades). I can work around this, but is it possible to just do new MixinMapColor(MapColor nmsMapColor, int shade)?
Or am I stuck with a static method that creates these?
Sorry if the explanation isn't very clear.
The title says it all. Because mixins require the @Mixin
annotation to refer to the target class literal, they cannot reference protected inner classes or any package-private classes.
Looking for opinions on adding a second targets array to the @Mixin
annotation which would allow additional targets to be specified as strings, this would allow even private inner classes to be referenced by a mixin by specifying the fully-qualified inner class name.
@Mixin(targets = { "net.minecraft.entity.monster.EntityGhast$AILookAround" })
public abstract class MixinEntityGhastAILookAround {
There are use-cases where we would likely want to mix in to a package-private class such as the one mentioned above.
Any thoughts? My main concern is that this is pretty easy to screw up, which is why the hard class references are used in the first place, but at the same time the only other way to deal with this is via access transformers (assuming access transformers can change the visibility of classes, not sure if they can) so it could be a more straightforward way to target classes which would otherwise not be mixinable.
I realise that this is not the intended purpose of this library, but it can come in handy. What I tried to do is write a mixins for the mod ComputerCraft. As mixins are much easier than manually ASM everything around. I wanted to add additional behaviour to the turtle block, so that it will give a break event with the last clicked user as breaking user.
MixinClass
(As far I understood I need to use the obfuscated names, as mixins doesn't check inheritance on compiletime)
ErrorLog
As far I understood, this is caused because mixins thinks the loading is done after coremods are loaded.
This causes issues where if the MixinTweaker, a coremod, and a regular mod are in the same jar file, only the MixinTweaker and the coremod are loaded, but the regular mod is ignored.
As I mentioned here, this is due to the MixinTweaker removing the container file from the "loaded coremods" list, which forces FML to look through the container file again, but this only happens during the coremod discovery phase.
A solution as implemented here would be to also add the container file to the list of files that FML should reparse in the regular mod loading phase (usually, this is handled by FML here, but as the file is treated with tweaker handling processes, that code does not execute).
I will make a PR by the end of this week to resolve this issue, but if you want, feel free to take the linked code from FELaunchHandler. Note that those code makes some assumptions (for example, there is always a @mod in the same file), which should be catered to with proper checks.
Right now accessing references to the outer class in mixins for inner classes is really hard because they have different names in decompiled and binary deobfuscated environment at runtime. In decompiled environment these references are called like this$0
by the Java decompiler, at runtime the deobfuscator will name them normally with the field_xxxxx
name.
This makes it nearly impossible to use a @Shadow
field to access this reference because you can always use only one of the names. Is there some other way to access the references to the outer class from mixins for inner classes already?
Here is an example where this is a problem: https://github.com/SpongePowered/Granite/blob/feature/console/src/main/java/org/spongepowered/granite/mixin/server/MixinConsoleHandler.java#L41-L42
Hello!
Is there a way to use Mixin without Minecraft, Forge, Sponge, etc? I want to use it in some other projects and initially thought it would be able to be used in a standalone project as the repostitory description suggested: "Mixin is a trait/mixin framework for Java using ASM". I then read further and found out it won
't work for my application in for example a Bukkit Plugin (I am still using it because I am too lazy to move to the SpongeAPI...)
When using just the MixinTweaker in a dev environment, I have not found a way to specify a JSON mixin config that should be loaded within the dev environment.
Is it possible to add a command line option --mixin mixin_something.json
or something that the MixinTweaker will use to look for mixin configs on the classpath?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.