Files
netease-modsdk-wiki/docs/mcguide/20-玩法开发/15-自定义游戏内容/2-自定义方块/3-特殊方块/3-自定义农作物方块.md
2025-03-18 14:46:12 +08:00

399 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
---
front:
hard: 入门
time: 分钟
---
# 自定义农作物
## 概述
开发者可以通过以下两种方式实现自定义农作物详见demo [CustomCropMod](../../../13-模组SDK编程/60-Demo示例.md#CustomCropMod)
1通过[netease:transform组件](#netease_transform)定义农作物之间的转换规则;
2通过python脚本监听<a href="../../../../../mcdocs/1-ModAPI/事件/物品.html#serveritemuseonevent" rel="noopenner"> ServerItemUseOnEvent </a>、<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockrandomtickserverevent" rel="noopenner"> BlockRandomTickServerEvent </a>、<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockneighborchangedserverevent" rel="noopenner"> BlockNeighborChangedServerEvent </a>等事件控制方式。
## 公共组件说明
### base_block设置
- **自定义农作物方块的base_block需要设为custom_crop_block**
<span id="netease_transform"></span>
### netease:transform
该组件用于自定义农作物方块之间的转换
| 键 | 类型 | 默认值 | 解释 |
| ---------- | ---- | ------ | ---------------------------------------------------------- |
| conditions | dict | | 农作物方块转换的条件三个条件同时满足时会转化为result方块 |
| result | str | | 农作物方块转换后的方块名称 |
例如:
```json
"netease:transform": {
"conditions": {
"brightness": { # 农作物生长必须满足的光照条件
"max": 15,
"min": 9
},
"random_tick_count": { # 转化需要经过的随机tick次数
"value": 2 # 2表示在第三次随机tick时转化不允许小于等于0的值
},
"surrouding": { # 转化需要的周围方块
"value": "minecraft:sand",
"radius": 1 # 半径
}
},
"result": "minecraft:egg" # 转化为哪种方块
}
```
### minecraft:seed
自定义种子,详见[minecraft:seed](../../1-自定义物品/1-自定义基础物品.md#minecraft_seed)
## 自定义农作物方式一
该方式适用于纯配置json不需要写任何python脚本逻辑。
这种方式包括一个种子(自定义物品)与三种自定义农作物的状态(自定义方块)。
### 1自定义种子
参照[自定义基础物品](../../1-自定义物品/1-自定义基础物品.md)自定义一个农作物种子customcrop:custom_wheat_seeds。
```json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customcrop:custom_wheat_seeds",
"category": "Nature"
},
"components": {
"minecraft:seed": {
"crop_result": "customcrop:customcrop_stage0",# 种子生成的方块
"plant_at": "minecraft:sand" #种植条件
}
}
}
}
```
json说明
该种子的标识为customcrop:custom_wheat_seeds它包含一个minecraft:seed组件其中
| 字段 | 值 | 说明 |
| ----------- | ---------------------------- | ------------------------------------------------------------ |
| crop_result | customcrop:customcrop_stage0 | 种子将生长为customcrop:customcrop_stage0自定义方块 |
| plant_at | minecraft:sand | 该种子只能在“沙子”上种植,种植后其所有的生长状态的下方方块也必须为“沙子”,如果底部的方块被破坏,农作物也将被破坏 |
### 2自定义三种农作物状态
参照[自定义方块](../0-自定义方块概述.md)我们将自定义三种农作物状态分别为customcrop:customcrop_stage0、customcrop:customcrop_stage1、customcrop:customcrop_stage2其中部分json如下所示
#### customcrop:customcrop_stage0
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_stage0",
"base_block": "custom_crop_block"
},
"components": {
...
"netease:transform": {
"conditions": {
"brightness": { # 光照条件
"max": 15,
"min": 9
},
"random_tick_count": { # 随机tick次数条件
"value": 1
},
"surrouding": { # 在半径为1的周围需要存在“沙子”
"value": "minecraft:sand",
"radius": 1
}
},
"result": "customcrop:customcrop_stage1" # 成长下一阶段的方块
},
...
}
}
}
```
#### customcrop:customcrop_stage1
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_stage1",
"base_block": "custom_crop_block"
},
"components": {
...
"netease:transform": {
"conditions": {
"brightness": {
"max": 15,
"min": 9
},
"random_tick_count": {
"value": 1
},
"surrouding": {
"value": "minecraft:sand",
"radius": 1
}
},
"result": "customcrop:customcrop_stage2" # 成长下一阶段的方块
},
...
}
}
}
```
#### customcrop:customcrop_stage2
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_stage2",
"base_block": "custom_crop_block"
},
"components": {
...
"minecraft:loot": {
"table": "loot_tables/blocks/customcrop_stage2.json"
}
...
}
}
}
```
该阶段为农作物的成熟阶段可以通过minecraft:loot的方式获得收获。
### 3成长过程
<img src="../../picture/customcrop/custom_stage_2.jpg" alt="流程" style="zoom:75%;" />
其中中间为阶段一customcrop:customcrop_stage0最右边为阶段二customcrop:customcrop_stage1左边为阶段三customcrop:customcrop_stage2
## 自定义农作物方式二
该方式适用于配置json+python脚本控制。
这种方式包括一个物品(自定义物品)与三种自定义农作物的状态(自定义方块)。
这种方式需要配置[netease:random_tick](../1-JSON组件.md#netease_random_tick)和[netease:block_entity](../1-JSON组件.md#netease_block_entity),使得<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockrandomtickserverevent" rel="noopenner"> BlockRandomTickServerEvent事件 </a>发送到脚本层并且支持[自定义方块实体](../4-自定义方块实体.md),从而实现方块转换的控制以及方块状态的存档。
#### 1自定义物品
在示例mod中该自定义物品为customcrop:custom_item在该物品的使用时通过监听事件<a href="../../../../../mcdocs/1-ModAPI/事件/物品.html#serveritemuseonevent" rel="noopenner"> ServerItemUseOnEvent </a>来判断是否可以在当前位置种植该物品类似customcrop:custom_wheat_seeds的minecraft:seed中的plant_at功能并且通过<a href="../../../../../mcdocs/1-ModAPI/接口/世界/方块管理.html#setblocknew" rel="noopenner"> SetBlockNew </a>设置农作物阶段一customcrop:customcrop_1_stage0
#### 2自定义三种农作物状态
##### customcrop:customcrop_1_stage0
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_1_stage0"
},
"components": {
...
"netease:random_tick": { # 该方块会触发BlockRandomTickServerEvent事件
"enable": true,
"tick_to_script": true
},
"netease:redstone_property": {
"value": "break_on_push"
},
"netease:neighborchanged_sendto_script": {# 该方块会触发BlockNeighborChangedServerEvent事件
"value": true
},
"netease:block_entity": { # 方块实体数据存储
"tick": false,
"movable": true
}
}
}
}
```
##### customcrop:customcrop_1_stage1
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_1_stage1"
},
"components": {
...
"netease:random_tick": {
"enable": true,
"tick_to_script": true
},
"netease:redstone_property": {
"value": "break_on_push"
},
"netease:neighborchanged_sendto_script": {
"value": true
},
"netease:block_entity": {
"tick": false,
"movable": true
}
}
}
}
```
##### customcrop:customcrop_1_stage2
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customcrop:customcrop_1_stage2"
},
"components": {
...
"netease:neighborchanged_sendto_script": {
"value": true
},
"netease:block_entity": {
"tick": false,
"movable": true
}
}
}
}
```
#### 3生长过程
<img src="../../picture/customcrop/custom_stage_1.jpg" alt="流程" style="zoom:75%;" />
其中左边为阶段一customcrop:customcrop_1_stage0中间为阶段二customcrop:customcrop_1_stage2右边为阶段三customcrop:customcrop_1_stage2
#### 4脚本简要说明
##### 物品使用条件限定
在自定义物品customcrop:custom_item使用生成农作物第一阶段方块customcrop:customcrop_1_stage0可以通过监听事件<a href="../../../../../mcdocs/1-ModAPI/事件/物品.html#serveritemuseonevent" rel="noopenner"> ServerItemUseOnEvent </a>来限制,例如:
```python
def OnServerItemUseOnEvent(self, args):
if args["itemName"] == "customcrop:custom_item":
# 使用自定义物品时生成自定义方块
comp = self.CreateComponent(self.playerId, "Minecraft", "blockInfo")
belowPos = (args["x"], args["y"], args["z"]) # below
blockDict = comp.GetBlockNew(belowPos)
if blockDict["name"] == "minecraft:dirt": # 底下为泥土才能种植这里同种子的plant_at判断
blockDict = {
'name': 'customcrop:customcrop_1_stage0',
'aux': 0
}
comp.SetBlockNew((args["x"], args["y"] + 1, args["z"]), blockDict)
```
##### 农作物转换条件
在示例mod中我们通过监听事件<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockrandomtickserverevent" rel="noopenner"> BlockRandomTickServerEvent </a>来判断是否可以转换到下一个阶段的自定义农作物判断条件不限定于netease:transform中描述的光照、tick数量以及周边环境。同时我们还可以借助blockEntityData组件来存储数据。
```python
def OnStage0BlockTick(self, args):
pos = (args["posX"], args["posY"], args["posZ"])
comp = self.CreateComponent(self.playerId, "Minecraft", "blockInfo")
lightlevel = comp.GetBlockLightLevel(pos)
if (15 >= lightlevel >= 0): # 光照条件判断
dimension = args["dimensionId"]
blockEntitycomp = self.CreateComponent(self.playerId, "Minecraft", "blockEntityData")
blockEntityData = blockEntitycomp.GetBlockEntityData(dimension, pos)
if not blockEntityData:
return
growth = blockEntityData["growth"]
if not growth:
growth = 0
growth += 1
# 使用blockEntity保存tick count数据
blockEntityData["growth"] = growth
if (growth >= 1): # tick数量条件判断
comp = self.CreateComponent(self.playerId, "Minecraft", "blockInfo")
blockDict = {
'name': 'customcrop:customcrop_1_stage1',
'aux': 0
}
comp.SetBlockNew(pos, blockDict) # 切换到农作物的下一个阶段
```
##### 农作物收获
开发者可以根据需要,通过监听事件<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#destroyblockevent" rel="noopenner"> DestroyBlockEvent </a>以及<a href="../../../../../mcdocs/1-ModAPI/接口/世界/实体管理.html#spawnitemtolevel" rel="noopenner"> SpawnItemToLevel </a>来实现农作物的掉落。
## 自定义农作物外观
- 可使用[自定义方块模型](../5-自定义方块模型.md)配置农作物的外观。
demo的`resource/bbmodel`下有demo中农作物的模型工程demo中所有农作物都共用一个工程只是贴图不一样。
## Q&A
1什么时候需要把自定义方块base_block配置成custom_crop_block
需要[netease:transform组件](#netease_transform)驱动方块之间的转换时
2如何限制农作物的种植条件
使用“自定义农作物方式一“的方式可以通过种子的”plant_at“字段进行限制
使用“自定义农作物方式二”的方式可以通过监听<a href="../../../../../mcdocs/1-ModAPI/事件/物品.html#serveritemuseonevent" rel="noopenner"> ServerItemUseOnEvent </a>来限制种植时的条件。
3自定义农作物下方的方块被破坏、被替换、被推动时如何检测
监听<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockneighborchangedserverevent" rel="noopenner"> BlockNeighborChangedServerEvent </a>事件监听周围方块的变化,并做响应的处理。