Files
netease-modsdk-wiki/docs/mconline/60-我的世界创造营教程/网络游戏开服教程/3-客户端效果的制作/2-自定义物品制作.md
boybook 760c2dd9ad 2.6
2025-12-01 20:59:16 +08:00

202 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 自定义物品制作
<iframe src="https://cc.163.com/act/m/daily/iframeplayer/?id=64818e58c31a9c0f360dc5f2" width="800" height="600" allow="fullscreen"/>
基于目前Spigot服相关接口、自定义物品流程Spigot服的自定义物品实际上是原生Java物品的换皮物品客户端Mod利用字段**java_identifier**来标识
在玩家通过Geyser转发之后利用**java_identifier**实现基岩版自定义物品和Java版物品的映射。
因此要实现自定义物品,我们不仅需要在服务端编写相关逻辑,还需要定义客户端行为包和资源包文件。
## 客户端定义物品
首先提前准备好一个服务端插件,这里命名为`testItem`。除此之外为了更加方便地编辑客户端物品我们可以另外再创建一个空白Addon用来完成物品之后复制到插件中。
编辑新创建的空白附加包,在编辑器中,首先在右上角作品菜单中,修改命名空间。教程中命名空间修改为`testitem`
![](./images/18.png)
找到资源管理的新建按钮->配置->物品。
![](./images/17.png)
接下来填写文件命名,同时它也是物品名,例如这里填写`example`。模板选择自定义武器。
**那么这个物品的标识符就是`命名空间:物品名`,即`testitem:example`。**
![](./images/19.png)
接下来我们可以给这个物品设置贴图贴图我们可以使用Spigot示例Demo中的武器贴图。
在资源管理中,点击导入,选择贴图,物品贴图。
![](./images/20.png)
找到目录`SpigotDemo\CustomItemDemo\CustomItemClientMod\resource_packs\CustomItemsMod_resource\textures\items`,导入`customitems_test_sword`,作为自定义武器的贴图。
如果你足够熟悉附加包的目录结构,也可以直接打开作品文件夹,将贴图复制到`资源包/textures/items`目录中,也可以不使用编辑器的贴图导入功能。
接下来在右侧属性窗口中,选择刚刚导入的贴图,也可以根据自己的需要,修改`游戏内名字`,它将会作为物品的默认物品名。
![](./images/21.png)
编辑完成后,点击`配套文件`中的`物品行为文件`后面的`打开文件`按钮。
![](./images/24.png)
在文件中添加`java_identifier`字段。这个字段用来表示在Java服中它所对应的实际的物品的标识符。
```json
{
"format_version": "1.10",
"minecraft:item": {
"components": {
"minecraft:max_damage": 10,
"netease:weapon": {
"attack_damage": 12,
"enchantment": 10,
"level": 3,
"speed": 5,
"type": "sword"
}
},
"description": {
"category": "Equipment",
"identifier": "testitem:example"
},
"java_identifier": "wooden_sword"
}
}
```
例如这里填写`wooden_sword`那么在Java服中木剑将尝试换皮为我们创建的自定义物品。
在编辑器的属性窗口中还包含了一些行为包组件。需要注意的是因为自定义物品本质上是Java版物品换皮这里的大多数属性都只是用来给客户端设置物品的表现的很多属性都无法生效。
### **需要注意的点**
- 字段工具挖掘速度、挖掘等级需要和Java物品对应不然会出现方块破坏速率不一致导致的卡方块现象。对应物品json中 `"netease:weapon":{ "type":"shovel", "level":0, "speed":2 }`
具体对应关系如下:
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| type | str | | 武器/工具的类型,目前支持类型有: sword剑 shovel铲 pickaxe镐 hatchet斧 hoe锄头 |
| level | int | | level为0当速度为2对应木板,否则对应金锭 level为1对应石头 level为2对应铁锭 level为3对应钻石 level大于3无法使用铁砧修复 |
| speed | int | 0 | 对采集工具生效,表示挖掘方块时的基础速度 木头2 石头4 铁6 钻石8 金12 |
使用编辑器,可以直接在`行为包组件中`进行修改,在`武器属性`中,选择对应的`类型``工具等级``挖掘基础速度`
- 同理盔甲字段json中需要和Java物品对应 `"netease:armor":{ "armor_slot":2 }` 盔甲槽位,详见[ ArmorSlotType](https://mc.163.com/dev/mcmanual/mc-dev/mcdocs/1-ModAPI/枚举值/ArmorSlotType.html)。使用编辑器,可以直接在`盔甲穿戴属性`类别中就可以选择槽位。
也有部分行为包组件不会生效,目前已知的有
````
- 基岩版自定义物品中用于物品防火的组件
```
设置物品是否防火
"netease:fire_resistant"{ "value" : true}
```
- 基岩版自定义物品中用于物品是否可做燃料的组件
```
设置物品是否可作为燃料
"netease:fuel" { "value" : true}
```
- 基岩版自定义物品中用于物品的使用间隔
```
设置物品使用间隔
"netease:cooldown" : { "duration" : 5}
```
````
完成了客户端物品的配置,我们就可以关闭编辑器。
打开附加包文件夹,将资源包和行为包目录中的部分涉及到自定义物品的内容,复制到`testItem`插件中的对应位置。
### 行为包
- netease_items_beh
![](./images/22.png)
### 资源包
- netease_items_res
- texts
- textures
![](./images/23.png)
至此,我们就完成了客户端物品的定义。
## 服务端逻辑
首先新建一个项目依赖SpigotMaster。
### 创建物品
```java
ItemStack itemStack = new ItemStack(Material.WOOD_SWORD);
itemStack = spigotMaster.setCustomItemIdentifier(itemStack, "testitem:example");
```
像正常Spigot插件一样直接实例化ItemStack来新建一个物品物品的Material为`java_identifier`字段中的值,即木剑。
然后调用spigotMaster的`setCustomItemIdentifier`方法,为这个物品设置自定义物品标识符,即`testitem:example`。
### 获取物品
```java
String customIdentifier = spigotMaster.getCustomItemIdentifier(itemStack);
```
调用spigotMaster的`getCustomItemIdentifier`方法来获取自定义物品标识符。如果是自定义物品返回标识符否则返回null。
我们可以编写测试一些测试用监听器,查看自定义物品如何生效。
```java
public class Listeners implements Listener {
private final SpigotMaster spigotMaster = TutorialItem.getInstance().getSpigotMaster();
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player player = e.getPlayer();
ItemStack itemStack = new ItemStack(Material.WOOD_SWORD);
itemStack = spigotMaster.setCustomItemIdentifier(itemStack, "testitem:example");
player.getInventory().addItem(itemStack);
}
@EventHandler
public void onInteract(PlayerInteractEvent e) {
Player player = e.getPlayer();
ItemStack itemStack = player.getInventory().getItemInMainHand();
if (itemStack == null) {
return;
}
String customIdentifier = spigotMaster.getCustomItemIdentifier(itemStack);
if (customIdentifier == null) {
player.sendMessage("你手持的物品不是自定义物品");
return;
}
player.sendMessage("你手持的物品的自定义ID为: " + customIdentifier);
}
}
```
安装插件到服务器,然后勾选`testItem`,重新部署。
进入游戏后,可以看到背包发送了一个我们的自定义物品。
![](./images/25.png)
对物品交互可以看到正常输出成功获取到了自定义物品的identifier。
![](./images/26.png)