6 | Modifying Arguments
What is ModifyArg?
Consider the following method
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
@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.
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
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
@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
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
@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
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
Last updated
Was this helpful?