Annotation Type At


  • @Documented
    @Retention(RUNTIME)
    public @interface At
    The At annotation selects one or multiple instructions (depending on the circumstances no instructions can also be matched) based on the parameters it was given to. What the selected instruction mean depends on the context. For Inject.at() it is the instruction at which the injection should occur.
    • Required Element Summary

      Required Elements 
      Modifier and Type Required Element Description
      java.lang.String value
      Defines the type of instructions that should be matched.
    • Optional Element Summary

      Optional Elements 
      Modifier and Type Optional Element Description
      java.lang.String[] args
      A list of arguments that can be consumed by the injection point provider.
      int by
      Define by how many instructions the selection should be shifted by.
      Desc desc
      The targeted signature.
      At.Shift shift
      At times the injection point selector defined by value() points to an instruction adjacent to the instruction that should actually be targeted, yet in some circumstances it can be infeasible or even impossible to target the intended instruction directly.
      java.lang.String slice
      The id of the Slice that should be passed to the injection point to narrow down the amount of resulting matched instructions.
      java.lang.String target
      The target attribute is a discriminator with whom the chosen instructions can be constrained with more specific accuracy if the injection point isn't descriptive enough as-is.
    • Element Detail

      • value

        java.lang.String value
        Defines the type of instructions that should be matched. The following values are all valid types:
        • HEAD - Before the first instruction
        • RETURN - Before all RETURN (including ARETURN, DRETURN, etc.) instructions
        • TAIL - Before the last RETURN (including ARETURN, DRETURN, etc.) instruction
        • INVOKE - Before all matching INVOKESTATIC, INVOKEVIRTUAL or INVOKESPECIAL instructions
        • INVOKE_ASSIGN - After all matching INVOKESTATIC, INVOKEVIRTUAL or INVOKESPECIAL instructions, where the return value is STORE'd immediately
        • FIELD - Before all matching GETFIELD, PUTFIELD, GETSTATIC or PUTSTATIC instructions
        • NEW - Before all matching NEW instructions
        • INVOKE_STRING - Like INVOKE, but instruction must only take in a string and return void. Furthermore, the instruction must be preceded by an LDC which is checked for a match.
        • JUMP - Before all matching jumping instructions (IFEQ, IFNE, IFLT, GOTO, JSR, etc. - if opcode is -1 it matches all)
        • CONSTANT - Before all matching constant instructions (ICONST_0, BIPUSH, SIPUSH, LDC, etc.)

        The spongeian implementation supports fully qualified names for custom injection points, however the micromixin implementation does not support such behaviour.

        Most injection points require additional arguments in order to resolve to an instruction. These arguments are supplied alongside this argument and are to be specified in the At annotation.

        Returns:
        The type of instructions to match
      • args

        java.lang.String[] args
        A list of arguments that can be consumed by the injection point provider. These arguments are used if target() and desc() either do not apply or are not descriptive enough.

        The probably most common use of this attribute is for use in the CONSTANT injection point. Examples of the syntax of this injection point are follows:

        • nullValue=true
        • intValue=8
        • stringValue=name
        Please be aware that the above examples may be a bit erroneous, but should still work for micromixin. However, it has not yet been investigated as to why that is the case. More specifically, micromixin-transformer supports the same keys as defined by the attributes of the Constant annotation.

        The exact syntax of the arguments differ from injection point provider to injection point provider. The provider is defined via value(). Consult the manual of your injection point for further details.

        Returns:
        The arguments to pass to the injection point provider for further discrimination.
        Default:
        {}
      • by

        int by
        Define by how many instructions the selection should be shifted by.

        The exact effects are explained in At.Shift.BY but simplified, using At.Shift.BY for shift() results in arbitrary shifts by n instructions (for n > 0, the shift is forwards while for n < 0 the shift is backwards. For n = 0 no shift occurs). This n is defined using by() (default value for this property is 0).

        Although permissible when using micromixin at this point in time, other mixin implementations (and potentially future iterations of micromixin) may produce warnings or application failures when using At.Shift.BY in combination with a by() that is a very large value. As a rule of thumb, an by() smaller than -3 or larger than 3 are to be avoided. Reason for this is that by() is rather blind, enabling the possibility of writing injection points that are more unstable than they actually need to be.

        This annotation element has no effect if shift() is not set to At.Shift.BY. It is undefined whether it is an error to define an by() when shift() is not At.Shift.BY.

        Returns:
        The amounts of instructions to shift the selection by.
        See Also:
        At.Shift.BY
        Default:
        0
      • desc

        Desc desc
        The targeted signature. Usage of Desc may result in better compile-time error and sanity checking, however depending on your tooling the difference between desc() and target() may be indistinguishable in this regard.

        Warning: Fabric's tiny-remapper does not support remapping this annotation. Proceed with caution. For more information, see the PR that introduced Desc remapping in tiny-remapper.

        Returns:
        The constraint to use as a Desc annotation.
        See Also:
        Inject.target(), target()
        Default:
        @org.spongepowered.asm.mixin.injection.Desc("")
      • shift

        At.Shift shift
        At times the injection point selector defined by value() points to an instruction adjacent to the instruction that should actually be targeted, yet in some circumstances it can be infeasible or even impossible to target the intended instruction directly. In this case, the instruction targeted by the injection point selector defined by value() can be "shifted" by a limited amount.

        This annotation element only modifies the selection of this At, but will not mutate the originally selected instruction, nor will it modify or move any other instruction. This annotation element is primarily used to inject code after an injection point selector, e.g. after an INVOKEVIRTUAL instruction matched by INVOKE.

        By default, the instruction is not shifted. This corresponds to the behaviour of At.Shift.NONE.

        It is not defined whether "virtual" instructions (for example LineInsnNodes, FrameInsnNodes and LabelNodes) are counted towards the shift or whether they are ignored. This behaviour may be subject to change depending on the behaviour of other mixin implementations as well as the (un-)intuitive semantics of such counting. The spongeian mixin documentation implicitly leaves this as an implementation detail.

        Returns:
        The type of shift to perform.
        Default:
        org.spongepowered.asm.mixin.injection.At.Shift.NONE
      • slice

        java.lang.String slice
        The id of the Slice that should be passed to the injection point to narrow down the amount of resulting matched instructions. This should be the preferred way of selecting one specific instruction from a pool of otherwise similar instructions as this would be the least brittle option - provided the slices are not used carelessly.

        Note that micromixin-transformer as well as the accompanying documentation only partly implements Slice.id() as well as slice(); significant derivations are to be expected between micromixin-transformer's behaviour (as well as the documented behaviour) and the spongeian transformer behaviour (as well as it's documentation). As such, usage of these attributes ought to be avoided in environments where usage of micromixin-transformer is expected and the spongeian documentation should be consulted before making use of this attribute.

        Returns:
        The id of the Slice to use, as per Slice.id().
        Default:
        ""
      • target

        java.lang.String target

        The target attribute is a discriminator with whom the chosen instructions can be constrained with more specific accuracy if the injection point isn't descriptive enough as-is.

        This attribute should match to a method for INVOKE, INVOKE_ASSIGN and INVOKE_STRING. It should match to a field for FIELD and match to a class/descriptor (can be an array) for NEW.

        The following are all valid formats of explicit target selectors:

        • targetMethod
        • targetMethod(Lcom/example/Argument;)V
        • (Lcom/example/Argument;)V
        • targetMethod(I)Lcom/example/ReturnValue;
        • targetMethod()Z
        • Lcom/example/Target;targetMethod(Lcom/example/Argument;)V
        • Lcom/example/Target;(Lcom/example/Argument;)V
        • Lcom/example/Target;targetMethod(Lcom/example/Argument;) V
        • Lcom/example/Target;target Method(Lcom/example/Argument;)V
        • Lcom/example/Target;targetMethod(Lcom/exam ple/Argument;)V

        The parts of the explicit target selector (owner, name, descriptor) must always have the same order, but the individual parts must not necessarily be present.

        While permissible, it is strongly discouraged to make use of whitespace in explicit target selectors. When they are used, the spongeian mixin implementation (and also micromixin) will discard all whitespace characters (tabs included). This is documented behaviour (in both micromixin and sponge's mixin) and is unlikely to change in the future. This discouragement exists as this feature may cause target selectors to be illegible.

        Warning: Depending on your platform and tooling, not specifying a fully qualified reference may cause errors. On SLL there will be no issues at runtime (with either micromixin or the spongeian mixin implementation), however other platforms and tooling may not be so considerate. Especially remappers (which are recommended if not necessary in obfuscated environments) may struggle with incompletely qualified targets.

        Hint: Usage of desc() should be preferred over target() if possible. However, beware that doing so may not be viable depending on your platform. Please heed the advice provided in the documentation of desc() and the documentation of your platform and other tooling.

        Returns:
        A target selector to use as a constraint.
        See Also:
        Inject.method()
        Default:
        ""