Code Monkey home page Code Monkey logo

mixin's People

Contributors

aaron1011 avatar abrarsyed avatar asiekierka avatar bloodmc avatar caseif avatar gabizou avatar jbyoshi avatar jordin avatar kashike avatar kobata avatar lexmanos avatar llamalad7 avatar modmuss50 avatar mumfrey avatar progwml6 avatar runemoro avatar shartte avatar simon816 avatar sizableshrimp avatar skinnybat avatar the-ppwd avatar xigbclutchix avatar zml2008 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mixin's Issues

Allow @Overwrite to work like @Inject

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.

Ability to selectively control which mixin classes are applied

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:

  • In order not to conflict with Sponge, I would like to use sponge events where there are no Forge equivalents available, and thus refrain from patching in my own events, only doing so should Sponge not be present and the Forge version installed does not have the hooks I need.
  • I would like to maintain a certain amount of compatibility across Forge versions, and thus have to apply my own patches for Forge events should the event not be available in a certain Forge build.

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.

Allow injecting arbitrary ASM nodes

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:

  • Modifying arguments for method calls. In many places, Vanilla uses magic numbers, instead of using a constant with that value. In order to modify the value, the rest of the method (and all necessary @Shadows) 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.
  • Skipping over a conditional, while preserving the rest of the method. This currently requires the same approach of copying in the method, as mentioned above. This could be solved by injecting a 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 AbstractInsnNodes 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.

A question relating to compatibility.

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.

Validate shadow methods/fields and injections at compile time

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.

@Inject on invokation of methods defined in super classes don't get reobfuscated

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.

Inject doesn't make sense [Read description]

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.

Wiki - Tutorial on setting up a mod to add mixins

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?

Force injection of FML coremods/mods does not work on MC 1.7.10 and below

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?

Asserts in mixins

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.

MemberInfo doesn't handle generic signatures

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 uses Guava 18.0 while Minecraft (1.8.X) provides only Guava 17.0

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.

[SV] Injection fails to apply in Explosion class and has incorrect LVT

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 ?

Annotation Processor still doesn't work properly in IntelliJ

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.

Invalid access flags error when mixing in on a class with inner class

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

Priority explanation or an issue (see inside)

@Mumfrey

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.

Breaking or Continuing a loop with mixins?

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
    }
}

Allow a mixin to have any super class in the target's hierarchy

(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.

Annotation processor does not compile against JDK 1.8

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.

Javadocs do not seem to build properly

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?

Translate casts to Mixin class into casts to target classes

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)

  • A mixin called MixinEntity adds a method - isTeleporting.
  • Another class wants to access the mixed in 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:

  • Create an interface (let's call it IMixinEntity) containing the method that you want to access - in this case, isTeleporting
  • Make the mixin class implement the interface, thus making the target class implementing it.
  • When another class wants to access 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.

Running Mixins on mod classes

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?

Allow Mixin to be run outside of a launchwrapper context

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.

Shift value of At annotation not handled correctly

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.

Methods in mixins not extending any other mixin are not transformed

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?

Mixins don't seem to work with FG and custom source sets?

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.

Constructors

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.

Mixins cannot target a package-private class or protected inner class

Paging @Zidane and @bloodmc

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.

Mixins can not modify non-coremods in a production environment.

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.

FMLCorePluginContainsFMLMod not supported by MixinTweaker

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.

Access reference to outer class in mixins for inner classes

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

Using Mixin without Minecraft

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...)

  • Rene

Add the ability to specify mixin configs using the command prompt

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.