feat:上传mcguide-开发指南部份

This commit is contained in:
Othniel su
2024-12-23 10:57:59 +08:00
parent 7292166c88
commit 0dc59fa4f0
3297 changed files with 63375 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
---
front: https://nie.res.netease.com/r/pic/20210728/d6a02b85-aba6-410c-9ed3-5c7ad395a3ab.gif
hard: 入门
time: 25分钟
---
# 配置
## 什么是配置
我的世界基岩版中,你可以使用一系列文件对游戏进行配置来制作附加包。
比如想要制作一个自定义的生物你可以在如下的3个文件夹中
- 在行为包的entities文件夹下添加生物的行为包Json
- 在资源包的entity文件夹下添加生物的资源包Json
- 在texts文件夹下的zh_CN.lang中添加生物的中文名称
作品文件夹
|--&nbsp;.mcs&nbsp;&nbsp;*<font color=#009900>//文件夹,保存了编辑器配置信息。</font>*
|--&nbsp;behavior_packs&nbsp;&nbsp;*<font color=#009900>//文件夹,行为包集合,下面可放置多个行为包。</font>*
|&nbsp;&nbsp;&nbsp;|--&nbsp;behavior_pack_\*\*\*&nbsp;&nbsp;*<font color=#009900>//文件夹,行为包,命名并没有固定的格式。</font>*
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--&nbsp;entities&nbsp;&nbsp;*<font color=#009900>//文件夹放置实体的JSON文件配置实体的血量、攻击、行为等。</font>*
|--&nbsp;resource_packs&nbsp;&nbsp;*<font color=#009900>//文件夹,资源包集合,下面可放置多个资源包。</font>*
|&nbsp;&nbsp;&nbsp;|--&nbsp;resource_pack_\*\*\*&nbsp;&nbsp;*<font color=#009900>//文件夹,资源包,命名并没有固定的格式。</font>*
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--&nbsp;entity&nbsp;&nbsp;*<font color=#009900>//文件夹放置实体客户端的配置JSON文件。</font>*
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|--&nbsp;texts&nbsp;&nbsp;*<font color=#009900>//文件夹放置文本lang文件。</font>*
在新版编辑器中这一系列的文件就叫做配置配置功能的本质就是将原本修改Json文件的方法改为可视化图形操作开发者在编辑器对配置的新建、编辑和删除都会同步更新到模组的资源文件中。
## 新建配置
你可以使用资源管理器的新建文件向导进行配置的创建,此时会同步创建配套文件
>每种配置都对应着不同的Json文件具体可以参考[配置与JSON关系说明](./14-配置与JSON文件关系.md)
我们当前提供11种配置可以使用
- 实体配置
- 物品配置
- 方块配置
- 配方配置
- 交易表配置
- 掉落表配置
- 生成规则配置
- 维度配置
- 生物群系配置
- 特征配置
- 特征生成配置
> 旧版关卡编辑器组件的配置类组件会在后续更新中逐渐补全。
![config001](./images/config001.png)
在新建配置时(以实体配置为例),你可以为配置选择一个数据模板(或者选空)。
如果你选择了模板,你创建出来的配置将与数据模板的大部分数据相同,通过使用这种方法,你可以很方便的创造出一种实体的变体。
> 当前数据模板几乎包含了所有MC的原版实体。
如果在这里勾选了“覆盖模板数据”,那么创建出来的配置将覆盖原版的数据。
> 比如你在这里选择僵尸,并且勾选覆盖模板数据,那么,你创建出来的僵尸将替换原版的僵尸。
>
> 每个模板最多可以被覆盖1次。
选择数据模板时,可以对数据模板进行搜索。
![config002](./images/config002.png)
## 管理配置
所有创建出来的配置都会显示在关卡编辑器的配置面板中。
> 事实上如果你没有通过新建文件向导创建而是手动创建了Json文件且创建正确的话你创建的结果仍然会显示在这个面板中。
不同种类的配置在配置面板中有不同的标签,你也可以在“全部”标签里找到所有的配置。
- 点击配置,可以在属性面板中对其进行修改。
- 右键某个配置,可以对其进行删除操作。
- 对于实体配置和方块配置来说,每种配置最多可以与一个预设进行绑定,你可以在配置面板中快捷创建绑定这个配置的预设。
> 方块配置和实体配置即使不绑定预设也可以生效,但实体预设和方块预设一定要绑定一个配置才行。
![image-20210710192226765](./images/config003.png)
## 修改配置
### 配套文件
以实体预设为例。
- 刷新所有属性:正常情况下,这个按钮是禁用的。但有时,对配置的修改无法立即生效,这个按钮在这时变为可用状态,点击按钮可以完成对配置的刷新。
- 整体模板行为包Json资源包Json你可以在下拉框中选择你需要的模板并点击√按钮进行模板数据的整体替换。
- 行为包Json资源包Json的刷子按钮点击可以将对应的文件清空。
> 资源包Json情况复杂我们已经对不能直接应用替换的资源包Json数据模板进行了过滤。
![config004](./images/config004.png)
整体模板行为包和资源包的数据模板的数量较多我们在这3个下拉框中进行了搜索的支持参考下面这张动图。
![config005](./images/config005.gif)
### 添加字段
> 以下针对具体字段的显示和修改(而非整体数据模板的应用)。
>
> 对于实体配置当前编辑器仅支持行为包的Component的修改。
>
> 对于资源包和行为包的其他字段需要等待后续支持当前仍需手动修改Json文件。
配置本质上是Json属性面板中的每一个属性条目就可以理解为Json中的一个字段。
- 点击属性标签或者属性条目右侧的“+” = 在这个字段下添加一个字段
- 点击属性条目右侧的“垃圾桶图标” = 删除这个字段
![image-20210710194642123](./images/config006.png)
在配置中,我们将添加字段称为添加特性。添加特性时,我们会自动为你筛选出可以被添加的特性,并且会过滤重复的特性。
下面这个就是点击“+”后弹出的添加特性界面,里面的每一个条目就是一个可以添加的字段,每一个条目显示如下的信息:
- 特性的英文名称,即字段名
- 特性的数据类型,即字段的数据类型
- 特性中文名称,即我们对字段名的中文翻译
- 特性描述,即该字段的作用
选中特性并点击添加,即可把选中的特性添加至配置中。
>提示:选择框为多选,你可以同时勾选或取消多个字段
![config007](./images/config007.png)
MC附加包的字段浩如烟海我们为此提供了搜索功能添加特性弹窗的所有文字都被纳入搜索范围。
![config008](./images/config008.png)
添加好特性(字段)后,你就可以对特性的值进行编辑了,对于一些特殊的数据类型,编辑器进行了一定程度改进,例如下图的物品,你可以充分发挥编辑器的威力来降低特性编辑出错的概率。
![config009](./images/config009.png)
> 了解MC的附加包MolangJson字段的含义是一个大工程我们强烈推荐您通过数据模板的方式了解MC每个原版实体生物物品等等是如何配置出来的并通过这种方式学习每个字段的含义、和其他字段的搭配、字段的值的取值范围以及具体的使用方法。
## 预设与配置的绑定
如前所述,实体预设和方块预设必须要绑定一个配置才能使用。
通常情况下,在创建预设时,新建文件向导会自动的处理好配套的配置的创建和绑定。如果先创建了配置,也可以通过配置的右键菜单进行绑定这个配置的预设的创建。
但是如果你想切换预设绑定的配置,可以在预设的属性面板中做到这一点,如下图所示。
> 这个下拉框选择的是MC原版的和你新建的所有实体的标识符。并且这个下拉框也提供了搜索功能。
![image-20210710200519632](./images/config010.png)
如下图所示,这个就是配置的标识符。
> MC中包括附加包Mod不能有重复的标识符否则后读取的同标识符的配置会替换之前读取的。
![image-20210710201102829](./images/config011.png)

View File

@@ -0,0 +1,345 @@
---
front: https://nie.res.netease.com/r/pic/20220408/3e2bb79b-32b3-4b95-a408-83556c00f775.jpg
hard: 入门
time: 20分钟
selection: true
---
# 自定义基础物品
## 概述
该功能不需要开启实验性玩法。
开发者可以通过在addon中配置json来添加自定义物品。添加的自定义物品支持“MOD SDK文档”中与物品相关的所有事件及接口。
## 物品相关组件事件流程
**组件事件流程**
<img src="./picture/item_event_flow.png" alt="流程" style="zoom:75%;" />
**注意ActorUseItemClientEventActorUseItemServerEvent与ClientItemTryUseEventServerItemTryUseEvent的先后顺序与使用的物品有关。**
## 注册
以demo [CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)为例
1. 在behavior中新建`netease_items_beh`目录
![avatar](./picture/customitem/base1.png)
2. 在目录下新建一个json编写物品的定义。json的格式可参考[官方wiki](https://minecraft.gamepedia.com/Bedrock_Edition_beta_item_documentation)。<a name="item_reg_2"></a>
* json中至少有一个component
* identifier分为命名空间及物品名命名空间推荐与mod名称一致identifier必须全局唯一。mod中其他地方都是用这个identifier与这个自定义物品对应上。**identifier由小写字母以及下划线组成请勿使用大写字母。**
![avatar](./picture/customitem/base2.png)
![avatar](./picture/customitem/base3.png)
3. 下面开始操作resource包。
将物品的贴图放到`textures\items`
![avatar](./picture/customitem/base4.png)
4. 在textures中新建`item_texture.json`编写资源名与贴图的对应关系。资源名的命名必须满足全局唯一。json格式可参考“Mod PC开发包”的`data\resource_packs\vanilla\textures\item_texture.json`
![avatar](./picture/customitem/base5.png)
![avatar](./picture/customitem/base6.png)
5. 在resource中新建一个`netease_items_res`文件夹在文件夹中添加json用于配置物品的表现属性例如贴图。category字段需要与behavior包中的设置一致或者不填否则可能出现错误。<a name="item_reg_5"></a>
这个json的identifier需要与behavior中的一致贴图的值需要与上一步`item_texture.json`中配置的资源名对应。json格式可参考“Mod PC开发包”的`data\resource_packs\vanilla\items`
![avatar](./picture/customitem/base7.png)
![avatar](./picture/customitem/base8.png)
6.`texts\zh_CN.lang`中配置物品的中文名称。
键的格式为item.物品identifier.name
![avatar](./picture/customitem/base9.png)
![avatar](./picture/customitem/base10.png)
7. 重复1-6编写其他自定义物品
## JSON组件
### format_version
请填写1.10
### description
| 键 | 类型 | 默认值 | 解释 |
| ----------------------- | ---- | ------ | ------------------------------------------------------------ |
| identifier | str | | 包括命名空间及物品名。需要全局唯一。<br>建议使用mod名称作为命名空间 |
| register_to_create_menu | bool | false | 是否注册到创造栏 |
| category | str | Nature | 注册到创造栏的分类,可选的值有:<br>Construction<br>Nature<br>Equipment<br>Items |
| custom_item_type | str | | 自定义物品类别,可选值有:<br/>weapon<br/>armor<br/>egg<br/>ranged_weapon<br/>projectile_item |
### 原版components
支持的微软原版component包括参数及解释见[官方wiki](https://minecraft.gamepedia.com/Bedrock_Edition_beta_item_documentation)
* minecraft:foil
可以使物品拥有类似附魔的闪烁效果
* minecraft:max_damage
可以使物品拥有耐久度,范围为[0, 32767]
> 若物品堆叠数量大于1时耐久度的变更对整一叠的物品生效。并且耐久度为0后每次消耗耐久度的行为会使数量减一
* minecraft:max_stack_size
设置物品最大堆叠数量,`注意该值不能超过64`
* minecraft:seed<span id="minecraft_seed"></span>
设置种子的属性如crop_result、plant_at
> plant_at列表中需要保持格式一致如["minecraft:grass", "minecraft:dirt"]或["grass", "dirt"],否则在相邻自定义农作物种植新的农作物会导致上一个农作物被破坏
* minecraft:use_animation
使用物品时播放的动画,如原版使用`apple`时会播放`eat`动画,需在材质包中定义,如在`resource_packs/vanilla/items/apple.json`中就有`"minecraft:use_animation": "eat"`配置。
* minecraft:stacked_by_data
值为bool类型不同aux值的物品是否能够堆叠例如AUX值为1的燃料无法和aux值为2的燃料堆叠在一起此外该组件也会导致不同aux的物品在合成配方中被识别为不同的合成原料。
> 1. 不同aux的物品可以使用<a href="../../../../mcdocs/1-ModAPI/接口/玩家/背包.html#spawnitemtoplayerinv" rel="noopenner">SpawnItemToPlayerInv</a>接口生成到玩家背包。
> 2. 该组件在物品无法和耐久度(minecraft:max_damage)组件共存。
配置示例:
``` json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "wiki:gem"
},
"components": {
"minecraft:stacked_by_data": true,
"minecraft:max_stack_size": 64
}
}
}
```
### 网易components
#### netease:compostable
设置物品是否可以堆肥
使用形式如:"netease:compostable" : 48 。其中48表示堆肥成功概率 48%。
详细例子如下:
``` json
//这是一个自定义物品的配置
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:test1",
"register_to_create_menu":true,
"category": "Nature"
},
"components": {
"minecraft:max_stack_size": 1,
"minecraft:max_damage": 10,
"netease:compostable": 100,
"netease:show_in_hand": {
"value": true
}
}
}
}
```
#### netease:show_in_hand
设置物品拿在手上时是否显示
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------------- |
| value | bool | | 手持时是否显示 |
- 备注格式和微软的component不一样里面多了一个“value"
- 可以参考[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)行为包的`netease_items_beh\customitems_test1.json`
<span id="netease_fire_resistant"></span>
#### netease:fire_resistant
设置物品是否防火,防火的物品会与下界合金一样,不会被火烧毁,掉进岩浆时会弹走
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------- |
| value | bool | | 是否防火 |
- 备注格式和微软的component不一样里面多了一个“value"
- 可以参考CustomItemsMod示例行为包的`netease_items_beh\customitems_test_sword.json`
#### netease:allow_offhand
设置物品是否可以放在副手
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ---------------- |
| value | bool | | 是否可以放在副手 |
- 备注格式和微软的component不一样里面多了一个“value"
- 可以参考CustomItemsMod示例行为包的`netease_items_beh\customitems_test_offhand.json`
- 目前基岩版原版副手功能较弱大多数时候都无法使用物品主要用于装饰和在mod中判断副手中是否持有某物品来执行特定逻辑
- 副手不支持一些其他组件,如`minecraft:foil``netease:render_offsets`
#### netease:enchant_material
设置物品是否可以当附魔材料
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------ |
| value | bool | false | 是否可以当附魔材料 |
- 备注格式和微软的component不一样里面多了一个“value"
- 可以参考CustomItemsMod示例行为包的`netease_items_beh\customitems_test_enchantmaterial.json`
#### netease:fuel
可燃类物品组件。允许该物品作为燃料在熔炉中燃烧
| 键 | 类型 | 默认值 | 解释 |
| ------- | ------ | ------ | ------------------------------------------------------------ |
| duration| int | 0 | 可填, 该物品可提供的熔炉燃烧时长(秒)。 |
#### netease:cooldown
定义物品冷却时间
| 键 | 类型 | 默认值 | 解释 |
| ------- | ------ | ------ | ------------------------------------------------------------ |
| category | string | "item" | 必填,物品的冷却类型,同种类型冷却会互相影响。 |
| duration| int | 0 | 可填,这个物品能够再次使用前的冷却时间。 |
- 备注:自定义食品(minecraft:food)的冷却时间需定义在minecraft:food中
#### netease:customtips
定义物品描述信息
| 键 | 类型 | 默认值 | 解释 |
| ------- | ------ | ------ | ------------------------------------------------------------ |
| value | string | "" | 物品的描述信息。 |
## 附属功能
### python事件及接口
支持“MOD SDK文档”中所有与物品相关的事件及组件包括旧版自定义物品支持的全部功能。与旧版自定义物品不同现在的事件及接口使用“itemName”传递物品identifier来区分不同的物品。
### 自定义配方
见“自定义配方”文档材料及结果都支持填写自定义物品的identifier。可参考[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)行为包的`netease_recipes`
### 自定义食品
原版apple json结构
```python
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "minecraft:apple"
},
"components": {
"minecraft:use_duration": 32,
"minecraft:food": {
"nutrition": 4,
"saturation_modifier": "low"
}
}
}
}
```
食品类的json结构需要包含在minecraft:item -> components中包含minecraft:food节点下面对minecraft:food节点进行解释说明。
| json字段 | 举例 | 含义 |
| ------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| nutrition | "nutrition": 2 | 营养值 |
| saturation_modifier | "saturation_modifier": "low" | 饱和度等级有poorlownormalgoodmaxsupernatural六个等级系数分别是0.10.30.60.81.01.2 |
| using_converts_to | "using_converts_to": "bowl" | 使用后转化为的Item如使用甜菜汤后留下碗 |
| on_use_action | "on_use_action": "chorus_teleport" | 使用食品产生的动作,目前仅支持传送到其他位置 |
| on_use_range | "on_use_range": [0, 10, 4] | 传送位置x,y,z的偏移值 |
| cooldown_type | "cooldown_type": "chorusfruit" | 冷却类型 |
| cooldown_time | "cooldown_time": 1 | 冷却时间 |
| can_always_eat | "can_always_eat": true | 是否可以一直使用 |
| effects | "effects": [<br/> {<br/> "name": "regeneration",<br/> "chance": 1.0,<br/> "duration": 30,<br/> "amplifier": 4<br/> },<br/> {<br/> "name": "absorption",<br/> "chance": 1.0,<br/> "duration": 120, // 2 * 60<br/> "amplifier": 3<br/> }] | 使用后的效果 |
### 村民交易
可将行为包的交易配置中的item修改为自定义物品的identifier。可参考[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)行为包的`trading\economy_trades\butcher_trades.json`里面将新手级屠夫的其中一个交易项替换为绿宝石兑换customitems:test0物品
### loot_table
自定义物品的identifier可用作loot_table配置掉落物。可参考[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)行为包的`loot_tables\entities\zombie.json`里面将僵尸的掉落物由腐肉改为customitems:test0物品
## demo解释
[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)中定义了2个自定义物品
* customitems:test0
平平无奇的只替换了贴图的自定义物品。
演示了"村民交易" “loot_table”的功能
* customitems:test1
无法堆叠,拥有耐久度,手持时不渲染的自定义物品
演示了“自定义配方”的功能
## Mod卸载
若使用了自定义物品的存档卸载mod后再进入时
2. 对玩家背包中的自定义物品:
物品会消失。若重新加载mod对卸载期间登录过的玩家物品不会恢复没登录过的玩家物品可以保留
3. 对地图上容器内的自定义物品:
物品会消失。若重新加载mod对卸载期间进行探索过的区域内的容器物品不会恢复未探索区域的容器物品可以保留
4. 对地图上未捡起的掉落物:
掉落物会消失。若重新加载mod对卸载期间进行探索过的区域掉落物不会恢复除非subchunk内没有其他任何entity未探索区域的掉落物可以保留。
## 常见报错
* JSON: xxx has an error
一般为json格式有问题检查是否漏写或多写逗号括号是否对应等
![avatar](./picture/customitem/base11.png)

View File

@@ -0,0 +1,94 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义武器及工具
## 概述
属于特殊的自定义物品,在支持自定义物品所有特性的基础上,还具有武器或工具相关的功能。
## 注册
1. 与自定义基础物品的注册1-6步相同
2. 在behavior/netease_items_beh的json中添加武器/工具相关的定义,包括:
custom_item_type为weapon
一个netease:weapon组件必填。组件的参数见[json组件](#json组件)
设置最大堆叠数量,可选
设置耐久度,可选
![avatar](./picture/customitem/tool1.png)
```python
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:test_sword",
"register_to_create_menu":true,
"custom_item_type": "weapon"
},
"components": {
"minecraft:max_stack_size":1,
"minecraft:max_damage":153,
"netease:weapon":{
"type":"sword",
"level":3,
"speed":8,
"attack_damage":7,
"enchantment":10
}
}
}
}
```
## JSON组件
### description
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | --------- | ---------------------------------------------- |
| category | str | Equipment | 与普通物品不同,武器/工具的默认分类是Equipment |
### 原版components
* minecraft:max_stack_size
自定义武器/工具只支持设置为1
### 网易components
* netease:weapon
| 键 | 类型 | 默认值 | 解释 |
| ------------- | ---- | ------ | ------------------------------------------------------------ |
| type | str | | 武器/工具的类型,目前支持类型有:<br>sword剑<br>shovel铲<br>pickaxe镐<br>hatchet斧<br>hoe锄头 |
| level | int | | 武器/工具的level说明及修复信息下面以镐举例<br>1. 对于镐,对应挖掘等级<br>即当使用镐挖掘某些方块时,镐子的挖掘等级大于等于方块的挖掘等级,才会产生掉落物。<br>对于原版镐子木镐与金镐是0石镐是1铁镐是2钻石镐是3<br>2. 并且该值与铁砧的修复材料有关。<br>level为0当速度为2对应木板,否则对应金锭 <br>level为1对应石头<br>level为2对应铁锭<br>level为3对应钻石<br>level大于3无法使用铁砧修复 |
| speed | int | 0 | 对采集工具生效,表示挖掘方块时的基础速度 |
| attack_damage | int | 0 | 攻击伤害 |
| enchantment | int | 0 | 附魔能力。该值的解释见[官方wiki](https://minecraft-zh.gamepedia.com/index.php?title=%E6%95%99%E7%A8%8B/%E9%99%84%E9%AD%94%E6%9C%BA%E5%88%B6&variant=zh#.E9.AD.94.E5.92.92.E6.98.AF.E5.A6.82.E4.BD.95.E9.80.89.E6.8B.A9.E5.87.BA.E6.9D.A5.E7.9A.84) |
## demo解释
[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)中定义了一个自定义武器:
* customitems:test_sword
剑类型的自定义武器

View File

@@ -0,0 +1,253 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义盔甲
## 概述
属于特殊的自定义物品,在支持自定义物品所有特性的基础上,还具有盔甲相关的功能。
## 注册
1. 与自定义基础物品的注册1-6步相同
2. custom_item_type为amor
3.`behavior/netease_items_beh`的json中添加netease:armor组件参数详见[json组件](#json组件)
```json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:modarmor1",
"register_to_create_menu":true,
"custom_item_type": "armor"
},
"components": {
"netease:armor":{
"defense": 10,
"enchantment":4,
"armor_slot":0
}
}
}
}
```
4. 添加模型贴图到资源包的`textures\models`
与微软内置盔甲贴图一致,自定义盔甲的贴图也需要设置贴图。
5. 在`resource/netease_item_res`目录下创建新json中添加盔甲物品的贴图参数详见自定义物品注册中贴图的设置解释
```json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:modarmor1",
"category": "Equipment"
},
"components": {
"minecraft:icon": "customitems:modarmor1"
}
}
}
```
6. 在resource目录下创建`attachables`目录创建新json描述文件其中可配置的参数详见[json组件](#json组件)
```json
{
"format_version": "1.8.0",
"minecraft:attachable": {
"description": {
"identifier": "customitems:modarmor1",
"materials": {
"default": "armor",
"enchanted": "armor_enchanted"
},
"textures": {
"default": "textures/models/diamond_1",
"enchanted": "textures/misc/enchanted_item_glint"
},
"geometry": {
"default": "geometry.customitems_modarmor1"
},
"scripts": {
"parent_setup": "variable.chest_layer_visible = 0.0;"
},
"render_controllers": [ "controller.render.armor" ]
}
}
}
```
7. 在`resource/models`目录下增加`entity`目录增加对应的geometry描述文件
可配置的参数主要为根节点描述符`geometry.modid_modarmor1`这个值与上一步中的geometry文件值对应。
```json
{
"geometry.customitems_modarmor1": {
"texturewidth": 64,
"textureheight": 32,
"visible_bounds_width": 2,
"visible_bounds_height": 2,
"visible_bounds_offset": [ 0, 1, 0 ],
"bones": [
{
"cubes": [
{
"origin": [ -4, 24, -4],
"uv": [ 0, 0 ],
"size": [ 8, 8, 8 ],
"inflate": 1.0
},
{
"origin": [ 4, 30, -1],
"size": [ 2, 2, 2],
"uv": [47, 0]
},
{
"origin": [-6, 30, -1],
"size": [2, 2, 2],
"uv": [47, 0]
},
{
"origin": [6, 31, -1],
"size": [2, 2, 2],
"uv": [42, 8]
},
{
"origin": [-8, 31, -1],
"size": [2, 2, 2],
"uv": [42, 8]
},
{
"origin": [8, 32, -1],
"size": [2, 4, 2],
"uv": [41, 0]
},
{
"origin": [-10, 32, -1],
"size": [2, 4, 2],
"uv": [41, 0]
},
{
"origin": [-8, 36, -1],
"size": [16, 2, 2],
"uv": [28, 28]
}
],
"name": "head",
"parent": null,
"pivot": [
0.0,
24.0,
0.0
]
}
]
}
}
```
## JSON组件
### `netease_item_beh`文件
**description**
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | --------- | ----------------------------------------- |
| category | str | Equipment | 与普通物品不同盔甲的默认分类是Equipment |
**网易components**
* netease:armor行为包
| 键 | 类型 | 默认值 | 解释 |
| -------------------- | ----- | ------ | ------------------------------------------------------------ |
| defense | int | 0 | 盔甲的防御值 |
| enchantment | int | 0 | 盔甲的附魔能力。该值的解释见[官方wiki](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89) |
| armor_slot | int | | 盔甲槽位,详见<a href="../../../../mcdocs/1-ModAPI/枚举值/ArmorSlotType.html" rel="noopenner"> ArmorSlotType </a> |
| toughness | int | 0 | 盔甲韧性范围0~20详见[盔甲机制](https://zh.minecraft.wiki/w/%E7%9B%94%E7%94%B2%E6%9C%BA%E5%88%B6) |
| knockback_resistance | float | 0 | 击退抗性范围0~1详见[伤害-击退抗性](https://zh.minecraft.wiki/w/%E4%BC%A4%E5%AE%B3#%E5%87%BB%E9%80%80%E6%8A%97%E6%80%A7) |
### attachables文件
| 键 | 类型 | 描述 |
| -------------------- | ---- | ------------------------------------------------------ |
| identifier | str | 盔甲的唯一描述符,与之前注册流程中的物品描述符保持一致 |
| textures/default | str | 盔甲对应的贴图路径设置 |
| geometry/default | str | 盔甲对应的模型描述文件路径设置 |
| scripts/parent_setup | str | 盔甲对应部位影响玩家渲染的设置参数 |
**parent_setup**
微软内置的盔甲对应设置的值为以下几种:
> variable.helmet_layer_visible 玩家是否显示
>
> variable.chest_layer_visible 玩家上半身是否显示
>
> variable.leg_layer_visible 玩家腿部是否显示
>
> variable.boot_layer_visible 玩家脚部是否显示
一般而言,当设置对应的部位的盔甲,需要设置在`scripts/parent_setup ` 设置对应的变量值为0
**geometry/default**
需要设置成盔甲对应位置的geometry例如`geometry.humanoid.armor.boots`。
| 键 | 说明 |
| ---------------------------------- | ---- |
| geometry.humanoid.armor.boots | 靴子 |
| geometry.humanoid.armor.chestplate | 护胸 |
| geometry.humanoid.armor.helmet | 头盔 |
| geometry.humanoid.armor.leggings | 脚部 |
## 附属功能
除了支持自定义物品的所有功能外还支持盔甲的python事件及接口包括OnNewArmorExchangeServerEvent事件及armorslot组件
## demo解释
[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)中定义了一个自定义装备:
* customitems:modarmor1
头盔类型的自定义装备
## 自定义模型设置建议
* 盔甲模型的基础参考文件为:`data\resource_packs\vanilla\models`目录下的`mobs.json`文件中的**geometry.humanoid**。
* 模型制作工具推荐使用BlockBench导出的模型JSON文件格式与要求的格式相近。
* 使用BlockBench制作模型并导出为JSON文件后按照我们提供的装备物品Demo的JSON样式进行调整
需注意的是请尽量使用JSON范例中key的顺序避免出现比较奇怪的Bug。
* 如果Cube和已有的模型或者Cube之间有重叠的面重叠部分可能会无法显示或者闪烁可通过调整每个Cube的`inflate`可为负数来避免这种情况。inflate的作用是让Cube向各个方向膨胀一定数值同时不会影响贴图坐标。
* **注意**:对于溺尸,不能使用`SetArmorNew`接口装备自定义盔甲,该行为会造成游戏闪退。

View File

@@ -0,0 +1,64 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义生物蛋
## 概述
属于特殊的自定义物品,在支持自定义物品所有特性的基础上,还具有右键可以生成[自定义生物](../3-自定义生物/01-自定义基础生物.md)的功能。
支持刷怪箱和发射器。
## 注册
1. 与自定义基础物品的注册1-6步相同
2. 在behavior/netease_items_beh的json中设置custom_item_type为egg
3. 添加生物蛋相关的定义,包括一个必填的**netease:egg组件**,组件的参数见[json组件](#json组件)
![avatar](./picture/customitem/egg1.png)
```json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:test_egg",
"register_to_create_menu":true,
"custom_item_type": "egg"
},
"components": {
"minecraft:max_stack_size":64,
"netease:egg":{
"entity":"minecraft:mod{customitems:chicken}"
}
}
}
}
```
## JSON组件
### 网易components
* netease:egg
| 键 | 类型 | 默认值 | 解释 |
| ------ | ---- | ------ | -------------------- |
| entity | str | | 生成生物的identifier |
## demo解释
[CustomItemsMod](../../13-模组SDK编程/60-Demo示例.md#CustomItemsMod)中定义了一个自定义生物蛋:
* customitems:test_egg
右键时会生成微软自定义生物"customitems:chicken"

View File

@@ -0,0 +1,126 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义蓄力物品
## 概述
属于特殊的自定义物品,在支持自定义物品所有特性的基础上,还具有右键按下开始蓄力过程,右键抬起触发释放事件。
与弓minecraft:bow、弩minecraft:crossbow类似在物品使用过程支持蓄力操作支持序列帧动画。
详细的物品定义以及物品使用详见示例mod [CustomRangedWeaponMod](../../13-模组SDK编程/60-Demo示例.md#CustomRangedWeaponMod)。
## 注册
1. 与自定义物品的注册1-6步相同
2. 在behavior创建的json文件
```python
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customitems:ranged_weapon",
"register_to_create_menu":true,
"custom_item_type": "ranged_weapon"
},
"components": {
"minecraft:use_duration": 72000
}
}
}
```
*注意use_duration的大小应该与序列帧帧数相匹配*
3. 自定义序列帧
3.1 将物品的序列帧贴图放到`textures\items`中,如:
![avatar](./picture/customitem/custom_ranged_weapon01.png)
3.2 在textures/item_texture.json中增加序列帧图片的定义
```python
"customitems:ranged_weapon": {
"textures": [
"textures/items/customitems_ranged_weapon_0",
"textures/items/customitems_ranged_weapon_1",
"textures/items/customitems_ranged_weapon_2"
]
}
```
3.3 在netease_items_res中增加json文件
```python
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customrangedweapon:bow",
"category": "Equipment"
},
"components": {
"minecraft:icon": "customrangedweapon:bow",
"minecraft:use_animation": "bow",
"netease:frame_animation": {
"frame_count": 3,
"texture_name": "customrangedweapon:bow_frame",
"animate_in_toolbar": true
}
}
}
}
```
## 网易components
* netease:frame_animation
| 键 | 类型 | 默认值 | 解释 |
| ------------------ | ---- | ------ | ----------------------------------- |
| frame_count | int | 1 | 序列帧帧数 |
| texture_name | str | | item_texture.json中定义的序列帧数组 |
| animate_in_toolbar | bool | true | 在物品栏中是否支持动画 |
* netease:render_offsets
手中物品渲染配置
右手坐标系x是拇指方向y是食指方向z是中指方向
| 键 | 类型 | 默认值 | 解释 |
| -------------------------- | ----- | ------------- | ------------ |
| controller_position_adjust | array | [0.0,0.0,0.0] | 物品位置调整 |
| controller_rotation_adjust | array | [0.0,0.0,0.0] | 物品旋转调整 |
| controller_scale | float | 1.0 | 物品大小调整 |
## 物品耐久
自定义蓄力物品可以通过minecraft:max_damage组件设置其耐久值
然后在在物品使用事件ItemReleaseUsingServerEvent中获取/设置耐久值
```python
slotIndex = 0
comp = serverApi.CreateComponent(playerId,'Minecraft','item')
val = comp.GetInvItemDurability(slotIndex)
if val == 0:
# 销毁物品
comp.SetInvItemNum(slotIndex, 0)
else:
comp.SetInvItemDurability(slotIndex, val - 1)
```

View File

@@ -0,0 +1,63 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义物品贴图使用序列帧动画
## 概述
开发者按规范制作资源及json配置可实现物品贴图使用序列帧动画。
物品贴图使用序列帧的修改分为两部分一种是手持及地图掉落贴图修改另一种是UI界面上的修改。实际中一般同时修改但也允许开发者单独配置其中一项。
## 物品手持及地图掉落贴图使用序列帧动画
实现分为两个步骤:
1) 资源制作:
应以由上往下平铺的方式,贴图高度必须为宽度的整数倍,第一帧在最上方位置,最后一帧在最下方位置, 贴图分辨率越大性能消耗越大建议贴图宽度不要超过32:
<img src="./picture/customitem/frames/frames1.png" style="zoom: 100%;" />
2) 添加json组件
修改netease_items_res相应自定义物品的json添加netease:frame_anim_in_scene组件这里以自定义的斧头为例:
<img src="./picture/customitem/frames/frames2.png" style="zoom: 80%;" />
| 键 | 类型 | 解释 |
| ------------------- | -------- | ---------------------------------------------------- |
| ticks_per_frame | int |代表多少帧切换一次贴图按1秒20帧算设置20的话即为1秒切换一帧贴图 |
| texture_path | str |序列帧贴图的路径 |
最终效果:
<img src="./picture/customitem/frames/frames_scene.gif" style="zoom: 100%;" />
## 物品UI界面上贴图使用序列帧动画
实现分为三个步骤:
1) 在图集中声明资源。因为UI界面显示的贴图取自于图集所以需要先声明。
在textures/item_texture.json声明我们上述使用的这张序列帧贴图hatchet_frames
<img src="./picture/customitem/frames/frames_ui1.png" style="zoom: 100%;" />
2) 修改netease_items_res自定义物品的json修改minecraft:icon字段为我们上面图集中声明的字段
<img src="./picture/customitem/frames/frames_ui2.png" style="zoom: 100%;" />
3) 新建textures/flipbook_textures_items.json(类似于微软原版的flipbook_textures.json文件),并在其中进行配置:
<img src="./picture/customitem/frames/frames_ui3.png" style="zoom: 100%;" />
| 键 | 类型 | 默认值 | 解释 |
| ----------------- | ---- | ---------- | -------- |
| flipbook_texture | str | | 序列帧资源的路径 |
| atlas_tile | str | |在图集中声明的名称 |
| ticks_per_frame | int | | 代表多少帧切换一次贴图按1秒20帧算设置20的话即为1秒切换一帧贴图 |
| blend_frames | bool | True | 切换贴图的时候是否混合上一帧 |
最终效果:
<img src="./picture/customitem/frames/frames_ui.gif" style="zoom: 140%;" />

View File

@@ -0,0 +1,59 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义桶
## 概述
自定义桶主要用于装载自定义流体,一般需配合自定义流体使用,使用后可以倒出指定的流体方块
## custom_item_type设置
- 自定义桶的**custom_item_type**需要设为**bucket**
## 注册
1. 与自定义基础物品的注册1-6步相同
2. 在behavior/netease_items_beh的json中设置custom_item_type为**bucket**
3. 添加自定义桶相关的定义,包括一个必填的**netease:bucket组件**,组件的参数见[json组件](#json组件)。注自定义桶的最大堆叠数为1无法通过max_stack_size进行修改
```json
{
"format_version": "1.10",
"minecraft:item": {
"description": {
"identifier": "customBucket:green_bucket",
"custom_item_type": "bucket",
"register_to_create_menu": true
},
"components": {
"netease:bucket": {
"fill_liquid": "flowing_green_water"
}
}
},
}
```
## JSON组件
### 网易components
* netease:bucket
| 键 | 类型 | 默认值 | 解释 |
| ----------- | ------ | --------------- | ---------------------------- |
| fill_liquid | string | "flowing_water" | 可选使用时倒出的流体方块id |
**注:该流体方块需为自定义流体的动态流体**

View File

@@ -0,0 +1,334 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义盾牌
## 概述
属于特殊的自定义物品,在支持自定义物品所有特性的基础上,还具有盾牌相关的功能,支持自定义盾牌的动画和模型。
## 注册
1. 与自定义基础物品的注册1-6步相同
**物品名即identifier冒号后的部分不可以叫shield否则会和原版盾牌冲突**
1. 如果resource中的icon填写为空则盾牌的物品形态会渲染为模型使用default模型与default贴图渲染不会播放动作
如果配置了贴图icon则物品形态渲染为贴图
```python
{
"minecraft:item": {
"description": {
"identifier": "customshield:test_shield"
},
"components": {
"minecraft:icon": ""
}
},
"format_version": "1.10"
}
```
1. 在behavior/netease_items_beh的json中添加武器/工具相关的定义,包括:
custom_item_type为shield
一个netease:shield组件必填。组件的参数见[json组件](#json组件)
```python
{
"minecraft:item": {
"description": {
"category": "Custom",
"identifier": "customshield:test_shield",
"custom_item_type": "shield",
"register_to_create_menu": true
},
"components": {
"netease:shield":{
"defence_damage_source_list":["drowning"],//防御的伤害类型,如果不配或者配置为空则走原生的格挡伤害逻辑
"undefence_damage_source_list":["entity_attack"],//不防御的伤害类型,和上面这个不能有相同元素,如果有相同则优先防御该伤害类型
"is_consume_damage":false//是否消耗耐久度false则不消耗
}
}
},
"format_version": "1.10"
}
```
1. 在resource/netease_item_res中增加json文件
```python
{
"minecraft:item": {
"description": {
"identifier": "customshield:test_shield"
},
"components": {
"minecraft:icon": "shield"
}
},
"format_version": "1.10"
}
```
1. 在resource/attachables中增加json文件
```python
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "customshield:test_shield",
"materials": {
"default": "entity_alphatest",
"enchanted": "entity_alphatest_glint"
},
"textures": {
"default": "textures/entity/test_shield", //模型表面的贴图
"enchanted": "textures/misc/enchanted_item_glint"
},
"geometry": {
"default": "geometry.test_shield" //模型
},
"animations": {
//我们提供了一个通用的animation controller他位于vanilla_netease/animation_controllers/shield.animation_controllers.json
"wield": "controller.animation.default_custom_shield.wield",
//普通的拿盾状态使用了自定义动作
//您也可以复用原版的动作animation.shield.xxx
"wield_main_hand_first_person": "animation.test_shield.wield_main_hand_first_person",
"wield_off_hand_first_person": "animation.test_shield.wield_off_hand_first_person",
"wield_third_person": "animation.test_shield.wield_third_person",
// 如果防御状态的动作复用了原版的动作, 则在举盾状态时盾牌的动画部分将会失效
// "wield_main_hand_first_person_block": "animation.shield.wield_main_hand_first_person_blocking",
// "wield_off_hand_first_person_block": "animation.shield.wield_off_hand_first_person_blocking"
// 为了使举盾状态时盾牌的动画部分也能正常运作,防御状态的动作使用了了自定义的动作
"wield_main_hand_first_person_block": "animation.test_shield.wield_main_hand_first_person_blocking",
"wield_off_hand_first_person_block": "animation.test_shield.wield_off_hand_first_person_blocking"
},
"scripts": {
"animate": [
"wield"
],
// 如果复用了原版动作,则需要有以下数值定义
"initialize": [
"variable.main_hand_first_person_pos_x = 5.3;",
"variable.main_hand_first_person_pos_y = 26.0;",
"variable.main_hand_first_person_pos_z = 0.4;",
"variable.main_hand_first_person_rot_x = 91.0;",
"variable.main_hand_first_person_rot_y = 65.0;",
"variable.main_hand_first_person_rot_z = -43.0;",
"variable.off_hand_first_person_pos_x = -13.5;",
"variable.off_hand_first_person_pos_y = -5.8;",
"variable.off_hand_first_person_pos_z = 5.1;",
"variable.off_hand_first_person_with_bow_pos_z = -25.0;",
"variable.off_hand_first_person_rot_x = 1.0;",
"variable.off_hand_first_person_rot_y = 176.0;",
"variable.off_hand_first_person_rot_z = -2.5;"
],
// 使用弓时的动作修正
"pre_animation": [
"variable.is_using_bow = (query.get_equipped_item_name == 'bow') && (query.main_hand_item_use_duration > 0.0f);"
]
},
"render_controllers": [ "controller.render.item_default" ]
}
}
}
```
1. resource/models/entity中自定义自己的盾牌模型
1. 在resource/animations以及resource/animation_controllers放置自定义的动作与动作控制器如果有的话
1. 在python绑定玩家的动画控制器同时这个给玩家绑定动画控制器的操作是在一个新增事件的回调函数里完成的
事件名称为<a href="../../../../mcdocs/1-ModAPI/事件/世界.html#addplayercreatedclientevent">"AddPlayerCreatedClientEvent"</a>触发此事件时会传递一个playerId参数此事件触发表明该玩家渲染相关资源已加载完毕。
```python
animaComp = clientApi.GetEngineCompFactory().CreateActorRender(playerId)
# 添加激活盾牌时玩家的动作
# animationKey需要唯一
# animationName复用了原版的
# 如果需要用自定义动作也可以参考player.animation.json编写新的动作
animaComp.AddPlayerAnimation("shield_block_main_hand_test", "animation.player.shield_block_main_hand")
animaComp.AddPlayerAnimation("shield_block_off_hand_test", "animation.player.shield_block_off_hand")
# blocking状态并且左手上不是原版盾牌与自定义盾牌并且主手是我们的自定义盾牌
animaComp.AddPlayerAnimationIntoState("root", "third_person", "shield_block_main_hand_test", "query.blocking && query.get_equipped_item_name('off_hand') != 'shield' && !query.get_equipped_item_is_netease_shield('off_hand') && query.get_equipped_item_full_name == 'customshield:test_shield'")
# blocking状态并且左手是我们的自定义盾牌
animaComp.AddPlayerAnimationIntoState("root", "third_person", "shield_block_off_hand_test", "query.blocking && query.get_equipped_item_full_name('off_hand') == 'customshield:test_shield'")
```
## Molang表达式
### 新增molang表达式
- query.get_equipped_item_is_netease_shield
* 描述
获取主手/副手是否自定义盾牌(原版盾牌不算)
* 参数:
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | --------- | ---------------------------------------------- |
| hand | str | 'main_hand' | 获取主手(main_hand)/副手('off_hand')是否盾牌 |
* 返回值:
| 说明 |
| ---- |
| 主手(main_hand)/副手('off_hand')是否网易自定义盾牌 |
- query.get_equipped_item_full_name
* 描述
获取主手/副手物品的identifier仅对自定义物品使用原版物品请使用query.get_equipped_item_name。
* 参数:
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | --------- | ---------------------------------------------- |
| hand | str | 'main_hand' | 获取主手(main_hand)/副手('off_hand')是否盾牌 |
* 返回值:
| 说明 |
| ---- |
| 主手/副手物品的identifier |
### 原版molang表达式
* c.item_slot
本物品所在的位置
**返回值:**
| 说明 |
| ---- |
| "main_hand":主手;"off_hand":副手;"head":头;"torso":躯干 |
* q.item_slot_to_bone_name
**返回值:**
| 说明 |
| ---- |
| "rightitem":主手;"leftitem":副手; |
## JSON组件
### 网易components
* netease:shield
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | --------- | ---------------------------------------------- |
| defence_damage_source_list | list | [] | 防御的伤害类型,如果不配或者配置为空则走原生的格挡伤害逻辑。暂时不支持抵御火烧(fire,fire_tick),自杀(suicide),凋零(wither)的伤害 |
| undefence_damage_source_list | list | [] | 不防御的伤害类型,和上面这个不能有相同元素,如果有相同则优先防御该伤害类型 |
| is_consume_damage | bool | true | 是否消耗耐久度false则不消耗 |
### 原版components
* minecraft:icon
贴图名字
* minecraft:attachable
minecraft:attachable主要健是description下面介绍description的值
| 键 | 类型 | 默认值 | 解释 |
| ---------- | ---- | ------ | ---------------------------------------------------- |
| identifier | str | | 盾牌的id |
| textures | dict | | "default":默认的表面贴图;"enchanted":附魔的表面贴图 |
| geometry | dict | | "default":物品模型 |
| animations | dict | | 物品动画控制器和动画相关,参考示例的解释 |
| scripts | dict | | "animate": [物品动画控制器名],参考示例 |
| materials | dict | | "default":默认的表面贴图;"enchanted":附魔的表面贴图 ,参考示例 |
| render_controllers | list | | 参考示例 |
## 新增的事件和接口
### 事件
* <a href="../../../../mcdocs/1-ModAPI/事件/物品.html#onplayerblockedbyshieldbeforeserverevent">OnPlayerBlockedByShieldBeforeServerEvent</a>
玩家使用盾牌抵挡伤害之前触发
* <a href="../../../../mcdocs/1-ModAPI/事件/物品.html#onplayerblockedbyshieldafterserverevent">OnPlayerBlockedByShieldAfterServerEvent</a>
玩家使用盾牌抵挡伤害之后触发
* <a href="../../../../mcdocs/1-ModAPI/事件/物品.html#onplayeractiveshieldserverevent">OnPlayerActiveShieldServerEvent</a>
玩家激活/取消激活盾牌触发的事件
### 接口
* <a href="../../../../mcdocs/1-ModAPI/接口/物品.html#getitemdefenceangle">GetItemDefenceAngle</a>
服务端接口。获取盾牌物品的抵挡角度范围
* <a href="../../../../mcdocs/1-ModAPI/接口/物品.html#setitemdefenceangle">SetItemDefenceAngle</a>
服务端接口。设置盾牌物品的抵挡角度范围,参考下面抵挡角度范围的解释
* <a href="../../../../mcdocs/1-ModAPI/接口/玩家/行为.html#setusingshield">setUsingShield</a>
客户端接口。设置是否激活盾牌
* <a href="../../../../mcdocs/1-ModAPI/接口/玩家/行为.html#getisblocking">GetIsBlocking</a>
服务端接口。获取玩家是否处于抵挡状态,即盾牌是否被激活
## 新增物品字典参数
**抵挡范围**
| 键 | 类型 | 默认值 | 解释 |
| -------- | ---- | ------ | ---------------------- |
| shieldDefenceAngleLeft | float | -90 | 左边的范围 ,默认是-90取值范围是[-180,180] |
| shieldDefenceAngleRight | float | 90 | 右边的范围,默认是90,取值范围是[-180,180],且shieldDefenceAngleLeft<shieldDefenceAngleRight |
```python
itemDict1 = {
'itemName': 'customshield:test_shield',
'count': 1,
'shieldDefenceAngleLeft':-45,
'shieldDefenceAngleRight':30
}
comp = serverApi.GetEngineCompFactory().CreateItem(playerId)
comp.SpawnItemToPlayerInv(itemDict1, playerId)
```
### 关于抵挡范围的解释
如示意图所示,如果一个抵挡范围是[-45°,30°]的盾牌即shieldDefenceAngleLeft=-45shieldDefenceAngleRight=30那么当玩家举起盾牌时如果伤害来源是一个实体那么在玩家前方-45°到30°范围内的伤害可以抵挡否则不能抵挡。注:原版的盾牌范围是[-90°,90°]
![示意图](./picture/customitem/shield1.png)
## demo解释
[CustomShieldItemMod](../../13-模组SDK编程/60-Demo示例.md#CustomShieldItemMod)中定义了一个自定义盾牌:
* customshield:test_shield
自定义盾牌

View File

@@ -0,0 +1,179 @@
# Json配置自定义3D物品
在本节教程中,我们将围绕**如何自定义一个3D物品**的话题教给大家如何仅使用JSON配置和附加包开发知识来快速创建你的第一个3D物品。
> 温馨提示开始读起这篇指南前我们希望你对《我的世界》基岩版附加包有一定了解有能力撰写JSON数据格式并能够独立阅读《我的世界》开发者官网-开发指南或其他技术引用文档。
**通过这节教程,你将学会:**
•如何将一个现有的微软基岩版格式物品模型变为自定义物品的3D模型。
•校对模型在模型空间的相对位置,以匹配并固定在玩家第三人称的手持位置。
## 背景介绍
模组API 2.0 (基岩版版本 1.17.2开始在资源包定义物品的附着物Attachable文件可以绑定微软原版模型至物品上。
## 制作模型规范
让人型生物(如 溺尸、尸壳、僵尸 或 玩家手持3D物品模型时我们推荐使模型骨骼遵守玩家模型骨骼布局。以便模型能优先保证在玩家手持的情况下能够跟随肢体动画进行正常的幅度摆动。
原版玩家模型使用一条root根骨骼作为基骨骼子骨骼内使用waist骨骼控制上半身rightLeg骨骼和leftLeg骨骼控制左腿和右腿。
基岩版标识符推荐以小写数字母搭配下划线因为在游戏中使用rightLeg或rightleg效果是一致的。以下是玩家模型的骨骼树状图锚点即模型格式内的pivot。
```
-root锚点[0, 0, 0]
--waist锚点[0, 12, 0]
---jacket用于persona
---cape披风
---body锚点[0, 24, 0]
----leftArm锚点[5, 22, 0]
-----leftSleeve用于persona
-----leftItem锚点[6, 15, 1]
----rightArm锚点[-5, 22, 0]
-----rightSleeve用于persona
-----rightItem锚点[-6, 15, 1]
--leftLeg锚点[-1.9, 12, 0]
---leftPants用于persona
--rightLeg锚点[1.9, 12, 0]
---rightPants用于persona
```
## 校正模型在空间下对应第三人称手持的位置
先在模型工程内点击 **【文件】** - **【保存项目】** 。
![img](./images/1_0.png)
新建一个人型模型工程,并根据骨骼树状图拉出人型模型格式。
![img](./images/2_0.png)
选择 **【文件】** - **【导入】** 导入前面保存的3D模型项目。
![img](./images/3_0.png)
此时可以看到物品模型的贴图完全丢失。但不用担心它默认援引了人型模型的材质只要它的UV在前面的工程内已经分好这边就无需多管。
![img](./images/4_0.png)
将物品模型基骨骼放入 **【root】** - **【waist】** - **【body】** - **【rightArm】** - **【rightItem】** 骨骼下。并删除除右手方块以外的其他模型方块体。
![img](./images/5_0.png)
继续调整3D物品模型直至调整到一个满意的手持角度。此时删去右手模型方块体。这样一个有效的基础第三人称右手手持模型就做好了。
![img](./images/6_0.png)
## 将3D模型实装
在附加包的自定义资源包内新建attachables文件夹新建一个JSON文件。
![img](./images/7_0.png)
- 渲染控制器:默认可填 **"controller.render.item_default"** ,这是原版提供的一个物品渲染控制器。
- 材质:填写 **"controller.render.item_default"** 后,必须新增 **"default"** 和 **"enchanted"** 键,其中前者对应物品模型默认的材质,后者对应附魔时物品携带的材质。 **"default"** 无特殊情况默认填写 **"entity_alphatest"** "enchanted"默认填写 **"entity_alphatest_glint"** 。
- 贴图纹理:填写 **"controller.render.item_default"** 后,必须 **"default"** 和 **"enchanted"** 键, 其中前者对应自定义物品模型贴图,后者对应物品附魔时的附魔效果贴图(一般默认填写 **""textures/misc/enchanted_item_glint"** )。
- 动画附着物与实体一样可以添加动画和动画控制器也可以添加粒子但目前粒子默认会以实体脚底坐标发射粒子暂时不能在粒子挂点locator上发射。
- 几何体附着物的模型以自定义3D模型的geometry标识符为准。
- 物品标识符:与行为包的自定义物品标识符一致即可。在这里预先填写一个自定义物品标识符 **"design:custom_golden_sword"** ,稍后将用一个自定义物品行为与之呼应。
```json
{
"format_version":"1.10.0",
"minecraft:attachable":{
"description":{
"identifier":"design:custom_golden_sword",
"materials":{
"default":"entity_alphatest",
"enchanted":"entity_alphatest_glint"
},
"textures":{
"default":"textures/entity/custom_golden_sword",
"enchanted":"textures/misc/enchanted_item_glint"
},
"geometry":{
"default":"geometry.custom_golden_sword"
},
"render_controllers":[
"controller.render.item_default"
]
}
}
}
```
接着在附加包的自定义行为包里创建netease_items_beh文件夹并创建子文件custom_golden_sword.json。有关更多自定义物品行为请查看此链接[自定义武器及工具](../2-自定义武器及工具.md)
```json
{
"format_version":"1.10",
"minecraft:item":{
"description":{
"identifier":"design:custom_golden_sword",
"register_to_create_menu":true,
"custom_item_type":"weapon",
"category":"Equipment"
},
"components":{
"minecraft:max_damage":700,
"minecraft:max_stack_size":1,
"netease:weapon":{
"type":"sword",
"level":0,
"attack_damage":7,
"enchantment":10
}
}
}
}
```
我们还可以继续在资源包内的netease_items_res文件夹为自定义物品添上2D的物品图标。有关更多自定义物品的基础内容请查看此链接[自定义基础物品](../1-自定义基础物品.md)
```json
{
"format_version":"1.10",
"minecraft:item":{
"description":{
"identifier":"design:custom_golden_sword",
"category":"Equipment"
},
"components":{
"minecraft:icon":"design:custom_golden_sword",
"minecraft:render_offsets":"tools"
}
}
}
```
现在你就可以在游戏加载附加包完成后使用这个自定义3D物品了
![img](./images/8_0.png)
可以使用快速格式化Json等在线工具定位到可能在撰写过程中出现的错误语法或结构。

View File

@@ -0,0 +1,194 @@
# 自定义3D物品第一人称动画
在上节教程中我们学会了如何使用微软的Attachable功能实现自定义3D物品并使用社区工具Blockbench校正模型在第三人称的位置最后在游戏内实装上一把自定义3D金剑。
**本节课程Demo[戳这里下载](https://g79.gdl.netease.com/CustomWeapon3D.zip)**
**目前我们已经掌握:**
- 如何将一个现有的微软基岩版格式物品模型变为自定义物品的3D模型。第一节内容
- 校对模型在模型空间的相对位置,以匹配并固定在玩家第三人称的手持位置。(第一节内容)✔
- 借助《我的世界》基岩版电脑开发版,使用开发者工具制作模型的第一人称动画。(本节内容)❌
所以接下来将带领大家借助《我的世界》基岩版电脑开发版,使用开发者工具制作模型的第一人称动画。
![img](./images/0_0.png)
我的世界基岩版中,第一人称和第三人称的摄像机存在空间角度区别。因此需要单独为物品模型设计第一人称的手持动画。(下图为第三人称手持正确,但在第一人称显示意外的图例)
<img src="./images/0_1.png" alt="image-20220608133313000" style="zoom:150%;" />
启动Blockbench选择之前预制好的自定义3D物品模型选择【动画模式】-【添加动画创建一个用于控制第一人称手持角度位置的动画一个用于控制第一人称手持3D物品缩放的动画。我的世界基岩版动画可以叠加叠加后会对同一时刻下对位移、缩放、旋转的值进行加总
![image-20220608133346326](./images/0_2.png)
需要将动画设置为循环播放并将动画时长长度设置为0。
在对应的第一人称手持缩放动画(以下简称"first_scale"插入一帧缩放关键帧任意填入关键帧的缩放参数这里我们填写XYZ为1.1并保存。
![image-20220608133438507](./images/0_3.png)
在对应的第一人称手持位置角度动画以下简称“first_hold”插入一帧关键帧同时调整位置和旋转值这里我们任意填写XYZ的位置和旋转值为3并保存。
![image-20220608133501905](./images/0_4.png)
接着回到附着物的定义文件,将前面的"first_hold"和"first_scale"动画进行挂载并加入进scripts/animate根动画中。
```json
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "design:custom_golden_sword",
"materials": {
"default": "entity_alphatest",
"enchanted": "entity_alphatest_glint"
},
"textures": {
"default": "textures/entity/custom_golden_sword",
"enchanted": "textures/misc/enchanted_item_glint"
},
"animations": {
"first_hold": "animation.custom_golden_sword.first_hold", //挂载自定义动画“第一人称手持”
"first_scale": "animation.custom_golden_sword.first_scale" //挂载自定义动画“第一人称剑缩放”
},
"geometry": {
"default": "geometry.custom_golden_sword"
},
"render_controllers": [ "controller.render.item_default" ]
}
}
}
```
再次回到《我的世界》电脑版基岩开发版在游戏界面中按F3按键3次或14次呼出开发者控制台。接着按下F11键呼出鼠标。
![image-20220608133527259](./images/0_11.png)
打开Animation动画列表点击Open Editor打开编辑器
![image-20220608133539709](./images/0_10.png)
默认情况下,编辑器窗口会很小。此时点击右下角的伸缩区域进行拉伸。
![image-20220608133552800](./images/0_9.png)
拉到足够看清楚的大小后,直接往下拉到最底,这里展示着附着物挂载的动画状态。
![image-20220608133606005](./images/0_8.png)
打开“first_hold”的Details动画细节再点击Bone Animation骨骼动画就可以看到前面用Blockbench制作的动画的各项值并且支持直接在编辑器内动态修改最后直观的体现在游戏内。
<img src="./images/0_7.png" alt="image-20220608133619036" style="zoom:150%;" />
这里我们对"first_hold"的position设置值为X为-8Y为5Z为-6。再对rotation设置X为-45Y为15Z为-135。对"first_scale"的scale设置为0.35。
![image-20220608133639677](./images/0_6.png)
再按F3按键直到界面消失就可以在游戏内看到基本合格的第一人称自定义3D物品手持效果了。
![image-20220608133650381](./images/0_5.png)
请格外注意在这里调整的动画并不会最终保存进动画Json文件里因此我们还需要将值背下来并写入动画文件中。
```json
{
"format_version": "1.8.0",
"animations": {
"animation.custom_golden_sword.first_hold": {
"loop": true,
"bones": {
"sword": {
"rotation": [-45, 15, 135],
"position": [-8, 5, -6]
}
}
},
"animation.custom_golden_sword.first_scale": {
"loop": true,
"bones": {
"sword": {
"scale": 0.35
}
}
}
}
}
```
最后,对"first_hold"和"first_scale"的加载模式添加条件,使用"c.is_first_person"来判定动画是否运行在第一人称模式下,是则运行。
```json
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "design:custom_golden_sword",
"materials": {
"default": "entity_alphatest",
"enchanted": "entity_alphatest_glint"
},
"textures": {
"default": "textures/entity/custom_golden_sword",
"enchanted": "textures/misc/enchanted_item_glint"
},
"animations": {
"first_hold": "animation.custom_golden_sword.first_hold", //挂载自定义动画“第一人称手持”
"first_scale": "animation.custom_golden_sword.first_scale" //挂载自定义动画“第一人称剑缩放”
},
"scripts": {
"animate": [ // 挂载动画至根动画中
{
"first_hold": "c.is_first_person" // 保证“第一人称手持”动画只在第一人称下显示
},
{
"first_scale": "c.is_first_person"// 保证“第一人称剑缩放”动画只在第一人称下显示
}
]
},
"geometry": {
"default": "geometry.custom_golden_sword"
},
"render_controllers": [ "controller.render.item_default" ]
}
}
}
```
c是context的缩写就像可以使用q来代表query一样query是查询某个活动对象特定状态的查询函数。c.is_first_person将返回附着物是否处于第一人称视角下在前面加上!运算符即可代表是否处于非第一人称视角则可能是第三人称前视角或第三人称后视角下。其他的已知context函数还有
- **context.owning_entity**返回附着物穿戴的实体可以使用Molang的->运算符获取该实体身上的属性假设已知自定义3D物品由玩家手持则可以使用"c.owning_entity -> q.is_sneaking"返回玩家是否此时手持该附着物并下蹲。
- **context.item_slot**附着物手持的位置,返回"main_hand"(主手)或者"off_hand"(副手)。

View File

@@ -0,0 +1,551 @@
# 自定义3D武器第一人称攻击效果
在前两节自定义3D物品教程结束后我们学会了如何使用微软的Attachable功能完全实现自定义3D物品功能。
许多武器动作模组在《我的世界》模组体验上占有非常高的地位自定义3D物品可以在武器方面着重凸显组件的特点。本节课将会带领开发者学习如何使用自定义金剑制作独特的攻击形式配合模组SDK让作品特色更上一层楼。
**假设你看过前两节自定义3D物品教程你应该已经学会**
- 如何将一个现有的微软基岩版格式物品模型变为自定义物品的3D模型。✔
- 校对模型在模型空间的相对位置,以匹配并固定在玩家第三人称的手持位置。✔
- 借助《我的世界》基岩版电脑开发版使用开发者工具制作3D模型的第一人称动画。✔
**在本节课程你将学会:**
- 使用Blockbench为附着物设计手臂模型并重新调整金剑建模。
- 使用Blockbench和基岩版动画叠加效果制作第一人称手持金剑攻击动画。
- 用额外的渲染控制器挂载手臂模型至附着物。
- 借助模组SDK和自定义Query节点完成第一人称手持金剑攻击效果。
**本节课程的[Demo请戳这里下载](https://g79.gdl.netease.com/CustomWeaponAttackFP.zip)**
![动画](./images/attack0_0.gif)
## 设计手臂模型并重新调整金剑建模
打开前一节[自定义3D物品的Demo](https://g79.gdl.netease.com/CustomWeapon3D.zip),目前金剑的骨骼会按照下列排序:
```
-root玩家根骨骼
--waist玩家上半身骨骼
---body玩家身体骨骼
----rightArm玩家右手骨骼
-----rightItem玩家右手手持物品骨骼
------sword金剑骨骼
```
![image-20220612014504234](./images/attack0_0.png)
**我们设法在玩家手持金剑时,会在第一人称下显示两个手臂紧握着金剑。则此时两只手臂是跟随着金剑模型,而不牵扯到玩家模型本身。这样的设计意图给予了一些新的启发与可预料到的挑战。**
![任务计划甘特图 (2)](./images/attack0_1.png)
首先金剑的模型直接挂载在右手手持物品骨骼下。为了在之后的动画可以让金剑跟随着挥舞的手臂需要用arm骨骼取代sword骨骼用来存放握住金剑把手的手臂并将原先sword骨骼的体块纳入一个新的骨骼组item并将它作为arm骨骼的子骨骼。 **为之后做第一人称动画提供便利** 直接调整arm骨骼的动画参数即可金剑会跟随arm旋转、偏移或缩放。
![任务计划甘特图 (2)](./images/attack0_2.png)
除此之外我们并不希望让arm骨骼会出现在第三人称视角。 **这是因为当玩家手持物品时,玩家模型的手臂会自动消失。但切换回第三人称将重新出现。玩家模型本身的手臂会与金剑的新双臂同时出现,影响观感。**
![任务计划甘特图 (2)](./images/attack0_3.png)
**最终得出的初步方案里我们需要使用一个新的渲染控制器挂接arm骨骼至附着物上。一个附着物是可以满足挂载多个渲染控制器同时在骨骼层级不变的情况下可以在默认渲染控制器下挂载剑模型在arm骨骼渲染控制器下挂载arm模型。接着设置渲染控制器只会在第一人称下显示。**
**最终剑模型的骨骼层级如下Tips右键对应骨骼点击Resolve Group可在不移动子骨骼的前提下展开父骨骼**
```
-root玩家根骨骼
--waist玩家上半身骨骼
---body玩家身体骨骼
----rightArm玩家右手骨骼
-----rightItem玩家右手手持物品骨骼
------arm金剑双臂骨骼-不放置体块)
------item金剑骨骼
```
![image-20220612025314595](./images/attack0_4.png)
**最终剑手臂模型的骨骼层级如下Tips将原版资源包/models/mobs.json内的humanoid模型的两只手臂直接复制到这里可以继承原版steve模型的UV展开并快速对手臂进行建模**
```
-root玩家根骨骼
--waist玩家上半身骨骼
---body玩家身体骨骼
----rightArm玩家右手骨骼
-----rightItem玩家右手手持物品骨骼
------arm金剑双臂骨骼
------item金剑骨骼-不放置体块)
```
![image-20220612025523344](./images/attack0_5.png)
## 制作第一人称手持金剑攻击动画
切换至动画模式新建用以表现第一人称攻击动画sword_attack。
![image-20220612094740384](./images/attack0_6.png)
选中sword_attack动画同时勾选first_hold动画在手持第一人称动画生效的同时以此视角基础设计挥舞动画。
![image-20220612095303937](./images/attack0_7.png)
这里设计了一个0.75秒的攻击动画,在游戏里将实际从右往左挥舞金剑。其他形式可自行创作。
![动画1](./images/attack0_1.gif)
## 挂载手臂模型至附着物
在资源包/render_controllers文件夹下新建一个自定义的剑渲染控制器用以显示手臂模型。
```json
{
"format_version": "1.8.0",
"render_controllers": {
"controller.render.sword_controller": {
"geometry": "Geometry.arm",
"materials": [
{
"*": "Material.default"
}
],
"textures": [
"Texture.arm"
]
}
}
}
```
接着将手臂模型、手臂贴图、渲染控制器和第一人称动画挂载于附着物上。
```json
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "design:custom_golden_sword",
"materials": {
"default": "entity_alphatest",
"enchanted": "entity_alphatest_glint"
},
"textures": {
"default": "textures/entity/custom_golden_sword",
"enchanted": "textures/misc/enchanted_item_glint",
"arm": "textures/entity/steve" // arm键对应渲染控制器内的Texture.arm贴图路径则是原版内置的steve粗手臂贴图
},
"animations": {
"first_hold": "animation.custom_golden_sword.first_hold",
"first_scale": "animation.custom_golden_sword.first_scale",
"attack_rotation_sword": "animation.custom_golden_sword.sword_attack" // 自定义第一人称剑攻击动画
},
"scripts": {
"animate": [
{
"first_hold": "c.is_first_person"
},
{
"first_scale": "c.is_first_person"
}
]
},
"geometry": {
"default": "geometry.custom_golden_sword",
"arm": "geometry.custom_golden_sword_arm" // arm键对应渲染控制器内的Geometry.arm
},
"render_controllers": [ "controller.render.item_default",
{
"controller.render.sword_controller": "c.is_first_person" // 只有在第一人称下显示手臂模型和手臂贴图
}
]
}
}
}
```
进入游戏后,可以看到拿出金剑时,显示了两支手臂握住剑柄的效果。
![image-20220612102522220](./images/attack0_9.png)
## 完成第一人称手持金剑攻击效果
使用自定义Query节点接口可以最大限度地减少组件冲突的影响。自定义Query接口可以在客户端线程上自定义新的Query查询函数可以内置在动画或动画控制器中作为条件改变动画和动画控制器的效果。
![任务计划甘特图 (2)](./images/attack0_10.png)
在行为包内创建Python脚本目录取名CustomSwordScripts并创建服务端系统和客户端系统。有关模组SDK目录创建和系统注册的模块可以查看[此官网教程链接](https://g.126.fm/00FchC4)。
```
-CustomSwordScripts文件夹
--client.py客户端Python文件
---AnimationClient客户端类
--modMain.pymod入口
--server.py服务端Python文件
---AnimationServer服务端类
```
```python
# -*- coding: UTF-8 -*-
from mod.common.mod import Mod
import mod.server.extraServerApi as serverApi
import mod.client.extraClientApi as clientApi
@Mod.Binding(name="CustomSwordMod", version="0.1")
class CustomSwordMod(object):
def __init__(self):
pass
@Mod.InitClient()
def init_client(self):
clientApi.RegisterSystem("CustomSwordMod", "AnimationClient",
"CustomSwordScripts.client.AnimationClient")
@Mod.InitServer()
def init_server(self):
serverApi.RegisterSystem("CustomSwordMod", "AnimationServer",
"CustomSwordScripts.server.AnimationServer")
@Mod.DestroyClient()
def destroy_client(self):
pass
@Mod.DestroyServer()
def destroy_server(self):
pass
```
在客户端类的\__init__函数内监听OnLocalPlayerStopLoading事件当玩家客户端加载完毕后调用Query节点接口并注册query.mod.sword_attack。
```python
# -*- coding: UTF-8 -*-
import mod.client.extraClientApi as clientApi
import time
compFactory = clientApi.GetEngineCompFactory()
ClientSystem = clientApi.GetClientSystemCls()
class AnimationClient(ClientSystem):
def __init__(self, namespace, system_name):
ClientSystem.__init__(self, namespace, system_name)
namespace = clientApi.GetEngineNamespace()
system_name = clientApi.GetEngineSystemName()
self.ListenForEvent(namespace, system_name,
'OnLocalPlayerStopLoading', self, self.client_init) # 监听事件
def client_init(self, event):
player_id = clientApi.GetLocalPlayerId()
query_comp = compFactory.CreateQueryVariable(clientApi.GetLevelId()) # 创建基于世界的query组件
query_comp.Register('query.mod.sword_attack_time', 0.0) # 注册自定义Query节点必须以query.mod开头
query_comp = compFactory.CreateQueryVariable(player_id)
query_comp.Set('query.mod.sword_attack_time', 0.0) # 对本地玩家再次设置此节点的默认值
```
新增第一人称剑攻击动画控制器controller.animation.sword.first_attack。
```json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.sword.first_attack": {
"initial_state" : "default",
"states" : {
"default": {
"transitions" : [
{
"first_person" : "c.is_first_person"
}
]
},
"first_person": {
"transitions" : [
{
"default" : "!c.is_first_person" // 若为非第一人称视角,则返回至默认状态
},
{
"first_person_attack": "query.mod.sword_attack_time" // 当query.mod.sword_attack_time为真时切换至播放攻击动画的状态
}
]
},
"first_person_attack": {
"animations": [
"attack_rotation_sword" // 攻击动画
],
"transitions" : [
{
"default" : "!c.is_first_person" // 若为非第一人称视角,则返回至默认状态
},
{
"first_person": "!query.mod.sword_attack_time"// 当query.mod.sword_attack_time为假时切换至默认状态
}
]
}
}
}
}
}
```
将第一人称剑攻击动画控制器置入附着物定义文件内。
```json
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
//...
"animations": {
"first_hold": "animation.custom_golden_sword.first_hold",
"first_scale": "animation.custom_golden_sword.first_scale",
"attack_rotation_sword": "animation.custom_golden_sword.sword_attack",
"controller.attack": "controller.animation.sword.first_attack"
},
"scripts": {
"animate": [
"controller.attack",
{
"first_hold": "c.is_first_person"
},
{
"first_scale": "c.is_first_person"
}
]
}
// ...
}
}
}
```
紧接着监听LeftClickBeforeClientEvent与TapBeforeClientEvent分别对应在电脑启动器上使用左键与在手机上点击屏幕的事件事件回调可指向同一个函数地址代码解析如下
1. 在客户端系统上贮存点击的时间戳。
2. 在事件响应时计算当前时间扣去过去时间戳是否大于攻击动画的时间我们的自定义攻击动画时间为0.75秒因此判断结果需要大于0.75。
3. 满足条件2时继续判断是否满足是金剑是则重新计算时间戳。并执行函数send_attacked_packet。
4. send_attacked_packet函数内的业务逻辑主要是创建定时器任务用来发送数据至服务端再依次通过服务端向其他玩家客户端通知本地玩家播放挥舞动画。并在本地客户端设置query.mod.sword_attack的值帮助动画控制器播放动画效果。
```python
# -*- coding: UTF-8 -*-
import mod.client.extraClientApi as clientApi
import time
compFactory = clientApi.GetEngineCompFactory()
ClientSystem = clientApi.GetClientSystemCls()
class AnimationClient(ClientSystem):
def __init__(self, namespace, system_name):
ClientSystem.__init__(self, namespace, system_name)
namespace = clientApi.GetEngineNamespace()
system_name = clientApi.GetEngineSystemName()
self.ListenForEvent(namespace, system_name,
'OnLocalPlayerStopLoading', self, self.client_init)
self.ListenForEvent(namespace, system_name,
'LeftClickBeforeClientEvent', self, self.attack_click)
self.ListenForEvent(namespace, system_name,
'TapBeforeClientEvent', self, self.attack_click)
self.click_cooldown = time.time()
def client_init(self, event):
# ...
pass
def attack_click(self, event):
current_time = time.time()
carried_item = compFactory.CreateItem(clientApi.GetLocalPlayerId()).GetCarriedItem()
if current_time - self.click_cooldown > 0.75 and carried_item and carried_item['newItemName'] == 'design:custom_golden_sword':
self.click_cooldown = time.time()
self.send_attacked_packet(0.0, {# 动画开始的时间点
'playerId': clientApi.GetLocalPlayerId(),
'type': 'start'
})
self.send_attacked_packet(0.16, {# 动画打击出伤害的时间点,具体以自定义动画的设计形式为准
'playerId': clientApi.GetLocalPlayerId(),
'type': 'will_hit'
})
self.send_attacked_packet(0.75, { # 动画结束时间点
'playerId': clientApi.GetLocalPlayerId(),
'type': 'end'
})
else:
# 正在播放动画时,若重复点击,则取消点击
if carried_item and carried_item['newItemName'] == 'design:custom_golden_sword':
event['cancel'] = True
def send_attacked_packet(self, _time, data):
game_comp = compFactory.CreateGame(clientApi.GetLevelId())
game_comp.AddTimer(
_time,
self.NotifyToServer, # 发送数据至服务端,用来告知其他客户端当前玩家的播放动画状态,以便在其他客户端上也能看到玩家播放动画的效果
'AttackedPacket',
data
)
game_comp.AddTimer(
_time,
compFactory.CreateQueryVariable(clientApi.GetLocalPlayerId()).Set, # 设置本地玩家客户端播放动画所需的query节点的值
'query.mod.sword_attack_time',
1.0 if data['type'] == 'start' or data['type'] == 'will_hit' else 0.0
)
```
在服务端系统代码上监听来自客户端的事件AttackedPacket。代码解析如下
1. 若玩家点击左键播放动画的自定义客户端事件判断状态为will_hit动画打击出伤害获取周围的实体执行扇形攻击函数sector_attack。
2. sector_attack函数内计算了某个实体是否在另一个实体的扇形视角范围内。通过计算攻击者和受害者的坐标距离与攻击者和受害者的视角差度判断视角差度在一个固定的扇形角度时则创建伤害组件对受害者创造伤害。
3. 使用GetRelevantPlayer接口获取周围的玩家ID并使用NotifyToMultiClients接口向其他玩家传送事件AttackSync告知此名玩家开始播放动画其他玩家需在自己的本地客户端同样设置该名玩家的query.mod.sword_attack为真以实现动画效果同步。
```python
# -*- coding: UTF-8 -*-
import mod.server.extraServerApi as serverApi
import math
from mod.common.utils.mcmath import Vector3
compFactory = serverApi.GetEngineCompFactory()
ServerSystem = serverApi.GetServerSystemCls()
class AnimationServer(ServerSystem):
def __init__(self, namespace, system_name):
ServerSystem.__init__(self, namespace, system_name)
namespace = serverApi.GetEngineNamespace()
system_name = serverApi.GetEngineSystemName()
self.ListenForEvent('CustomSwordMod', 'AnimationClient',
'AttackedPacket', self, self.attacked)
def attacked(self, event):
_type = event['type']
player_id = event['playerId']
if _type == 'will_hit':
entities = compFactory.CreateGame(player_id).GetEntitiesAround(player_id, 6,
{
'any_of': {
'test': 'is_family',
'subject': 'other',
'operator': 'not',
'value': 'instabuild'
}
})
for entity in entities:
self.sector_attack(player_id, entity, 65.0, 6.0, 7, attacker_id=player_id)
elif _type == 'start':
players = compFactory.CreatePlayer(player_id).GetRelevantPlayer([player_id])
self.NotifyToMultiClients(players, 'AttackSync', {
'playerId': player_id,
'value': 1.0
})
else:
players = compFactory.CreatePlayer(player_id).GetRelevantPlayer([player_id])
self.NotifyToMultiClients(players, 'AttackSync', {
'playerId': player_id,
'value': 0.0
})
def sector_attack(self, attacker, victim, between_angle=0.0, radius=0.0, damage=0, cause=serverApi.GetMinecraftEnum().ActorDamageCause.EntityAttack, attacker_id=None, child_attacker_id=None, knock=True):
attacker_foot_pos = compFactory.CreatePos(attacker).GetFootPos()
victim_foot_pos = compFactory.CreatePos(victim).GetFootPos()
delta = Vector3(victim_foot_pos) - Vector3(attacker_foot_pos)
forward_vector = serverApi.GetDirFromRot(compFactory.CreateRot(attacker).GetRot())
angle = math.degrees(math.acos(Vector3.Dot(delta.Normalized(), Vector3(forward_vector).Normalized())))
if angle < between_angle and delta.Length() < radius:
compFactory.CreateHurt(victim).Hurt(damage, cause, attacker_id, child_attacker_id, knock)
```
最后在客户端上监听来自自定义服务端的AttackSync事件。在本地客户端设置其他玩家播放动画的进度。
```python
# -*- coding: UTF-8 -*-
import mod.client.extraClientApi as clientApi
import time
compFactory = clientApi.GetEngineCompFactory()
ClientSystem = clientApi.GetClientSystemCls()
class AnimationClient(ClientSystem):
def __init__(self, namespace, system_name):
ClientSystem.__init__(self, namespace, system_name)
namespace = clientApi.GetEngineNamespace()
system_name = clientApi.GetEngineSystemName()
# ....
self.ListenForEvent('CustomSwordMod', 'AnimationServer',
'AttackedSync', self, self.attacked_sync)
# ....
def client_init(self, event):
# ....
pass
def attack_click(self, event):
# ....
pass
def attacked_sync(self, event):
player_id = event['playerId']
value = event['value']
compFactory.CreateQueryVariable(player_id).Set(
'query.mod.sword_attack_time',
value
)
def send_attacked_packet(self, _time, data):
# ....
pass
```
可以看到最后实际效果如预期所示,对羊群造成了范围伤害并播放自定义攻击动画。有条件联机的开发者,也可以验证多人联机下攻击动画的播放效果。
![动画2](./images/attack0_2.gif)

View File

@@ -0,0 +1,250 @@
# 自定义3D武器第三人称攻击效果
在上节中我们初步掌握如何自定义3D武器在第一人称视角下的攻击效果。由于玩家存在第一人称和第三人称适配第三人称是必不可少的。
第三人称下的自定义3D武器攻击效果需要依赖Python代码这里使用传统的注册自定义系统的模组开发方式为大家讲解。
**在本章你将学会:**
- 使用Blockbench和基岩版动画叠加效果制作第三人称手持金剑动画与对应的攻击动画。
- 使用模组SDK挂载新的动画资源并重构第三人称动画控制器。
本节课程所使用到的[Demo请戳这里](https://g79.gdl.netease.com/customweaponnew.zip),以下是最终效果呈现:**
![444](./images/attack21_0.gif)
## 创建第三人称所需的动画资源
启动Blockbench打开custom_golden_sword_arm.geo.json并切换至动画模式新建表现第三人称手持动画的third_hold。并将手臂向X轴朝上方旋转。
![image-20220702104920739](./images/attack21_0.png)
新建表现第三人称挥舞动画的third_arm_attack选择third_arm_attack动画并勾选third_hold动画自定义一段0.75秒的攻击动画。并将关键帧设置为平滑,让动画效果更丝滑。
![0_0](./images/attack21_1.gif)
由于手臂和剑分成两个模型手臂的动画通道无法影响武器为了让手臂挥舞时剑能与之轨迹同步我们需要在剑模型上再多做一个动画。打开custom_golden_sword.geo.json切换至动画模式新增third_sword_attack动画在选中后勾选third_hold动画也自定义一段和手挥舞时长一样的0.75秒攻击动画这里可以将third_arm_attack的arm骨骼关键帧拷贝一份过来并对third_sword_attack的item骨骼打上动画关键帧。最后选择third_sword_attack动画并勾选third_hold和third_arm_attack动画可以看到完整的第三人称攻击动画效果。
![0_1](./images/attack21_2.gif)
## 挂载新的动画资源并创建新的动画控制器
新建controller.animation.player.third_person_attack_fixed动画控制器下设default和third_person_attack两个状态当满足query.mod.sword_attack_time不等于0时切换至播放第三人称攻击动画的状态动画播放结束时且对应的query.mod.sword_attack_time为0时切换回default状态以下是代码示例。
```json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.player.third_person_attack_fixed" : {
"states" : {
"default": {
"transitions": [
{
"third_person_attack": "query.mod.sword_attack_time"
}
]
},
"third_person_attack": {
"animations": [
"third_arm_attack"
],
"transitions": [
{
"default": "!query.mod.sword_attack_time"
}
]
}
}
}
}
}
```
接着在CustomSwordScripts/client.py内的client_init函数下添加ActorRender组件在游戏运行时动态添加美术资源至玩家资源定义内。由于第三人称的手臂动画涉及到玩家的资源这是不得不采取的措施为了尽量减少冲突的可能性我们不选择直接修改玩家资源定义内容而是使用Python代码导入。
```python
class AnimationClient(ClientSystem):
# ...
def client_init(self, event):
# ...
actor_comp.AddPlayerAnimationController( # 第三人称攻击动画控制器
'controller.third_person_attack_fixed',
'controller.animation.player.third_person_attack_fixed'
)
actor_comp.AddPlayerAnimation(
'sword_third_hold',
'animation.custom_golden_sword.third_hold' # 第三人称手持动画
)
actor_comp.AddPlayerAnimation(
'third_arm_attack',
'animation.custom_golden_sword.third_arm_attack' # 第三人称手臂动画
)
# 添加第三人称手持动画进玩家root动画控制器下的third_person状态里这里存放的都是玩家在第三人称时会使用到的动画
# 动画需满足主手手持必须是自定义金剑才会生效
actor_comp.AddPlayerAnimationIntoState(
'root', 'third_person', 'sword_third_hold', "query.get_equipped_item_full_name('main_hand') == 'design:custom_golden_sword'"
)
# 添加第三人称手持动画控制器进玩家root动画控制器下的third_person状态里动画控制器同样可以被嵌套在其他动画控制器内
# 动画控制器需满足主手手持必须是自定义金剑才会生效
actor_comp.AddPlayerAnimationIntoState(
'root', 'third_person', 'controller.third_person_attack_fixed', "query.get_equipped_item_full_name('main_hand') == 'design:custom_golden_sword'"
)
actor_comp.RebuildPlayerRender() #导入资源后必须重新构建玩家渲染调用RebuildPlayerRender方法
```
在剑的attachable定义文件内挂接third_sword_attack动画。这是因为剑挥舞的效果可以转移给剑本身因此third_sword_attack应该挂在剑的资源定义文件内。
```json
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "design:custom_golden_sword",
//materials
//textures
"animations": {
//...
"attack_rotation_sword": "animation.custom_golden_sword.sword_attack",
"third_attack_rotation_sword": "animation.custom_golden_sword.third_sword_attack",
"controller.attack": "controller.animation.sword.attack"
},
"scripts": {
"animate": [
"controller.attack",
{
"first_hold": "c.is_first_person"
},
{
"first_scale": "c.is_first_person"
}
]
}
//geometry
//render_controlls
}
}
}
```
重写controller.attack动画控制器新增third_person和third_person_attack两个状态。要求在第三人称下状态切换为third_person攻击开始时状态切换至third_person_attack并播放第三人称的剑挥舞动画在query.mod.sword_attack_time为0时切换回third_person状态。在有关第三人称的所有状态下提供切换至default状态的条件即满足c.is_first_person手持实体处于第一人称时。
```json
{
"format_version": "1.10.0",
"animation_controllers": {
//...
"controller.animation.sword.attack": {
"initial_state" : "default",
"states" : {
"default": {
"transitions" : [
// first_person
{
"third_person": "!c.is_first_person"
}
]
},
// first_person
"third_person": {
"transitions" : [
{
"default" : "c.is_first_person"
},
{
"third_person_attack": "query.mod.sword_attack_time"
}
]
},
"third_person_attack": {
"animations": [
"third_attack_rotation_sword"
],
"transitions" : [
{
"default" : "c.is_first_person"
},
{
"third_person": "!query.mod.sword_attack_time"
}
]
}
// first_person_attack
}
}
}
}
```
最后进入游戏,可以看到第三人称效果已经生效。
![444](./images/attack21_0.gif)
## 一些其他优化
由于我们并没有屏蔽玩家在挥舞时点触方块的逻辑造成挥舞的区域若离方块较近会叠加出较为难看的挖掘动画。为了避免这个问题可以在client.py和server.py文件分别监听StartDestroyBlockClientEvent和StartDestroyBlockServerEvent根据实际情况判断结果对挖掘进行取消。
以下是代码示例:
```python
# client.py
class AnimationClient(ClientSystem):
def __init__(self, namespace, system_name):
#....
namespace = clientApi.GetEngineNamespace()
system_name = clientApi.GetEngineSystemName()
self.ListenForEvent(namespace, system_name,
'StartDestroyBlockClientEvent', self, self.attack_click_block)
#....
def attack_click_block(self, event):
player_id = event['playerId']
if player_id != clientApi.GetLocalPlayerId():
return
current_time = time.time()
if current_time - self.click_cooldown < 0.75:
event['cancel'] = True
```
```python
# server.py
class AnimationServer(ServerSystem):
def __init__(self, namespace, system_name):
ServerSystem.__init__(self, namespace, system_name)
#....
namespace = serverApi.GetEngineNamespace()
system_name = serverApi.GetEngineSystemName()
self.ListenForEvent(namespace, system_name,
'StartDestroyBlockServerEvent', self, self.attack_click_block)
self.player_attacked_cache = {}
self.attack_type = ['start', 'will_hit', 'end']
#...
def attack_click_block(self, event):
player_id = event['playerId']
if self.player_attacked_cache.get(player_id, '') != 'end':
event['cancel'] = True
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,135 @@
---
front:
hard: 入门
time: 分钟
---
# 微缩方块
微缩方块用于将游戏内的若干区域的方块形状缩小成若干个单个小方块进行显示,目前游戏内仅开放预微缩方块。
1. 预微缩方块,通过使用 modsdk 接口生成对应的微缩方块信息并由开发者保存为微缩方块文件,然后将该文件放入到 mod 中,重进游戏后,微缩方块便类似于游戏的原生方块,可以在物品列表里找到并使用
## Demo 解释
MicroBlocksMod 定义了三个不同的微缩方块:
1. number_9一个 2x2x2 大小的微缩方块,并附带图标
2. number_9_2一个 1x1x1 大小的微缩方块
3. number_9_3和 number_9_2 一样,只是修改了方块颜色。
## 预微缩方块注册
注意:以下文件都可以在 MicroBlocksMod 里找到
首先需要在 `MicroBlocksMod_behavior/netease_micro_blocks/` 文件夹下新建微缩方块信息,然后需要在 `MicroBlocksMod_resource/models/netease_micro_block/` 文件夹下新建微缩方块图像信息,这里我们以建立 number_9_2.json 为例:
1. 在 MicroBlocksMod_behavior/netease_micro_blocks/ 文件夹下新建 number_9_2.json 文件
2. 向 number_9_2.json 中写入如下信息,其中:
- `identifier` 用于表示微缩方块的唯一标识,对于微缩方块来说,必须以 `micro_block:` 开头,否则游戏中无法识别为微缩方块,推荐 identifier 为 micro_block:命名空间_方块名。命名空间推荐与 mod 名称一致。而冒号后的方块名必须全局唯一为避免与原版方块以及其他mod重复请加上 命名空间_ 作为前缀来保证唯一。
- `register_to_creative_menu` 用于控制是否在物品列表里显示该微缩模型,通过设置为 `true`,即可像原版方块一样在物品列表里找到
- `micro_size` 用于表示当前微缩方块占据的方格大小,例如 `"1 1 2"` 即表示该微缩方块占据 1x1x2 大小的方格(注:原版草方块占据 1x1x1 的方格大小),配置时必须为整数且中间需要使用空格分隔,注意目前微缩方块最大支持为 4x4x4 的大小,即使配置超过 4 也无法占据更多方格。
- 注意微缩方块不支持原版和网易版的json组件。
```
{
"format_version": "1.13.0",
"minecraft:block": {
"description": {
"identifier": "micro_block:number_9_2",
"register_to_creative_menu": true,
"micro_size": "1 1 1"
},
"components": {
}
}
}
```
3.`MicroBlocksMod_resource/models/netease_micro_block/` 文件夹下新建 number_9_2.json 文件,文件的内容可以通过 `blockCompServer` 下的 `CreateMicroBlockResStr` 获取,其中函数的原型如下:
`CreateMicroBlockResStr(self, identifier, start, end, colorMap=None, isMerge=False, icon="")`
- identifierstr微缩方块的唯一标识由于会自动添加 `micro_block:`,所以这里只用填入 `x` 即可
- start(int, int, int),微缩的起始坐标,例如 (30, 65, 78)
- end(int, int, int),微缩的结束坐标,例如 (44, 77, 90)
- colorMapDict用于指定某类型方块的微缩后的方块颜色例如 colorMap={"minecraft:grass": [12, 12, 12, 255], "minecraft:stone": [12, 233, 24]},会将所有符合类型的方块的颜色改变
- isMergeBool用于标识是否合并同类型方块这样可以减少性能消耗
- iconstr用于指定微缩方块的 icon。注意 icon 并不能直接使用图标所在的相对路径,而是需要先将图标添加到 terrain_texture.json 中,然后引用图标的注册名称,具体使用方法可以参考 [自定义方块注册](https://mc.163.com/mcstudio/mc-dev/MCDocs/2-ModSDK%E6%A8%A1%E7%BB%84%E5%BC%80%E5%8F%91/03-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B8%B8%E6%88%8F%E5%86%85%E5%AE%B9/05-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%96%B9%E5%9D%97/0-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%96%B9%E5%9D%97%E6%A6%82%E8%BF%B0.html)
使用 `CreateMicroBlockResStr` 返回的结果的为字符串,需要开发者主动进行保存
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateBlock(levelId)
result = comp.CreateMicroBlockResStr("x", (12, 60, 12), (26, 76, 26), colorMap={'minecraft:grass': [12, 22, 123, 255]}, isMerge=True, icon="micro_block_datiangou")
with open("micro_block_x.json", "w+") as f:
f.write(result)
#该例子中,方块将以 (12 60 12) 为起点,以 (26 76 26) 为终点进行微缩,最终微缩方块里所有草方块的颜色为 rgba(12,22,123,255),实际显示颜色会依据环境光照微调,物品栏里的图标为 terrain_texture.json 里 micro_block_datiangou 对应的图片。
```
- 使用 start 和 end 选中的区域,仅仅会生成其中的方块数据(包括自定义方块),对于生物等实体数据并不会包含其中。当选中的区域没有被加载时,不会产生数据,当选中的区域包含已加载区域和未加载区域时,仅仅只会产生已加载区域的数据。
- 将 start 和 end 反向,渲染方向会相反。
## 微缩方块资源数据说明
下面来查看 MicroBlocksMod 里自带的 number_9_2 微缩方块资源数据
```
{
"netease:micro_block": {
"data": {
"11": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"10": [[], [], [0, 0, 0, 1], [], [], [], [], [], [], [], [0, 0, 0, 1]],
"13": [[], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"12": [[], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"14": [[], [], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 2]],
"1": [[], [], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]],
"3": [[], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"2": [[], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"5": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [], [], [], [0, 0, 0, 1]],
"4": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"7": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"6": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]],
"9": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]],
"8": [[], [], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [], [], [], [0, 0, 0, 1], [0, 0, 0, 1]]
},
"description": {
"identifier": "micro_block:number_9_2",
"blocks": {
"1": {
"aux": 0,
"name": "minecraft:grass",
"color": [254, 46, 45, 255]
},
"2": {
"aux": 1,
"name": "minecraft:grass",
"color": [254, 46, 45, 255]
}
}
"icon": "",
"size": [11, 15, 6]
}
},
"format_version": "1.13.0"
}
```
对于一个基本的微缩方块资源数据来说,主要有 6 个需要专注的数据:
1. identifier需要在 behavior 下有同样匹配的方块 identifier
2. icon微缩方块所对应的图标
3. block_size用于标识微缩方块渲染图形所占的大小对于 1x1x1 的方格来说,其渲染大小为 [16, 16, 16],即游戏会使用 16x16x16 的方块数据去渲染一个体积为游戏原生方格大小的微缩模型。 从游戏性能的角度,目前最大支持 [64, 64, 64],即一个微缩方块集合所生成的最大范围为 `4*4*4` 的方格(注意这里的大小需要匹配 behavior 下的方块 micro_size
4. blocks该微缩方块所包含的所有方块信息每个字符串序号对应的序号方块的信息
5. data微缩方块具体的组成数据。
- 对于 block_size 小于或等于 [16, 16, 16] 的数据来说(即整个模型只占用一个原版方块的位置),其 data 由单个字典组成,每个字典下的标识,例如数据中的 `"3"` 用于标识第三层的组成数据,然后对应 `"3"` 的数据来说,依次为从北向南的每排渲染数据,对于具体到某一排的数据来说,依次会从东向西进行渲染。渲染数据中,用 0 表示空气方块代表这里并没有任何方块1 表示这里为 "blocks" 里的第一个方块,依此类推。
- 对于 block_size 大于 [16, 16, 16] 的数据来说,即包含较多的微缩方块,例如为 [32, 32, 32] 的数据(模型需要占用 `(32 / 16) x (32 / 16) x (32 / 16) = 8`data 下的数据由一个列表组成,分别对应以 `x + z*x + y*z*x` 为序的列表数据。
6. light_factor默认值 [1.0, 1.0, 1.0, 1.0, 1.0, 1.0],每个值的范围为 0 ~ 1.0,用于调整微缩方块各个面的光照强度
注意:对于 PE 端来说,如果微缩方块的数据过大,会导致游戏的初始加载时间延长,如果包含的微缩方块过多,且每个数据都特别大,会导致游戏初始加载时间大大延长。

View File

@@ -0,0 +1,589 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义附魔
在原有游戏的基础上增加自定义附魔自定义附魔效果需通过mod编写具体实现
## Demo 解释
1.[EnchantDemo](../13-模组SDK编程/60-Demo示例.md#EnchantDemo) 定义了4中魔咒类型
- 疾行 -- 常驻类型附魔,移动速度变快,只可附在鞋子上
- 雷鸣四方 -- 循环类型附魔,每过一段时间在玩家周围落雷,只能附在头盔上
- 战利品 -- 触发类型附魔,攻击生物会在生物的位置产生一个苹果,只能附在镐上
- 沉重 -- 诅咒类型附魔,给玩家添加饥饿状态效果,只能附在剑上
2.修改了羊,马,牛,鸡的战利品表,分别对应下方文档中四种战利品表配置情况
3.添加了一个自定义稿子,可用于测试自定义附魔碰到自定义物品的情况
4.重写了图书管理员和武器匠的交易,可以卖附魔书和带有附魔的武器
## 1 功能
1. 注册新的附魔
2. 设置附魔可以附到哪些工具或装备
3. 设置附魔的最大等级,以及每级所消耗的经验值
4. 设置附魔稀有度
5. 设置附魔是否为宝藏型魔咒
6. 设置附魔是否可以通过图书管理员获得
7. 设置附魔是否为诅咒型魔咒
8. 设置冲突附魔
9. 可以从itemdict获取物品的附魔信息
10. 可以从附魔台对合适的工具或装备或书进行附魔
11. 带有自定义附魔的附魔书可以在铁砧上使用
12. 可以通过MC原生的附魔获取途径获取相应的附魔道具 [【附魔途径Wiki】](https://zh.minecraft.wiki/w/%E9%AD%94%E5%92%92)
## 2 注册自定义附魔
在mod**行为包和资源包**内添加`netease_enchants`文件夹向其中添加自定义附魔json
### 2.1 自定义附魔json示例
```json
{
"netease:enchant": {
// 必填项
"identifier": "demoenchant:customenchant1", // 自定义附魔id需全为小写字母
"description": "enchantment.demoenchant.customenchant1", // 自定义附魔名称对应zh_CN.lang中的langStr
"primary_slots": ["elytra"], // 附魔槽位,被附魔物品只有槽位相同才能附魔成功
"cost": [3,6,9,12,15], // 附魔威力等级对应的经验消耗会影响砂轮移除魔咒时返回的经验值以及在附魔台上被附魔到该魔咒的概率cost越大附魔概率越小;列表内元素数量需与max_level一致否则注册失败
// 选填项
"frequency": "very_rare", // 自定义附魔稀有度影响铁砧结合附魔物品的经验消耗默认为common
"is_treasure_only": false, // 设为true时为宝藏型魔咒将影响附魔获取方式默认为false
"is_discoverable": true, // 设为false时为宝藏型魔咒将影响附魔获取方式默认为true
"is_lootable": true, // 设为true时可以通过与图书管理员交易获得默认为true
"is_curse": false, // 设为true时为诅咒附魔不可通过砂轮移除默认为false
"max_level": 5, // 附魔威力等级设置后会自动在创造物品栏注册各等级的附魔书默认为1
"incompatible": ["unbreaking"] // 冲突附魔名称
}
}
```
### 2.2 primary_slots(附魔槽位)
自定义附魔可选槽位
| string | 对应槽位 |
| -------------- | ------------------------------------------------------------ |
| all | 全部(以下全部槽位,非游戏中所有物品) |
| g_armor | 全部盔甲 |
| armor_head | 头盔 |
| armor_torso | 胸甲 |
| armor_legs | 护腿 |
| armor_feet | 靴子 |
| sword | 剑 |
| bow | 弓 |
| spear | 三叉戟 |
| crossbow | 弩 |
| g_tool | 锄、剪刀、打火石、盾 |
| hoe | 锄 |
| shears | 剪刀 |
| flintsteel | 打火石 |
| shield | 盾牌 |
| g_digging | 锄、斧、镐、锹 |
| axe | 斧 |
| pickaxe | 镐 |
| shovel | 锹 |
| fishing_rod | 钓竿 |
| carrot_stick | 胡萝卜钓竿 |
| elytra | 鞘翅 |
| cosmetic_head | 骷髅模型/凋零骷髅模型/模型/僵尸模型/龙的模型/爬行者的模型/雕刻南瓜 |
| compass | 指南针 |
| mushroom_stick | 诡异菌钓竿 |
### 2.3 frequency(稀有度)
稀有度影响铁砧结合附魔物品时的经验消耗计算
默认common
#### 2.3.1 各等级稀有度对应cost
| 稀有度 | cost |
| --------- | ---- |
| common | 1 |
| uncommon | 2 |
| rare | 4 |
| very_rare | 8 |
#### 2.3.2 铁砧结合附魔物品消耗经验计算规则
1. 假定 物品1 拥有 附魔a、附魔b它们稀有度对应的cost分别为cost_a和cost_b威力等级分别为level_a和level_b则物品的总cost计算规则如下
total_cost = cost_a * level_a + cost_b * level_b
若物品为附魔书则total_cost计算规则如下
total_cost = max(1, cost_a / 2) * level_a + max(1, cost_b / 2) * level_b
若物品拥有更多数量的附魔,依上述公式类推
2. 计算铁砧上 物品1 的total_cost此处设为initial_total_cost
3. 根据[铁砧结合物品规则](https://zh.minecraft.wiki/w/%E9%93%81%E7%A0%A7#.E7.94.A8.E9.80.94)计算结合后预计产生的物品2的total_cost此处设为combined_total_cost
4. final_cost = combined_total_cost - initial_total_cost
5. 若final_cost大于0且物品1的数量大于1则final_cost = 40 如下图:
6. 若铁砧结合的物品2不携带附魔则final_cost = 0
**最终铁砧结合物品操作消耗经验还受其他因素影响最终消耗等级可能大于final_cost**
![image-20210817155010961](./picture/custom_enchant.png)
#### 2.3.3 原生附魔id及frequency
| Type | 附魔名称 | identifier | frequency |
| ---- | ---------- | --------------------- | --------- |
| 0 | 保护 | protection | common |
| 1 | 火焰保护 | fire_protection | uncommon |
| 2 | 摔落保护 | feather_falling | uncommon |
| 3 | 爆炸保护 | blast_protection | rare |
| 4 | 弹射物保护 | projectile_protection | uncommon |
| 5 | 荆棘 | thorns | very_rare |
| 6 | 水下呼吸 | respiration | rare |
| 7 | 深海探索者 | depth_strider | rare |
| 8 | 水下速掘 | aqua_affinity | rare |
| 9 | 锋利 | sharpness | common |
| 10 | 亡灵克星 | smite | uncommon |
| 11 | 节肢克星 | bane_of_arthropods | uncommon |
| 12 | 击退 | knockback | uncommon |
| 13 | 火焰附加 | fire_aspect | rare |
| 14 | 抢夺 | looting | rare |
| 15 | 效率 | efficiency | common |
| 16 | 精准采集 | silk_touch | very_rare |
| 17 | 耐久 | unbreaking | uncommon |
| 18 | 时运 | fortune | rare |
| 19 | 力量 | power | common |
| 20 | 冲击 | punch | rare |
| 21 | 火矢 | flame | rare |
| 22 | 无限 | infinity | very_rare |
| 23 | 海之眷顾 | luck_of_the_sea | rare |
| 24 | 饵钓 | lure | rare |
| 25 | 冰霜行者 | frost_walker | rare |
| 26 | 经验修补 | mending | rare |
| 27 | 绑定诅咒 | binding | very_rare |
| 28 | 消失诅咒 | vanishing | very_rare |
| 29 | 穿刺 | impaling | uncommon |
| 30 | 激流 | riptide | rare |
| 31 | 忠诚 | loyalty | common |
| 32 | 引雷 | channeling | very_rare |
| 33 | 多重箭 | multishot | rare |
| 34 | 穿透 | piercing | common |
| 35 | 快速装填 | quick_charge | uncommon |
| 36 | 灵魂疾行 | soul_speed | very_rare |
### 2.4 is_treasure_only(是否为宝藏型魔咒)
当is_treasure_only设为true时该附魔仅能通过以下方式获取
1. 通过配置[ ***指定附魔等级的附魔物品*** 的战利品表](#enchant_with_levels),概率获取
2. 通过配置[ ***随机附魔物物品*** 的战利品表](#enchant_randomly),概率获取
3. 通过配置[ ***指定附魔物品*** 的战利品表](#specific_enchants),概率获取
4. 通过与图书管理员交易获取,且图书管理员会为宝藏型魔咒的附魔书提出双倍要价
默认false
### 2.5 is_discoverable
当is_discoverable设为false时该附魔仅能通过以下方式获取
1. 当is_lootable为true时通过与图书管理员交易获取
2. 通过配置[ ***指定附魔物品*** 的战利品表](#specific_enchants),概率获取
默认true
### 2.6 is_lootable(是否可通过图书管理员交易)
is_lootable只影响与图书管理员的交易当设为true时图书管理员可能出售包含该附魔的附魔书
### 2.7 is_curse(是否为诅咒型附魔)
is_curse设为true时为诅咒附魔不可通过砂轮移除
默认值:false
### 2.8 max_level(附魔威力等级)
max_level设置后会自动在创造栏注册各等级的附魔书(max_level必须和cost数组长度相等)
默认值1
## 3 附魔指令/enchant
成功注册的自定义附魔将出现在/enchant指令备选项中仅支持以下格式
**/enchant <*玩家:目标*> <*魔咒名魔咒id(string)*> [*等级:整数*]**
关于/enchant指令详见[官方wiki](https://zh.minecraft.wiki/w/%E5%91%BD%E4%BB%A4/enchant)
## 4 战利品表配置自定义附魔
### 4.1 战利品表概念见[官方wiki](https://zh.minecraft.wiki/w/%E6%88%98%E5%88%A9%E5%93%81%E8%A1%A8)
### 4.2 获得附魔物品的战利品表配置举例:
#### 4.2.1 获得 ***指定附魔等级的附魔物品*** 的战利品表配置<span id="enchant_with_levels"></span>
```json
{
"pools": [
{
"rolls": 1, // 抽取次数
"entries": [
{
"type": "item", // 掉落类型
"name": "minecraft:book", // 物品名称
"weight": 15, // 权重
"functions": [
{
// 指定附魔等级的附魔物品函数
"function": "enchant_with_levels",
// 附魔等级
"levels": 30,
// 物品是否能被附上宝藏型附魔("is_lootable")默认为false
"treasure": true
}
]
}
]
}
]
}
```
附魔函数enchant_with_levels 指定附魔等级的附魔物品函数
附魔参数levels [附魔等级](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89#%E9%99%84%E9%AD%94%E7%AD%89%E7%BA%A7)
treasure 物品是否能附上宝藏型附魔
4.2.2 获得 ***随机附魔物品*** 的战利品表配置<span id="enchant_randomly"></span>
```json
{
"pools": [
{
"rolls": 1, // 抽取次数
"entries": [
{
"type": "item", // 掉落类型
"name": "minecraft:golden_sword", // 物品名称
"weight": 15, // 权重
"functions": [
{
// 随机附魔函数附魔等级为1-30内随机整数
"function": "enchant_randomly",
// 物品是否能被附上宝藏附魔("is_lootable")默认为false
"treasure": true
}
]
}
]
}
]
}
```
附魔函数enchant_randomly 随机附魔函数,[附魔等级](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89#%E9%99%84%E9%AD%94%E7%AD%89%E7%BA%A7)为1-30内的随机数
附魔参数treasure 物品是否能附上宝藏型附魔
#### 4.2.3 获得 ***指定附魔物品*** 的战利品表配置<span id="specific_enchants"></span>
```json
{
"pools": [
{
"rolls": 1, // 抽取次数
"entries": [
{
"type": "item", // 掉落类型
"name": "minecraft:iron_boots", // 物品名称
"weight": 5, // 权重
"functions": [
{
// 获取指定附魔的附魔物品函数
"function": "specific_enchants",
"enchants": [
{
// 指定的附魔id/自定义附魔identifier
"id": "soul_speed",
// 魔咒威力范围,默认为[1,1],非附魔等级
"level": [1, 3]
}
]
}
]
}
]
}
]
}
```
附魔函数specific_enchants 指定附魔的附魔物品函数
附魔参数enchants 指定附魔列表
4.2.4 获得 ***附魔装备*** 的战利品表配置
```json
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "item",
"name": "minecraft:golden_sword",
"weight": 1,
"functions": [
{
// 随机附魔装备/工具的函数
"function": "enchant_random_gear",
// 被附魔的概率
"chance": 0.25
}
]
}
]
}
]
}
```
附魔函数enchant_random_gear 随机附魔装备/工具的函数
附魔参数chance 被附魔的概率
注:[附魔等级](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89#%E9%99%84%E9%AD%94%E7%AD%89%E7%BA%A7)非[魔咒威力](https://zh.minecraft.wiki/w/%E9%AD%94%E5%92%92),具体可查看[【官方Wiki】](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89#%E9%99%84%E9%AD%94%E7%AD%89%E7%BA%A7)
## 5 村民交易
### 5.1 村民交易所需物品数量计算规则:
- 交易所需第一个物品数量(costA)遵循以下规则:
1. 若quantity配置为`"quantity" : {"min": min, "max": max}`则costA在min和max之间取随机整数
2. 若quantity配置为`"quantity": num`则costA = num
3. 若costA大于所需消耗物品最大堆叠数costA取该物品最大堆叠数
4. 根据配置的函数修改costA例如与图书管理员交易获取附魔书"enchant_book_for_trading"会修改costA规则见[图书管理员交易](#librarain)
5. 最终costA会根据玩家是否拥有[村庄英雄](https://zh.minecraft.wiki/w/%E6%9D%91%E5%BA%84%E8%8B%B1%E9%9B%84)状态,及"price_multiplier"配置(见[交易经济](https://zh.minecraft.wiki/w/%E6%B5%81%E6%B5%AA%E5%95%86%E4%BA%BA)),再进行增减
- 交易所需第二个物品数量(如有)(costB)遵循以下规则:
1. 若quantity配置为`"quantity" : {"min": min, "max": max}`则costB在min和max之间取随机整数
2. 若quantity配置为`"quantity": num`则costB = num
3. 若costB大于所需消耗物品最大堆叠数costB取该物品最大堆叠数
4. 与第一个物品不同的是第二个物品仅受quantity影响不会因其他原因增减
### 5.2 图书管理员交易表<span id="librarain"></span>
图书管理员交易附魔书所需第一个物品数量计算规则:
1. 随机选取一个"is_lootable": true的附魔灵魂疾行不包含在内
2. 最终附魔威力等级在该附魔最小威力等级和最大威力等级间取随机整数
3. baseCostA = base_cost + random.int(base_random_cost + 附魔威力等级 * per_level_random_cost) + per_level_cost * 附魔威力等级
*base_cost/base_random_cost/per_level_random_cost/per_level_cost见下文enchant_book_for_trading配置*
4. 若该附魔为宝藏附魔则baseCostA = baseCostA * 2
5. 若baseCostA大于所需消耗物品最大堆叠数baseCostA取该物品最大堆叠数
图书管理员交易表举例如下:
```json
{
"tiers": [
{
"total_exp_required": 0, // 解锁该组交易所需的村民经验
"groups": [
{
"num_to_select": 1, // 从下列交易中选取几项交易
"trades": [
{
// 该交易需求的物品信息
"wants": [
// 第一个物品
{
"item": "minecraft:paper", // 物品名称
"quantity": 24, // 物品数量
"price_multiplier": 0.05 // 价格乘数(影响补货后的价格)
},
// 第二个物品(也可不设第二个物品)
{
"item": "minecraft:book", // 物品名称
"quantity": 1 // 物品数量
}
],
// 该交易给予玩家的物品信息
"gives": [
{
"item": "minecraft:book", // 物品名称
"quantity": 1, // 物品数量
"functions": [
{
"function": "enchant_book_for_trading", // 交易附魔书
"base_cost": 2, // 默认为2
"base_random_cost": 5, // 默认为5
"per_level_random_cost": 10, // 默认为10
"per_level_cost": 3 // 默认为3
}
]
}
],
// 单次交易完成后增加的村民经验值
"trader_exp": 2,
// 最大交易次数
"max_uses": 16,
// 交易完成后是否给予玩家经验默认为true
"reward_exp": true
}
]
}
]
}
]
}
```
### 5.3 武器商交易表
武器商交易表举例如下:
```json
{
"tiers": [
{
"total_exp_required": 0, // 解锁该组交易所需的村民经验
"groups": [
{
"num_to_select": 1, // 从下列交易中选取几项交易
"trades": [
{
// 该交易需求的物品信息
"wants": [
// 第一个物品
{
"item": "minecraft:coal:0", // 物品名称
"quantity": 15, // 物品数量
"price_multiplier": 0.05 // 价格乘数(影响补货后的价格)
}
],
// 该交易给予玩家的物品信息
"gives": [
{
"item": "minecraft:iron_sword", // 物品名称
"quantity": 1, // 物品数量
"functions": [
{
"function": "enchant_with_levels", // 为物品附上指定等级附魔
// 物品是否能被附上宝藏附魔("is_lootable")默认为false
"treasure": false,
// 最终等级在最小等级和最大等级间取随机整数
"levels": {
"min": 5, // 最小附魔等级
"max": 19 // 最大附魔等级
}
}
]
}
],
// 单次交易完成后增加的村民经验值
"trader_exp": 2,
// 最大交易次数
"max_uses": 16,
// 交易完成后是否给予玩家经验默认为true
"reward_exp": true
}
]
}
]
}
]
}
```
## 6 自定义附魔与自定义物品
### 6.1 自定义武器及工具
自定义武器及工具支持原生附魔和自定义附魔
自定义武器/工具的netease:weapon组件type值及对应自定义附魔槽位关系如下:
| type | 对应自定义附魔槽位 |
| ------- | ------------------ |
| sword | sword |
| shovel | shovel |
| pickaxe | pickaxe |
| hatchet | **axe** |
| hoe | hoe |
### 6.2 自定义盔甲
自定义盔甲支持原生附魔及自定义附魔
自定义盔甲的netease:armor组件armor_slot值及对应的自定义附魔槽位关系如下:
| armor_slot | ArmorSlotType | 自定义附魔槽位 |
| ---------- | ------------- | -------------- |
| 0 | HEAD | armor_head |
| 1 | BODY | armor_torso |
| 2 | LEG | armor_legs |
| 3 | FOOT | armor_feet |
### 6.3 自定义远程武器
自定义远程武器无法附上原生魔咒但可以附上primary_slots配置为**bow**或**crossbow**的自定义附魔
### 6.4 无法在附魔台上进行自定义附魔的物品
由于原版特性,下列物品**无法在附魔台上进行自定义附魔,但可以在铁砧上进行自定义附魔**
- 剪刀对应槽位shears
- 打火石对应槽位flintsteel
-对应槽位shield
- 鞘翅对应槽位elytra
- 骷髅模型/凋零骷髅模型/模型/僵尸模型/龙的模型/爬行者的模型/雕刻南瓜对应槽位cosmetic_head
- 指南针对应槽位compass
## 7 自定义附魔相关API
### 7.1 AddModEnchantToInvItem
给物品栏中物品添加自定义附魔信息
### 7.2 RemoveModEnchantToInvItem
给物品栏中物品移除自定义附魔信息
### 7.3 GetInvItemModEnchantData
获取物品栏的物品自定义附魔信息
### 7.4 GetEquItemModEnchant
获取装备槽位中盔甲的自定义附魔
## 8 自定义附魔相关事件
### 8.1 OnItemPutInEnchantingModelServerEvent
触发时机:玩家将可附魔物品放到附魔台上时,可修改附魔台选项
## 9 参考资料
[官方wiki-附魔机制](https://zh.minecraft.wiki/w/%E9%99%84%E9%AD%94%EF%BC%88%E7%89%A9%E5%93%81%E4%BF%AE%E9%A5%B0%EF%BC%89)
[官方wiki-附魔](https://zh.minecraft.wiki/w/%E9%AD%94%E5%92%92)
[官方wiki-附魔指令/enchant](https://zh.minecraft.wiki/w/%E5%91%BD%E4%BB%A4/enchant)
[官方wiki-交易](https://zh.minecraft.wiki/w/%E4%BA%A4%E6%98%93)

View File

@@ -0,0 +1,134 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义物品分组
## 概述
用于扩展原版背包分组,让自定义物品展示更加清晰
## 原版分组拓展
支持将自定义物品放入原版分组之后需在behavior文件夹下建立netease_group文件夹并在netease_group目录下添加任意名称json,例如:group_config.json配置如下
```json
{
"groups":[
{
"group_name":"itemGroup.name.wool", //分组名称如需加入到原版分组之后需填写固定的group_name下方会列出所有原版group的名称自定义物品的json中category必须和原版分组的category一致例如需要将自定义物品放入羊毛分组之后那么自定义物品的category字段必须为"Nature"
"icon" : "customblocks:customblocks_redstone", //分组的图标填写自定义物品的identifier,注如果group_name为原版group则icon字段无法生效
"list":[ //分组所包含自定义物品的identifier如果group_name为原版group自定义物品会加入到原版物品之后自定义物品的顺序按list中数组序排列
"customblocks:customblocks_redstone",
]
},
...
]
}
```
![image-20210726210050118](./picture/custom_group1.png)
## 原版保留分组名称
```json
itemGroup.name.planks //木板
itemGroup.name.walls //墙
itemGroup.name.fence //围墙
itemGroup.name.fenceGate //围墙门
itemGroup.name.stairs //楼梯
itemGroup.name.door //门
itemGroup.name.glass //玻璃
itemGroup.name.glassPane //玻璃板
itemGroup.name.slab //台阶
itemGroup.name.stoneBrick //装饰石头
itemGroup.name.sandstone //沙石
itemGroup.name.wool //羊毛
itemGroup.name.woolCarpet //羊毛地毯
itemGroup.name.concretePowder //混凝土粉末
itemGroup.name.concrete //混凝土
itemGroup.name.stainedClay //陶瓦
itemGroup.name.glazedTerracotta //带釉陶瓦
itemGroup.name.dye //染料
itemGroup.name.ore //矿石
itemGroup.name.stone //石头
itemGroup.name.log //原木
itemGroup.name.leaves //树叶
itemGroup.name.sapling //树苗
itemGroup.name.seed //种子
itemGroup.name.crop //农作物
itemGroup.name.grass //地表植物
itemGroup.name.flower //花
itemGroup.name.rawFood //生食
itemGroup.name.cookedFood //熟食
itemGroup.name.miscFood //其他食物
itemGroup.name.mushroom //蘑菇
itemGroup.name.monsterStoneEgg //被虫蚀的石头
itemGroup.name.mobEgg //生物蛋
itemGroup.name.helmet //头盔
itemGroup.name.chestplate //胸甲
itemGroup.name.leggings //护腿
itemGroup.name.boots //靴子
itemGroup.name.horseArmor //马甲
itemGroup.name.sword //剑
itemGroup.name.axe //斧头
itemGroup.name.pickaxe //镐
itemGroup.name.shovel //锹
itemGroup.name.hoe //锄头
itemGroup.name.arrow //箭
itemGroup.name.potion //药水
itemGroup.name.splashPotion //喷溅药水
itemGroup.name.lingeringPotion //滞留药水
itemGroup.name.bed //床
itemGroup.name.anvil //铁砧
itemGroup.name.chest //箱子
itemGroup.name.shulkerBox //潜影盒
itemGroup.name.record //唱片
itemGroup.name.skull //生物模型
itemGroup.name.boat //船
itemGroup.name.rail //铁轨
itemGroup.name.minecart //矿车
itemGroup.name.pressurePlate //压力板
itemGroup.name.trapdoor //活板门
itemGroup.name.enchantedBook //附魔书
itemGroup.name.banner //旗帜
itemGroup.name.firework //烟花火箭
itemGroup.name.fireworkStars //烟火之星
itemGroup.name.coral //珊瑚块
itemGroup.name.coral_decorations //珊瑚装饰
itemGroup.name.buttons //按钮
itemGroup.name.sign //告示牌
itemGroup.name.wood //树林
itemGroup.name.banner_pattern //旗帜图案
```
## 自定义分组
自定义分组与原版分组拓展类似只需修改group_name为非原版保留分组名称即可
```json
{
"groups":[
{
"group_name":"itemGroup.name.groupTest1", //分组名称需避免和原版分组重名可将group_name填入zh_CN.lang中设置中文名称
"icon" : "customblocks:customblocks_redstone_consumer", //分组的图标填写自定义物品的identifier(仅支持填写当前分组内的自定义物品)
"list":[ //分组内所包含自定义物品identifier分组中的顺序按如下数组序排列
"customblocks:customblocks_redstone",
"customblocks:customblocks_redstone_consumer"
]
},
...
]
}
```
![image-20210726210430734](./picture/custom_group2.png)
## 注意点
1.如果自定义分组"list"中物品数量最少为两个,否则将注册失败
2.同一个自定义物品只可放到一个分组中

View File

@@ -0,0 +1,81 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义物品分页
## 概述
用于扩展原版背包分页让同一mod的自定义物品统一展示
## 注册
在 behavior 文件夹下新建 netease_tab 文件夹并在其目录下添加任意名称json 文件,例如 category_config.json配置如下
```json
{
"category":[
{
"name":"custom1", //分页名称自定义物品的json中category的值
"labelText":"itemCategory.name.custom1", //分页描述可在zh_CN.lang中设置中文名称
"icon": "textures/items/bed_green", //分页图标路径
"sort_by_identifier" : true //分页内的item是否进行排序选填默认false
},
{
"name":"custom2",
"labelText":"itemCategory.name.custom2",
"icon":"textures/items/apple"
}
...
]
}
```
**注:**
**1.name由小写字母组成请勿使用大写字母支持下划线**
**2."sort_by_identifier"排序规则如下:**
- **分页中全部为未分组item则按照item的identifier进行排序**
- **分页中全部为具有分组的item则按照分组中第一个item的identifier进行排序**
- **分页中既有分组item和未分组item则按照分组中第一个item的identifier和未分组item的identifier进行排序**
效果如下图自定义分页将排列在原版分页之后分别对应custom1custom2排列在原版分页之后点击右箭头即可展示下一组分页自定义分页的顺序按照category数组顺序排列。
![image-20210727153920711](./picture/custom_category1.png)
![image-20210727154037383](./picture/custom_category2.png)
## 使用
在 behavior 文件夹下的自定义物品的 json 里,修改 `category` 值为 custom1
要在自定义分页默认显示,将 `register_to_create_menu` 设置为 true参考示例如下
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:test_block1",
"register_to_creative_menu": true,
"is_experimental": false,
"category":"custom1" //修改为custom1
},
"components": {
}
}
}
```
![image-20210727153819654](./picture/custom_category3.png)
## 注意事项
从2.6版本开始当多个mod都配置了自定义分页时引擎会将name和labelText字段都完全相同的物品合并到同一个分页。

View File

@@ -0,0 +1,118 @@
---
front:
hard: 入门
time: 分钟
---
# 配置与Json文件关系
## 配套文件
使用编辑器的配置功能和直接修改Json文件制作Addon的本质是一样的每个不同类型的配置都对应着不同的配套文件修改配置对应的Json文件也会实时改变。
这里我们以实体配置举例当我们新建好实体配置后选中即可在属性面板的配套文件处看到其对应的Json文件路径点击右侧的打开文件下图红框内按钮即可打开Json
![image](./images/open_json_file.png)
Json支持多种软件打开和查看这里我们使用vscode进行查看。
![image](./images/openjsonfile2.gif)
此时我们在配置界面增加字段,文件也会实时更新,如下图所示
![image](./images/editjsonfile.gif)
<br/>
关于如何进行配置的创建和使用可参考[配置的使用](./0-配置.md),下面为你列出了当前编辑器支持的所有配置及其对应的文件:
>**点击标题的链接可以从Json文件层面深入了解自定义游戏内容的原理和作用**
<br/>
## [自定义实体](./3-自定义生物/01-自定义基础生物.md)配置对应文件
> 行为包jsonbehavior_pack_xxxxxx/entities/实体名称.json
>
> 资源包jsonresource_pack_xxxxxx/entity/实体名称.json
>
> 语言文件(单个模组唯一)resource_pack_xxxxxx/texts/zh_CN.lang
<br/>
## [自定义物品](./1-自定义物品/1-自定义基础物品.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_items_beh/物品名称.json***
>
> 资源包json***resource_pack_xxxxxx/netease_items_res/物品名称.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
>
> 盔甲穿戴属性文件:***resource_pack_xxxxxx/textures/物品名称.json***
>
> 物品贴图文件(单个模组唯一)***resource_pack_xxxxxx/textures/item_texture.json***
<br/>
## [自定义方块](./2-自定义方块/0-自定义方块概述.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_blocks/方块名称.json***
>
> 方块贴图文件(单个模组唯一):***resource_pack_xxxxxx/textures/item_texture.json***
>
> 方块列表文件:***resource_pack_xxxxxx/block.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
<br/>
## [自定义配方](./5-自定义配方.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_recipes/配方名称.json***
<br/>
## <a href="../../../mconline/100-历史归档教程/20-玩法地图教程/第05章设置NPC的基本状态和交易表/课程03.给NPC添加对应的交易表.html" rel="noopenner"> 自定义交易表 </a>配置对应文件
> 行为包json***behavior_pack_xxxxxx/trading/交易表名称.json***
<br/>
## <a href="../../../mconline/100-历史归档教程/10-addon教程/第12章更完善的自定义掉落物/课程01.更完善的自定义掉落物.html" rel="noopenner"> 自定义掉落表 </a>配置对应文件
> 行为包json***behavior_pack_xxxxxx/loot_tables/掉落表名称.json***
<br/>
## [自定义生成规则](./4-自定义维度/3-生物生成.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/spawn_rules/生成规则名称.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
<br/>
## [自定义维度](./4-自定义维度/1-自定义维度.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_dimension/维度配置名称.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
<br/>
## [自定义生物群系](./4-自定义维度/2-群系地貌.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_biomes/生物群系配置名称.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
<br/>
## [自定义特征](./4-自定义维度/4-自定义特征.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_features/特征名称.json***
>
> 语言文件(单个模组唯一)***resource_pack_xxxxxx/texts/zh_CN.lang***
<br/>
## [自定义特征生成](./4-自定义维度/4-自定义特征.md)配置对应文件
> 行为包json***behavior_pack_xxxxxx/netease_feature_rules/特征生成规则.json***
>
> 语言文件(单个模组唯一) ***resource_pack_xxxxxx/texts/zh_CN.lang***

View File

@@ -0,0 +1,16 @@
## 配置已知问题说明
配置的一些json字段可能导致表现异常此处给出一些已知的问题说明。
### 1.实体配置组件的覆盖
实体配置中除components字段可以定义组件外也可以使用component_groups来定义组件的动态增删。因此部分components中定义的组件可能被动态覆盖。如原生生物猪的掉落表配置会因为幼年或成年替换成对应的掉落表。
![image-20210824155900206](./images/image-20210824155900206.png)
### 2.实体的突然消失
部分抛射物类实体,如附魔之瓶,在接触地面后会破裂消失,这是由于抛射物组件决定的,如果自己的实体有使用这个组件,也会产生类似的现象。
![image-20210824160320716](./images/image-20210824160320716.png)

View File

@@ -0,0 +1,245 @@
# 自定义成就系统
## 1.概述
自定义成就系统是提供给开发者用于创建一套符合自己要求的成就系统开发者可通过配置json来定义自己独特的成就事件。
目前给开发者提供了两种内嵌成就类型分别为[击杀生物事件](#击杀)和[获得物品事件](#获得),开发者也可通过自己监听事件来判断玩家是否达成成就。
该系统还提供了自动调用的奖励机制开发者只需在serverSystem编写奖励函数在json中配置对应的命名空间与系统名自定义成就系统即可在玩家完成成就时自动调用对应的函数。详见示例[CustomAchievementMod](./../13-模组SDK编程/60-Demo示例.md#CustomAchievementMod)
![POPO-screenshot-20220613-145720](./picture/customSystem/POPO-screenshot-20220613-145720.png)
## 2.json配置成就节点
### 2.1 创建成就节点
- 一个成就节点对应一个json文件必须放在“**behavior_pack/customAchievements**”文件夹下
- 如果修改已经发布的节点目标值"goal_number"请注意奖励函数的调用。如原先进度5目标进度10将目标进度改为3将不会触发奖励函数。如原先进度5目标进度5已经触发了奖励函数这时将目标进度改为10当进度为10时将再一次触发奖励函数的调用。
- 节点的排序方式是按照python的sort函数进行排序将node_ID字母按从A到Z数字按从小到大逐位排序如果对节点位置有要求请按照该规则编写节点ID
### 2.2 编写json
#### 1根节点json
```json
{
"node_ID": "rootNode",
"title": "奶牛爱好者",
"unfinished_icon": "textures/ui/item/diamond_sword",
"finished_icon": "textures/ui/item/diamond_sword",
"use_default_icon_background": true,
"goal_details":{
"goal_type":"default_kill",
"entity_identifier":"minecraft:cow"
},
"goal_number":3,
"node_description":"杀死3只奶牛",
"window_background":"textures/ui/background/sign_warped",
"reward":[
{
"function_name":"fun1",
"name_space":"namespce:systemname",
"data":{
"EXP":20,
"string":"hellowerld"
}
},
{
"function_name":"fun2",
"name_space":"namespce:systemname",
"data":{
"EXP":20,
"string":"hellowerld"
}
}
],
"is_hidden":false,
"finish_tip":true,
"is_cloud" :false,
"auto_sent_cloud":true
}
```
| 属性 | 解释 |
| :-------------------------: | ------------------------------------------------------------ |
| node_ID | 必选成就节点的唯一标识符不可重复出现使用多个MOD前请检查各个MOD下的成就节点是否有该属性重复 |
| title | 必选,成就节点标题,根节点的标题会在对应窗口显示时作为该窗口的主标题,该标题在点击节点时也会展示,也会用于完成成就时的弹框展示,[支持颜色代码](https://minecraft-zh.gamepedia.com/%E6%A0%B7%E5%BC%8F%E4%BB%A3%E7%A0%81) |
| unfinished_icon | 必选成就未达成前的图标路径为resource文件下的“texture/../..”仅支持png格式根节点的unfinished_icon将作为该成就分页的标题图标 |
| finished_icon | 必选成就达成后的图标路径为resource文件下的“texture/../..”仅支持png格式 |
| use_default_icon_background | 可选是否使用提供的图标背景默认为True如果开发者想使用自己的背景图标可设置为False然后在上述的unfinished_icon/finished_icon中设置自己想要的图标样式即一张图标中包括Icon与Icon的背景 |
| goal_details | 可选,如果是想使用提供的“击杀事件”或“获得事件”,需要按照要求进行内容填写。详参**3.两个基础预设的成就类型** |
| goal_number | 必选成就的目标值例如“击杀3头牛”则为3“获得5个苹果”则为5如果是特殊事件如”进入下界“则玩家可自行设置为1 |
| node_description | 必选,用于描述该节点的具体信息,建议在这里写上成就目标与成就奖励,[支持颜色代码](https://minecraft-zh.gamepedia.com/%E6%A0%B7%E5%BC%8F%E4%BB%A3%E7%A0%81) |
| window_background | 必选,**根节点特有属性**,该根节点对应的成就分页的背景图,当图片小于背景板大小时,会进行平铺。如果不想使用平铺效果,可设置与背景板大小一致的图片,背景板的大小是随开发者提供的节点形成的树的高度与宽度决定的。计算公式为: 宽度 = 树的深度 * 30 px如果宽度小于227贴图宽度应为227 高度 = 树的最大宽度 *24 px如果宽度小于129贴图宽度应为129。 |
| reward | 可选注册可调用的奖励函数“function_name”函数名“name_space”nameSpacesystemName即Mod注册RegisterSystem时填写的nameSpace和systemName这里为serverSystem不可为clientSystemdata为调用这个函数时传入的参数dict该dict参数还会添加一个“playID”用于传输触发奖励的玩家ID |
| is_hidden | 可选是否隐藏默认为False如果设置为True根节点设置为隐藏时会将整个成就分页隐藏只有当这个节点或该节点的某个子节点完成时才可见。 |
| finish_tip | 可选完成该成就时是否弹出提示框默认为True |
| is_cloud | 可选是否为云成就默认为False即成就进度是否上传开发者平台如果为云成就每次进入都会从服务器读取对应的成就进度进行初始化**仅联机大厅与Apollo有用** |
| auto_sent_cloud | 可选是否自动上传云成就默认为True当“is_cloud”也为True时才有作用如果设置为自动上传会在每次调用<a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#addnodeprogress" rel="noopenner">AddNodeProgress</a>修改成就进度的时候将属于云成就的节点进度上传。如果为False由开发者自行选择上传时机。可以用<a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#addnodeprogress" rel="noopenner">AddNodeProgress</a>接口更新本地数据并用一个变量存储相加每次的Delta使用云成就上报接口<a href="./../../../mcdocs/1-ModAPI/接口/成就.html#lobbysetachievementstorage" rel="noopenner">LobbySetAchievementStorage</a>**仅联机大厅与Apollo有用** |
![POPO-screenshot-20220613-174917](./picture/customSystem/POPO-screenshot-20220613-174917.png)
#### 2非根节点json
```json
{
"node_ID": "Node5",
"parent_node":"rootNode",
"title": "111111",
"unfinished_icon": "textures/ui/item/book_enchanted",
"finished_icon": "textures/ui/item/book_enchanted",
"use_default_icon_background": true,
"goal_details":{
"goal_type":"default_get",
"item_dict":{
"newItemName":"minecraft:apple"
}
},
"goal_number":2,
"node_descriptrion":"111111111",
"reward":[
{
"function_name":"fun1",
"name_space":"namespce:systemname",
"data":{
"EXP":20,
"string":"hellowerld"
}
},
{
"function_name":"fun2",
"name_space":"namespce:systemname",
"data":{
"EXP":20,
"string":"hellowerld"
}
}
],
"is_hidden":false,
"finish_tip":true,
"is_cloud" :false,
"auto_sent_cloud":true,
"depend_parent":false
}
```
| 属性 | 解释 |
| :-------------------------: | ------------------------------------------------------------ |
| node_ID | 必选成就节点的唯一标识符不可重复出现使用多个MOD前请检查各个MOD下的成就节点是否有该属性重复 |
| parent_node | 必选,**非根节点特有属性**填写该节点的父节点node_ID |
| depend_parent | 可选,**非根节点特有属性**是否依赖父节点默认为False如为True该节点的进度只有当其父节点完成时才能开始记录 |
| title | 必选,成就节点标题,该标题在点击节点时会展示,也会用于完成成就时的弹框展示,[支持颜色代码](https://minecraft-zh.gamepedia.com/%E6%A0%B7%E5%BC%8F%E4%BB%A3%E7%A0%81) |
| unfinished_icon | 必选成就未达成前的图标路径为resource文件下的“texture/../..” |
| finished_icon | 必选成就达成后的图标路径为resource文件下的“texture/../..” |
| use_default_icon_background | 可选是否使用提供的图标背景默认为True如果开发者想使用自己的背景图标可设置为False然后在上述的unfinished_icon/finished_icon中设置自己想要的图标样式即一张图标中包括Icon与Icon的背景 |
| goal_details | 可选,如果是想使用提供的“击杀事件”或“获得事件”,需要按照要求进行内容填写,详参*[3.两个基础预设的成就类型](#两个基础预设)* |
| goal_number | 必选成就的目标值例如“击杀3头牛”则为3“获得5个苹果”则为5如果是特殊事件如”进入下界“则玩家可自行设置为1 |
| node_description | 必选,用于描述该节点的具体信息,建议在这里写上成就目标与成就奖励,[支持颜色代码](https://minecraft-zh.gamepedia.com/%E6%A0%B7%E5%BC%8F%E4%BB%A3%E7%A0%81) |
| reward | 可选注册可调用的奖励函数“function_name”函数名“name_space”nameSpacesystemName即Mod注册RegisterSystem时填写的nameSpace和systemName这里为serverSystem不可为clientSystemdata为调用这个函数时传入的参数dict该dict参数还会添加一个“playID”用于传输触发奖励的玩家ID |
| is_hidden | 可选是否隐藏默认为False如果设置为True则这个节点在对应的成就分页中隐藏只有当这个节点或者该节点的某个子节点完成时才可见 |
| finish_tip | 可选完成该成就时是否弹出提示框默认为True |
| is_cloud | 可选是否为云成就默认为False即成就进度是否上传开发者平台如果为云成就每次进入都会从服务器读取对应的成就进度进行初始化**仅联机大厅与Apollo有用** |
| auto_sent_cloud | 可选是否自动上传云成就默认为True当“is_cloud”也为True时才有作用如果设置为自动上传会在每次调用<a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#addnodeprogress" rel="noopenner">AddNodeProgress</a>修改成就进度的时候将属于云成就的节点进度上传。如果为False由开发者自行选择上传时机。可以用<a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#addnodeprogress" rel="noopenner">AddNodeProgress</a>接口更新本地数据并用一个变量存储相加每次的Delta使用云成就上报接口<a href="./../../../mcdocs/1-ModAPI/接口/成就.html#lobbysetachievementstorage" rel="noopenner">LobbySetAchievementStorage</a>**仅联机大厅与Apollo有用** |
## 3.两个基础预设的成就类型<span id="两个基础预设"></span>
### 3.1 击杀生物成就<span id="击杀"></span>
1在成就节点的json文件中将“goal_details”的"goal_type"属性设置为"default_kill",系统将进行自动的监听
2在成就节点的json文件中将“goal_details”的"entity_identifier"属性设置为对应生物的identifier ,如"minecraft:cow"
3该事件中一个成就节点只能监听一种生物无法在一个节点中监听多种生物
4当监测到目标事件会自动添加节点进度。
示例:
```json
"goal_details":{
"goal_type":"default_kill",
"entity_identifier":"minecraft:cow"
}
```
### 3.2 获得物品成就<span id="获得"></span>
1在成就节点的json文件中将“goal_details”的"goal_type"属性设置为"default_get",系统将进行自动的监听
2在成就节点的json文件中将“goal_details”的"item_dict"属性设置为对应的[物品信息字典](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/10-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/1-%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5.html#%E7%89%A9%E5%93%81%E4%BF%A1%E6%81%AF%E5%AD%97%E5%85%B8#%E7%89%A9%E5%93%81%E4%BF%A1%E6%81%AF%E5%AD%97%E5%85%B8)
- 如果检查信息涉及enchantData和modEnchantData的附魔属性需将list中的()改为为[],可参考[示例1](#示例1)。
- “item_dict”必须配置“newItemName”不可配置“count”。
- 检查信息不包括“userdata”里面的信息如配置羊毛时获得任意羊毛都能触发成就监测参考[示例2](#示例2)。
- 另外如果配置了“userdata”将导致无法触发监测请勿配置该信息。
3该事件中一个成就节点只能监听一种物品无法在一个节点中监听多种物品
4触发监测事件是当玩家物品栏发生改变的时候统计玩家物品栏中符合要求的物品数量
5对于需要云成就本地会保存两份数据一份是从云端获得的成就进度一份是本地该节点的进度如云端的进度为8本地的进度为3只有当玩家物品栏的目标物品数量大于3的时候才会触发成就进度更新
6当监测到目标事件会自动添加节点进度。
示例1<span id="示例1"></span>
```json
"goal_details": {
//获得一把具有锋利I、自定义附魔3II的钻石剑
"item_dict": {"newItemName":"minecraft:diamond_sword",
"enchantData": [[9,1]],
"modEnchantData":[["customenchant3",2]]
},
"goal_type": "default_get"
}
```
示例2<span id="示例2"></span>
```json
"goal_details": {
//获得任意颜色羊毛时触发
"item_dict": {
"newItemName": "minecraft:wool"
},
"goal_type": "default_get"
}
```
## 4.提示框
1只有该节点的Json文件中的“finish_tip”选择为true才有提示框
2一共设计有5个提示框槽位当五个提示框槽位都播放有动画时会将待播放的提示缓存等待有空槽位的时候才弹出提示框
3提示框左边的Icon会读取“finished_icon”属性下的图片路径
4白色文本是对应节点的title
5提示框的层级为150高于入口按钮层级
![POPO-screenshot-20220613-150745](./picture/customSystem/POPO-screenshot-20220613-150745.png)
## 5.入口图标
1入口图标只有当有可以显示的节点时才会初始化如果没有节点或者所有根节点隐藏不可见时该图标不会显示
2该图标支持拖拽拖动释放时不会调用按钮事件
3入口图标层级为110会被提示框覆盖
![POPO-screenshot-20220613-162148](./picture/customSystem/POPO-screenshot-20220613-162148.png)
## 6.成就接口与事件
### 6.1接口
- <a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#getnodedetailinfo" rel="noopenner">GetNodeDetailInfo</a>:获取对应玩家的对应节点信息
- <a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#setnodefinish" rel="noopenner">SetNodeFinish</a>:设置对应玩家的对应成就节点完成
- <a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#addnodeprogress" rel="noopenner">AddNodeProgress</a>:增加对应玩家的对应成就节点的成就进度
- <a href="./../../../mcdocs/1-ModAPI/接口/自定义UI/自定义成就系统.html#getchildrennode" rel="noopenner">GetChildrenNode</a>获得该成就节点的下一级所有孩子节点的list
### 6.2成就事件
- <a href="./../../../mcdocs/1-ModAPI/事件/世界.html#achievementcompleteevent">AchievementCompleteEvent</a>:玩家完成自定义成就时触发该事件

View File

@@ -0,0 +1,88 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义方块概述
<span id="customBlockJump"></span>
该功能不需要开启实验性玩法。
开发者可以通过在addon中配置json来添加自定义方块。添加的自定义方块支持ModAPI中与方块及物品相关的所有事件及接口。
## 注册
以demo [CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)为例:
1. 在行为包中新建`netease_blocks`目录
![reg-1](./picture/customblock/reg_1.png)
2. 在目录下新建一个json用于编写方块的定义。json的格式可参考[官方wiki](https://minecraft.gamepedia.com/Bedrock_Edition_blocks_documentation)。
![reg-2](./picture/customblock/reg-2.png)
![reg-3](./picture/customblock/reg-3.png)
- json中至少有一个component
- **identifier**的格式为:命名空间[冒号]方块名。命名空间推荐与mod名称一致。而冒号后的**方块名**必须全局唯一为避免与原版方块以及其他mod重复**请加上命名空间作为前缀来保证唯一**。
(例如图中的<font size="5" style="font-weight: bold;">customblocks:<font color="red">customblocks_</font>test0</font>
而不要写成customblocks:test0。
- **mod中其他地方都是用这个identifier与这个自定义方块对应上**。
3. 将方块的贴图放到`textures\blocks`
可以支持高于16x16分辨率的高清贴图但需要注意过高的分辨率会导致手机端尤其是低端机上无法进入游戏。
![reg-4](./picture/customblock/reg-4.png)
4. 在textures中新建`terrain_texture.json`编写资源名与贴图的对应关系。资源名的命名必须满足全局唯一。json格式可参考“Mod PC开发包”的`data\resource_packs\vanilla\textures\terrain_texture.json`
![reg-5](./picture/customblock/reg-5.png)
![reg-6](./picture/customblock/reg-6.png)
5. 在resource中新建一个`blocks.json`,编写方块贴图及声音,贴图的值需要与上一步`terrain_texture.json`中配置的资源名对应。json格式可参考“Mod PC开发包”的`data\resource_packs\vanilla\blocks.json`
![reg-7](./picture/customblock/reg-7.png)
![reg-8](./picture/customblock/reg-8.png)
6.`texts\zh_CN.lang`中配置方块中文名称:
键的格式为`tile.方块identifier.name`
![reg-9](./picture/customblock/reg-9.png)
![reg-10](./picture/customblock/reg-10.png)
7. 重复1-6编写其他自定义方块
## 卸载
若使用了自定义方块的存档卸载mod后再进入时
1. 对地图上已存在的自定义方块:
1自定义方块会变为未知的方块。如果用GetBlockNew接口获取它的信息indentifier是之前的自定义方块。生存模式下玩家可以用手瞬间破坏这个未知的方块生成掉落物且可以拾取。拾取到背包后显示的物品名字为”未知“且无法放置到世界中。
2若某个subchunk未进行过方块更新那么重新加载mod时自定义方块会保留。但一旦subchunk进行了方块更新即使重新加载mod自定义方块会永远消失。
2. 对玩家背包中的自定义方块:
物品会消失。若重新加载mod对卸载期间登录过的玩家物品不会恢复没登录过的玩家物品可以保留。
3. 对地图上容器内的自定义方块:
物品会消失。若重新加载mod对卸载期间进行探索过的区域内的容器物品不会恢复未探索区域的容器物品可以保留。
4. 对地图上未捡起的掉落物:
掉落物会消失。若重新加载mod对卸载期间进行探索过的区域掉落物不会恢复除非subchunk内没有其他任何entity未探索区域的掉落物可以保留。

View File

@@ -0,0 +1,461 @@
---
front:
hard: 入门
time: 分钟
---
# JSON组件
## format_version
基岩版自定义方块的json结构曾经过多次调整当填写format_version时需要按照对应版本的json结构编写components。
你可以在以下两个版本进行选择:
- 1.16.0
该版本的components结构详见[bedrock.dev](https://bedrock.dev/zh/docs/1.16.0.0/1.16.0.66/Blocks)。
- 1.10.0
该版本的components结构详见[bedrock.dev](https://bedrock.dev/zh/docs/1.12.0.0/1.12.0.28/Blocks)。该版本相比于1.16.0component的值为一个Json Object例如`minecraft:destroy_time`在1.10.0中为
```json
"minecraft:destroy_time": {
"value": 4.0
}
```
而在更高的版本中为
```json
"minecraft:destroy_time": 4.0
```
## description
| 键 | 类型 | 默认值 | 解释 |
| ----------------------- | ---- | ------ | ------------------------------------------------------------ |
| identifier | str | | 包括命名空间及物品名。需要全局唯一。<br>建议使用mod名称作为命名空间 |
| register_to_create_menu | bool | false | 是否注册到创造栏 |
| category | str | Nature | 注册到创造栏的分类,可选的值有:<br>Construction<br>Nature<br>Equipment<br>Items |
## components
目前行为包中自定义方块json中支持的component包括原版component和网易独有的component。minecraft开头的为原版componentnetease开头的为网易独有component。
对于原版component你可以在上方的format_version解释中找到更多的参数及解释。
<span id="minecraft_loot"></span>
### minecraft:loot
可用于使用loot table控制掉落物
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_test_ore方块
<span id="minecraft_max_stack_size"></span>
### minecraft:max_stack_size
可用于设置方块物品最大堆叠数量,`注意该值不能超过64`
<span id="minecraft_destroy_time"></span>
### minecraft:destroy_time
可用于控制挖掘所需的时间。该值的含义与[官方wiki](https://minecraft-zh.gamepedia.com/%E6%8C%96%E6%8E%98#.E6.96.B9.E5.9D.97.E7.A1.AC.E5.BA.A6)的“硬度”一致
主要用于[挖掘](./2-功能.md#wajue)的功能
<span id="minecraft_block_light_emission"></span>
### minecraft:block_light_emission
可用于设置方块亮度。关于亮度及方块光源可参考[官方wiki](https://minecraft-zh.gamepedia.com/%E4%BA%AE%E5%BA%A6)
主要用于[亮度](./2-功能.md#liangdu)的功能
<span id="minecraft_explosion_resistance"></span>
### minecraft:explosion_resistance
可用于设置爆炸抗性。原版方块的爆炸抗性见[官方wiki](https://minecraft-zh.gamepedia.com/%E7%88%86%E7%82%B8#.E7.88.86.E7.82.B8.E6.8A.97.E6.80.A7)
<span id="minecraft_block_light_absorption"></span>
### minecraft:block_light_absorption
可用于设置方块的透光率。具体可参考[官方wiki](https://minecraft-zh.gamepedia.com/%E4%BA%AE%E5%BA%A6#.E9.98.BB.E7.A2.8D.E5.85.89.E7.85.A7.E7.9A.84.E6.96.B9.E5.9D.97)
默认为不透光。
主要用于[亮度](./2-功能.md#liangdu)的功能
<span id="minecraft_map_color"></span>
### minecraft:map_color
可用于设置方块显示在地图上的颜色
<span id="netease_tier"></span>
### netease:tier
用于设置与挖掘相关的属性
主要用于[挖掘](./2-功能.md#wajue)的功能
| 键 | 类型 | 默认值 | 解释 |
| :-------------: | :----: | :----: | :----------------------------------------------------------- |
| digger | string | | 必须设置。表示方块使用此工具挖掘时有速度加成。<br>可选的值有:<br> shovel铲<br> pickaxe镐<br> hatchet斧<br> hoe锄 |
| destroy_special | bool | false | 可选。<br>当设置为true时表示只有使用digger设置的工具进行挖掘才会产生掉落物。 |
| level | int | 0 | 可选。<br>当destroy_special为true时才会生效。表示挖掘所需的工具等级若手持工具等级小于该值则不会产生掉落物。<br>原版工具的等级:<br> 空手/其他非工具物品0<br> 木制/金制工具0<br> 石制工具1<br> 铁制工具2<br> 钻石工具3 |
<span id="netease_aabb"></span>
### netease:aabb
用于设置方块的碰撞盒
**注意事项:**
1. 无碰撞箱的方块请将collision的每个项都设置为0
2. 有碰撞箱的方块clip的范围需要小于或等于collision的范围否则弹射物命中时会异常
3. aabb的min不要小于[-1, -1, -1]max不要大于[2, 2, 2]
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks_model_flower及customblocks_model_wire方块。
| 键 | 类型 | 默认值 | 解释 |
| --------- | ------------- | ------ | ------------------------------------------------------------ |
| collision | object或array | | 计算与物体碰撞时用的碰撞盒 |
| clip | object或array | | 计算射线检测时用的碰撞盒。如准心选取及弹射物碰撞。<br>那么当该AABB没有体积时准心与弹射物都会无视这个方块 |
当collision或clip为object时用于表示恒定大小的单一碰撞盒结构为
| 键 | 类型 | 默认值 | 解释 |
| ---- | ------------ | --------- | ---------------------------------- |
| min | array(float) | [0, 0, 0] | min的三个值必须小于等于max的三个值 |
| max | array(float) | [1, 1, 1] | |
当collision或clip为array时用于可变化的多个碰撞盒的组合通常用于可变化的自定义方块模型。元素的结构为
| | 类型 | 默认值 | 解释 |
| ------ | ------------ | --------- | ------------------------------------------------------------ |
| enable | molang | true | 控制是否开启该碰撞箱<br/>目前仅支持is_connect查询详见[netease:connection](#netease_connection) |
| min | array(float) | [0, 0, 0] | min的三个值必须小于等于max的三个值 |
| max | array(float) | [1, 1, 1] | |
<span id="netease_face_directional"></span>
### netease:face_directional
用于设置方块的多面向
主要用于[多面向](./2-功能.md#duomianxiang)的功能
| 键 | 类型 | 默认值 | 解释 |
| ---- | ------ | ------ | ----------------------------------------------------- |
| type | string | | direction四面向方块<br>facing_direction六面向方块 |
<span id="netease:fuel "></span>
### netease:fuel
可燃类物品组件。允许该方块物品作为燃料在熔炉中燃烧
| 键 | 类型 | 默认值 | 解释 |
| ------- | ------ | ------ | ------------------------------------------------------------ |
| duration| float | 0 | 可填, 该物品可提供的熔炉燃烧时长(秒)。 |
<span id="netease_render_layer"></span>
### netease:render_layer
用于设置方块渲染时使用的材质
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_model_flower方块。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ------ | ------ | ------------------------------------------------------------ |
| value | string | | 目前支持的材质有:<br>opaque不透明即“terrain_opaque”材质。默认为此项<br>alpha全透明即“terrain_alpha”材质如火焰该材质用于异形方块用在方块类上但与其他方块重合时会出现闪烁可以使用no_crop_face_block组件避免闪烁。<br>blend半透明即“terrain_blend”材质如彩色玻璃。<br>optionalAlpha局部透明与alpha不同alpha超过一定距离将不渲染而optionalAlpha不会能配合no_crop_face_block组件实现原版叶子效果。 |
<span id="netease_solid"></span>
### netease:solid
用于设置方块是否为实心方块主要与生物在方块内时是否受到窒息伤害有关。
使用了这个组件,自定义方块将不会产生阴影。
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_model_flower方块。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| value | bool | true | 为true时生物在方块内会受到窒息伤害<br>为false时生物在方块内不会受到窒息伤害 |
<span id="netease_pathable"></span>
### netease:pathable
用于设置游戏内AI在进行寻路时方块是否被当作障碍物。
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_model_flower方块。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| value | bool | false | 为true时寻路时被当作空气<br>为false时寻路时被当作障碍物并且可在其上方行走 |
<span id="netease_block_entity"></span>
### netease:block_entity
用于给自定义方块添加[自定义方块实体](./4-自定义方块实体.md)。
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_test_block_entity方块。
| 键 | 类型 | 默认值 | 解释 |
| ------- | ---- | ------ | ------------------------------------------------------------ |
| tick | bool | false | 为true时当玩家进入方块tick范围时该方块每秒会发送**20次**ServerBlockEntityTickEvent事件<br>为false时该方块不会发送ServerBlockEntityTickEvent事件 |
| client_tick | bool | false | 为true时当玩家进入方块tick范围时该方块每秒会发送**20次**ModBlockEntityTickClientEvent事件<br>为false时该方块不会发送ModBlockEntityTickClientEvent事件 |
| movable | bool | true | 为true时该方块可被粘性活塞拉回<br>为false时该方块不可被粘性活塞拉回 |
<span id="netease_random_tick"></span>
### netease:random_tick
用于给自定义方块定义是否可以随机tick并且设置该tick事件是否发送到脚本层。
| 键 | 类型 | 默认值 | 解释 |
| -------------- | ---- | ------ | ------------------------------------------------------------ |
| enable | bool | false | 方块是否随机tick |
| tick_to_script | bool | false | 是否发送事件<a href="../../../../mcdocs/1-ModAPI/事件/方块.html#blockrandomtickserverevent" rel="noopenner"> BlockRandomTickServerEvent </a>到python脚本 |
### netease:redstone_property
用于给自定义方块设置红石属性
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| value | str | None | 目前只支持break_on_push设置之后方块可以被活塞破坏变成掉落物否则方块会被活塞推动而不破坏 |
### netease:neighborchanged_sendto_script
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| value | bool | false | 方块周围环境变化是否发送事件<a href="../../../../mcdocs/1-ModAPI/事件/方块.html#blockneighborchangedserverevent#blockneighborchangedserverevent" rel="noopenner"> BlockNeighborChangedServerEvent </a>到脚本层 |
<span id="netease_connection"></span>
### netease:connection
用于给自定义方块定义“连接”属性
使用枚举的方式配置该方块与哪些方块具有“连接”属性,并且此属性是单向的。不支持附加值。
由于方块更新的特性,“床”和“旗帜”方块在区块边缘放置时,与其他方块会出现连接失败。
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks_model_wire方块。
| 键 | 类型 | 解释 |
| ------ | ------------- | -------------------------- |
| blocks | array(string) | 数组元素为方块的identifier |
目前该属性只用于[netease:aabb](#netease_aabb)及[自定义方块模型](./5-自定义方块模型.md)的is_connect查询
| 名称 | 解释 |
| ---------------- | ------------------------------------------------------------ |
| query.is_connect | 传入一个参数返回该方块与对应临面上的方块是否有connection属性<br/>参数取值与对应的面:<br>0-down面1-up面2-north面3-south面4-west面5-east面。 |
<span id="netease_redstone"></span>
### netease:redstone
用于配置自定义红石源与自定义红石机械元件;
可以配置自定义红石的类型,如红石源或者红石机械元件;
可以配置初始信号强度默认为15。
| 键 | 类型 | 默认值 | 说明 |
| -------- | ---- | ------ | ---------------------------------------------------------- |
| type | str | | 红石类型:<br/>producer红石源<br/>consumer红石机械元件 |
| strength | int | 15 | 红石信号值,范围[0,15] |
<span id="listen_block_remove"></span>
### netease:listen_block_remove
用于配置自定义方块是否监听方块的<a href="../../../../mcdocs/1-ModAPI/事件/方块.html#blockremoveserverevent" rel="noopenner"> BlockRemoveServerEvent </a>事件
| 键 | 类型 | 默认值 | 说明 |
| ----- | ---- | ------ | ------------ |
| value | bool | false | 是否监听事件 |
<span id="netease_may_place_on"></span>
### netease:may_place_on
用于配置自定义方块可存在于哪些方块的上面。
会生效于玩家右键放置方块时;以及已存在的方块下方的方块发生改变时。
可参考CustomBlocksMod示例中的customblocks_model_flower
| 键 | 类型 | 默认值 | 说明 |
| --------------- | ------------ | ------ | ------------------------------------------------------------ |
| block | list(str) | | 方块identifier的列表。这些方块的所有[方块状态](../../10-基本概念/1-我的世界基础概念.md#方块状态)都可放置 |
| block_state | list(object) | | [方块状态](../../10-基本概念/1-我的世界基础概念.md#方块状态)的列表。<br>每个元素只对应一个特定的方块状态,如果方块有多个种类的状态,需要考虑排列组合的所有情况<br>最终可在上面放置的方块是block字段与block_state字段的并集 |
| spawn_resources | bool | true | 已存在的方块因下方的方块发生改变而被破坏时,是否生成掉落物 |
<span id="netease_fire_resistant"></span>
### netease:fire_resistant
用于配置自定义方块是否防火。
设置为防火时,方块的掉落物会与下界合金一样,不会被火烧毁,掉进岩浆时会弹走。
可参考CustomBlocksMod示例中的customblocks_test_ore
| 键 | 类型 | 默认值 | 说明 |
| ----- | ---- | ------ | -------- |
| value | bool | | 是否防火 |
### netease:block_properties
用于配置自定义方块的方块属性
这些方块属性可以叠加,主要用于引擎对一些方块特性逻辑的判断
可参考CustomBlocksMod示例中的customblocks_slime、customblocks_flower_extend
| 键 | 类型 | 默认值 | 说明 |
| ----- | ---- | ------ | -------- |
| properties | array | | 所有属性字符串 |
其中properties数组目前支持以下字符串填充
| 键 | 说明 |
| ----- |-------- |
| piston_block_grabber | 被活塞推动时是否带动旁边方块 |
| slime | 主要用于变为移动方块(例如被活塞推)时修改对实体力的计算 |
|breaks_when_fallen_on_by_heavy| 当重力方块结束下落在该方块位置后,自身是否被毁坏|
如果方块碰撞盒体积使用netease:aabb或minecraft:entity_collision改小可能会导致无法触发目前可参考范围是边长0.4以下不会触发)。
### netease:on_stand_on
用于触发实体站在方块上的事件
可参考CustomBlocksMod示例中的customblocks_slime利用了该事件组合做出了个模拟原版粘液块的效果。
| 键 | 类型 | 默认值 | 说明 |
| ----- | ---- | ------ | -------- |
| send_python_event | bool | | 是否发送事件至python |
当send_python_event为true时该方块会触发OnStandOnBlockClientEvent、OnStandOnBlockServerEvent事件。
如果方块碰撞盒体积使用netease:aabb或minecraft:entity_collision改小可能会导致无法触发目前可参考范围是边长0.4以下不会触发)。
### netease:on_before_fall_on
用于触发实体刚下落至方块的事件,主要用于伤害计算
可参考CustomBlocksMod示例中的customblocks_slime利用了该事件组合做出了个模拟原版粘液块的效果。
如果方块碰撞盒体积使用netease:aabb或minecraft:entity_collision改小可能会导致无法触发目前可参考范围是边长0.4以下不会触发)。
### netease:on_after_fall_on
用于触发实体下落至方块后的事件,主要用于力的计算
可参考CustomBlocksMod示例中的customblocks_slime利用了该事件组合做出了个模拟原版粘液块的效果。
如果方块碰撞盒体积使用netease:aabb或minecraft:entity_collision改小可能会导致无法触发目前可参考范围是边长0.4以下不会触发)。
### netease:on_entity_inside
用于触发实体碰撞盒所在位置有方块时的事件(判断位置逻辑有无方块,与方块碰撞盒大小无关)。
当send_python_event为true时该方块会触发OnEntityInsideBlockClientEvent、OnEntityInsideBlockServerEvent事件。
### netease:on_step_on
用于触发实体刚移动至一个实心方块上的事件
可参考CustomBlocksMod示例中的customblocks_slime在触发该事件时进行了日志打印
### netease:on_step_off
用于触发实体刚离开一个实心方块上的事件
可参考CustomBlocksMod示例中的customblocks_slime在触发该事件时进行了日志打印
<span id="netease_offset"></span>
### netease:block_random_offset
用于设置方块的偏移,能实现原版花朵的偏移效果。
注意:制作可偏移方块时,请尽量配套使用方块模型,当使用贴图方块随机偏移时,若相邻方块是不透明方块,则该方块对应的面会被裁切渲染!!普通贴图方块的物品栏渲染也可能会有异常!!
该组件会把方块的材质设置为透明且不可与netease:render_layer的不透明材质一起共用否则会出现渲染错误
| 键 | 类型 | 默认值 | 解释 |
| ------- | ------------- | ------ | ------------------------------------------------------------ |
| x_scope | [float,float] | [0,0] | x轴方向的偏移范围size为2的array取值范围为0.0~1.0,如果两个值相同则为指定点 |
| z_scope | [float,float] | [0,0] | z轴方向的偏移范围size为2的array取值范围为0.0~1.0,如果两个值相同则为指定点 |
<span id="block_chest"></span>
### netease:block_chest
用于给方块添加箱子功能使用了该组件会创建一个block_entity方块会与其他block_entity逻辑有冲突请谨慎使用。
该组件会覆盖带有base_block及其相关组件的功能。
使用了这个组件后请勿再配置netease:face_directional。
使用SetBlockNew接口创建自定义箱子的时候需要先调用一次SetBlockNew将目标位置方块设置为Air再使用AddTimer延后调用SetBlockNew创建自定义箱子
| 键 | 类型 | 默认值 | 解释 |
| ------------------ | ---- | ------ | ------------------------------------------------------------ |
| custom_description | str | | 箱子UI上面显示的箱子名称不填为空 |
| chest_capacity | int | | 必填箱子的容量行数取值范围1-8如果can_pair取值为true且该值大于4将自动变为4 |
| can_pair | bool | false | 是否可以与隔壁箱子组合,合成一个大箱子 |
| is_shulker_box | bool | false | 是否为潜影盒箱子,如果开启摧毁方块将不会掉落,与原版潜影盒功能相同,无法与隔壁箱子进行组合 |
| mute | bool | true | 是否关闭箱子开启与关闭时的音效 |
| can_be_blocked | bool | false | 是否能被阻挡,即箱子上面有阻挡的方块时能否打开箱子 |
<span id="no_crop_face_block"></span>
### netease:no_crop_face_block
该组件能实现当两个方块相邻时相邻面渲染其中一个方块的一面与原版2个叶子方块相邻效果一致不会把相邻面都裁剪掉
为了避免相邻面变黑需要在配置中新增minecraft:block_light_absorption组件并将值设置为0。
需要配合netease:render_layer使用使用 optionalAlpha 能实现原版的叶子方块效果,使用 alpha 超过一定距离后方块将不渲染。
该组件无参数直接在JSON按下面格式写即可调用
```json
"components": {
"netease:no_crop_face_block":{}
}
```
<span id="custom_tips"></span>
### netease:custom_tips
该组件用于自定义方块Item的物品信息描述与自定义物品中的 netease:customtips 作用相同
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | -------- | -------------- |
| value | str | 物品名称 | 物品的描述信息 |

View File

@@ -0,0 +1,276 @@
---
front:
hard: 入门
time: 分钟
---
# 功能
## 获取及设置某个位置的方块
获取见服务端blockInfo组件的GetBlockNew接口
设置见服务端blockInfo组件的SetBlockNew接口
## 物品形式的生成及获取
支持“MOD SDK文档”中所有与物品相关的接口及事件其中的物品identifier对应方块identifier。
## 方块及物品事件
支持“MOD API”中所有与方块相关的事件其中添加了“fullName”字段返回对应的方块identifier
支持"MOD API"中所有与物品相关的事件其中添加了“itemName”字段返回对应的方块identifier。
## 自定义配方
见[自定义配方文档](../5-自定义配方.md)材料及结果都支持填写方块identifier。可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)行为包的netease_recipes
## 方块组合
见"MOD API"的服务端block组件defines项支持填写自定义方块的identifier。可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)脚本的CustomBlocksServer.RegisterBlockPattern
## 村民交易
可将行为包的交易配置中的item修改为自定义方块的identifier。可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)行为包的`trading\economy_trades\armorer_trades.json`里面将新手级盔甲商的其中一个交易项替换为绿宝石兑换customblocks:customblocks_test0方块
## 构成自定义群系
阅读这条前请先阅读[群系地貌文档](../4-自定义维度/2-群系地貌.md)。
可通过修改minecraft:overworld_surface字段来使用自定义方块生成区块。可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)行为包的`netease_biomes\dm5`里面在自定义群系demo[CustomBiomesMod](../../13-模组SDK编程/60-Demo示例.md#CustomBiomesMod)中dm5维度的基础上进行修改将该维度的dm5_cold_beach、dm5_frozen_ocean、dm5_frozen_river、dm5_ice_plains、dm5_river几个群系的地表方块进行了替换。
<span id="shengyin"></span>
## 声音
resource包中`blocks.json`配置方块的sound。
可以使用原版`sounds.json`中block_sounds里的类型。不支持添加自定义block_sounds类型
<span id="liangdu"></span>
## 亮度
行为包中使用[minecraft:block_light_emission](./1-JSON组件.md#minecraft_block_light_emission)可将方块设置为光源。
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_model_flower方块。
[minecraft:block_light_absorption](./1-JSON组件.md#minecraft_block_light_absorption)可设置方块透光率值的范围为0-15
<span id="wajue"></span>
## 挖掘
挖掘的详细介绍可参考[官方wiki](https://minecraft-zh.gamepedia.com/挖掘)
挖掘时间可使用[minecraft:destroy_time](./1-JSON组件.md#minecraft_destroy_time)配置
挖掘工具可使用[netease:tier](./1-JSON组件.md#netease_tier)配置
可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_test_ore方块
<span id="duomianxiang"></span>
## 多面向
行为包中使用[netease:face_directional](./1-JSON组件.md#netease_face_directional)配置。
四面向可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_test_face4方块
六面向可参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)的customblocks:customblocks_test_face6方块
对于两种面向当玩家进行放置时都是north的贴图面向玩家。
方块的面向等于north贴图面向的方向即玩家放置时准心的反方向
当设置为四面向时方块面向与附加值auxvalue的关系为
| 方块面向 | auxvalue |
| -------- | -------- |
| south | 0 |
| west | 1 |
| north | 2 |
| east | 3 |
当设置为六面向时方块面向与附加值auxvalue的关系为
| 方块面向 | auxvalue |
| -------- | -------- |
| down | 0 |
| up | 1 |
| north | 2 |
| south | 3 |
| west | 4 |
| east | 5 |
<span id="zidingyiqunxiyanse"></span>
## 自定义方块及自定义方块模型的群系颜色
关于生物群系颜色的描述可看[生物群系 - Minecraft Wiki最详细的我的世界百科 ](https://zh.minecraft.wiki/w/%E7%94%9F%E7%89%A9%E7%BE%A4%E7%B3%BB)
原版方块在不同生物群系中会有稍稍不同的颜色变化,例如草、树叶等方块,它们会随着它们所在的群系的温度以及降雨量而产生颜色变化,在温度高的环境中会偏绿,在降雨量低的环境中会变黄。
[自定义方块](./0-自定义方块概述.md)及[自定义方块模型](./5-自定义方块模型.md)也支持该特性。开发者们也可以参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中的**customblocks:customblocks_leaves_tinted**方块、**customblocks:customblocks_leaves_tinted_by_dimension**方块、**customblocks:customblocks_test_face4_tinted**方块、**customblocks:customblocks_test_face4_tinted_by_dimension**方块以及**customblocks:customblocks_model_flower_tinted**方块并参考这五个方块所使用的的颜色渐变图CustomBlocksMod\CustomBlocksMod_resource\textures\colormap\my_grass.png和CustomBlocksMod\CustomBlocksMod_resource\textures\colormap\my_color2.png
以下将会说明如何为自定义方块添加自定义群系颜色和在不同的维度中指定使用不同的颜色渐变图。
#### **1. 颜色渐变图的准备**
首先我们需要为方块准备两张颜色渐变图color map,该图示例如下:
<img src="./picture/customblock/custom_foliage-0-1.png" style="zoom: 67%;" />
该图分辨率固定为256x256目前暂不支持其他分辨率并且仅图像中的左下三角形部分会被使用右上三角形部分不会被使用因此可以置为空白。
方块在被添加群系颜色时,会按照该群系的降雨量及温度来决定我们所取的群系颜色是这张颜色渐变图上的哪一个颜色点。其规则如下:
- 温度从低往高时会按照红色箭头方向从颜色渐变图的右边到左边决定颜色点的x坐标值
- 降雨量从低往高时会按照蓝色箭头方向从颜色渐变图的下方到上方决定颜色点的y坐标值。
举个例子,在降雨量低而且温度高的群系,所取的颜色为这张颜色渐变图的最左下角部分,即颜色会偏黄色。
**根据以上规则,开发者可以自己来定义自己的颜色渐变图来为自定义方块添加特殊的群系颜色。制作时也可以根据原版的颜色渐变图来修改。需要注意的是,分 辨率固定为256x256。**
制作好的渐变图可以放在resource_pack/textures/colormap/这个路径下。
#### **2. 为自定义方块设置这张渐变图**
渐变图的使用方式有两种,一种是为方块整体使用渐变图,一种是为方块中指定的贴图使用渐变图。
两种使用方式中,渐变图的设定方式也有两种,一种是为所有维度设定使用一张渐变图,一种是为不同维度设定使用不同渐变图。
##### 1为方块整体使用这张渐变图
在准备好颜色渐变图后我们需要在resource_pack/blocks.json中添加渐变图的配置
1对所有维度使用同一张渐变图
```json
"customblocks:customblocks_leaves_tinted": {
"sound": "grass",
"textures": "customblocks:customblocks_leaves_tinted",
// 使用"use_colormap"字段指定使用的colormap贴图路径
// 使用colormap后, 该方块的颜色将会随群系的变化而变化
"use_colormap":"textures/colormap/my_grass"
}
```
2对不同维度指定使用不同渐变图
```json
"customblocks:customblocks_leaves_tinted_by_dimension": {
"sound": "grass",
"textures": "customblocks:customblocks_leaves_tinted",
// 使用"use_colormap"字段指定使用的colormap贴图路径, 分辨率固定为256x256, 暂不支持其他分辨率
// 使用colormap后, 该方块的颜色将会随群系的变化而变化
// colormap支持字符串和dict格式配置成字符串格式表示所有维度使用同一张colormap贴图
// 配置成dict格式可以对指定维度使用指定colormap贴图其中default所指定为默认贴图
"use_colormap":{
"default":"textures/colormap/my_grass", // 默认的colormap贴图所在维度没有配置对应贴图时使用默认贴图
"overworld":"textures/colormap/my_grass", // 主世界的colormap贴图
"nether":"textures/colormap/my_color2", // 下界的colormap贴图
"the end":"textures/colormap/my_color2", // 末地的colormap贴图
// 自定义维度colormap贴图
"dm3":"textures/colormap/my_color2",
"dm5":"textures/colormap/my_color2",
"dm22":"textures/colormap/my_color2"
}
}
```
我们使用"use_colormap"字段来指定这个方块使用自定义群系颜色,
其中customblocks:customblocks_leaves_tinted方块对所有维度使用同一张渐变图use_colormap这个字段的值则是这张颜色渐变图的相对路径。
而customblocks:customblocks_leaves_tinted_by_dimension方块对不同维度使用不同渐变图use_colormap的格式为字典字典的key为维度名字主世界、下界、末地分别对应overworld、nether、the end自定义维度以“dm_”拼接维度id为名value为对应渐变图的相对路径。default为默认配置所在维度没有指定对应渐变图时使用该渐变图
这样我们的自定义方块就能在不同群系中表现出不同的颜色差异了。
<img src="./picture/customblock/custom_foliage-0-3.png" style="zoom: 67%;" />
其中customblocks:customblocks_leaves_tinted_by_dimension则可以在不同的维度中展现出不同的颜色渐变图的效果。
<img src="./picture/customblock/custom_foliage-0-4.png" style="zoom: 67%;" />
##### 2为方块指定的贴图使用这张渐变图
为方块指定的贴图使用这张渐变图时我们需要在resource_pack/textures/terrain_texture.json中为某张贴图进行指定
1对所有维度使用同一张渐变图
```json
"customblocks:customblocks_test_face4_top_tinted":{
"textures": "textures/blocks/glazed_terracotta_white",
// 使用"use_colormap"字段指定使用的colormap贴图路径, 分辨率固定为256x256, 暂不支持其他分辨率
"use_colormap":"textures/colormap/my_grass"
},
```
2对不同维度指定使用不同渐变图
```json
"customblocks:customblocks_test_face4_top_tinted_by_dimension":{
"textures": "textures/blocks/glazed_terracotta_white",
// 使用"use_colormap"字段指定使用的colormap贴图路径, 分辨率固定为256x256, 暂不支持其他分辨率
// colormap支持字符串和dict格式配置成字符串格式表示所有维度使用同一张colormap贴图
// 配置成dict格式可以对指定维度使用指定colormap贴图其中default所指定为默认贴图。
"use_colormap":{
"default":"textures/colormap/my_grass", // 默认的colormap贴图所在维度没有配置对应贴图时使用默认贴图
"overworld":"textures/colormap/my_grass", // 主世界的colormap贴图
"nether":"textures/colormap/my_color2", // 下界的colormap贴图
"the end":"textures/colormap/my_color2", // 末地的colormap贴图
// 自定义维度colormap贴图
"dm3":"textures/colormap/my_color2",
"dm5":"textures/colormap/my_color2",
"dm22":"textures/colormap/my_color2"
},
}
```
我们在上面的代码示例中为"customblocks:customblocks_test_face4_top_tinted"这张贴图在所有维度中指定了同一张渐变图,为"customblocks:customblocks_test_face4_top_tinted_by_dimension"这张贴图在不同维度中指定了不同的渐变图。这样一来我们可以在resource_pack/blocks.json为这个方块的某个面指定使用这两张贴图了
```json
"customblocks:customblocks_test_face4_tinted": {
"textures": {
// 这个贴图使用了带colormap的贴图(colormap在textures/terrain_texture.json中指定), 该面的颜色将会随群系的变化而变化
"down": "customblocks:customblocks_test_face4_front_tinted",
"up": "customblocks:customblocks_test_face4_front_not_tinted",
// 这个贴图使用了带colormap的贴图(colormap在textures/terrain_texture.json中指定), 该面的颜色将会随群系的变化而变化
"north": "customblocks:customblocks_test_face4_top_tinted",
"south": "customblocks:customblocks_test_face4_top_sides_not_tinted",
"west": "customblocks:customblocks_test_face4_top_sides_not_tinted",
// 这个贴图使用了带colormap的贴图(colormap在textures/terrain_texture.json中指定)
// 该面的颜色将会随群系的变化而变化且在不同的维度中会使用不同的colormap的贴图
"east": "customblocks:customblocks_test_face4_top_tinted_by_dimension"
},
"sound": "stone"
}
```
我们为这个方块的下表面,东表面以及北表面使用了这些带有渐变图的贴图,如此,方块就表现为某些面能在群系中产生不同颜色的变化,而某些面则不会产生颜色变化。
<img src="./picture/customblock/custom_foliage-0-2.png" style="zoom: 67%;" />
其中东表面的贴图对不同维度指定使用不同的渐变图,能在不同的维度中展现出使用不同渐变图的颜色变化效果。
<img src="./picture/customblock/custom_foliage-0-5.png" style="zoom: 67%;" />
#### **3.不适用的方块及情况**
注意,以下自定义方块或情形将不适用自定义群系颜色:
1重力方块在下落时由于会转换为方块实体因此方块颜色将变为原来的颜色。
2使用了textures/flipbook_textures.json中定义的动态贴图的自定义方块自定义群系颜色也不会生效。
3自定义方块实体外观不适用自定义群系颜色。
4自定义流体不适用自定义群系颜色。
5自定义刷怪箱、自定义传送门不适用自定义群系颜色。
6自定义方块模型无法支持为这个模型中指定的贴图使用自定义群系颜色只能整体使用自定义群系颜色。

View File

@@ -0,0 +1,23 @@
---
front:
hard: 入门
time: 分钟
---
# 特殊方块概述
开发者可通过在方块定义json中添加base_block来修改方块的基础行为。
base_block包括
* mob_spawner 自定义刷怪箱
* portal 自定义传送门
* custom_crop_block 自定义农作物
* custom_heavy_block 自定义重力方块
* liquid 自定义静态流体方块
* flowing_liquid 自定义动态流体方块
![special-1](.././picture/customblock/special-1.png)
如下图为自定义刷怪箱的base_block配置
![special-2](.././picture/customblock/special-2.png)

View File

@@ -0,0 +1,27 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义刷怪箱
## base_block设置
- **自定义刷怪箱方块的base_block需要设为mob_spawner**
- **还应在blocks.json中进行如下设置**
![special-3](.././picture/customblock/special-3.png)
## netease:mob_spawner
可在netease:mob_spawner组件中设置刷怪的类型目前支持原生生物、微软自定义生物。
| 键 | 类型 | 默认值 | 解释 |
| ---- | ------ | ------ | -------------------------------- |
| type | string | | 必须设置,用于控制生成的生物类型 |
- 原生生物type为"minecraft:Namespaced ID",如"minecraft:parrot"Namespaced ID可参考[官方wiki](https://minecraft.gamepedia.com/Mob#List_of_mobs)中各Mob的详细信息。
- 微软自定义生物type为"minecraft:entity"中"description"的"identifier"项,可参考[自定义生物文档](../../3-自定义生物/01-自定义基础生物.md)及[CustomBlocksMod](../../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中的customblocks_test_mobspawner1.json。

View File

@@ -0,0 +1,81 @@
---
hard: 入门
time: 分钟
---
# 自定义工作台
## 概述
自定义工作台组件支持将一个方块改造成一个指定配方的自定义工作台。
需设置以下组件
## netease:block_crafting_table
可在netease:block_crafting_table组件中为工作台命名并指定允许在这个工作台使用的配方
| 键 | 类型 | 默认值 | 解释 |
| ------------------ | ------ | ------ | ------------------------------------------------------------ |
| custom_description | string | | 可选不填为自定义方块的identifier。pocket模式下存在字数限制限制为9个中文字符。 |
| crafting_tags | list | | 必填用于该自定义工作台的配方的tag不填无法打开工作台原版工作台的tag是crafting_table |
### 示例
```json
//自定义工作台方块的json,相关内容都在component里面添加
{
"format_version": "1.16.100",
"minecraft:block": {
"description": {
"identifier": "customblocks:customblocks_test_mobspawner1",
"register_to_creative_menu": true
},
"components": {
"netease:block_crafting_table": {
"custom_description": "你好呀,我的自定义工作台",
"crafting_tags": [
"customTag"
]
}
}
}
}
```
效果如下图
![image-20230330215418831](../picture/customblock/customCraftingTable.png)
```json
//自定义配方例子其中的tags对应上文工作台中的crafting_tags
{
"format_version": "1.12",
"minecraft:recipe_shaped": {
"description": {
"identifier": "customblocks:customblocks_model_flower"
},
"tags": ["customTag"],
"pattern": [
"X",
"#"
],
"key": {
"#": {
"item": "customblocks:customblocks_test0"
},
"X": {
"item": "minecraft:dirt"
}
},
"result": {
"item": "customblocks:customblocks_model_flower"
}
}
}
```
## 注意
目前国际版也有一套自定义工作台,两者是冲突的,网易版自定义工作台会覆盖微软版的自定义工作台,请勿一起使用

View File

@@ -0,0 +1,65 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义传送门方块
## base_block设置
- **自定义传送门方块的base_block需要设为portal。**
## 动画纹理
- 可通过在`resource/textures/flipbook_textures.json`中配置动画纹理使其贴图拥有动态效果,属于微软功能。
## 传送门方块介绍
- 传送门方块拥有两种朝向其方块延伸方向分别与X轴、Z轴相同如图所示
- 可在netease:portal中设置传送门方块上播放的粒子特效以及目标维度
![special-4](.././picture/customblock/special-4.png)
## netease:portal
| 键 | 类型 | 默认值 | 解释 |
| -------------------- | ------ | ------ | ------------------------------------------------------------ |
| particle_east_west | string | | 可选对应于粒子json文件中的identifier用于控制方块与Z轴同向时播放的粒子特效 |
| particle_north_south | string | | 可选对应于粒子json文件中的identifier用于控制方块与X轴同向时播放的粒子特效 |
| target_dimension | int | | 必须设置,用于控制进入传送门方块后到达的目标维度 |
- 粒子特效应放置于`resource/particles`,粒子特效编写可参考[官方关于粒子组件的说明](https://minecraft.gamepedia.com/Bedrock_Edition_particle_documentation)。
- **目标维度为0或3-20的整数或者大于21的新版自定义维度的数值1下界和2末地会被视作0来处理。**
## 自定义传送门方块相关特性
- 若通过服务端blockInfo组件的SetBlockNew接口放置传送门方块
- 附加值'aux'设为1时该方块延伸方向与X轴相同播放particle_north_south对应的粒子
- 附加值'aux'设为2时该方块延伸方向与Z轴相同播放particle_east_west对应的粒子。
- **避免将附加值'aux'设为0。**
- 还可以在游戏内通过指令/setblock放置方块**注意'aux'值应设为1或2。**
如下为在(0, 65, 0)处放置aux值为2的customblocks_test_portal_blue方块的指令
`/setblock 0 65 0 customblocks_test_portal_blue 2`
- 手动放置的传送门方块附加值'aux'始终为0无论它朝向哪里**不建议开发者手动放置传送门方块。**
- 目标维度与当前维度相同时,将不会进行传送。
- 只有玩家才能够通过自定义传送门方块进行传送。
- 同一玩家存在一定的传送冷却时间,不会连续传送。
- 传送前后玩家坐标不发生改变。

View File

@@ -0,0 +1,411 @@
---
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",
"register_to_create_menu":true,
"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",
"register_to_creative_menu": true,
"is_experimental": false,
"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",
"register_to_creative_menu": true,
"is_experimental": false,
"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",
"register_to_creative_menu": true,
"is_experimental": false,
"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",
"register_to_creative_menu": true,
"is_experimental": false
},
"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",
"register_to_creative_menu": true,
"is_experimental": false
},
"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",
"register_to_creative_menu": true,
"is_experimental": false
},
"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>事件监听周围方块的变化,并做响应的处理。

View File

@@ -0,0 +1,67 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义红石方块
自定义红石方块是一种特殊的自定义方块,包括信号源方块与红石机械元件方块,支持方块相关的所有事件以及接口。
## 自定义红石信号源方块
自定义红石信号源方块放置在地图上会发出红石信号,信号的初始值可以配置。
其中type为producerstrength为初始红石信号量。
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:customblocks_redstone",
"register_to_creative_menu": true,
"is_experimental": false,
},
"components": {
"minecraft:map_color": {
"color": "#408080"
},
"netease:redstone": {
"type": "producer",
"strength": 10
}
}
}
}
```
## 自定义红石机械元件方块
自定义红石机械元件方块放置在地图上会接收红石信号,可以被激活。
对于自定义红石机械元件方块,其红石信号变化时触发事件<a href="../../../../../mcdocs/1-ModAPI/事件/方块.html#blockstrengthchangedserverevent" rel="noopenner"> BlockStrengthChangedServerEvent </a>。
其中type为consumer初始红石信号量为0未激活状态不能通过netease:redstone的strength字段进行配置。
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:customblocks_redstone_consumer",
"register_to_creative_menu": true,
"is_experimental": false,
},
"components": {
"netease:redstone": {
"type": "consumer"
}
}
}
}
```

View File

@@ -0,0 +1,149 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义流体
## 概述
自定义流体需要设置两个方块,一个静态流体,一个动态流体。液体在流动过程中最外层是动态流体,其他都是静态流体,二者会相互转换。当流体扩散完毕后可见的均已转化为静态流体,可以通过设置不同颜色来观察动态流体与静态流体之间的相互转换。
## base_block设置
- 自定义流体的**base_block**,静态流体需要设为**liquid**,动态流体需要设为**flowing_liquid**
- 命名规则因为静态流体与动态流体是相互转换的在引擎层通过flowing去定位所以需要注册一对才能正常使用
- 静态流体——**命名空间:流体方块名**,例如`customLiquid:red_water`
- 动态流体——**命名空间:flowing_流体方块名**,例如`customLiquid:flowing_red_water`
## 动画纹理
- 流体需要在`resource/textures/flipbook_textures.json`中配置动画纹理使其贴图拥有动态流动效果,属于微软功能。
## 流体方块介绍
- 可在netease:liquid中设置流体方块的流动速度、流动范围、颜色以及能否使船浮起来
- 流体方块与原版水一致,如图所示:
![special-4](.././picture/customblock/special-5.png)
## netease:liquid
| 键 | 类型 | 默认值 | 解释 |
| -------------- | ------------- | ---------------------------------------- | ------------------------------------------------------------ |
| liquid_color | array | [255, 255, 255, 255] | 可选流体颜色4个数依次对应RGBA取值范围均为0-255。透明度只有在开启了“精美图像”选项时生效。 |
| spread_range | int | 8 | 可选流体范围以动态流体为中心往外扩散的格数取值范围1-8仅动态流体有效 |
| spread_delay | int | 5 | 可选流体扩散刻数每经过该刻数扩散一格每秒20刻仅动态流体有效 |
| spread_fire | bool | false | 可选,是否传播火,可参考岩浆效果 |
| can_float_boat | bool | true | 可选,流体是否能浮起船来,动态流体及静态流体均需要设置 |
| bucket_name | string | "water_bucket" | 可选空桶对水源使用使获得的物品默认是原版的水桶如果是自定义物品需带上命名空间输入完整的物品id |
| water_splash | string | "minecraft:water_splash_particle_manual" | 可选,实体进入流体时会播放对应的粒子特效,在玩家所在位置附近随机播放若干该特效,特效需采用微软特效 |
| mob_effects | array(dict) | [] | 可选,实体进入流体时添加状态效果,会触发对应的添加/刷新状态效果的事件 |
| remove_effects | array(string) | [] | 可选,实体进入流体时移除状态效果,会触发对应的移除状态效果的事件 |
- 如果没有注册该组件,液体颜色、范围及扩散延迟默认和原版水一样,**但是将无法使船浮起来**
添加状态效果mob_effects各字段配置如下
| 键 | 类型 | 解释 |
| ------------- | ------ | -------------------------------------------- |
| effect_name | string | 状态效果名称 |
| duration | int | 状态效果持续时间 |
| amplifier | int | 状态效果倍率比等级小1例如力量II的倍率为1 |
| show_particle | bool | 是否显示状态效果的粒子效果,默认不显示 |
## 自定义流体方块相关特性
- 可以在游戏内通过指令/setblock放置方块静态方块放置后不会向周围扩散当其周围方块发生变化时会转变成流动方块继承流动特性
- 继承自原版水,因此会有原版水的特性,例如和岩浆有互动、玩家进入会有流动效果、溺水、与海绵互动等。
- 用水桶装载后会生成普通水桶通过配置bucket_name可实现生成别的物品可结合自定义桶实现自定义流体的装载与倒出
## 示例
动态流体:
```json
{
"format_version": "1.16.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:flowing_green_water",
"register_to_creative_menu": true,
"base_block": "flowing_liquid"
},
"components": {
"netease:liquid": {
"liquid_color": [ 0, 128, 0, 254 ],
"spread_range": 4,
"spread_delay": 5,
"bucket_name": "customBucket:green_bucket",
"spread_fire": true,
"mob_effects": [
{
"effect_name": "slowness",
"duration": 3,
"amplifier": 1,
"show_particle": true
},
{
"effect_name": "weakness",
"duration": 1,
"amplifier": 4
}
],
"remove_effects": [ "speed", "jump_boost" ]
}
}
}
}
```
静态流体:
```json
{
"format_version": "1.16.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:green_water",
"register_to_creative_menu": false,
"base_block": "liquid"
},
"components": {
"netease:liquid": {
"liquid_color": [ 0, 128, 0, 254 ],
"bucket_name": "customBucket:green_bucket",
"spread_fire": true,
"mob_effects": [
{
"effect_name": "slowness",
"duration": 3,
"amplifier": 1,
"show_particle": true
},
{
"effect_name": "weakness",
"duration": 1,
"amplifier": 4
}
],
"remove_effects": [ "speed", "jump_boost" ]
}
}
}
}
```

View File

@@ -0,0 +1,73 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义重力方块
## 概述
自定义重力方块可以模拟[下落的方块](https://zh.minecraft.wiki/w/%E4%B8%8B%E8%90%BD%E7%9A%84%E6%96%B9%E5%9D%97)并且支持在组件中修改配置、python监听事件。
## base_block设置
- 自定义重力方块的base_block需要设为`custom_heavy_block`
## netease:fall
| 键 | 类型 | 默认值 | 解释 |
| ------------ | ----- | -------------------- | ------------------------------------------------------------ |
| send_python_event | bool | false | 可选,是否发送重力方块/下落方块实体相关事件至python |
| fall_acceleration | float | 0.04 | 可选下落的方块实体每次tick的垂直加速增量 |
| adjust_percentage | float | 0.98 | 可选下落的方块实体每次tick移动完后移速乘的调整数值 |
| hurt_entity | bool | false | 可选,下落的方块实体结束下落后是否要计算对碰撞实体的伤害 |
| fall_damage_amount | float | 2.0 | 可选,原版下落伤害计算完后乘的倍率 |
| max_fall_damage | int | 40 | 可选,下落伤害乘完倍率后也会被限制在该值的范围内 |
| min_height_remove_tick | int | 100 | 可选当下落的方块实体低于区块最低高度后多少tick将其强制删除 |
| force_break_tick | int | 600 | 可选下落的方块实体多少tick后会强制被破坏 |
| cancel_drop | bool | false | 可选,下落的方块实体被破坏时是否取消方块物品的掉落 |
- `send_python_event`主要影响HeavyBlockStartFallingServerEvent、FallingBlockCauseDamageBeforeServerEvent、FallingBlockBreakServerEvent、FallingBlockReturnHeavyBlockServerEvent、FallingBlockCauseDamageBeforeClientEvent几个事件。
- 如果没有在mod程序中监听的需要可以不将`send_python_event`设为true以优化性能不发python事件也可以配置组件的其他值
- 原版对于下落的方块实体计算下落的过程使用python伪代码表示大致为
```python
while Tick:
falling_block.move_vector.y -= fall_acceleration # 当前移动向量增加一个向下的力
move(falling_block) # 按照当前的移动向量调整实体位置
falling_block.move_vector *= adjust_percentage # 移动完后将当前移速(移动向量)乘个数值回调
```
- 原版下落的方块实体并没有对实体实时的碰撞检测,这就意味着在调整下落的方块移动速度时可能会遇到两个问题:
- 如果两个下落的方块速度不一致,会看到一个方块实体从另一个方块实体传过去,并没有碰撞效果。
- 下落的方块对实体造成伤害的计算并不是在刚接触到实体时,而是在落地时才检测范围有无实体,把移速调整的慢点更容易观察到此现象。
## 示例配置
可参考[CustomBlocksMod](../../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中的customblocks:customblocks_test_heavy.json。
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "customblocks:customblocks_test_heavy",
"register_to_creative_menu": true,
"is_experimental": false,
"base_block": "custom_heavy_block",
"category": "custom"
},
"components": {
"netease:fall": {
"send_python_event":true,
"fall_acceleration":0.04,
"adjust_percentage":0.98,
"hurt_entity":true,
"min_height_remove_tick":100,
"force_break_tick":600,
"fall_damage_amount":2.0,
"max_fall_damage":40
}
}
}
}
```

View File

@@ -0,0 +1,133 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义含水方块
## 概述
自定义含水方块支持在组件中配置自定义方块含水的相关功能并支持python监听事件、接口设置等。
## netease:water_destory
可在netease:water_destory组件中设置是否无法摆放在水源和流水方块中如果设置为true会被流水摧毁。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------------------------------------------- |
| value | bool | | 必须设置,用于设置无法摆放在水源和流水方块中 |
- 可以在方块的loottable中设置被水流摧毁后的掉落物
### 示例
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"register_to_creative_menu": true,
"identifier": "customblocks:water_destroy_test_block",
"is_experimental": false,
"category": "custom"
},
"components": {
"netease:water_destory": {
"value": true
}
}
}
}
```
## netease:water_only
可在netease:water_only组件中设置是否必须放置在水中。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------ |
| value | bool | | 必须设置,用于设置是否必须放在水中。 |
### 示例
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"register_to_creative_menu": true,
"identifier": "customblocks:water_only_test_block",
"is_experimental": false,
"category": "custom"
},
"components": {
"netease:water_only": {
"value": true
}
}
}
}
```
## netease:water_source
可在netease:water_source组件中设置是否在水源方块中表现为含水。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------------------------------------- |
| value | bool | | 必须设置,是否在水源方块中表现为含水。 |
### 示例
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"register_to_creative_menu": true,
"identifier": "customblocks:water_source_test_block",
"is_experimental": false,
"category": "custom"
},
"components": {
"netease:water_source": {
"value": true
},
"netease:render_layer": {
"value": "alpha"
}
}
}
}
```
## netease:water_flow_source
可在netease:water_flow_source组件中设置是否在水源和流水方块中表现为含水。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------------------------------------- |
| value | bool | | 必须设置,是否在水源和流水方块中表现为含水。 |
### 示例
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"register_to_creative_menu": true,
"identifier": "customblocks:water_flow_source_test_block",
"is_experimental": false,
"category": "custom"
},
"components": {
"netease:water_flow_source": {
"value": true
},
"netease:render_layer": {
"value": "alpha"
}
}
}
}
```

View File

@@ -0,0 +1,56 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义交叉贴图方块
## 概述
自定义交叉贴图方块支持使用引擎预设的交叉贴图模型,自己配置物品贴图和模型贴图,制作出类似于甘蔗、蜘蛛网的模型方块。
![web_reeds.png](../picture/customblock/web_reeds.png)
## model_item_texture
可在model_item_texture中设置使用的物品贴图。
| 类型 | 默认值 | 解释 |
| ------ | ------ | ----------------------------------------------- |
| string | | 使用的物品贴图,必须设置"netease_model"才能生效 |
## model_texture
可在model_texture中设置使用的模型贴图。
| 类型 | 默认值 | 解释 |
| ----- | ------ | ----------------------------------------------- |
| array | | 使用的模型贴图,必须设置"netease_model"才能生效 |
- model_texture和model_item_texture必须同时设置才能生效
## 使用交叉贴图模型
- 在resource_packs\blocks.json下面添加自定义的方块identifier的配置
- 在"netease_model"里配置"customblocks:web_preset""model_item_texture"和"model_textures"根据需求配置自己的物品贴图和模型贴图
### blocks.json示例
```json
{
"format_version": [
1,
1,
0
],
"customblocks:web_preset": {
"netease_model": "customblocks:web_preset",
"model_item_texture": "customblocks:reeds_item",
"model_textures": [
"customblocks:reeds"
]
}
}
```

View File

@@ -0,0 +1,70 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义含雪方块
## 概述
自定义含雪方块支持在组件中配置自定义方块含雪的相关功能并支持python监听事件、接口设置等。
需要配置方块含雪,需设置以下两个组件
## netease:snow_recover_able
可在netease:snow_recover_able组件中设置方块是否能含雪。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | -------------------------------- |
| value | bool | | 必须设置,用于设置方块是否能含雪 |
## netease:can_built_over
可在netease:can_built_over组件中设置在放置其他方块时如果该位置已有含netease:can_built_over配置的方块其他方块能否和放置在此方块中。
| 键 | 类型 | 默认值 | 解释 |
| ----- | ---- | ------ | ------------------------------------------------------------ |
| value | bool | | 必须设置用于设置在放置其他方块时如果该位置已有含netease:can_built_over配置的方块其他方块能否和放置在此方块中 |
### 示例
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"register_to_creative_menu": true,
"identifier": "customblocks:customblocks_test_ore",
"is_experimental": false,
"category": "custom"
},
"components": {
"minecraft:block_light_absorption": {
"value": 0
},
"netease:render_layer": {
"value": "alpha"
},
"netease:snow_recover_able": {
"value": true
},
"netease:can_built_over": {
"value": true
},
"netease:aabb": {
"collision": {
"min": [0.0, 0.0, 0.0],
"max": [0.0, 0.0, 0.0]
},
"clip": {
"min": [0.0, 0.0, 0.0],
"max": [1.0, 0.188, 1.0]
}
}
}
}
}
```
## 注意
目前自定义含雪方块和方块实体不兼容(包括自定义方块实体,自定义刷怪箱等),请不要一起使用

View File

@@ -0,0 +1,154 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义方块实体
## 概念
方块实体的概念详见[官方wiki](https://minecraft-zh.gamepedia.com/方块实体)
## 添加自定义方块实体
需要添加netease:block_entity组件才能为自定义方块添加自定义方块实体。
| 键 | 类型 | 默认值 | 解释 |
| ------- | ---- | ------ | ------------------------------------------------------------ |
| tick | bool | false | 为true时当玩家进入方块tick范围时该方块每秒会发送**20次**ServerBlockEntityTickEvent事件<br>为false时该方块不会发送ServerBlockEntityTickEvent事件 |
| client_tick | bool | false | 为true时当玩家进入方块tick范围时该方块每秒会发送**20次**ModBlockEntityTickClientEvent事件<br>为false时该方块不会发送ModBlockEntityTickClientEvent事件 |
| movable | bool | true | 为true时该方块可被粘性活塞拉回<br>为false时该方块不可被粘性活塞拉回 |
- **对于已有方块实体的方块,如[自定义刷怪箱](./3-特殊方块/1-自定义刷怪箱.md),将无法再添加自定义方块实体。**
- 添加了自定义方块实体的方块,可通过**服务端blockEntityData组件**来管理方块实体内的数据。
## 相关组件与事件
- <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#getblockentitydata" rel="noopenner"> GetBlockEntityData接口 </a>
可用于管理方块实体内的数据。
- <a href="../../../../mcdocs/1-ModAPI/事件/方块.html#serverplaceblockentityevent" rel="noopenner"> ServerPlaceBlockEntityEvent事件 </a>
当玩家手动放置含自定义方块实体的自定义方块时触发,此时可向该方块实体中存储数据。
- <a href="../../../../mcdocs/1-ModAPI/事件/世界.html#chunkgeneratedserverevent" rel="noopenner"> ChunkGeneratedServerEvent事件 </a>
通过自定义特征放置含自定义方块实体的自定义方块时,在区块生成完毕时触发,其中包含了该区块中自定义方块实体信息列表,此时可向该方块实体中存储数据。
- <a href="../../../../mcdocs/1-ModAPI/事件/方块.html#serverblockentitytickevent" rel="noopenner"> ServerBlockEntityTickEvent事件 </a>
若在netease:block_entity组件中配置tick为true则当该自定义方块位于模拟范围内时触发。该事件触发频率为**每秒20次**
<span id="demo"></span>
## demo解释
- 方块配置
[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中,`customblocks:customblocks_test_block_entity`方块配置了自定义方块实体,具体配置如下:
即该方块在距离玩家不远时会每秒发送20次ServerBlockEntityTickEvent事件且无法被粘性活塞拉回。
![block_entity_1](./picture/customblock/block-entity-1.png)
- 方块放置
customBlocksServer.py中注册了对ServerPlaceBlockEntityEvent事件的监听在回调里通过blockEntityData组件向每个由玩家手动创建的自定义方块实体中写入数据
```python
def ServerPlaceBlockEntityEvent(self, args):
print 'ServerPlaceBlockEntityEvent ', args
dimension = args['dimension'] # 该自定义方块实体所在的维度
blockPos = (args['posX'], args['posY'], args['posZ']) # 该自定义方块实体所处位置
blockName = args['blockName'] # 含该自定义方块实体的方块名称
# 创建blockEntityData组件
comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData")
# 获取可操作该自定义方块实体的对象
blockEntityData = comp.GetBlockEntityData(dimension, blockPos)
# 在对自定义方块实体内数据进行操作前,要先进行判空处理
if blockEntityData:
# 使用与dict类似的操作方式存入键为"abc"、值为{"1":True,"2":None,"3":"123"}的数据
blockEntityData['abc'] = {"1": True, "2": None, "3": "123"}
```
- 方块交互
监听了ServerBlockUseEvent在其中判断玩家是否在与customblocks:customblocks_test_block_entity方块进行交互。是则向其中写入数据
```python
def ServerBlockUseEvent(self, args):
blockName = args['blockName'] # 方块名称
blockPos = (args['x'], args['y'], args['z']) # 方块位置
playerId = args['playerId'] # 玩家id
dimensionComp = serverApi.CreateComponent(playerId, "Minecraft", "dimension")
dimension = dimensionComp.GetPlayerDimensionId() # 获取玩家所在维度
# 判断交互的方块类型
if blockName == 'customblocks:customblocks_test_block_entity':
comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData")
blockEntityData = comp.GetBlockEntityData(dimension, blockPos)
if blockEntityData:
# 向方块实体中写入键为"key"、值为[1, 2, 3]的数据
blockEntityData['key'] = [1, 2, 3]
```
- 方块实体tick
```python
def OnBlockEntityTick(self, args):
# 避免在Tick中频繁打印输出易造成卡顿
# print 'blockEntityTick ', args
pass
```
监听了ServerBlockEntityTickEvent事件netease:block_entity组件中配置tick为true的自定义方块每秒会触发20次其自定义方块实体tick事件。
- **应避免在诸如tick事件回调等高频函数中进行打印输出易造成卡顿。**
- **应避免在地图中放置过多netease:block_entity组件配置tick为true的自定义方块频繁事件调用也可能造成卡顿**
- 方块销毁
监听了ServerPlayerTryDestroyBlockEvent事件当有玩家尝试摧毁customblocks:customblocks_test_block_entity方块时会尝试从其自定义方块实体中读取数据并输出。
```python
def ServerPlayerTryDestroyBlockEvent(self, args):
pos = (args["x"], args["y"], args["z"])
playerId = args['playerId']
dimensionComp = serverApi.CreateComponent(playerId, "Minecraft", "dimension")
dimension = dimensionComp.GetPlayerDimensionId()
comp = self.CreateComponent(self.levelId, "Minecraft", "blockEntityData")
blockEntityData = comp.GetBlockEntityData(dimension, pos)
if blockEntityData:
# 根据key获取方块实体中对应的value
value1 = blockEntityData['key']
value2 = blockEntityData['abc']
print 'value of "key" is', value1
print 'value of "abc" is', value2
```
- 对于从未进行过交互的customblocks:customblocks_test_block_entity方块当玩家尝试摧毁它时会输出
```python
# 不存在于方块实体中的数据将返回None
'value of "key" is None'
'value of "abc" is {"1": True, "2": None, "3": "123"}'
```
- 若玩家曾经与该方块进行过交互,会输出:
```python
'value of "key" is [1, 2, 3]'
'value of "abc" is {"1": True, "2": None, "3": "123"}'
```

View File

@@ -0,0 +1,658 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义方块实体外观
## 概述
根据[自定义方块实体](./4-自定义方块实体.md)以及[自定义方块实体模型](./5-自定义方块模型.md)这两个步骤,我们可以做出具有个人特色的自定义方块实体,如果希望这个自定义方块实体能够具有更强的表现力,能够像原版方块实体如附魔台那样动起来,又或是具有更酷炫的特效,那么则可遵循本教程来进一步扩展我们的自定义方块实体。
自定义方块实体的扩展功能包含两个方面:
1 **为自定义方块实体添加动画功能**。支持使用由BlockBench制作的原版模型或者是游戏原版模型并支持这些模型附带的动画可以使自定义方块实体具有动画效果。
2 **为自定义方块实体添加特效功能**。通过配置或者接口可为自定义方块实体附加网易版粒子特效及序列帧特效,并且支持使用特效及序列帧等系列接口来进行控制和管理。自定义方块实体还支持配置微软原版粒子特效及音效。
接下来我们将讲解如何为我们的自定义方块实体使用以上两个扩展功能,并制作一个小松鼠自定义方块实体,用户可同时参考[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)示例中的自定义方块实体-小松鼠custom_block_squirrel学习。
注意: 自定义方块实体外观由于需要方块实体渲染功能支持因此如果通过原版特征例如minecraft:ore_feature等方式进行放置由于原版特征无法正常放置方块实体会缺失方块实体功能因此自定义方块实体外观不能正常显示。 如果想要通过特征放置方块实体,可以尝试使用[结构特征](../4-自定义维度/4-自定义特征.md#结构)来进行放置。
## 为自定义方块实体添加动画功能
在这一节,我们将讲述如何为自定义方块实体添加动画功能
#### 1. 准备粒子特效或者序列帧特效文件
我们首先需要一个原版实体模型这个可以通过BlockBench软件进行制作这一步用户可以参考[自定义方块实体模型](./5-自定义方块模型.md)中的使用BlockBench制作小蓝花步骤但需要注意的是制作好的模型bbmodel文件**不需要通过MC Studio导入模型来生成模型的json文件**,而是只需要在制作好模型后,点击**文件-导出-导出基岩版几何体**即可,如下图所示:
<img src="./picture/customblock/model-7-1.png" style="zoom: 67%;" />
与此同时我们可以利用BlockBench为该模型制作动画在制作好动画后我们通过软件右上方切换到动画模式然后点击左上方的**动画-Export Animations**即可导出该模型的动画json文件。如下图所示
<img src="./picture/customblock/model-7-2.png" style="zoom:80%;" />
关于模型的制作以及动画的制作,用户也可以参考[原版模型制作指南](../../../16-美术/6-模型和动作/01-原版模型制作指南.md)来进行制作。制作好的模型json文件放在resource_pack/models/entity目录下 动画json文件则放在resource_pack/animations目录下这些都与原版实体生物相同。
#### 1.1 BlockBench模型调整
在使用BlockBench制作模型时往往需要知道所制作的模型在游戏中的实际大小和偏移以此为基准来调节模型的大小及位置。目前自定义方块实体外观功能所表现出的模型大小、旋转、尺寸与BlockBench里的位置、尺寸、旋转的表现效果是一致的。
如下图所示我们在BlockBench里制作一个**位置0,0,0尺寸16,16,16旋转0,0,0**且**粉红色贴图的表面正对着北方**的方块
<img src="./picture/customblock/model-7-5.png" style="zoom:80%;" />
则这个方块在游戏的表现如下图所示:
<img src="./picture/customblock/model-7-6.png" style="zoom:80%;" />
该方块在游戏中同样以粉红色贴图正对着北方且大小正好为一个普通方块大小。同时如果用户在BlockBench中调整方块的旋转及尺寸那么在游戏中会有与BlockBench相同的旋转及尺寸调整效果。在使用<a href="../../../../mcdocs/1-ModAPI/接口/方块/索引.html" rel="noopenner"> **技术手册-ModAPI-方块** </a>中的自定义方块实体模型调整接口时也与BlockBench中调整参数所带来的效果相同。
但需要注意的是用户在使用接口调整模型y轴方向的缩放时会与BlockBench的拉伸方向相反同时会在缩放模型的同时带有一段y轴方向的位置平移。
总的来说,模型调整要点可以归结如下:
1 实体json文件中scale没有定义或者定义为1时BlockBench中尺寸为16等于游戏中一个普通方块的边长长度。 实体json文件的scale定义可查看下一节介绍。
2 BlockBench中模型的面向、尺寸拉伸方向y轴除外与游戏中的表现一致。使用缩放接口调整的效果也与BlockBench中调整参数的效果一致。
3 BlockBench中位置为0,0,0时对应游戏中自定义方块实体实际的位置方块面向的南北方向、BlockBench中的坐标轴方向也与游戏中一致。
用户可在BlockBench中调整好预期的效果大部分模型的调整可在BlockBench中完成再在游戏中进行测试以减少在游戏中反复调整模型的效果所带来的时间消耗。
使用接口对模型进行缩放、旋转时的特性归结如下:
1 对模型使用<a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentitymodelrotation" rel="noopenner"> SetBlockEntityModelRotation </a>接口旋转
对模型使用接口进行旋转时,旋转以方块位置的西北方向的下顶点作为原点的坐标轴作为旋转轴来进行旋转,如下图所示:
<img src="./picture/customblock/model-7-7.png" style="zoom:80%;" />
假设使用接口旋转30度绕x轴旋转时会以上图中的**粗红线**作为旋转轴,以看向**x轴正方向的顺时针**旋转30度。
绕z轴旋转时会以上图中的**粗蓝线**作为旋转轴,以看向**z轴正方向的顺时针**旋转30度。
绕Y轴旋转时会以上图中的**粗绿线**作为旋转轴,以看向**y轴正方向的顺时针**旋转30度。
2 对模型使用<a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentitymodelscale" rel="noopenner"> SetBlockEntityModelScale </a>接口缩放
对模型使用接口进行旋转时,旋转以方块位置的西北方向的下顶点作为原点的坐标轴作为起始轴来进行拉伸,如下图所示:
<img src="./picture/customblock/model-7-8.png" style="zoom:80%;" />
假设使用接口放大2倍x轴方向放大时会以上图中的**粗蓝线**作为起始轴,向**x轴正方向**拉伸为原来的2倍长。
z轴方向放大时会以上图中的**粗红线**作为起始轴,向**z轴正方向**拉伸为原来的2倍长。
y轴方向放大时会向**y轴负方向**拉伸为原来的2倍长。
#### 1.2 方块实体的多面向
自定义方块实体外观支持四面向或六面向。如果方块实体定义了[netease:face_directional](2-功能.md#duomianxiang)组件后方块实体具有多面向功能。在没有定义该组件时方块实体的面向与BlockBench中一致即默认朝向北方。定义该组件后方块实体的面向会根据玩家放置的方向或者利用接口<a href="../../../../mcdocs/1-ModAPI/接口/世界/方块管理.html#setblocknew" rel="noopenner"> SetBlockNew </a>设置时所设定的auxValue来决定。
方块实体的面向改变后,
1 方块的面向改变**不会**影响旋转轴的改变,因为旋转轴是以世界坐标系为准。利用接口旋转方块时的旋转轴**仍然为未改变面向之前的旋转轴**,即默认朝向北方时方块的西北方向的下顶点作为原点的坐标轴。
2 方块的面向改变**会**影响拉伸方向改变,因为拉伸方向是以方块的本身的模型坐标系为准。因此面向改变后,会以面向改变后的模型坐标系来进行拉伸。例如, 方块面向默认朝向北面时x方向的拉伸方向为从西到东拉伸当方块面向变为朝向东时利用接口进行x方向的拉伸则变为从北到南可以看成模型坐标系顺时针旋转了90度。
### 2. 配置模型及动画
在准备好模型及动画文件后,我们需要进行模型及动画的配置。这一步其实与原版生物的配置相同,如果用户熟悉原版生物的配置,可以跳过这一步。
首先我们需要准备一个控制实体动画及渲染的entity.json文件这个文件在resource_pack/entity目录下创建命名为xxx.entity.jsonxxx为用户自定义的文件名称。这个文件可以参考[自定义基础生物](../3-自定义生物/01-自定义基础生物.md)中的资源包生物定义进行创建。有一定的外语阅读能力的用户还可以参考基岩版百科中的[实体创建说明](https://bedrock.dev/zh/docs/stable/Entities)以及[实体动画](https://bedrock.dev/zh/docs/stable/Animations)
我们的实体custom_block_squirrel.entity.json创建如下
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
// 自定义方块实体的identitfier
"identifier": "customblocks:custom_block_squirrel",
// 指定使用的实体模型,位于resource_pack/models/entity目录下
"geometry": {
"default": "geometry.squirrel"
},
// 指定使用的模型贴图,位于resource_pack/textures/entity目录下
"textures": {
"red": "textures/entity/squirrel/red"
},
// 指定使用的模型材质
"materials": {
"red": "entity_alphatest"
},
// 指定使用的模型渲染控制器,位于resource_pack/render_controllers目录下
"render_controllers": [ "controller.render.squirrel" ],
"scripts": {
// 模型的缩放值
"scale": "0.9375",
// 实体Molang变量初始化用于切换动画状态
"initialize": [
"variable.mod_is_moving = 2.0;"
],
// 运行的动画general为我们创建的自定义动画控制器表示该模型会一直运行该动画控制器。
"animate": [
"general"
]
},
// 该模型包含的动画general为动画控制器定义在resource_pack/animations_controllers目录下
// move,idle,look_at_target为动画定义在resource_pack/animations目录下
"animations": {
"move": "animation.squirrel.move",
"idle": "animation.squirrel.idle",
"general": "controller.animation.squirrel.general"
}
}
}
}
```
以上文件创建了一个使用”geometry.squirrel”模型文件的实体该实体包含了一个名为”general“的动画控制器默认运行该动画控制器该动画控制器包含了2个动画“move”以及”idle”这些都可以参考resource_pack/animations_controllers/squirrel.animation_controllers.json中的示例
```json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.squirrel.general": {
"initial_state" : "default",
"states": {
// 默认待机动画状态
"default": {
"animations": [ "idle" ],
"transitions": [
// 由实体Molang变量variable.mod_is_moving控制动画状态切换初始值在entity.json中的sripts字段中进行定义。
{ "squMove": "variable.mod_is_moving==1" }
]
},
// 行走动画状态
"squMove": {
"animations": ["move"],
"transitions": [
// 由实体Molang变量variable.mod_is_moving控制动画状态切换初始值在entity.json中的sripts字段中进行定义。
{ "default": "variable.mod_is_moving==2" }
]
}
}
}
}
}
```
我们定义了一个实体Molang变量”variable.mod_is_moving“该Molang变量用于在控制”general“的动画状态切换它的初始值为2.0表示实体模型的默认动画状态为“default”该动画状态运行的动画为”idle”。
### 3. 将实体模型与方块实体联系起来
在配置好实体模型以及动画之后,我们需要将这个模型与方块实体联系起来。
在resource_pack/blocks.json文件中找到我们想要对其添加实体模型和动画的方块实体在这里我们是”customblocks:custom_block_squirrel”并加入“client_entity”的字段表示这个方块实体将会用到实体模型如下所示
```json
{
"format_version": [
1,
1,
0
],
///...
"customblocks:custom_block_squirrel": {
"sound": "grass",
// 可与netease_model字段一起使用
"netease_model": "customblocks:customblocks_model_decoration",
// --- 实体模型配置 ---
// 这个方块实体将会使用到实体模型
"client_entity": {
// 对应custom_block_squirrel.entity.json里面的identifier
"identifier": "customblocks:custom_block_squirrel",
// 这个方块实体的手持模型或掉落时模型是否使用该实体模型。
"hand_model_use_client_entity": true,
// 这个方块实体的物品icon贴图
"block_icon": "test_block_icon",
// 方块实体被破坏时使用的贴图
"destroyed_textures":"destroy_squirrel"
},
},
///...
}
```
“client_entity”的字段中包含了四个字段他们的作用分别如下表格所示
| 字段名称 | 说明 |
| ---------------------------- | ------------------------------------------------------------ |
| identifier | 对应custom_block_squirrel.entity.json里面的identifier用于指定使用resource_pack/entity目录下的哪个entity.json文件 |
| hand_model_use_client_entity | 这个方块实体的手持模型或掉落时模型是否使用该实体模型。定义为true时玩家手持这个方块实体或者方块实体掉落在地上时显示所定义的这个实体模型。定义为false时根据用户是否定义了“netease_model”这个字段会出现两种情况<br />1定义了netease_model字段手持模型和掉落模型会显示netease_model所定义的方块模型<br />2没有定义netease_model字段手持模型和掉落模型会显示由block_icon所定义的贴图所组成的方块模型同时放置在地上的方块实体也会出现该贴图组成的方块模型。 |
| block_icon | 这个方块实体的物品icon贴图定义了这个字段后方块实体的icon贴图将会使用这个字段中的贴图贴图的路径定义resource_pack/textures/terrain_texture.json文件中。以下情况需要定义这个字段<br />1在"hand_model_use_client_entity"为true的情况否则将看不到这个方块实体的物品icon。<br />2在"hand_model_use_client_entity"为false并且没有定义“netease_model”字段的情况。否则将看不到这个方块实体的物品icon。 |
| destroyed_textures | 可选项。方块实体被破坏时产生的粒子所取样的贴图贴图的路径定义resource_pack/textures/terrain_texture.json文件中。方块被破坏时粒子的取样贴图按照如下优先顺序来决定<br /> 1destroyed_textures (2) block_icon (3) netease_model里面的贴图 4textures字段<br /> 即1有定义就优先使用11没有定义就使用2如此类推。 |
通过以上步骤的配置,我们就可以实现一个具有动画效果的方块实体了:
![动画实体](./picture/customblock/model-7-3.gif)
### 4. 使用接口来控制动画及调整模型
我们为用户提供了一些可用的接口来调整模型的大小,旋转及相对位置,也提供了一些用于控制动画播放的接口。这些接口可以在<a href="../../../../mcdocs/1-ModAPI/接口/方块/索引.html" rel="noopenner"> **技术手册-ModAPI-方块** </a>中查看。
| 接口 | 所属端 | 用处 |
| ------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------ |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentitymodelposoffset" rel="noopenner"> SetBlockEntityModelPosOffset </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体的实体模型位置偏移值。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentitymodelrotation" rel="noopenner"> SetBlockEntityModelRotation </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体的实体模型在各个轴上的旋转值。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentitymodelscale" rel="noopenner"> SetBlockEntityModelScale </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体的实体模型大小的缩放值。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#setenableblockentityanimations" rel="noopenner"> SetEnableBlockEntityAnimations </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置是否开启自定义方块实体的动画效果。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#setblockentitymolangvalue" rel="noopenner"> SetBlockEntityMolangValue </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体的Molang变量。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#getblockentitymolangvalue" rel="noopenner"> GetBlockEntityMolangValue </a> | <span style="display:inline;color:#7575f9">客户端</span> | 获取自定义方块实体的Molang变量的值。 |
## 为自定义方块实体添加特效功能
在这一节,我们将讲述如何为方块实体添加特效功能。特效功能分为网易版特效以及微软原版特效。
### 添加网易版特效
#### 1. 准备粒子特效或者序列帧特效文件
这一步用户可以参考[粒子特效制作](../../../16-美术/9-特效/30-中国版特效创建与使用.md#制作一个中国版粒子特效)或者[序列帧特效制作](../../../16-美术/9-特效/30-中国版特效创建与使用.md#制作一个中国版序列帧特效)进行特效制作。
- 粒子特效资源中的json文件放于resource_pack/effects目录下贴图文件放于resource_pack/textures/particle目录下。
- 序列帧特效支持使用由Texture Packer导出的贴图和json序列帧文件也支持使用由MC Studio导出的序列帧json文件。如果是由Texture Packer导出的贴图和json序列帧文件均放在resource_pack/textures/sfx目录下。如果是由MC Studio导出的序列帧json文件则放于resource_pack/effects目录下。
#### 2. 配置粒子特效或者序列帧特效
与实体模型的配置相同特效的配置同样在resource_pack/blocks.json文件中进行配置。
在resource_pack/blocks.json文件中找到我们想要对其添加特效的方块实体在这里我们同样是”customblocks:custom_block_squirrel”并加入“netease_particle_effects”的字段或者是“netease_frame_effects”的字段表示这个方块实体将会用到特效如下所示
```json
{
"format_version": [
1,
1,
0
],
///...
"customblocks:custom_block_squirrel": {
"sound": "grass",
// 可与netease_model一起使用
"netease_model": "customblocks:customblocks_model_decoration",
// --- 实体模型配置 ---
// 这个方块实体将会使用到实体模型
"client_entity": {
// 对应custom_block_squirrel.entity.json里面的identifier
"identifier": "customblocks:custom_block_squirrel",
// 这个方块实体的手持模型或掉落时模型是否使用该实体模型。
"hand_model_use_client_entity": true,
// 这个方块实体的物品icon贴图
"block_icon": "test_block_icon",
// 方块实体被破坏时使用的贴图
"destroyed_textures":"destroy_squirrel"
},
// --- 特效配置 ---
// 使用网易粒子特效
"netease_particle_effects": {
// 粒子特效
"particle1": { "path": "effects/xy_electro_fpA_gangqinlizu.json", "pos": [1.0,0.5,1.0]},
"particle2": { "path": "effects/yx_electro_fpA_02.json", "pos": [-1.0,0.5,-1.0]}
//... 可以定义多个,注意性能消耗
},
// 使用网易序列帧特效
"netease_frame_effects": {
// 序列帧特效
"frame1": { "path": "effects/yx_electro_fzb_waiquan2.json", "pos": [1.0,1.0,1.0]},
"frame2": { "path": "textures/sfx/zhishujie_fz01", "pos": [-1.0,1.0,-1.0]}
//... 可以定义多个,注意性能消耗
}
},
///...
}
```
粒子特效或者是序列帧特效,我们使用以下格式来配置:
```json
"particle1": { "path": "effects/xy_electro_fpA_gangqinlizu.json", "pos": [1.0,0.5,1.0]}
```
其中,
- "particle1": 特效的自定义键值名称,可由用户自由决定
- "path"特效的相对路径位置对于粒子特效则该路径应该是以”effects/”开头的相对路径。对于序列帧特效,有两种情况:
1由Texture Packer导出的序列帧特效则是以“textures/“开头的相对路径,并且不需要添加.json后缀名。
2由MC Studio导出的json文件则是以”effects/”开头的相对路径,并且需要添加.json后缀名。
- "pos": 该特效的位置,是相对于方块实体位置的位置偏移,即以方块实体位置为原点的坐标系下的坐标。
通过以上两个步骤的配置,我们就可以为方块实体添加粒子特效以及序列帧特效了:
![动画实体](./picture/customblock/model-7-4.gif)
#### 3. 使用接口来控制粒子及序列帧特效
我们提供了一些接口来供用户进行方便的特效添加、删除及调整功能。这些接口可以在<a href="../../../../mcdocs/1-ModAPI/接口/方块/索引.html" rel="noopenner"> **技术手册-ModAPI-方块** </a>中查看。
同时用户可以通过定义好的特效键值名称获取在自定义方块实体上创建好的特效Id利用这个Id用户可以使用<a href="../../../../mcdocs/1-ModAPI/接口/特效/粒子.html" rel="noopenner"> **技术手册-ModAPI-特效-粒子** </a>中的粒子系列接口及<a href="../../../../mcdocs/1-ModAPI/接口/特效/序列帧.html" rel="noopenner"> **技术手册-ModAPI-特效-序列帧** </a>中的序列帧系列接口进行特效的一系列操作。
**序列帧**
| 接口 | 所属端 | 用处 |
| ------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------ |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#createframeeffectforblockentity" rel="noopenner"> CreateFrameEffectForBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 在自定义方块实体上创建序列帧特效创建后该接口返回序列帧特效的Id。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#getframeeffectidinblockentity" rel="noopenner"> GetFrameEffectIdInBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 获取在自定义方块实体中已创建的指定序列帧特效的Id。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#removeframeeffectinblockentity" rel="noopenner"> RemoveFrameEffectInBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 移除在自定义方块实体上创建的序列帧特效。移除后的特效Id将会失效。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentityframeposoffset" rel="noopenner"> SetBlockEntityFramePosOffset </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体中序列帧特效位置偏移值,用于调整序列帧特效相对于方块位置的偏移。 |
**粒子**
| 接口 | 所属端 | 用处 |
| ------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------ |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#createparticleeffectforblockentity" rel="noopenner"> CreateParticleEffectForBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 在自定义方块实体上创建粒子特效创建后该接口返回粒子特效的Id。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#getparticleeffectidinblockentity" rel="noopenner"> GetParticleEffectIdInBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 获取在自定义方块实体中已创建的指定粒子特效的Id。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/方块实体.html#removeparticleeffectinblockentity" rel="noopenner"> RemoveParticleEffectInBlockEntity </a> | <span style="display:inline;color:#7575f9">客户端</span> | 移除在自定义方块实体上创建的粒子特效。移除后的特效Id将会失效。 |
| <a href="../../../../mcdocs/1-ModAPI/接口/方块/渲染.html#setblockentityparticleposoffset" rel="noopenner"> SetBlockEntityParticlePosOffset </a> | <span style="display:inline;color:#7575f9">客户端</span> | 设置自定义方块实体中粒子特效位置偏移值,用于调整粒子特效相对于方块位置的偏移。 |
### 添加微软原版粒子特效及音效
微软动画功能支持在动画控制器json文件中或者动画json文件中配置粒子特效或者音效。自定义方块实体外观功能同样也支持这种配置方式。
有一定外语阅读能力的用户,可以查看[原版wiki](https://wiki.bedrock.dev/visuals/custom-particles.html)来了解关于在实体动画控制器或动画中定义粒子特效和音效的方式。
#### 1. 使用原版粒子
原版粒子的资源可以采用游戏自带的粒子资源,也可以进行自行制作,游戏自带的粒子资源可参考[Wiki中对Particles部分](https://wiki.bedrock.dev/documentation/particles.html)的罗列。自定制作的方法也可参考[这个Wiki中的介绍](https://wiki.bedrock.dev/visuals/custom-particles.html)。本指引在这里就不再叙述。
制作好的粒子资源可在游戏中使用
```
/particle <namespace:particle_id> ~ ~2 ~
```
该指令来测试是否生效。
当拥有了一些粒子资源后我们就需要在entitiy.json文件中进行声明以及在animation_controllers.json文件中进行配置。配置的方式实际上与在生物实体中配置原版粒子的方法相同如果用户对这部分的内容熟悉就可以跳过这部分的指引。
以resource_pack/entity/custom_block_squirrel.entity.json为例我们在现有的基础上增加一个particle_effects的组件
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
// 自定义方块实体的identitfier
"identifier": "customblocks:custom_block_squirrel",
/// ... 省略中间的文件内容
// 该模型包含的动画general为动画控制器定义在resource_pack/animations_controllers目录下
// move,idle,look_at_target为动画定义在resource_pack/animations目录下
"animations": {
"move": "animation.squirrel.move",
"idle": "animation.squirrel.idle",
"general": "controller.animation.squirrel.general"
},
// 该模型所包含的微软原版粒子
"particle_effects": {
"headsmoke": "minecraft:water_fog"
}
}
}
}
```
并添加了一个键值为headsmoke的粒子粒子使用的是粒子资源minecraft:water_fog。
接着我们使用BlockBench对模型添加一个名为head_locator的Locator定位器来决定我们的粒子在模型中的位置我们可以对模型的head组件右键点击添加定位器导出保存即可
![动画实体](./picture/customblock/model-7-9.png)
有了定位器及粒子定义后我们就可以打开animation_controllers.json文件来决定我们的粒子在哪个动画状态进行播放了
以squirrel.animation_controllers.json为例我们对default动画状态配置这个粒子在default动画状态中添加一个名为particle_effects的序列
```json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.squirrel.general": {
"initial_state" : "default",
"states": {
// 默认待机动画状态
"default": {
"animations": [ "idle" ],
// 该动画状态所播放的原版粒子效果
"particle_effects": [
{
// entity.json中定义的粒子名称
"effect": "headsmoke",
// geometry中定义的定位器
"locator": "head_locator"
}
//,
//... 可配置多个原版粒子
],
"transitions": [
// 由实体Molang变量"variable.mod_is_moving"控制动画状态切换初始值在entity.json中的sripts字段中进行定义。
{ "squMove": "variable.mod_is_moving==1" }
]
}
///, ... 其他动画状态
}
}
}
}
```
至此,我们就完成了一个微软原版粒子效果的配置了。
另外粒子的配置不仅可以在animation_controllers.json中进行配置也可以直接在对应的动画文件animations.json中进行配置。
以squirrel.animation.json为例我们直接对idle动画进行粒子配置配置方式是在动画定义中添加一个particle_effects的序列同时以动画时间为键值来决定我们的粒子效果在动画播放到什么时候进行播放
```json
{
"format_version": "1.8.0",
"animations": {
"animation.squirrel.idle": {
"loop": true,
"animation_length": 2,
"bones": {
/// ... 省略骨骼内容
},
/// 原版粒子
"particle_effects": {
/// 在0.4833这个动画帧播放粒子效果
"0.4833": {
// entity.json中定义的粒子名称
"effect": "headsmoke",
// geometry中定义的定位器
"locator": "head_locator"
}
}
}
}
```
#### 2.使用原版音效
音效的定义及配置方式实际上与原版粒子特效的方式类似,用户也可以参考这个[指引](https://wiki.bedrock.dev/concepts/sounds.html)来进行。
我们首先需要在resource_pack/sounds/sound_definitions.json定义好我们的音效如果没有这个json文件则需要自己创建。它的内容如下
```json
{
"format_version": "1.14.0",
"sound_definitions": {
// 定义一个自定义音效
"squirrel.idle.thunder": {
"category": "music",
"min_distance": 0.0,
"max_distance": 5.0,
"sounds": [
{
"name": "sounds/music/blocks",
"pitch": 1,
"volume": 1,
"load_on_low_memory": true
}
]
}
}
}
```
在这个文件中我们定义了一个名叫squirrel.idle.thunder的自定义音效。
接下来与原版粒子特效的配置类似我们需要在entity.json文件中声明这个音效
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
// 自定义方块实体的identitfier
"identifier": "customblocks:custom_block_squirrel",
/// ... 省略中间的文件内容
// 该模型包含的动画general为动画控制器定义在resource_pack/animations_controllers目录下
// move,idle,look_at_target为动画定义在resource_pack/animations目录下
"animations": {
"move": "animation.squirrel.move",
"idle": "animation.squirrel.idle",
"general": "controller.animation.squirrel.general"
},
// 该模型所包含的微软原版粒子
"particle_effects": {
"headsmoke": "minecraft:water_fog"
},
// 该模型所包含的自定义音效
"sound_effects": {
"thunder": "squirrel.idle.thunder"
}
}
}
}
```
在entity.json中声明了该音效之后我们就可以在animation_controllers.json或者animations.json中使用这个音效了。
注意format_version为1.8.0的版本的animation_controller.json**不支持**sounds_effects组件的配置否则会报错。用户需要改成1.10.0的版本。
以squirrel.animation_controllers.json为例我们对default动画状态配置这个音效实际就是增加一个"sound_effects"的序列:
```json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.squirrel.general": {
"initial_state" : "default",
"states": {
// 默认待机动画状态
"default": {
"animations": [ "idle" ],
// 该动画状态所播放的原版粒子效果
"particle_effects": [
{
// entity.json中定义的粒子名称
"effect": "headsmoke",
// geometry中定义的定位器
"locator": "head_locator"
}
//,
//... 可配置多个原版粒子
],
// 该动画状态所播放的自定义音效
"sound_effects": [
{
// 使用thunder这个自定义音效
"effect": "thunder"
}
],
"transitions": [
// 由实体Molang变量"variable.mod_is_moving"控制动画状态切换初始值在entity.json中的sripts字段中进行定义。
{ "squMove": "variable.mod_is_moving==1" }
]
}
///, ... 其他动画状态
}
}
}
}
```
以squirrel.animation.json为例我们直接对idle动画进行音效配置配置方式与粒子特效也类似。注意format_version为1.8.0的版本的animations.json**支持**sounds_effects组件的配置。
```json
{
"format_version": "1.8.0",
"animations": {
"animation.squirrel.idle": {
"loop": true,
"animation_length": 2,
"bones": {
/// ... 省略骨骼内容
},
/// 原版粒子
"particle_effects": {
/// 在0.4833这个动画帧播放粒子效果
"0.4833": {
// entity.json中定义的粒子名称
"effect": "headsmoke",
// geometry中定义的定位器
"locator": "head_locator"
}
},
/// 自定义音效
"sound_effects": {
"0.4833": {
"effect": "thunder"
}
}
}
}
```
至此,我们就完成了自定义音效的配置。

View File

@@ -0,0 +1,295 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义方块模型
## 概述
下面将按照[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)示例中的三个自定义模型方块由浅入深讲述如何借助BlockBench以及MCStudio搭建自定义方块的模型。
## 从零开始制作方块模型 - 小蓝花
手把手指导如何制作[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)示例中的小蓝花customblocks_model_flower
在示例中的`resource/bbmodel/flower`中提供了小蓝花的工程文件。
### 使用BlockBench制作模型
1. 找个地方新建一个文件夹作为工作路径,并准备好小蓝花的贴图
![image-20200713141928885](./picture/customblock/model-a-0.png)
1. 打开blockbench这里使用的版本为3.3.1)。
在File->Settings->General可设置为中文重启blockbench生效。
<img src="./picture/customblock/model-0--1.png" alt="image-20200304174000311" style="zoom:67%;" />
1. 新建一个“自由模型”项目,填写文件名以及几何体名称。
盒子UV不要勾选贴图长宽最大不能超过64。在下面示例中我们使用16x16的贴图。
![image-20200713142240647](./picture/customblock/model-a-1.png)
1. 游戏里一个方块的大小对应为16 x 16 x 16即面板上网格的大小。网格上的N标识了北面的朝向
![image-20200713143140863](./picture/customblock/model-a-2.png)
1. 为了避免光照影响预览,可以打开文件->设置->预览,把“阴影”去掉
<img src="./picture/customblock/model-0-3-1.png" alt="image-20200304174348146" style="zoom:67%;" />
1. 打开文件->设置->默认把“自动UV“勾上这样调整cube大小时各个面的uv大小也会自动跟着调整
<img src="./picture/customblock/model-0-3-2.png" alt="image-20200304174844623" style="zoom:67%;" />
1. 将小蓝花贴图拖进来
![image-20200713143419975](./picture/customblock/model-a-3.png)
1. 添加一个cube调整其大小位置及旋转使其的north面位于16 x 16网格的对角线上
![image-20200713143645975](./picture/customblock/model-a-4.png)
1. 选择北面然后把小蓝花贴图拖上去。这样这个cube的北面就应用了小蓝花贴图
![image-20200713144036430](./picture/customblock/model-a-5.png)
1. 点击插件目录-移除空白面。这样这个cube就会只显示北面
![image-20200713144141391](./picture/customblock/model-a-6.png)
1. 重复上面三步,添加另一个垂直的面片
![image-20200304210159699](./picture/customblock/model-0-7.png)
1. 点击文件-保存工程,保存到我们刚才放贴图的路径。
![image-20200713144454174](./picture/customblock/model-a-7.png)
### 使用MCStudio导入模型
1. 打开MCStudio新建一个AddOn或者导入已有的然后启动编辑
![image-20200714115027639](./picture/customblock/model-a-8.png)
1. 设置好命名空间
![image-20200714141322104](./picture/customblock/model-a-11.png)
1. 在资源管理器中选择导入方块模型
![image-20200714115834234](./picture/customblock/model-a-9.png)
1. 选择我们刚才保存的BlockBench工程文件
![image-20200714120055068](./picture/customblock/model-a-10.png)
这一步导入的背后MCStudio做了这些操作
* 将bbmodel工程文件转换为自定义方块模型格式的json并放到`resourcepack/models/netease_block`
* 将贴图拷贝到了`resourcepack/textures/blocks`
* 将贴图配置到了`resourcepack/textures/terrain_texture.json`
### 配置其他需要的文件
MCStudio帮我们做了一些工作接下来还有几个文件需要手动配置
1. 编写behavior的定义
<img src="./picture/customblock/model-0--2.png" alt="image-20200304213457975" style="zoom:67%;" />
2.`resourcepack/blocks.json`中,添加该方块
<img src="./picture/customblock/model-0-11.png" alt="image-20200304212134086" style="zoom:80%;" />
其中使用“netease_model”配置为`resourcepack/models/netease_block`中生成的模型json的identifier。
![image-20200714145835565](./picture/customblock/model-a-12.png)
3. 完成一个自定义模型方块所涉及的路径汇总:
<img src="./picture/customblock/model-0-12.png" alt="image-20200304220109659" style="zoom:67%;" />
## 制作更复杂的模型 - 装饰品
大致流程与小蓝花类似比较重复的内容不再赘述不同之处只在于blockbench中的操作。
这里讲述当单张16x16贴图不足以满足需求时如何制作具有多张贴图的模型以及uv翻转及uv旋转的使用
**注意我们使用多张16x16贴图来解决贴图大小的需求而不是使用高分辨率的贴图**
在[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)示例中的`resource/bbmodel/decoration`中提供了装饰品的工程文件。
### 多贴图模型
对一些比较复杂的模型单张16x16的贴图不够用时可以把不同的骨骼立方体或者面绘制到多张贴图上。
1. 新建一个自由模型的工程搭好骨骼与cube
![image-20200714161411832](./picture/customblock/model-a-14.png)
2. 新建一个工作目录准备好要用到的贴图并且全部拖进BlockBench。
![image-20200714161536270](./picture/customblock/model-a-13.png)
3. 给每个cube的每个面配置UV
熟悉BlockBench的开发者也可以使用右上角的画板模式来绘制方块模型
![image-20200714161947428](./picture/customblock/model-a-15.png)
### uv的翻转与旋转
可以直接使用BlockBench的UV旋转以及UV镜像功能。贴图的右上角会显示该面使用的旋转与翻转。
![image-20200714195619078](./picture/customblock/model-a-16.png)
## 制作可变化的模型 - 电线
大致流程与小蓝花类似比较重复的内容不再赘述不同之处只在于blockbench中的操作对导出模型json的调整以及behavior中方块json的定义。
这里讲述如何制作会随周围方块不同而发生改变的模型。
在[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)示例中的`resource/bbmodel/wire`中提供了电线的工程文件。
1. 在behavior的定义中使用[netease:connection](./1-JSON组件#netease:connection)配置与其他方块的“连接”属性
示例中的电线,与熔炉,草方块,以及电线自身具有“连接"属性
![image-20200308121341271](./picture/customblock/model-3-1.png)
2. 分析电线的效果:当六个方向都没有可连接的方块时,只显示一个中间小方块;当某个方向上的方块可以连接时,则从中间”长“出一个长方体与其连接。
<img src="./picture/customblock/model-3-.png" alt="image-20200308122302847" style="zoom:67%;" />
3. 那么当六个方向都有可连接的方块时电线的模型将由一个中心正方体六个长方体构成。于是在blockbench中将他们搭好。这里为了显示出层次感把设置中的“阴影”启用了
![image-20200714195941072](./picture/customblock/model-a-17.png)
4. 如果细心观察可以发现,那六个长方体中的每一个,都会有其中两个面是永远看不到的,可以进行优化,把他们设置为透明。跳过这一步不会影响实际效果,但还是推荐开发者们进行性能优化。
![image-20200714200050901](./picture/customblock/model-a-18.png)
5. 使用MCStudio导入后打开`resourcepack/models/netease_block`中导出的json在六个长方体的骨骼中添加enable字段该字段的详细解释见[模型文件结构](#模型文件结构)
<img src="./picture/customblock/model-3-4.png" alt="image-20200308172042542" style="zoom:67%;" />
6. 示例中将中间root骨骼的正方体手动拆成了六个骨骼每个骨骼分别只有其中的一个面。这是因为如果某些方向连接了其他方块时中间正方体的某些面是看不到的不需要渲染。跳过这一步不会影响实际效果但还是推荐开发者们进行性能优化。
![image-20200308172753618](./picture/customblock/model-3-5.png)
7. 额外制作一张用于物品形式渲染的贴图并配置到模型json中。
对于可变模型物品形式下具有enable条件的骨骼都不会绘制一般需要使用单独的物品贴图。
![image-20200308180112542](./picture/customblock/model-3-8.png)
![image-20200308180201587](./picture/customblock/model-3-7.png)
8. 开启环境光遮蔽,可以与自身相连的方块模型一般需要开启,可以改善在室内或夜晚时,相邻方块亮度不一样时的情况。
<img src="./picture/customblock/model-3-9.png" alt="image-20200308181036127" style="zoom:67%;" />
9. 在behavior的方块json中将aabb同样拆分为中间一个正方体以及周围的六个长方体。该组件的详细解释见[netease:aabb](./1-JSON组件#netease:aabb)
<img src="./picture/customblock/model-3-6.png" alt="image-20200308175056402" style="zoom:67%;" />
<span name="moxingwenjianjiegou"></span>
## 模型文件结构
- `resource/models/netease_block`中模型json的详细参数解释
| 键 | 类型 | 解释 |
| ---------------------- | ------ | -------------------------------------------- |
| format_version | string | 目前为1.13.0对应blockbench 3.3.1及以上版本 |
| netease:block_geometry | object | |
- netease:block_geometry结构
| 键 | 类型 | 解释 |
| ----------- | ------------- | ---------------------- |
| description | object | 模型的基本信息 |
| bones | array(object) | 模型的骨骼及立方体信息 |
- description结构
| 键 | 类型 | 解释 |
| --------------------- | ------------- | ------------------------------------------------------------ |
| identifier | string | 模型的标识符,建议使用命名空间加名称的方式命名 |
| textures | array(string) | 该模型用到的贴图与terrain_texture.json中对应 |
| item_texture | string | 可选<br>该方块的物品形态的贴图与terrain_texture.json中对应。<br>配置了该项时手持、UI物品格子、掉落物等物品形态使用该贴图渲染而非方块模型 |
| use_ao | bool | 可选,是否启用环境光遮蔽。<br>启用时方块的亮度会更加自然,但总体会比不启用时要暗一点<br>默认不开启 |
| textures_descriptions | array(dict) | 每张模型贴图的实际分辨率的长和宽配置长宽最大不能超过64超过则会使用64。与textures数组中的同一下标位置的贴图一一对应。即第一张贴图的长宽配置为"textures_descriptions"中第一个长宽对,第二张贴图的长宽配置对应"textures_descriptions"中第二个长宽对如此类推。如果textures中定义的贴图没有在"textures_descriptions"找到对应的贴图长宽配置则会使用默认值width = 16 length = 16。<br/>填写示例:<br/>`"textures_descriptions":[ { "width": 32, "length":32} , { "width": 64, "length":64} , { "width": 16, "length":16} ]`<br/>**width和length的值请根据贴图的实际分辨率进行填写。** |
- bones每个元素的结构
除了texture及enable项需要另外配置其余均可使用blockbench生成。
| 键 | 类型 | 解释 |
| -------- | ------------- | ------------------------------------------------------------ |
| name | string | 该骨骼的名称 |
| parent | string | 父骨骼的名称 |
| pivot | array(float) | 该骨骼的旋转中心 |
| rotation | array(float) | 该骨骼绕旋转中心的旋转 |
| texture | int | 可选<br>该骨骼使用的贴图对应description中textures数组的下标。<br>默认为0 |
| enable | molang | 可选。控制该骨骼是否渲染。默认返回true<br>目前仅支持is_connect查询详见[netease:connection](./1-JSON组件.md#netease_connection) |
| cubes | array(object) | 该骨骼所包含的立方体的信息 |
- cubes每个元素的结构
除了texture需要另外配置其余均可使用blockbench生成。
| 键 | 类型 | 解释 |
| -------- | ------------ | ------------------------------------------------------------ |
| origin | array(float) | 该立方体最小点的位置 |
| size | array(float) | 该立方体的大小 |
| pivot | array(float) | 该立方体的旋转中心 |
| rotation | array(float) | 该立方体绕旋转中心的旋转 |
| texture | int | 可选。该立方体使用的贴图对应description中textures数组的下标。<br>缺省时会继承所在骨骼使用的贴图 |
| uv | object | 该立方体包含的面的信息<br>可选的面包括updownnorthsouthwesteast<br>可以只选其中若干个面渲染。 |
- uv中每个元素的结构
除了texture需要另外配置其余均可使用blockbench生成。
| 键 | 类型 | 解释 |
| ------- | ---------- | ------------------------------------------------------------ |
| uv | array(int) | 起始uv坐标 |
| uv_size | array(int) | uv的大小 |
| texture | int | 可选。该立方体使用的贴图对应description中textures数组的下标。<br/>缺省时会继承所在立方体使用的贴图 |
| rot | int | 将uv顺时针旋转的角度<br>可选90180270 |
## 注意事项
- 目前每张贴图尺寸不能超过64x64
- **[特殊方块](./3-特殊方块/0-特殊方块概述.md)不支持自定义方块模型**(农作物除外)
- **使用模型的方块支持[netease:face_directional](./1-JSON组件.md#netease_face_directional)中的四面向,但不支持六面向**。当使用多面向时is_connect查询会根据当前的面向自动匹配
- 使用自定义方块模型时,需要配合[minecraft:block_light_absorption](./1-JSON组件.md#minecraft_block_light_absorption)使用,否则模型会变黑
- 需要用到全透明或半透明时,可配合[netease:render_layer](./1-JSON组件.md#netease_render_layer)使用,但是属性会应用到整个模型
- 请勿将自定义模型方块用于自定义群系的构成中,也避免在频繁出现的自定义特征中放入大量自定义模型方块
- 立方体不支持inflate功能
![image-20200309171920798](./picture/customblock/model-4-1.png)

View File

@@ -0,0 +1,15 @@
---
front:
hard: 入门
time: 分钟
---
# 常见报错
1. JSON: xxx has an error
一般为json格式有问题可以检查一下逗号是否漏写或多写括号是否对应。
下图为多写逗号的报错:
![error-1](./picture/customblock/error-1.png)

View File

@@ -0,0 +1,94 @@
---
front:
hard: 入门
time: 分钟
---
# demo解释
[CustomBlocksMod](../../13-模组SDK编程/60-Demo示例.md#CustomBlocksMod)中定义了以下自定义方块:
- customblocks:customblocks_test0
上表面与其他面不同的方块。
`resource/blocks.json`中将isotropic的up设置为true使其上表面在放置时会随机旋转可以达到视觉上没有明显的贴图重复的效果属于微软自定义方块的功能
演示了构成自定义群系,村民交易,自定义配方,方块组合的功能
- customblocks:customblocks_test_ore
性质与矿物相似的自定义方块
演示了挖掘,掉落物的功能
- customblocks:customblocks_test_face4
拥有4个面向的方块
演示了多面向中四面向的功能
- customblocks:customblocks_test_face6
拥有6个面向的方块
演示了多面向中六面向的功能
- customblocks:customblocks_test_mobspawner
自定义刷怪箱方块-原生生物
演示了“特殊方块-自定义刷怪箱”中生成原生生物的功能
- customblocks:customblocks_test_mobspawner1
自定义刷怪箱方块-微软自定义生物
演示了“特殊方块-自定义刷怪箱”中生成微软自定义生物的功能
- customblocks:customblocks_test_portal_blue
前往维度3的自定义传送门方块
演示了“特殊方块-自定义传送门方块”的功能
- customblocks:customblocks_test_block_entity<span id="demo解释_block_entity"></span>
含自定义方块实体的自定义方块
演示了自定义方块实体相关功能,详细解释见[自定义方块实体](./4-自定义方块实体.md#demo)文档
- customblocks:customblocks_model_flower
花形状的自定义方块
演示了自定义方块模型,亮度,碰撞盒,渲染材质,是否实心,是否可寻路的功能
- customblocks:customblocks_flower_extend
除了涵盖customblocks_model_flower花形状的自定义方块的基本功能外额外拓展了实体穿过时减速、重力方块下落时被破坏等功能。
- customblocks:customblocks_model_decoration
四面向的使用自定义模型的方块
- customblocks:customblocks_model_wire
电线形状的自定义方块,可与旁边的其他电线,熔炉或草方块相连
演示了可变模型与可变碰撞箱
- customblocks:customblocks_test_heavy
演示了自定义重力方块
- customblocks:customblocks_slime
利用netease:block_properties组件和python事件复刻了一个原版粘液块特性
演示了自定义实体方块外观功能
- customblocks:custom_block_squirrel
包含了自定义实体方块的实体模型配置,网易版粒子、序列帧特效、微软原版粒子特效及音效配置。

Some files were not shown because too many files have changed in this diff Show More