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,819 @@
---
front:
hard: 入门
time: 分钟
---
# 自定义生物
## 1.概述
自定义生物涉及材质material、贴图texture、模型model、几何建模geometry、动画animation、动画控制器animation controller和渲染控制器render controller等概念在阅读本文档时希望你对这些专业名词有所了解。
开发者可以通过在addon中配置json来添加自定义生物添加的自定义生物支持“MOD SDK文档”中与生物/实体相关的所有事件与接口。
下面将通过定义一个松鼠squirrel来展现如何定义一个生物。详见示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)
<img src="./picture/customentity/squirrel_entity.png" alt="zombie" style="zoom:100%;" />
自定义的松鼠包括以下json文件
* behavior_pack/entities/squirrel.json 服务端实体定义
* resource_pack/entity/squirrel.entity.json 客户端实体定义
* resource_pack/animations/squirrel.animation.json 动画定义
* resource_pack/animation_controllers/squirrel.animation_controllers.json 动画控制器定义
* resource_pack/models/entity/squirrel.geo.json 模型定义
* resource_pack/render_controllers/squirrel.render_controllers.json 渲染控制器定义
* resource_pack/textures/entity/squirrel/red.png 贴图
* resource_pack/textures/entity/squirrel/gray.png 贴图
* resource_pack/materials/entity.material 材质
下图是上述文件之间的关系图:
<img src="./picture/customentity/squirrel.png" alt="zombie" style="zoom:100%;" />
## 2. 行为包实体定义
### 2.1 示例
在行为包behavior_pack/entities目录下增加squirrel.json
```json
{
"format_version": "1.10.0",
"minecraft:entity": {
"description": {
"identifier": "netease:squirrel", #
"is_summonable": true, # 使
"is_spawnable": true, # 使
"runtime_identifier": "minecraft:squirrel" # entity
},
"component_groups": {
"minecraft:color_red": {
"minecraft:type_family": {
"family": [
"red_squirrel",
"squirrel"
]
},
# render_controller
"minecraft:variant": {
"value": 0
}
},
"minecraft:color_gray": {
"minecraft:type_family": {
"family": [
"gray_squirrel",
"squirrel"
]
},
"minecraft:variant": {
"value": 1
}
}
},
"components": {
...
},
"events": {
"minecraft:entity_spawned": {
"sequence": [
{
"randomize": [
{
"weight": 1, #
"add": {
"component_groups": [
"minecraft:color_red"
]
}
},
{
"weight": 1, #
"add": {
"component_groups": [
"minecraft:color_gray"
]
}
}
]
}
]
}
}
}
}
```
创建松鼠时有50%的概率生成红色松鼠另外50%的概率生成灰色松鼠。
### 2.2 components
定义每一种实体独立的行为特性如minecraft:identitier和minecraft:type_family等。
更多的组件介绍请请查阅微软文档https://minecraft-zh.gamepedia.com/基岩版实体组件文档)
**注在2.2以及之后的版本我们对自定义生物的移动流量进行了优化距离玩家较远的生物会出现瞬移的情况如果感觉效果较差可在components手动添加netease:ban_bandwidth_optimization:{}组件来主动关闭此优化**
### 2.3 component_groups
将多个components放在一个集合内便于增加和删除多个components比如实体的boby和adult两个不同的阶段很多属性不同那么就可以在合适的事件中增加或移除对应阶段的component group。
在本例子中定义了红色松鼠minecraft:color_red与灰色松鼠minecraft:color_gray两个分组并且在创建生物进行添加。
### 2.4 事件events
#### minecraft:entity_spawned
触发时机当entity被放置在地图中时
#### minecraft:entity_transformed
触发时机当entity转化为另外一个entity时
#### minecraft:entity_born
触发时机当entity繁殖时
#### minecraft:on_prime
触发时机当entity被点燃将要爆发时
## 3.自定义材质
### 3.1 示例
#### 3.1.1 原生材质
MC原生的材质定义都在"/data/resource_packs/vanilla/materials"下,生物的材质都在这个目录下的"entity.material"文件中。
材质可通过继承达到复用的效果原生材质中常被继承的基础生物材质entity定义如下
```json
"entity:entity_static": { # entity_staticentityentity_static"entity.material"
"+defines": [ "USE_OVERLAY" ], # USE_OVERLAY
"msaaSupport": "Both" # 使MSAA齿
},
```
#### 3.1.2 添加自定义材质
在资源包resource_pack/materials目录下创建json文件entity.material。
```json
{
"materials": {
"version": "1.0.0",
"custom_entity1:entity": { # entitycustom_entity1
"+defines": [ "USE_ONLY_EMISSIVE", "USE_UV_ANIM"] # USE_ONLY_EMISSIVEUSE_UV_ANIM
"-defines": [ "USE_OVERLAY" ], # entity"+defines"USE_OVERLAY使"-defines"USE_OVERLAYentity3.1.1
"msaaSupport": "NonMSAA" # 使MSAA齿
},
"custom_entity2:custom_entity1": { # custom_entity1custom_entity2
"msaaSupport": "Both" # 使MSAA齿
}
}
}
```
在同一目录resource_pack/materials下创建common.json将上面文件路径填入。common.json列出的文件才会被正确读取作为自定义材质。
```python
[
{"path":"materials/entity.material"}
]
```
在自定义生物的资源包实体定义中添加以下字段使用上述自定义材质。
```json
{
"format_version": "1.8.0",
"minecraft:client_entity": {
"description": {
"identifier": "netease:squirrel",
"min_engine_version": "1.8.0",
"materials": {
"default": "custom_entity1", #
"charged": "custom_entity2" # charged使使SDK使default()
},
...
}
}
}
```
注:
- 生物默认使用key值为default的材质,因此在需要修改生物材质时,使用类似如下的接口:
```
# 把松鼠的渲染材质修改为custom_entity2
import mod.client.extraClientApi as clientApi
comp = clientApi.GetEngineCompFactory().CreateActorRender(levelId)
comp.AddActorRenderMaterial('netease:squirrel', 'default', 'custom_entity2')
comp.RebuildActorRender('netease:squirrel')
```
- 目前SDK暂不支持设置生物的材质key值如"把key值从default修改为charged",因此一般使用default字段即可
### 3.2 字段说明
#### 3.2.1 宏定义defines
MC渲染器在不同的宏定义下会采取不同的策略因此这些宏定义类似开关式的配置选项。通过"+defines""-defines"可在继承的材质的基础上添加或者去掉对应的宏定义,支持的宏定义如下:
```
ALPHA_TEST
COLOR_SECOND_TEXTURE
COLOR_BASED
DISABLE_TINTING
FANCY
ENABLE_FOG
ENABLE_LIGHT
GLINT
ITEM_IN_HAND
MULTI_COLOR_TINT
MULTIPLICATIVE_TINT
NO_TEXTURE
TINTED_ALPHA_TEST
UI_ENTITY
USE_COLOR_MASK
USE_EMISSIVE
USE_MULTITEXTURE
MASKED_MULTITEXTURE
USE_ONLY_EMISSIVE
USE_OVERLAY
USE_SKINNING
USE_UV_ANIM
```
#### 3.2.2 其他字段
材质除了宏定义这类开关形式的配置外还支持其他如字符串形式的配置如示例中的”msaaSupport“可在“NonMSAA”“MSAA”“Both”选择一个作为配置的值。自定义材质支持的各种配置如下
| 字段名 | 待选值 | 描述 |
| ---------------- | ------------------------------------------------------------ | ------------- |
| msaaSupport | NonMSAAMSAABoth | MSAA抗锯齿 |
| depthFunc | AlwaysEqualNotEqualLessGreaterGreaterEqualLessEqual | 深度测试 |
| blendSrc | DestColorSourceColorZeroOneOneMinusDestColorOneMinusSrcColorSourceAlphaDestAlphaOneMinusSrcAlpha | blend混合模式 |
| blendDst | 同上 | blend混合模式 |
| vertexShader | 一般使用“shaders/entity_hide.vertex”即可 | 顶点着色器 |
| vrGeometryShader | 一般使用“shaders/entity.geometry”即可 | 几何着色器 |
| fragmentShader | 一般使用“shaders/entity_hide.fragment“即可 | 片元着色器 |
## 4. 自定义动画
自定义的动画应该放在resource_pack根目录下的animations文件夹内。
动画是基于旋转角度、位置和大小的变化的帧动画。
开发者可以引用vanilla的动画或者创建自定义的动画。
可以通过blockbench制作动画。
#### 4.1 示例
resource_pack/animations/squirrel.animation.json
```python
{
"format_version": "1.8.0",
"animations": {
"animation.squirrel.idle": {
"loop": true,
"animation_length": 2,
"bones": {
"rearFootLeft": {
"rotation": {
"0.0": [0, 0, 0],
"0.4833": [15, 0, 0],
"1.6": [10, 0, 0],
"1.8833": [-10, 0, 0],
"2.0": [0, 0, 0]
}
},
...
}
},
"animation.squirrel.move": {
"loop": true,
"animation_length": 0.48,
"bones": {
"rearFootLeft": {
"rotation": {
"0.0": [5, 0, 0],
"0.1667": [125, 0, 0],
"0.4333": [5, 0, 0]
}
},
...
}
}
}
}
```
#### 4.2 说明
该动画有2种动作分别是空闲idle、移动move
## 5. 自定义动画控制器
自定义动画控制器应该放在resource_pack/animation_controllers目录下。
动画控制器被用来控制动画如何转换何时进行转换。每一个动画控制器包含多个状态states每一个state播放一个或者多个动画。
自定义的动画控制器可以引用vanilla中的动画如示例中的look_at_target。
#### 5.1 示例
resource_pack/animation_controllers/squirrel.animation_controllers.json
```json
{
"format_version": "1.8.0",
"animation_controllers": {
"controller.animation.squirrel.general": {
"initial_state" : "default",
"states": {
"default": {
"parameters": [ "query.ground_speed" ],
"animations": [
...
],
"transitions": [
{ "move": "query.mod.is_moving" }
]
},
"move": {
"parameters": [ "query.ground_speed" ],
"animations": [
...
],
"transitions": [
{ "default": "!query.mod.is_moving" }
]
}
}
}
}
}
```
默认动画为defaultdefault中使用idle和look_at_target动画其中look_at_target为vanilla定义的动画。
transitions为动画转移条件当query.mod.is_moving为True时从default转移到move反之从move转移到default。query.mod.is_moving的使用[后面](#molang_node)会讲到。
## 6. 自定义模型
模型定义了实体的几何形状自定义的模型放在resource_pack/models/entity目录下。
可以通过blockbench制作模型。
### 6.1 示例
resource_pack/models/entity/squirrel.geo.json
```json
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.squirrel",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 4,
"visible_bounds_height": 1,
"visible_bounds_offset": [0, 0.5, 0]
},
"bones": [
{
"name": "body",
"pivot": [0, 5, 8],
"rotation": [-20, 0, 0],
"mirror": true,
"cubes": [
{"origin": [-3, 2, -2], "size": [6, 5, 10], "uv": [0, 0], "mirror": false},
{"origin": [-3, 7, 1], "size": [6, 1, 7], "uv": [22, 0], "mirror": false}
]
},
...
]
}
]
}
```
### 6.2 定位器locators
定位器偏移在模块空间中指定。
定位器的例子有 "lead“定位器用于显示指引将附加到何处。
```json
"locators": {
"lead": {
"head": [ 0.0, 14.0, -6.0 ]
}
}
```
## 7. 自定义渲染控制器
渲染控制器负责生物实体的渲染控制流程,包括使用的材质、贴图、几何模型等。
### 7.1 示例
资源包resource_pack/render_controllers目录下增加squirrel.render_controllers.json
```json
{
"format_version": "1.8.0",
"render_controllers": {
"controller.render.squirrel": {
"arrays": {
"textures": {
"Array.base": [
"Texture.red",
"Texture.gray"
]
},
"materials": {
"Array.skin": [
"Material.red",
"Material.gray"
]
}
},
"geometry": "Geometry.default",
"materials": [ { "*": "Array.skin[query.variant]" }],
"textures": ["Array.base[query.variant]"]
},
"controller.render.squirrel_more": {
"materials": [ { "*": "query.mod.is_enchanted ? Material.gray : Material.red" } ],
},
"controller.render.squirrel_multi": {
"materials": [
{ "*": "Material.gray" },
{ "head": "Material.red" }
]
}
}
}
```
说明:
1在controller.render.squirrel_more中对于材质的选用使用python的变量[query.mod.is_enchanted](#molang_node)进行了控制注意Material.gray必须在资源包minecraft:client_entity中进行声明否则渲染时会找不到对应的material。
2在controller.render.squirrel_multi中
首先对模型的所有部件使用材质Material.gray
然后对模型中的head部件使用Material.red
3更多用法请参考微软官方文档
**注意:如果存在多个渲染控制器,其中的渲染顺序并不保证顺序。**
### 7.2 玩家渲染控制器
下面通过举例vanilla玩家的渲染控制器说明渲染控制器。
首先我们看player.entity.json下面一段json:
```json
"render_controllers": [
{ "controller.render.player.first_person": "variable.is_first_person" },
{ "controller.render.player.third_person": "!variable.is_first_person && !variable.map_face_icon" },
{ "controller.render.player.map": "variable.map_face_icon" },
{ "controller.render.player.first_person_bloom": "variable.is_first_person" },
{ "controller.render.player.third_person_bloom": "!variable.is_first_person && !variable.map_face_icon" }
],
```
在render_controllers数组中玩家存在五个渲染控制器。
| 渲染控制器名称 | 渲染控制器应用条件 | 说明 |
| ------------------------------------------- | ---------------------------------------------------- | -------------------------------- |
| controller.render.player.first_person | variable.is_first_person | 第一人称时该渲染控制器生效 |
| controller.render.player.third_person | !variable.is_first_person && !variable.map_face_icon | 非第一人称下同时非地图图标下生效 |
| controller.render.player.map | variable.map_face_icon | 地图图标模式下生效 |
| controller.render.player.first_person_bloom | variable.is_first_person | 第一人称时该渲染控制器生效 |
| controller.render.player.third_person_bloom | !variable.is_first_person && !variable.map_face_icon | 非第一人称下同时非地图图标下生效 |
**其中,以上五个渲染控制器在渲染过程中并不保证顺序。**
## 8.资源包实体定义
### 8.1 概述
客户端实体client_entity的定义在resource_pack当中。
在resource_pack目录下创建文件夹“entity”然后在该文件夹中创建json文件如squirrel.entity.json此json文件需要一个“format_version”和“minecraft:client_entity”的信息。
其中“minecraft:client_entity”部分只包含一个节点descriptiondescription下包含一些实体的详细定义一般而言都会包括材质、贴图、动画、几何、渲染控制器等部分。
### 8.2 示例
resource_pack/entity/squirrel.entity.json
```json
{
"format_version": "1.8.0",
"minecraft:client_entity": {
"description": {
"identifier": "netease:squirrel",
"spawn_egg":{
"base_color":"#1778D2",
"overlay_color":"#1778D2"
},
"render_controllers": [
"controller.render.squirrel"
],
"geometry": {
"default": "geometry.squirrel"
},
"textures": {
"red": "textures/entity/squirrel/red",
"gray": "textures/entity/squirrel/gray"
},
"materials": {
"red": "entity_alphatest",
"gray": "custom_entity"
},
"animations": {
"move": "animation.squirrel.move",
"idle": "animation.squirrel.idle",
"look_at_target": "animation.common.look_at_target"
},
"animation_controllers": [
{ "general": "controller.animation.squirrel.general"}
]
}
}
}
```
#### 说明
##### animations
对应于resource_pack/animations/squirrel.animation.json
##### animation_controllers
对应于resource_pack/animation_controllers/squirrel.animation_controllers.json
##### render_controllers
对应于resource_pack/render_controllers/squirrel.render_controllers.json
##### 贴图
资源包resource_pack/textures/entity目录下增加squirrel贴图包括red.png和gray.png
### 8.3 Spawn Egg
用于设置实体刷怪蛋的颜色或者纹理。
当一个文件中包含多张纹理时可以使用texture_index指定默认为0
```json
"spawn_egg": {
"texture": "spawn_egg",
"texture_index": 2
}
```
另外也可以指定刷怪蛋的颜色,如:
```json
"spawn_egg": {
"base_color": "#53443E",
"overlay_color": "#2E6854"
}
```
### 8.4 enable_attachables
指定实体是否可以穿戴装备,这允许实体渲染盔甲,如:
```json
"enable_attachables": true
```
### 8.5 脚本
脚本允许开发者使用*MoLang*来计算和存储数据,该数据可以被重复利用而不是不断重复地计算。
目前脚本支持初始化initialize、设置父实体parent_setup、预动画pre_animation、动画animate、放大缩小scale后续将会支持更多。
我们简单通过如下示例来了解一下:
**示例1史莱姆**
```json
"scripts": {
"pre_animation": [
"variable.squish_factor = (query.previous_squish_value + (query.current_squish_value - query.previous_squish_value) * query.frame_alpha);",
"variable.bounce = 1 / ((variable.squish_factor / (query.variant * 0.5 + 1)) + 1);",
"variable.horizontal_scale_amount = variable.bounce * query.variant;",
"variable.vertical_scale_amount = (1 / variable.bounce) * query.variant;"
],
"scaleX": "variable.horizontal_scale_amount",
"scaleY": "variable.vertical_scale_amount",
"scaleZ": "variable.horizontal_scale_amount"
},
```
**示例2**
```json
"scripts": {
"animate": [
"setup",
"look_at_target",
"move",
{ "baby_transform": "query.is_baby" }
]
},
```
## 9 创建自定义生物
```python
self.CreateEngineEntityByTypeStr("netease:squirrel", pos, rot)
```
## 10 脚本注册驱动节点<span id="molang_node"/>
```python
import mod.client.extraClientApi as clientApi
ClientSystem = clientApi.GetClientSystemCls()
class AnimationTestClientSystem(ClientSystem):
def __init__(self, namespace, systemName):
ClientSystem.__init__(self, namespace, systemName)
self.mRotating = False # 脚本状态
# 这里注册了"query.mod.is_moving"的计算节点调用self.UpdateScriptVariable更新状态值
self.queryVariableName = 'query.mod.is_moving'
comp = self.CreateComponent('', "Minecraft", "queryVariable")
result = comp.Register(self.queryVariableName, 0.0)
def UpdateScriptVariable(self):
comp = self.CreateComponent('', "Minecraft", "queryVariable")
result = comp.Set(self.queryVariableName, 1.0)
```
## 11 自定义生物行为<span id="molang_node"/>
### 11.1 概述
开发者通过配置behaviorpack\entities中生物json的behavior增加自定义behavior节点并在python实现对应节点的逻辑以实现自定义的生物行为。以下逐步讲解如何实现squirrel使用tnt攻击玩家的行为
### 11.2 behaviorpack\entities的生物json中配置behavior
CustomEntityMod_behavior/entities/squirrel.json
```json
...
"minecraft:behavior.python_custom:avoid_tnt": {
"priority": 2,
"module_path": "customEntityModScripts.avoidTntGoal",
"class_name": "AvoidTntGoal",
"arg_dict": {},
"control_flags": [ "move"]
},
"minecraft:behavior.python_custom:place_tnt_to_target": {
"priority": 3,
"module_path": "customEntityModScripts.placeTntToTarget",
"class_name": "PlaceTntToTarget",
"control_flags": [ "move"]
},
...
```
格式说明:
behaviorName:{
"priority":int
"module_path":string
"class_name":string
"arg_dict":dict
}
**其中behaviorName必须以 minecraft:behavior.python_custom: 为前缀**
字段说明:
| 字段名 | 类型 | 必填项| 描述 |
| ----------- | ------------ | -- | ------------- |
| priority | int | 是 |行为的优先级 |
| module_path | string | 是 | 行为的python模块路径以 "." 分隔 |
| class_name | string | 是 | 行为的python类名 |
| arg_dict | dict | 否 | 行为的参数会被传至python实例中 |
| control_flags | list(string) | 否 | 控制标志,包含相同控制标志的行为被为冲突,**同一时刻下冲突的行为最多只有一个会被执行**。可用的标志有move, look, jump |
### 11.3 mod的scripts脚本中实现生物自定义行为的逻辑
CustomEntityMod_behavior/customEntityModScripts/placeTntToTarget.py - 生物向目标放置tnt
CustomEntityMod_behavior/customEntityModScripts/avoidTntGoal.py - 生物远离tnt
以placeTntToTarget.py为例
```python
import mod.server.extraServerApi as serverApi
CustomGoalCls = serverApi.GetCustomGoalCls()
class PlaceTntToTarget(CustomGoalCls):
def __init__(self, entityId, argsJson):
CustomGoalCls.__init__(self, entityId, argsJson)
print "PlaceTntToTarget init, entityId:", self.GetEntityId()
print "PlaceTntToTarget init, args:", self.GetArgs()
def CanUse(self):
# return True or False
pass
def CanContinueToUse(self):
# return True or False
pass
def CanBeInterrupted(self):
# return True or False
pass
def Start(self):
pass
def Stop(self):
pass
def Tick(self):
pass
```
函数说明:
| 函数名 | 返回值 | 描述 |
| ----------- | ------------- | ---------- |
| CanUse | bool | 行为能否使用行为未被执行时引擎每帧调用。返回True时若没有其他低优先级值的冲突行为且正在执行的高优先级值行为能被打断时则开始执行此行为调用Start函数 |
| CanContinueToUse | bool |行为能否被继续使用,行为被执行时,每帧判断。是行为是否能继续使用的判断条件之一 |
| CanBeInterrupted | bool | 行为能否被其他行为打断行为在执行状态时引擎每帧调用。运行时不能动态修改返回值必须一直返回True或False |
| Start | 无 |行为开始时执行的函数 |
| Stop | 无 |行为停止时执行的函数 |
| Tick | 无 |行为执行状态下每秒执行最多20次机器性能差时会降频 |
**注意:**
1文件路径即模块路径必须与json配置中的**module_path**匹配
2自定义行为的类名必须与json中配置的**class_name**匹配
3自定义行为的类必须继承自**serverApi.GetCustomGoalCls()** 并调用父类的__init__函数
4所有函数均在**服务器线程server**调用
### 11.4 自定义AI执行流程图
<img src="./picture/customentity/custom_AI.png" alt="zombie" style="zoom:100%;" />
### 11.5 自定义AI代码流程图
<img src="./picture/customentity/custom_AI_code.png" alt="zombie" style="zoom:100%;" />
**注意:**
1若两个CanUse的行为不冲突且正在执行的高优先级值行为能被打断时两个行为同时执行
2生物的行为通道有两条一条为普通行为通道一条为敌对对象选择通道两条通道可同时存在每条通道仅可执行一种行为组件目前存在七个选择对象的行为组件
minecraft:behavior.defend_village_target
minecraft:behavior.owner_hurt_by_target
minecraft:behavior.vex_copy_owner_target
minecraft:behavior.hurt_by_target
minecraft:behavior.nearest_attackable_target
minecraft:behavior.wither_target_highest_damage

View File

@@ -0,0 +1,132 @@
---
front:
hard: 入门
time: 分钟
---
# 重写原版生物
我们可以通过自定义与原版生物一样的identifier来重写原版生物的行为与外观。
请结合示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)来阅读该文档。
## 1. 重写生物行为
如示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)中在behavior_pack/entities下添加custom_pig.jsonidentifier依然为minecraft:pig然后加上了**苦力怕**的攻击组件minecraft:nearest_attackable_target和minecraft:target_nearby_sensor以及爆炸事件使得它会攻击玩家并且爆炸消失。
## 2. 重写生物外观
重写生物外观有两种方式:
* **重写客户端实体的定义resource_pack/entity下改方式为纯配置json的方式**
与重写生物行为一样我们可以通过重写资源包下的entity定义、贴图、动画、模型、渲染控制器等json文件来重写生物的外观如示例[CustomEntityMod](../../13-模组SDK编程/60-Demo示例.md#CustomEntityMod)中,猪穿上了屠夫的贴图。
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "minecraft:pig",
"materials": { "default": "custom_entity" },
"textures": {
"default": "textures/entity/custom_pig", # 修改此贴图
"saddled": "textures/entity/custom_pig_saddle" # 修改此贴图
},
"geometry": {
"default": "geometry.pig"
},
"animations": {
"setup": "animation.pig.setup.v1.0",
"walk": "animation.quadruped.walk",
"look_at_target": "animation.common.look_at_target",
"baby_transform": "animation.pig.baby_transform"
},
"scripts": {
"animate": [
"setup",
{ "walk": "query.modified_move_speed" },
"look_at_target",
{ "baby_transform": "query.is_baby" }
]
},
"render_controllers": [ "controller.render.custom_pig" ],
"spawn_egg": {
"texture": "spawn_egg",
"texture_index": 2
}
}
}
}
```
并在textures/entity目录下增加贴图custom_pig.png和custom_pig_saddle.png
## 3. 关于重写玩家的客户端实体定义
**对玩家客户端定义的修改,都应该基于`data\resource_packs\vanilla_netease\entity\player.entity.json`进行而非vanilla或其他的原版资源包。**
引擎支持玩家皮肤时会对player的render_controllers进行硬编码的修改
1. 根据玩家是否使用拥有自发光的会员皮肤移除controller.render.player.first_person_bloom及controller.render.player.third_person_bloom或者controller.render.player.first_person及controller.render.player.third_person。因为为了兼容自发光请同时保留以上4个render controller。
2. 若玩家使用了个性化搭配则会添加controller.render.persona_animated_face.third_person。
这会导致当开发者想完全重写player的外观时例如
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "minecraft:player",
"materials": {
"MC_default": "entity"
},
"textures": {
"MC_default": "textures/entity/penguin/penguin"
},
"geometry": {
"MC_default": "geometry.penguin"
},
"animations": {
...
},
"scripts": {
...
},
"render_controllers": [ "controller.render.penguin" ]
}
}
}
```
那么当玩家使用了个性化搭配时会多出一个render controller。
为了解决这种情况可以在description中添加netease_override_persona属性。当该属性为true时引擎不会对player的render_controllers作任何修改。例如
```json
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "minecraft:player",
"netease_override_persona": true,
...
"render_controllers": [ "controller.render.penguin" ]
}
}
}
```

View File

@@ -0,0 +1,90 @@
---
front:
hard: 入门
time: 分钟
---
# 实体位置绑定
开发者也可以在entity json中增加位置组件来增加可以骑乘的位置该组件以 `minecraft:rideable` 开头,以**minecraft:boat**
```json
"format_version": "1.13.0",
"minecraft:entity": {
"description": {
"identifier": "minecraft:boat",
"is_spawnable": false,
"is_summonable": true,
"is_experimental": false
},
"components": {
//省略不关注的组件
"minecraft:rideable": {
"seat_count": 2,
"interact_text": "action.interact.ride.boat",
"pull_in_entities": true,
"seats": [
{
"position": [ 0.0, -0.2, 0.0 ],
"min_rider_count": 0,
"max_rider_count": 1,
"rotate_rider_by": -90,
"lock_rider_rotation": 90
},
{
"position": [ 0.2, -0.2, 0.0 ],
"min_rider_count": 2,
"max_rider_count": 2,
"rotate_rider_by": -90,
"lock_rider_rotation": 90
},
{
"position": [ -0.6, -0.2, 0.0 ],
"min_rider_count": 2,
"max_rider_count": 2,
"lock_rider_rotation": 90
}
]
},
}
}
}
```
**minecraft:horse_wild**
```
"minecraft:rideable": {
"seat_count": 1,
"family_types": [
"player",
"zombie"
],
"interact_text": "action.interact.mount",
"seats": {
"position": [ 0.0, 1.1, -0.2 ]
}
},
```
**参数解释**
- seat_count默认值 1 改生物拥有的骑乘位置数目
- crouching_skip_interact默认值 true为true时如果与该实体互动的实体蹲伏则无法与该实体互动
- interact_text默认值“” 与玩家交互时显示的UI按钮上的文本内容
- family_types默认值 ”“,能够骑乘该实体的实体种类
- controlling_seat默认值 0 控制该实体的位置index
- pull_in_entities默认值 false如果为true则此实体会将正确family_type的实体拉入任何可用的座位
- rider_can_interact默认值 false如果为true则由骑手查看时将选择此实体
- seats 默认值 “”,位置的详细内容:
- position默认值 [0.0,0.0,0.0],该座位的位置相对于该实体的位置
- min_rider_count默认值 0 定义在可以使用此座位之前必须乘坐此实体的最少乘客数量
- max_rider_count默认值 0定义在可以使用此座位之前必须乘坐此实体的最大乘客数量
- rotate_rider_by默认值 0.0,骑乘者旋转角度
- lock_rider_rotation默认值 181.0,允许骑乘者在旋转此实体时旋转的角度(以度为单位),忽略此设置时则无限制。

View File

@@ -0,0 +1,152 @@
---
front:
hard: 入门
time: 分钟
---
# 使用API修改玩家表现
下面结合示例CustomEntityMod说明如何通过接口动态修改玩家模型与动作。
## 修改材质
### 接口
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayerrendermaterial" rel="noopenner"> AddPlayerRenderMaterial </a>
### 示例
```python
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
actorRenderComp.AddPlayerRenderMaterial("default", "custom_entity")
actorRenderComp.RebuildPlayerRender()
def reset():
actorRenderComp.AddPlayerRenderMaterial("default", "entity_alphatest")
actorRenderComp.RebuildPlayerRender()
self.ShowMsg("恢复默认玩家渲染材质")
comp = clientApi.CreateComponent(clientApi.GetLevelId(), "Minecraft", "game")
comp.AddTimer(3.0, reset)
self.mIsTranform = True
self.ShowMsg("切换玩家渲染材质中")
```
### 说明
玩家的默认渲染材质为entity_alphatest首先先修改为自定义材质custom_entity然后定时3s恢复默认值。
### 效果
<img src="./picture/customentity/change_material.png" style="zoom:100%;" />
左边custom_entity
右边entity_alphatest
## 修改几何体与贴图
### 接口
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayergeometry" rel="noopenner"> AddPlayerGeometry </a>
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayertexture" rel="noopenner"> AddPlayerTexture </a>
### 示例
```python
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
actorRenderComp.AddPlayerGeometry("default", "geometry.zombie.v1.8")
actorRenderComp.AddPlayerTexture("default", "textures/entity/zombie/zombie")
actorRenderComp.RebuildPlayerRender()
def reset():
actorRenderComp.AddPlayerGeometry("default", "geometry.humanoid.custom")
actorRenderComp.AddPlayerTexture("default", "textures/entity/steve")
actorRenderComp.RebuildPlayerRender()
self.ShowMsg("恢复默认玩家渲染几何体")
comp = clientApi.CreateComponent(clientApi.GetLevelId(), "Minecraft", "game")
comp.AddTimer(3.0, reset)
```
### 说明
玩家的默认渲染几何体为geometry.humanoid.custom
玩家的默认渲染贴图为textures/entity/steve
首先把玩家默认渲染几何体改为geometry.zombie.v1.8默认渲染贴图改为textures/entity/zombie/zombie然后定时3s恢复默认值。
### 效果
<img src="./picture/customentity/change_geometry.png" style="zoom:100%;" />
左边:默认
右边:修改后的僵尸几何体以及贴图
**备注:修改几何体还会涉及到贴图以及动画,如果只是修改几何体,会出现动画无法正常播放等问题**
## 修改动画
### 接口
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayeranimation" rel="noopenner"> AddPlayerAnimation </a>
### 示例-修改动作
新增动作定义
```json
"animation.player.custom.move.arms" : {
"loop" : true,
"bones" : {
"leftarm" : {
"rotation" : [ "variable.tcos0 + 30", 0.0, 0.0 ]
},
"rightarm" : {
"rotation" : [ "-variable.tcos0 + 30", 0.0, 0.0 ]
}
}
}
```
接口增加动画
```python
actorRenderComp = self.CreateComponent(entityId, "Minecraft", "actorRender")
actorRenderComp.AddPlayerAnimation("move.arms", "animation.player.custom.move.arms")
```
说明对原版move.arms动作进行调整leftarm和rightarm的rotation各增加30然后使用接口覆盖原版的定义。
### 示例-控制动画
move.arms和move.legs分别为玩家手部和腿部摆动的动画。在原版中此两种动画没有任何条件限制只要走动就会计算出两者的旋转角度。
在此我们通过简单queryVariable组件定义的变量来控制这两个动画。
```json
{
"move.arms": "query.mod.rn_anim_index > 0"
},
{
"move.legs": "query.mod.rn_anim_index > 1"
}
```
脚本控制如下:
```python
comp = self.CreateComponent(entityId, "Minecraft", "queryVariable")
comp.Register("query.mod.rn_anim_index", 0)
comp.Set("query.mod.rn_anim_index", 1)
```
## 修改动画控制器
### 接口
<a href="../../../../mcdocs/1-ModAPI/接口/玩家/渲染.html#addplayeranimationcontroller" rel="noopenner"> AddPlayerAnimationController </a>
可以通过自定义动画控制器后,使用该接口添加到玩家。

View File

@@ -0,0 +1,200 @@
# 使用坐骑拓展接口
## 概述
通过API控制坐骑的骑乘者和座位开发者可指定骑乘者坐到任意座位并且能够对坐骑上的座位进行动态的修改
## 前置知识
在新增自定义坐骑的时候需要在json文件中为实体添加`minecraft:rideable`组件。以游戏中的船为例,下面是船的`minecraft:rideable`组件定义,忽略了该组件的一些参数:
```json
"minecraft:rideable": {
"seat_count": 2,
"seats": [
{
"position": [ 0.0, -0.2, 0.0 ],
"min_rider_count": 0,
"max_rider_count": 1,
"rotate_rider_by": -90,
"lock_rider_rotation": 90
},
{
"position": [ 0.2, -0.2, 0.0 ],
"min_rider_count": 2,
"max_rider_count": 2,
"rotate_rider_by": -90,
"lock_rider_rotation": 90
},
{
"position": [ -0.6, -0.2, 0.0 ],
"min_rider_count": 2,
"max_rider_count": 2,
"lock_rider_rotation": 90
}
]
},
```
**参数解释**
- seat_count表示同时能有多少个骑乘者在这个坐骑上默认为1
- seats座位的定义包含如下内容
- position该座位相对于坐骑的位置默认为 [0, 0, 0]
- rotate_rider_by该座位上的骑乘者相对于坐骑的转向默认为0
- lock_rider_rotation在该座位上的骑乘者视角允许转动的角度默认为181不设置即不限制角度
- min_rider_count定义该座位在骑乘者最少有多少个的时候启用默认为0
- max_rider_count定义该座位在骑乘者最多有多少个的时候启用默认为seat_count
- controlling_seat默认为0一般不需要修改即默认`riderIndex`为0的骑乘者来控制坐骑`riderIndex`的含义见下文
**座位与乘客队列**
可以看到,原版的船定义了三个座位,并且最多只能有两个骑乘者同时在船上,为了便于理解,可以将座位与骑乘者看成两个独立的队列来理解
当第一个骑乘者上船时当前的骑乘者数量变为1依次检查`seats`参数中的座位是否满足条件。第二个和第三个座位因为不满足`min_rider_count`需要为2的条件所以不会启用。骑乘者上船以后会让船上所有的骑乘者依次寻找启用的座位
![one_passenger](./picture/customride/one_passenger.png)
于是第一个骑乘者就坐到了一号位上,表现上就是骑乘者坐在了船的正中间
![image-20230207110607380](./picture/customride/one_passenger_game.png)
当第二个骑乘者上船时当前的骑乘者数量变为2依次检查`seats`参数中的座位是否满足条件。第一个座位因为不满足`max_rider_count`需要为1的条件所以不会启用。骑乘者上船以后会让船上所有的骑乘者依次寻找启用的座位
![image-20230207112103436](./picture/customride/two_passenger.png)
于是第一个骑乘者就坐到了二号位上,新加入的第二个骑乘者就坐到了三号位上,表现上就是两个骑乘者坐在了船的前后两边
![image-20230207111107769](./picture/customride/two_passenger_game.png)
**自定义坐骑**
在定义自定义坐骑的过程中,如果没有特殊的需求,一般不需要定义座位的`min_rider_count``max_rider_count`即任何座位的启用条件都是默认值0~`seat_count`个,在这种情况下骑乘者和座位其实是一一对应的,也就是第一个乘客会坐到一号位,第二个乘客会坐到二号位
![image-20230207112357764](./picture/customride/custom_ride.png)
但为了适应原版的特性,在接口里仍然对这两个部分进行分开处理,分别用`seatIndex``riderIndex`表示座位的序号和骑乘者的序号,但大部分情况这两者是相同的。
![image-20230207112826017](./picture/customride/index.png)
## 使用
**获取坐骑上所有骑乘者的信息**
使用<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#getriders" rel="noopenner">GetRiders</a>接口来获取坐骑上所有骑乘者的信息包括实体ID、在骑乘者队列中所处的位置以及当前的座位编号
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
riders = comp.GetRiders()
```
### 骑乘者相关
**锁定坐骑上骑乘者队列,骑乘者上下坐骑不会影响其他骑乘者**
在原版坐骑中,当一个骑乘者离开坐骑时,后面的所有骑乘者会往前移动一位,使用<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentitylockriders" rel="noopenner">SetEntityLockRider</a>可以屏蔽这种逻辑,当一个骑乘者离开时不会变动坐骑上已有乘客的骑乘者序号。利用该接口可以实现类似车辆载具的效果,驾驶位上的司机下车以后,副驾驶的玩家依旧在原来的位置上
![image-20230207144156298](./picture/customride/lock_passenger.png)
![image-20230207145009391](./picture/customride/lock_passenger_game.png)
坐骑锁定后实体骑乘坐骑的逻辑将发生变化前提是未通过接口指定实体成为第n个骑乘者下方会介绍
**开始骑乘**
- **情况A-坐骑被锁定**:实体将在骑乘者者队列中从队首开始寻找是否有空的位置,如果有则成为该位置的骑乘者;如果没有则插入队尾,成为当前骑乘者队列中最后一位
- **情况B-坐骑未锁定**:坐骑首先会将骑乘者队列中的所有空位删除,然后按照原版的逻辑来执行添加骑乘者操作
- 如果当前待骑乘的实体是玩家,则会检测队列中第一个实体是否为玩家,如果不是玩家则会将待骑乘的玩家插到队首,成为队列中第一个骑乘者,否则插入队尾
- 如果当前待骑乘的实体不是玩家,则插入队尾,成为当前骑乘者队列中的最后一位
**结束骑乘**
- **情况A-坐骑被锁定**:实体离开坐骑,实体原先在骑乘者队列中的位置将会变为空,当前坐骑上所有其他的骑乘者在骑乘者队列中的位置不会发生变化
- **情况B-坐骑未锁定**:实体离开坐骑,在该坐骑的骑乘者队列中,位于该实体后面的所有骑乘者,在骑乘者队列中的位置往前移动一位
**注意**:如果坐骑未锁定,则重载存档后空的位置将被删除,并且坐骑上如果有玩家,同原版逻辑一样玩家会移动到最前面
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
comp.SetEntityLockRider(True)
```
**让玩家或实体骑乘坐骑并且成为队列中指定序号的骑乘者(建议搭配锁定骑乘者接口使用)**
在<a href="../../../../mcdocs/1-ModAPI/接口/玩家/行为.html#setplayerrideentity" rel="noopenner">SetPlayerRideEntity</a>或<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setriderrideentity" rel="noopenner">SetRiderRideEntity</a>接口中可以通过参数`riderIndex`设定玩家或实体在骑乘时直接成为骑乘者队列中指定序号的骑乘者,不会受到实体是否通过接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentitylockriders" rel="noopenner">SetEntityLockRider</a>锁定的影响
若玩家或实体当前已处在另一个坐骑上,则会先离开当前的坐骑并骑乘到目标坐骑上。注意,目标坐骑指定的序号必须没有骑乘者
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
comp.SetRiderRideEntity(playerId,rideEntityId,1)
```
设定以后玩家或实体会成为队列中第二个骑乘者,于是该骑乘者会找到坐骑上第二个可以坐的位置,此时坐骑的情况如下:
![image-20230207142650150](./picture/customride/specific_index.png)
**改变坐骑上骑乘者在队列中的所处的位置(建议搭配锁定骑乘者接口使用)**
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#changeriderseat" rel="noopenner">ChangeRiderSeat</a>可以改变骑乘者的`riderIndex`,若指定的`riderIndex`上已经有骑乘者,则交换两个骑乘者的位置。注意,该接口需要对应的实体已经在骑乘状态下才能使用
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
comp.ChangeRiderSeat(1)
```
### 座位相关
**增加坐骑上的座位**
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#addentityseat" rel="noopenner">AddEntitySeat</a>可以在坐骑上增加一个座位,并设定座位的位置和转向。该接口同时也会使`minecraft:rideable`组件中的`seat_count`变量+1新增的座位默认的`min_rider_count``max_rider_count`默认为0和新的`seat_count`,即表示该新增的座位不管坐骑上的骑乘者有几人都会处于启用状态
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
seatIndex = comp.AddEntitySeat((1.0, 1.0, 1.0), 90.0, 90.0)
```
**修改坐骑上的座位**
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#setentityseat" rel="noopenner">SetEntitySeat</a>可以修改一个已有座位的位置、转向以及玩家可旋转角度范围,处在该位置上的玩家在接口调用后也会移动到修改后的位置
**注意**:只能修改通过接口添加的座位
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
comp.SetEntitySeat(3, (1.0, 1.0, 1.0), 90.0, 90.0)
```
**删除坐骑上的座位**
接口<a href="../../../../mcdocs/1-ModAPI/接口/实体/行为.html#deleteentityseat" rel="noopenner">DeleteEntitySeat</a>可以删除一个已有座位,处于该座位上的骑乘者会被强制离开坐骑
**注意**:只能删除通过接口添加的座位
示例:
```python
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory().CreateRide(entityId)
comp.DeleteEntitySeat(3)
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB