Minecraft 1.19.2 Fabric模组开发 09.Mixin

我们今天用mixin在1.19.2 fabric中实现一个望远镜

1.由于fabric已经自动配置好了mixin,所以我们无需配置mixin,先在ItemInit中新建一个我们的望远镜物品:

ItemInit.java

    public static final Item BIRDWATCHER =  registerItem("birdwatcher",
    		new Item(new FabricItemSettings().group(ModMain.ITEMTAB).maxCount(1)));

2.新建一个Zoom类用来对望远镜的放大效果进行渲染:

Zoom.java

package net.joy187.joyggd;

import org.lwjgl.glfw.GLFW;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.Version;
import net.joy187.joyggd.init.ItemInit;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.math.MathHelper;

public enum Zoom
{
	INSTANCE;
	
	public static final MinecraftClient MC = MinecraftClient.getInstance();
	
	private final double defaultLevel = 1;
	private Double currentLevel;
	private Double defaultMouseSensitivity;
	
	//返回实时改变的放大倍率
	public double changeFovBasedOnZoom(double fov)
	{
		SimpleOption<Double> mouseSensitivitySetting =
			MC.options.getMouseSensitivity();
		
		if(currentLevel == null)
			currentLevel = defaultLevel;
		
		if(!Screen.hasShiftDown() && (MC.player.getMainHandStack().getItem()!=ItemInit.BIRDWATCHER))
		{
			currentLevel = defaultLevel;
			
			if(defaultMouseSensitivity != null)
			{
				mouseSensitivitySetting.setValue(defaultMouseSensitivity);
				defaultMouseSensitivity = null;
			}
			
			return fov;
		}
		
		if(defaultMouseSensitivity == null)
			defaultMouseSensitivity = mouseSensitivitySetting.getValue();
			
		// Adjust mouse sensitivity in relation to zoom level.
		// 1.0 / currentLevel is a value between 0.02 (50x zoom)
		// and 1 (no zoom).
		mouseSensitivitySetting
			.setValue(defaultMouseSensitivity * (1.0 / currentLevel));
		
		return fov / currentLevel;
	}
	
	//鼠标滚动来调整放大倍率
	public void onMouseScroll(double amount)
	{
		if(isScope())
		{
		if(currentLevel == null)
			currentLevel = defaultLevel;
		
		if(amount > 0)
			currentLevel *= 1.1;
		else if(amount < 0)
			currentLevel *= 0.9;	
		currentLevel = MathHelper.clamp(currentLevel, 1, 60);		
		}

		return;
		
	}
    //判断是否开镜	
	public boolean isScope()
	{
		return Screen.hasShiftDown() 
				&& (MC.player.getMainHandStack().getItem()==ItemInit.BIRDWATCHER);
	}

}

3.我们需要在按下shift键时出现一个望远镜的镜头,所以需要新建一个客户端屏幕渲染类ClientEvents

ClientEvents.java

package net.joy187.joyggd;

import java.awt.event.InputEvent;

import com.mojang.blaze3d.systems.RenderSystem;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents.AfterMouseScroll;
import net.joy187.joyggd.init.ItemInit;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.input.Input;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Matrix4f;

public class ClientEvents implements HudRenderCallback {
    //这个是我们望远镜的镜头贴图
    private static final Identifier VIEWFINDER = new Identifier(ModMain.MOD_ID, "textures/gui/assassin.png");

    public static final float MAX_FOV = 90F;
    public static final float MIN_FOV = 5F;

    //对贴图进行渲染
    @Override
    public void onHudRender(MatrixStack matrixStack, float tickDelta) {
        int x = 0;
        int y = 0;
        //贴图的宽度
        float imageWidth = 192F;
        //贴图高度
        float imageHeight = 100F;
        float hnew=0;
        float wnew=0;
        MinecraftClient client = MinecraftClient.getInstance();
        if (client != null) {
            int width = client.getWindow().getScaledWidth();
            int height = client.getWindow().getScaledHeight();
            
            float rs = width / height;
            float ri = imageWidth / imageHeight;
            
            
	        if (rs > ri) {
	          wnew = width;
	          hnew = height;
	        } else {
		      wnew = width;
		      hnew = height;
	        }
	        x = Math.round((height - hnew) / 2F);
	        y = Math.round((width - wnew) / 2F);
	        
	        
	        RenderSystem.setShader(GameRenderer::getPositionTexShader);
	        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
	        RenderSystem.setShaderTexture(0, VIEWFINDER);
	        //如果玩家手持望远镜并且按下了shift键,就进行渲染
	        if(Screen.hasShiftDown() && client.player.getMainHandStack().getItem()==ItemInit.BIRDWATCHER)
	        {
		        for(int i = 0; i < 1; i++) {
		            DrawableHelper.drawTexture(matrixStack,x,y, 0 , 0,Math.round(wnew),Math.round(hnew),
		            		Math.round(wnew),Math.round(hnew));
		        }
	        }
        }
    }
}

4.Java包中新建一个mixin包,包中新建3个文件GameRendererMixin.java,MouseMixin.java,PlayerInventoryMixin.java

游戏内渲染放大效果

GameRendererMixin.java

package net.joy187.joyggd.mixin;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import net.joy187.joyggd.ClientEvents;
import net.joy187.joyggd.Zoom;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.resource.SynchronousResourceReloader;


@Mixin(GameRenderer.class)
public abstract class GameRendererMixin
	implements AutoCloseable, SynchronousResourceReloader
{
	@Inject(at = @At(value = "RETURN", ordinal = 1),
		method = {"getFov(Lnet/minecraft/client/render/Camera;FZ)D"},
		cancellable = true)
	private void onGetFov(Camera camera, float tickDelta, boolean changingFov,
		CallbackInfoReturnable<Double> cir)
	{
		cir.setReturnValue(
		        //渲染望远镜的放大效果
				Zoom.INSTANCE.changeFovBasedOnZoom(cir.getReturnValueD()));
	}
	
}

鼠标滚动调整放大倍率

MouseMixin.java

package net.joy187.joyggd.mixin;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.joy187.joyggd.Zoom;
import net.minecraft.client.Mouse;

@Mixin(Mouse.class)
public class MouseMixin
{
	@Inject(at = {@At("RETURN")}, method = {"onMouseScroll(JDD)V"})
	private void onOnMouseScroll(long long_1, double double_1, double double_2,
		CallbackInfo ci)
	{
	    //改变鼠标滚轮效果
		Zoom.INSTANCE.onMouseScroll(double_2);
	}
}

改变玩家物品栏的鼠标滚轮效果

PlayerInventoryMixin.java

package net.joy187.joyggd.mixin;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.joy187.joyggd.Zoom;
import net.minecraft.entity.player.PlayerInventory;

@Mixin(PlayerInventory.class)
public class PlayerInventoryMixin
{
	@Inject(at = {@At("HEAD")},
		method = {"scrollInHotbar(D)V"},
		cancellable = true)
	private void onScrollInHotbar(double scrollAmount, CallbackInfo ci)
	{
	    //如果拿到放大镜,就锁定该物品栏
		if(Zoom.INSTANCE.isScope())
			ci.cancel();
	}
}

5.在资源包中新建一个mixin文件,将上一步中的mixin都加入到方法中:

Minecraft 1.19.2 Fabric模组开发 09.Mixin_第1张图片
joyggd.mixins.json

{
  "required": true,
  "minVersion": "0.8",
  "package": "net.joy187.joyggd.mixin",
  "compatibilityLevel": "JAVA_17",
  "mixins": [
  ],
  "client": [
    //加入这3个mixin文件名称
    "GameRendererMixin",
    "MouseMixin",
    "PlayerInventoryMixin"
  ],
  "injectors": {
    "defaultRequire": 1
  }
}

同时修改一下模组信息文件fabric.mod,指定mixin的路径:

fabric.mod.json

{
  "schemaVersion": 1,
  "id": "joyggd",
  "version": "0.1",

  "name": "Mine Goose Duck Mod",
  "description": "Just have fun in the Goose Goose Duck world!",
  "authors": [
    "joy187"
  ],
  "contact": {
    "homepage": "https://fabricmc.net/",
    "sources": "https://github.com/FabricMC/fabric-example-mod"
  },

  "license": "MIT License",
  "icon": "assets/joyggd/icon.png",

  "environment": "*",
  "entrypoints": {
    "main": [
      "net.joy187.joyggd.ModMain"
    ],
    "client": [
      "net.joy187.joyggd.ModClient"
    ]
  },
  //指定上面minxin文件名称
  "mixins": [
    "joyggd.mixins.json"
  ],

  "depends": {
    "fabricloader": ">=0.14.8",
    "fabric-api": "*",
    "fabric": "*",
    "minecraft": "~1.19",
    "java": ">=17"
  },
  "suggests": {
    "another-mod": "*"
  }
}

在资源包中的lang文件夹中添加物品名称:

en_us.json

  "item.joyggd.birdwatcher":"Birdwatcher",

models/item中添加物品模型:

birdwatcher.json

{
  "parent":"minecraft:item/generated",
  "textures":{
    "layer0":"joyggd:item/birdwatcher"
  }
}

在texture中分别添加物品模型和望远镜镜头模型:

Minecraft 1.19.2 Fabric模组开发 09.Mixin_第2张图片

6.保存文件,进行调试。

如果你手持望远镜按住shift键成功开镜,之后鼠标滚轮实现了视野放大/缩小功能,那么说明你成功了!

你可能感兴趣的:(我的世界Fabric,fabric,java,minecraft)