# 6 | Modifying Arguments

### What is ModifyArg?

Consider the following method

```java
private void aMethod() {
    System.out.println("No. 4561!");
    System.out.println("HElooo 25!");
    System.out.println("idk 356!");
    System.out.println("interesting 46!");
    System.out.println("Hi! 5!");
    System.out.println("Hello 1!");
    System.out.println("no? 456!");
    System.out.println("Bye 48!");
    System.out.println("ALLRIGHt 33!");
    System.out.println("lol 10!");
}
```

As you can clearly observe, it consists of a set print statements, which outputs 10 strings with no noticeable pattern.

So, what if I wanted to change the text `"Hi! 5!"` to `"Hello world!"`?

With our current knowledge all we could do is `@Overwrite` it, but this becomes very painful with larger method bodies with functions/variables that need `@Shadow`'ing (I will talk about shadowing later)

So what do we do?

May I introduce you to `@ModifyArg`; a neat function that allows us to modify the arguments of a method in a function

In the example provided, we can use `@ModifyArg` like so

```java
@ModifyArg(method = "aMethod", at = @At(
            value = "INVOKE",
            target = "Ljava/io/PrintStream;println(Ljava/lang/String;)V",
            ordinal = 4),
           index = 0)
private String modifyOutput(String x) {
    return "Hello World!";
}
```

Since we've already covered most of what's going on inside that annotation, all we need to cover is the `ordinal` and the `index` .

* `ordinal = 4` (optional)
  * This allows you to set an offset of which `println` statement you actually want to modify, indexed by zero, in this case, it was set to 4, meaning that the 4th zero indexed println statement's arguments will be modified
* `index = 0`
  * This is the last parameter that we have set, which isn't inside the `@At` statement, this allows us to select which argument in the function we want to modify (indexed by zero)

Lastly, the return statement, `return "Hello World!"`, just returns what we want that argument to be

### Modify Arg cont. <a href="#more-context" id="more-context"></a>

What happens if the argument we want to modify depends on all of the other arguments being passed in?

Say, instead of `println` accepting 1 argument (`String`), rather, it accepted 2 arguments, your message, and the number of times you want it to be printed

```java
private void aMethod() {
    System.out.println("No. 4561!", 5);
    System.out.println("HElooo 25!", 3);
    System.out.println("idk 356!", 45);
    System.out.println("interesting 46!", 34);
    System.out.println("Hi! 5!", 34);
    System.out.println("Hello 1!", 42);
    System.out.println("no? 456!", 4);
    System.out.println("Bye 48!", 1);
    System.out.println("ALLRIGHt 33!", 99);
    System.out.println("lol 10!", 27);
}
```

In this example, once again, we want to change the text of `"Hi! 5!"` to `"Hello world!"`, but this time we also want to add the number of times it will repeat to it (ie: `"Hello World! (34)"`)

It's as simple as adding the extra arguments to the function, like shown below

```java
@ModifyArg(method = "aMethod", at = @At(
            value = "INVOKE",
            target = "Ljava/io/PrintStream;println(Ljava/lang/String;I)V",
            ordinal = 4),
           index = 0)
private String modifyOutput(String x, int nTimesToRepeat) {
    return "Hello World! (" + nTimesToRepeat + ")";
}
```

### ModifyArg vs Modify Args <a href="#what-is-modifyargs" id="what-is-modifyargs"></a>

While going through this tutorial, you might've noticed that there's another annotation called `ModifyArgs` instead of `ModifyArg` . So, what's the difference?

Well, using the former example where `println` has 2 arguments, a message and a number of times to print that message, we can modify multiple arguments like so

```java
@ModifyArgs(method = "aMethod", at = @At(
            value = "INVOKE",
            target = "Ljava/io/PrintStream;println(Ljava/lang/String;I)V",
            ordinal = 4))
private void modifyOutput(Args args) {
    String x = args.get(0);
    int nTimesToRepeat = args.get(1);

    args.set(0, "Hello world! (" + nTimesToRepeat + ")");
    args.set(1, nTimesToRepeat + 20);
}
```

Args? What's that?

`Args` is a class provided by `Mixin` that provides 2 major methods

* `args.get(int index)`
  * This allows you to retrieve one of the function's arguments be index
* `args.set(int index, T value)`
  * This allows you to set an arguments value by index

An annotated example of `ModifyArgs` is shown below

```java
String x = args.get(0); // Get the first argument, the string
int nTimesToRepeat = args.get(1); // Get the second argument, the number of times to repeat the message

args.set(0, "Hello world! (" + nTimesToRepeat + ")"); // Set the first argument to the string "Hello world! (n)", with n being the number of times to repeat
args.set(1, nTimesToRepeat + 20); // This takes the number of times to repeat, and adds the value 20 to it
```

###
