Package org.spongepowered.asm.mixin.injection

## Annotation Type ModifyArg

-     @Target(METHOD)
      @Retention(RUNTIME)
      public @interface ModifyArg

  Specifies that this mixin method should inject an argument modifier to itself in the target method(s) identified by `method()`. This type of injection provides a lightweight mechanism for changing a single argument of a selected method invocation within the target method(s). To affect multiple arguments of an invocation all at once, use `ModifyArgs` instead.

  Use this injector when a (target) method contains an method invocation (the subject) and you wish to change a single value being passed to that subject method. If you need to alter an argument received by a target method, use `ModifyVariable` instead.

  Consider the following method:

  >     private void targetMethod() {
  >         Entity someEntity = this.obtainEntity();
  >         float x = 1.0F, y = 3.0F, z = 0.1F;
  >         someEntity.setLocation(x, y, z, true); // subject
  >     }

  Let us assume that we wish to modify the `y` value when calling the `setLocation` method. We know that the arguments are `float`s and that the `y` value is the second (index = 1) `float` argument. Thus our injector requires the following signature:

  > `@ModifyArg(method = "targetMethod", at = @At(value = "INVOKE", target = "setLocation(FFFZ)V"), index = 1)
  > private float adjustYCoord(float y) {
  > return y + 64.0F;
  > }`

  The callback consumes the original value of `y` and returns the adjusted value.

  `@ModifyArg` can also consume all of the subject method's arguments if required, to provide additional context for the callback. In this case the arguments of the callback should match the target method:

  > `@ModifyArg(method = "targetMethod", at = @At(value = "INVOKE", target = "setLocation(FFFZ)V"), index = 1)
  > private float adjustYCoord(float x, float y, float z, boolean interpolate) {
  > return (x == 0 && y == 0) ? 0 : y;
  > }`

  Note that `@ModifyArg` cannot capture the arguments of the target method like some other injectors can

- - ### Required Element Summary

    Required Elements
    Modifier and Type | Required Element | Description
    --- | --- | ---
    `At` | `at` | An `At` annotation which describes the `InjectionPoint` in the target method.

  - ### Optional Element Summary

    Optional Elements
    Modifier and Type | Optional Element | Description
    --- | --- | ---
    `int` | `allow` | Injection points are in general expected to match every candidate instruction in the target method or slice, except in cases where options such as `At.ordinal()` are specified which naturally limit the number of results.
    `java.lang.String` | `constraints` | Returns constraints which must be validated for this injector to succeed.
    `int` | `expect` | Like `require()` but only enabled if the `mixin.debug.countInjections` option is set to `true` and defaults to 1.
    `int` | `index` | Gets the argument index on the target to set.
    `java.lang.String[]` | `method` | String representation of one or more `target selectors` which identify the target methods.
    `int` | `order` | By default almost all injectors for a target class apply their injections at the same time.
    `boolean` | `remap` | By default, the annotation processor will attempt to locate an obfuscation mapping for all `ModifyArg` methods since it is anticipated that in general the target of a `ModifyArg` annotation will be an obfuscated method in the target class.
    `int` | `require` | In general, injectors are intended to "fail soft" in that a failure to locate the injection point in the target method is not considered an error condition.
    `Slice` | `slice` | A `Slice` annotation which describes the method bisection used in the `at()` query for this injector.
    `Desc[]` | `target` | Literal representation of one or more `@Desc` annotations which identify the target methods.

- - ### Element Detail

    - #### at

          At at

      An `At` annotation which describes the `InjectionPoint` in the target method. The specified `InjectionPoint` must only return `MethodInsnNode` instances and an exception will be thrown if this is not the case.
      Returns:
        `At` which identifies the target method invocation

  - - #### method

          java.lang.String[] method

      String representation of one or more `target selectors` which identify the target methods.
      Returns:
        target method(s) for this injector
      Default:
        {}

  - - #### target

          Desc[] target

      Literal representation of one or more `@Desc` annotations which identify the target methods.
      Returns:
        target method(s) for this injector as descriptors
      Default:
        {}

  - - #### slice

          Slice slice

      A `Slice` annotation which describes the method bisection used in the `at()` query for this injector.
      Returns:
        slice
      Default:
        @org.spongepowered.asm.mixin.injection.Slice

  - - #### index

          int index

      Gets the argument index on the target to set. It is not necessary to set this value if there is only one argument of the modifier type in the hooked method's signature. For example if the target method accepts a boolean, an integer and a String, and the modifier method accepts and returns an integer, then the integer parameter will be automatically selected.

      The index is zero-based.

      Returns:
        argument index to modify or -1 for automatic
      Default:
        -1

  - - #### remap

          boolean remap

      By default, the annotation processor will attempt to locate an obfuscation mapping for all `ModifyArg` methods since it is anticipated that in general the target of a `ModifyArg` annotation will be an obfuscated method in the target class. However since it is possible to also apply mixins to non-obfuscated targets (or non- obfuscated methods in obfuscated targets, such as methods added by Forge) it may be necessary to suppress the compiler error which would otherwise be generated. Setting this value to false will cause the annotation processor to skip this annotation when attempting to build the obfuscation table for the mixin.
      Returns:
        True to instruct the annotation processor to search for obfuscation mappings for this annotation
      Default:
        true

  - - #### require

          int require

      In general, injectors are intended to "fail soft" in that a failure to locate the injection point in the target method is not considered an error condition. Another transformer may have changed the method structure or any number of reasons may cause an injection to fail. This also makes it possible to define several injections to achieve the same task given expected mutation of the target class and the injectors which fail are simply ignored.

      However, this behaviour is not always desirable. For example, if your application depends on a particular injection succeeding you may wish to detect the injection failure as an error condition. This argument is thus provided to allow you to stipulate a minimum number of successful injections for this callback handler. If the number of injections specified is not achieved then an `InjectionError` is thrown at application time. Use this option with care.

      Returns:
        Minimum required number of injected callbacks, default specified by the containing config
      Default:
        -1

  - - #### expect

          int expect

      Like `require()` but only enabled if the `mixin.debug.countInjections` option is set to `true` and defaults to 1. Use this option during debugging to perform simple checking of your injectors. Causes the injector to throw a `InvalidInjectionException` if the expected number of injections is not realised.
      Returns:
        Minimum number of expected callbacks, default 1
      Default:
        1

  - - #### allow

          int allow

      Injection points are in general expected to match every candidate instruction in the target method or slice, except in cases where options such as `At.ordinal()` are specified which naturally limit the number of results.

      This option allows for sanity-checking to be performed on the results of an injection point by specifying a maximum allowed number of matches, similar to that afforded by `Group.max()`. For example if your injection is expected to match 4 invocations of a target method, but instead matches 5, this can become a detectable tamper condition by setting this value to `4`.

      Setting any value 1 or greater is allowed. Values less than 1 or less than `require()` are ignored. `require()` supercedes this argument such that if `allow` is less than `require` the value of `require` is always used.

      Note that this option is not a limit on the query behaviour of this injection point. It is only a sanity check used to ensure that the number of matches is not too high

      Returns:
        Maximum allowed number of injections for this
      Default:
        -1

  - - #### constraints

          java.lang.String constraints

      Returns constraints which must be validated for this injector to succeed. See `ConstraintParser.Constraint` for details of constraint formats.
      Returns:
        Constraints for this annotation
      Default:
        ""

  - - #### order

          int order

      By default almost all injectors for a target class apply their injections at the same time. In other words, if multiple mixins target the same class then injectors are applied in priority order (since the mixins themselves are merged in priority order, and injectors run in the order they were merged). The exception being redirect injectors, which apply in a later pass.

      The default order for injectors is `1000`, and redirect injectors use `10000`.

      Specifying a value for `order` alters this default behaviour and causes the injector to inject either earlier or later than it normally would. For example specifying `900` will cause the injector to apply before others, while `1100` will apply later. Injectors with the same `order` will still apply in order of their mixin's `priority`.

      Returns:
        the application order for this injector, uses DEFAULT (1000) if not specified
      Default:
        1000