Minecraft 1.19.2 Fabric模组开发 09.Mixin

news2024/11/9 2:06:47

我们今天用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都加入到方法中:

cr1.jpg
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中分别添加物品模型和望远镜镜头模型:

cr2.jpg

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185378.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Smart-doc的脚本生成在线文档(精简官方文档描述)

Smart-doc优点&#xff1a; 无侵入的接口文档、在线文档生成器。三种生成文档方式。对于程序代码开发中只需要加注释&#xff08;符合一定的语法&#xff0c;五分钟可掌握&#xff09;就能生成在线文档。可以支持c、java、php、node等等常见的主流语言。 如何使用&#xff1a; …

47.Isaac教程--ORB

ORB ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录ORBGem 提供的类型关键点描述符如何使用 Gem&#xff08;界面&#xff09;构建包Isaac Codelets示例应用程序主机设备嵌入式 Jetson 设备这个 gem 提供了一个特征检测器和描述符提取器…

2011年专业408算法题

文章目录0 结果1 题目2 思路2.1 思路1&#xff08;暴力解&#xff1a;排序&#xff09;2.2 思路2&#xff08;较优解&#xff1a;归并合并数组&#xff09;2.3 思路3&#xff08;较优解&#xff1a;数组指针后移&#xff09;2.4 思路4&#xff08;最优解&#xff1a;两个数组的…

webpack是如何进行依赖图谱收集的?

我自己学习webpack已有很长时间了&#xff0c;但是经常会遇到这样的问题: 可以熟练配置webpack的一些常用配置&#xff0c;但是对一些不常见的api或者概念总是云里雾里。因此&#xff0c;对着网上资料手写了一个简易版的webpack&#xff0c;现在对其中的依赖图谱收集部分进行梳…

Numpy(7)—字节交换、NumPy 副本和视图、深浅拷贝、矩阵库、NumPy 线性代数、NumPy IO(读写)、NumPy Matplotlib

1.字节交换 import numpy as npA np.array([1, 256, 8755], dtypenp.int16) print(A) print(list(map(hex, A))) print(A.byteswap(inplaceTrue)) print(list(map(hex, A)))2.NumPy 副本和视图 副本是一个数据的完整的拷贝&#xff0c;如果我们对副本进行修改&#xff0c;它不…

【MyBatis 持久层框架】Mapper代理开发详细解读

文章目录1. 前言2. Mapper 代理开发3. 过程剖析4. 总结1. 前言 前面在 MyBatis 快速入门篇中&#xff0c;我们使用了 MyBatis 原生的开发方式操作数据库&#xff0c;解决了 JDBC 操作数据库时的硬编码和操作繁琐的问题。实际上&#xff0c;在 Java 项目中&#xff0c;我们更常…

python3——函数

目录 一、函数定义 二、函数调用 1.打印Hello World 2.判断最大值 3.计算矩形面积 4.help说明文档 三、参数传递 (一)位置参数 (二)关键字参数 (三)默认参数(缺省参数) (四)可变参数(收集参数) 1.位置可变参数(接收所有的位置参数&#xff0c;返回一个元组) 2.关键…

高通开发系列 - MSM8909 lk aboot阶段点灯操作

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 第一种LK提供的接口实现第二种直接操作寄存器这篇文章之前请参考下:高通开发系列 - MSM8909指示灯操作 在LK中点灯有两种方式,一种…

JAVA-定位排查bug

在开发过程中难免会遇到bug&#xff0c;理解bug的含义&#xff0c;定位bug的位置&#xff0c;对于解决bug至关重要&#xff01;掌握高效的排错技巧&#xff0c;对于程序员来说必不可少。 目录 一、错误异常的分类 二、常见报错信息及原因&#xff08;持续更新中&#xff09;…

域内权限维持:AdminSDHolder

01、简介 AdminSDHolder是一个特殊的AD容器&#xff0c;通常作为某些特权组成员的对象的安全模板。Active Directory将采用AdminSDHolder对象的ACL并定期将其应用于所有受保护的AD账户和组&#xff0c;以防止意外和无意的修改并确保对这些对象的访问是安全的。如果攻击者能完全…

Flex布局和主要属性用法详解

目录 前言 一个小例子 基本概念&#xff1a; 设置在主轴上的排列方式 设置在侧轴上的排列方式 更换主轴和侧轴方向 换行 align-content属性 元素&#xff08;子容器&#xff09;的相关属性 flex-basis flex-grow flex-shrink属性 flex属性 前言 flex布局是继标准…

JDBC-Statement

1.Statement执行静态sql语句&#xff08;“字符串”&#xff09; 返回结果 2.&#xff01;实际工作一般用PreparedStatement来进行sql语句的执行&#xff0c;因为sql注入的风险 3and4.SQl注入就是Statement没有检查我们输入sql语句&#xff0c;一些别有用心的可能写一些危害数据…

智能手表主控芯片盘点,智能手表GUI,智能手表市场

聚焦&#xff1a;无线连接芯片&#xff0c;市场&#xff0c;技术 祝大家新年快乐&#xff0c;开工大吉&#xff01;趁寒假简单梳理了下智能手表应用&#xff0c;做个分享&#xff0c;不对的地方欢迎交流指正&#xff1b; 01 市场容量&#xff0c;分类及拓扑 2个数据供参考 一个…

C++ dll、lib 的定义以及引用,

最近在研究socket&#xff0c;发现socket程序要依赖ws2_32.dll,涉及到动态链接库&#xff0c;有点懵&#xff0c;上网恶补了一下链接库的知识&#xff0c;最后总结出这么一篇文章 链接库分为两种&#xff1a;动态链接库(dll) 和静态链接库(lib) 动态链接库 &#xff1a; 动态链…

【C++】C++11语法解析

&#x1f308;欢迎来到C专栏~~C11 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&#x1f…

大数据分析案例-基于多元线性回归算法构建用户信用评分模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

ue4c++日记9(指定区域生成角色)

目录 创建C类 头文件 代码文件 结果 创建C类 头文件 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "ASPawnVolum.generated…

vSphere with Tanzu概念介绍

vSphere with Tanzu是在vSphere7.0及之后出现的新功能&#xff0c;它可以在虚拟化层创建一个Kubernetes 控制平面&#xff0c;并将vSphere 集群资源转化为Kubernetes集群资源&#xff0c;这样可以直接在ESXI主机上运行Kubernetes工作负载&#xff0c;创建Kubernetes集群并部署容…

测试环境频繁Full GC问题的解决思路

背景 上游调用方&#xff0c;反馈当前welink-front服务不可用&#xff1b; 临时解决办法 手动重启welink-front服务&#xff0c;重启之后观测到业务日志正常刷&#xff0c;说明该问题暂时得到了解决&#xff1b; 但没过多久&#xff0c;上游调用方的同学又找来了&#xff0…

C++ 继承

一. 概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对程序设计的层次结构&#xff0c;体现了由…