Mixins are a powerful and important tool used in the Fabric ecosystem. Their primary use case is modifying existing code in the base game, whether it be through injecting custom logic, removing mechanics, or modifying values. Note that mixins must be written in Java, even if you use Kotlin or another language.
You need to do the following:
yourmod/src/main/java/yourmodname/mixin
SomethingMixin.java
.src/main/resources/yourmod.mixins.json
{
"required": true,
"minVersion": "0.8",
"package": "deus.rune.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"EntityLivingMixin",
"EntityMixin",
"EntityPlayerMixin",
"EntityPlayerMPMixin",
"EntityPlayerSPMixin",
"MinecraftMixin"
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}
package your.package.name;
import net.minecraft.client.render.window.GameWindow;
import net.minecraft.core.entity.Entity;
import net.minecraft.core.entity.player.EntityPlayer;
import net.minecraft.core.player.inventory.InventoryPlayer;
import net.minecraft.core.util.helper.DamageType;
import net.minecraft.core.world.World;
import org.checkerframework.checker.units.qual.A;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList;
import java.util.List;
import static your.package.name.YourMod.MOD_CONFIG;
@Mixin(EntityPlayer.class)
public abstract class EntityPlayerMixin {
/**
* The `@Inject` annotation in a mixin is used to inject additional behavior into an existing method.
*
* - `@At` specifies where the injection should occur:
* - `RETURN`: Inject the method just before the return statement of the target method.
* - `TAIL`: Inject the method at the end of the target method.
* - `HEAD`: Inject the method at the beginning of the target method.
*
* - `remap`: Determines whether to remap the target method if it is obfuscated.
*/
@Inject(method = "methodMixinReference", at = @At("RETURN"), cancellable = true, remap = false)
private void modifyMaxHealth(CallbackInfoReturnable<Integer> cir) {
// Modify the return value of the method.
cir.setReturnValue(10); // Half of the original life value.
}
/**
* The `@Redirect` annotation in a mixin is used to redirect method calls to your custom implementation.
*
* - `@At` specifies where the redirection should occur:
* - `value = "INVOKE"`: Redirect the method call when the target method is invoked.
* - `target`: Defines the method to which the call should be redirected.
*
* - `remap`: Determines whether to remap the target method if it is obfuscated.
*/
@Redirect(
method = "attackTargetEntityWithCurrentItem(Lnet/minecraft/core/entity/Entity;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/core/player/inventory/InventoryPlayer;getDamageVsEntity(Lnet/minecraft/core/entity/Entity;)I"),
remap = false
)
private int redirectGetDamageVsEntity(InventoryPlayer inventory, Entity entity) {
// Return a custom damage value instead of the original method's result.
return randomValue;
}
}
Using an interface is a way to add your own methods to vanilla Minecraft classes.
If you want to add functionality to make the player’s punches stronger, follow these steps:
IEntityPlayerAccessor.java
, to declare the methods you want to add.By using interfaces, you can extend vanilla Minecraft classes with custom behavior without directly modifying the game’s source code.
package your.package.name;
public interface IEntityAccessor {
boolean ModName$isCoveredInFlames();
void ModName$setIsInvulnerableFire(boolean value);
}
The @Shadow
annotation is used in mixins to indicate that a method or field in a mixin class corresponds to a private or protected method or field in the target class. It allows the modder to access or modify those elements without directly altering the original code, maintaining compatibility and avoiding conflicts with other mods
package your.package.name;
import your.package.name.interfaces.IEntityAccessor;
import net.minecraft.core.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Entity.class)
public abstract class EntityMixin implements IEntityAccessor {
@Shadow
protected boolean fireImmune;
@Shadow
public int remainingFireTicks;
@Override
public boolean ModName$getIsInvulnerableFire() {
return fireImmune;
}
@Override
public void ModName$setIsInvulnerableFire(boolean value) {
fireImmune = value;
}
@Override
public int ModName$getRemainingFireTicks() {
return remainingFireTicks;
}
@Override
public boolean ModName$isCoveredInFlames() {
return !(remainingFireTicks <= 0);
}
}
// When you have an entity variable reference, you need to do this:
IEntityAccesor customEntity = (IEntityAccesor) entityReference;
customEntity.ModName$setIsInvulnerableFire(true)
https://github.com/Garkatron/BTA-Rune/tree/7.2