API
生物
自定义生物借用游戏中某个生物的身体(模型、动画、体型和移动方式),在上面绘制你的纹理,配上你的属性、行为和战利品。声明方式和其他内容一样:一组属性。
声明生物
creature "ghost" {
body: "minecraft:zombie"
texture: "entity/ghost"
health: 40
speed: 0.3
attack: 4
behaviour: ["swim", "melee_attack", { wander: 0.8 }, { look_at_players: 10 }, "look_around"]
targets: ["hurt_by", "minecraft:pig"]
loot: [ { item: "ghostmod:ecto", count: [1, 2] } ]
}| 属性 | 取值 | 默认值 |
|---|---|---|
body |
游戏中某个生物的 id:minecraft:zombie、minecraft:wolf、minecraft:cow…… |
必填 |
texture |
纹理路径,绘制在身体的模型上:entity/ghost 即模组中的 textures/entity/ghost.png |
身体原本的外观 |
model |
你自己的 3D 模型:entity/robot 即模组的 models/entity/robot.json(见下文) |
身体的模型 |
size |
以方块为单位的 [width, height]:它的碰撞范围和被点击的范围(见下文) |
身体原本的值 |
health |
生命值 | 身体原本的值 |
speed |
行走速度(僵尸为 0.23,狼为 0.3) | 身体原本的值 |
attack |
近战攻击伤害 | 身体原本的值 |
follow_range |
在多少格外发现目标 | 身体原本的值 |
behaviour |
行为列表,从最重要到最不重要(见下文) | 身体原本的行为 |
targets |
攻击谁,按优先级排列(见下文) | 无 |
loot |
[{ item, count, chance }, …],与方块相同:每个物品单独掷骰 |
无 |
spawns |
自然出现的群系,含权重与群体大小(见下) | 不会自然生成 |
breed_item |
能让两只繁殖的物品(见下) | 不能繁殖 |
tame_item |
能驯服它的物品(见下) | 无法驯服 |
rideable |
true 允许玩家骑乘(见下) |
false |
行为
列表顺序就是优先级:两个行为同时想执行时,靠前的胜出。每个行为可以写成名称、写成 { 名称: 数字 } 来设置主要参数,或写成包含全部参数的映射。
| 行为 | 作用 | 参数 |
|---|---|---|
"swim" |
在水中保持漂浮。 | |
"look_around" |
空闲时四处张望。 | |
"wander"、{ wander: 0.8 } |
四处游荡。 | speed,默认 1 |
"look_at_players"、{ look_at_players: 10 } |
注视附近的玩家。 | range(格),默认 8 |
"melee_attack"、{ melee_attack: 1.2 } |
追击并攻击目标。 | speed,默认 1 |
"panic"、{ panic: 1.5 } |
受到伤害时逃跑。 | speed,默认 1.25 |
{ avoid: "minecraft:wolf", distance: 8, speed: 1.2 } |
远离该生物。 | distance(格)、speed |
{ follow: "minecraft:wheat", speed: 1 } |
跟随手持该物品的人。 | speed |
{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 } |
向目标发射投射物(见下)。 | projectile, interval, range, speed, power, damage |
"breed", { breed: 1 } |
喂食后,与同类繁殖。 | speed |
"follow_parent", { follow_parent: 1.1 } |
幼崽待在父母身边。 | speed |
{ follow_owner: 1.2, distance: 8 } |
被驯服的生物跟随主人。 | speed、distance(格数) |
{ fly_around: 1 } |
四处飞行;适用于会飞的身体(鹦鹉、蜜蜂、悦灵)。 | speed |
{ can_start: …, tick: … } |
你自己的代码(见下)。 | can_start, tick, keep_going, moves |
速度数值是生物基础速度的倍数:{ wander: 0.8 } 游荡时比正常行走稍慢。
攻击目标
targets 说明它攻击谁,从最高优先级到最低。"hurt_by" 是对它造成伤害的人;实体 id 表示最近的该类实体("minecraft:player" 表示玩家,"minecraft:pig" 表示猪)。要真正发起攻击,生物还需要一个执行攻击的行为,例如 "melee_attack"。
生成生物
command haunt requires "ghostmod.haunt" describe "在你所站的位置召唤一只幽灵" {
if player == null { return "仅限玩家使用" }
world().spawn("ghostmod:ghost", player.location)
return "&7一只幽灵出现了……"
}id 属于你的模组:ghostmod:ghost。游戏命令 /summon ghostmod:ghost 同样可用。
让它们自然生成
添加 spawns,生物就会像游戏自带的生物一样在世界中自然出现。
creature "ghost" {
body: "minecraft:zombie"
spawns: [ { biomes: ["minecraft:dark_forest", "#minecraft:is_forest"], weight: 20, group: [1, 2] } ]
}每一项列出它出现的 biomes(一个 id,或用 #标签 指代整组群系)、weight(权重:相对于该群系其他生物的出现频率,牛是 8,僵尸是 95)以及 group 的数量范围。
它遵循其身体的生成规则:僵尸身体在黑暗中生成,牛身体在有光的草地上生成。无论是世界生成时还是之后,都是如此。
刷怪蛋。 每个生物还会得到一个刷怪蛋,其 id 加上 _spawn_egg(ghost_spawn_egg),位于创造模式的刷怪蛋标签页。如果模组里有 textures/item/ghost_spawn_egg.png,就用它作纹理;否则外观与其身体的刷怪蛋相同。
Kotlin 中:
content.creature("ghost") {
body = "minecraft:zombie"
spawn("minecraft:dark_forest", "#minecraft:is_forest", weight = 20, group = 1..2)
}用代码操控生物
你声明的生物以及其他任何生物都是 Creature。你可以在事件、命令或计时器中向它们下达指令:
| 成员 | 作用 |
|---|---|
target |
它正在攻击的对象。可读取,也可设置。 |
moveTo(location, speed), move_to |
走到某个位置。speed 会乘以它的正常速度。 |
stop() |
停止行走。 |
isMoving, is_moving |
是否正在走向某处。 |
lookAt(location), look_at |
转头看向某个位置。 |
canSee(entity), can_see |
与该实体之间是否有畅通的视线。 |
isBaby |
是否为幼崽。 |
ownerId |
被驯服后,其主人的 id。 |
tame(player) |
让该玩家成为它的主人。 |
isSitting |
是否正坐着。 |
playAnimation(name), play_animation |
播放其模型的一个动画(见下)。 |
每个实体都有 velocity,这是一个以每刻多少格计的 Vector。读取或设置它即可推动实体:entity.velocity = vector(0, 0.6, 0) 会把它向上弹起。
在 CraftScript 中,带类型的 let 会把实体收窄为生物,运行时会进行检查:
command pup requires "dogmod.pup" describe "Get a pet dog" {
if player == null { return "Players only" }
let dog: Creature = world().spawn("dogmod:dog", player.location)
dog.tame(player)
dog.look_at(player.location)
dog.velocity = vector(0, 0.6, 0) // a little hop
return "&7Good dog!"
}你自己的行为
当现成的行为不够用时,就用自己的代码写一个。它和其他行为一样放进 behaviour 列表,位置就是它的优先级。
creature "herder" {
body: "minecraft:wolf"
targets: ["minecraft:pig"]
behaviour: [
"swim",
{
can_start: fun(c) { return c.target != null && c.can_see(c.target) },
tick: fun(c) {
if c.target != null {
c.look_at(c.target.location)
if !c.is_moving { c.move_to(c.target.location, 1.2) }
}
}
},
{ wander: 1 }
]
}can_start:每隔几刻被询问一次;返回是否应该开始。tick:行为运行期间每刻执行一次。keep_going:返回是否继续。省略时与can_start相同。moves:默认true。会移动的行为不会与另一个会移动的行为同时运行,列表中靠前的优先。只观察或只做出反应的行为请用false。
Kotlin 中: Behaviour.Custom(canStart = { … }, tick = { … }, keepGoing = …, moves = true)
动物:繁殖、驯服、骑乘与飞行
几个属性和行为就能把生物变成动物。这只生物用苹果繁殖,用骨头驯服,还可以骑乘:
creature "mooble" {
body: "minecraft:cow"
tame_item: "minecraft:bone"
breed_item: "minecraft:apple"
rideable: true
behaviour: ["swim", { breed: 1 }, { follow_parent: 1.1 }, { follow_owner: 1.2, distance: 8 }, { wander: 0.8 }]
}- 繁殖。
breed_item加上行为"breed":用该物品喂食后,两只同类会生出同类的幼崽。需要动物身体(牛、狼、鸡……)。幼崽用"follow_parent"跟在父母身边。 - 驯服。
tame_item:每次尝试有三分之一的成功率。主人会被记住,被驯服的生物绝不会以主人为目标。潜行并空手使用,可让它坐下或站起。{ follow_owner: 1.2, distance: 8 }让它跟随主人。 - 骑乘。
rideable: true:空手使用即可骑上去(驯服后只有主人可以)。用移动键和鼠标操控,潜行下来。 - 飞行。 会飞的身体(鹦鹉、蜜蜂、悦灵)用
{ fly_around: 1 }。身体会飞且rideable的生物,骑乘者抬头时会爬升,低头时会俯冲。
Kotlin 中:breedItem = …、tameItem = …、rideable = true,以及行为 Behaviour.Breed()、Behaviour.FollowParent()、Behaviour.FollowOwner(speed, distance) 和 Behaviour.FlyAround()。
自己的投射物
除了游戏自带的投射物,模组也可以声明自己的投射物。它有自己的伤害、重力,以及落地时发生的事:
projectile "frost_bolt" {
damage: 4
gravity: false
on_hit: fun(e) {
let at = e.entity?.location ?? e.block?.location
if at != null { e.projectile.world.spawn_particle("minecraft:snowflake", at.add(0.5, 1, 0.5), 12, 0.4, 0.02) }
}
}damage:对命中目标造成的伤害。gravity:设为false则沿直线飞行。on_hit:fun(e),落地时调用,参数e与hit事件相同:e.projectile、e.shooter,以及e.entity或e.block。texture:投射物飞行时外观就是它的物品,所以默认使用textures/item/<id>.png;设置texture可改用其他纹理。
像其他投射物一样使用:world.shoot("mymod:frost_bolt", from, velocity, shooter),在生物中则是 { ranged_attack: "mymod:frost_bolt" }。在 Kotlin 中:
content.projectile("frost_bolt") {
damage = 4.0
gravity = false
onHit = { e -> /* … */ }
}远程攻击与投射物
行为 ranged_attack 让生物开火。它会靠近,直到目标进入射程且在视线内,然后射击。
creature "frost_spirit" {
body: "minecraft:snow_golem"
behaviour: [{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 }, { wander: 0.6 }]
targets: ["minecraft:zombie", "hurt_by"]
}
on hit(e) {
if e.shooter?.type == "frostmod:frost_spirit" && e.entity != null {
e.entity.velocity = vector(0, 0.2, 0) // knocked up
}
}| 设置 | 含义 |
|---|---|
ranged_attack |
ranged_attack:投射物(minecraft:arrow、minecraft:snowball、minecraft:small_fireball、minecraft:wind_charge 等)。 |
interval |
interval:两次射击之间的刻数。 |
range |
range:开始射击的距离(格)。 |
speed |
speed:靠近时的行走速度。 |
power |
power:投射物的飞行速度。 |
damage |
damage:命中时的额外伤害。 |
若要从代码中发射(用于生物或玩家的能力),使用 world().shoot(projectile, from, velocity, shooter, damage)。
在 Kotlin 中:
creature("frost_spirit") {
body = "minecraft:snow_golem"
behaviour(Behaviour.RangedAttack(Identifier.parse("minecraft:snowball"), interval = 20, range = 14.0, damage = 3.0))
target(TargetRule.Nearest(Identifier.parse("minecraft:zombie")))
}
// From code, e.g. a player's ability:
world.shoot(Identifier.parse("minecraft:small_fireball"), from, Vector(0.0, 0.0, 1.5), shooter = player, damage = 4.0)投射物落点命中时会触发 hit 事件(ProjectileHitEvent)。它带有 e.projectile、e.shooter,以及 e.entity 或 e.block(取决于击中了什么)。取消它,投射物就会穿过去。见事件。
注意事项
- **每种身体都有限制。**有些游戏生物缺少某项属性:牛没有攻击伤害。如果你设置了它,会被忽略,Crafting 会在日志中发出警告。
- **不会行走的身体。**无法自行寻路的身体会忽略行走类行为(游荡、追击、逃跑、跟随、躲避);其他行为照常生效。
- **不写
behaviour时,**生物的行为与它所用的身体相同。一旦写了列表,它就只做列表中的事。 - **模型只改变外观。**移动和行为始终来自身体,体型也是,除非你设置了
size。 - 自定义生物和其他生物一样是活体实体:它会触发
spawn、damage和entity_death事件,拥有data,可以用世界与玩家中的内容来操作它。
Kotlin 中
package com.example.rubies.content
object Creatures {
fun register(content: ContentBuilder) {
content.creature("ruby_golem") {
body = "minecraft:zombie"
texture = "entity/ruby_golem"
health = 60.0
speed = 0.25
attackDamage = 6.0
behaviour(Behaviour.Swim)
behaviour(Behaviour.MeleeAttack())
behaviour(Behaviour.Wander(0.6))
behaviour(Behaviour.LookAtPlayers(12f))
behaviour(Behaviour.LookAround)
target(TargetRule.HurtBy)
target(TargetRule.Nearest(Identifier.parse("minecraft:player")))
drop(Items.RUBY, 2..4)
}
}
}行为:Behaviour.Swim、LookAround、Wander(speed)、LookAtPlayers(range)、MeleeAttack(speed)、Panic(speed)、Avoid(entity, distance, speed)、Follow(item, speed)。攻击目标:TargetRule.HurtBy 和 TargetRule.Nearest(id)。用 drop(item, count, chance) 添加战利品,与方块相同。
你自己的 3D 模型
添加 model 后,生物就会用你的模型而不是身体的模型来绘制。体型、移动和行为仍然来自身体,模型只改变外观。
creature "robot" {
body: "minecraft:pig"
model: "entity/robot"
texture: "entity/robot"
behaviour: ["swim", { wander: 0.8 }, { look_at_players: 10 }]
}模型是模组的 models/entity/robot.json,它的纹理是 textures/entity/robot.png。在 Kotlin 中:creature("robot") { body = "minecraft:pig"; model = "entity/robot"; texture = "entity/robot" }。该格式在不同游戏版本之间保持一致。
{ "texture_size": [64, 64],
"bones": [
{ "name": "body", "pivot": [0, 6, 0], "cubes": [ { "origin": [-5, 6, -3], "size": [10, 10, 6], "uv": [0, 0] } ] },
{ "name": "head", "parent": "body", "pivot": [0, 16, 0], "cubes": [ { "origin": [-4, 16, -4], "size": [8, 8, 8], "uv": [0, 16] } ] },
{ "name": "left_leg", "pivot": [2.5, 6, 0], "cubes": [ { "origin": [1, 0, -1.5], "size": [3, 6, 3], "uv": [32, 0] } ] },
{ "name": "right_leg", "pivot": [-2.5, 6, 0], "cubes": [ { "origin": [-4, 0, -1.5], "size": [3, 6, 3], "uv": [32, 16] } ] }
],
"animations": { "head": "look", "left_leg": "walk", "right_leg": "walk_opposite", "body": "idle" } }尺寸以像素为单位(16 为一格),y 轴从生物的脚底向上。
- 骨骼:
name、可选的parent(随它一起移动)、pivot(它转动所绕的点)和cubes。 - 立方体:
origin(最低的角)、size和uv(它的纹理在图片中的起点)。布局是常见的盒子展开方式:宽 w、高 h、深 d 的立方体占用 2(w+d) × (d+h) 像素的区域。 - 动画按骨骼设置,写成一个名称或名称列表:
| 动画 | 作用 |
|---|---|
look |
转向生物注视的方向;用于头部。 |
walk、walk_opposite |
行走时摆动;后者相位相反,用于另一侧的肢体。 |
idle |
轻微摇摆。 |
spin |
持续旋转。 |
如果模型无法绘制,生物会显示为身体的样子,日志中会说明原因。
体型
生物的大小与它的身体一致。当你的模型更小或更大时,用 size: [width, height](以方块为单位)设置,让碰撞范围和被点击的范围与玩家看到的样子一致:
creature "drake" {
body: "minecraft:bee"
model: "entity/drake"
texture: "entity/drake"
size: [1.4, 1.1]
}在 Kotlin 中:size = 1.4 to 1.1。
关键帧动画
如需超出现成动画的动作,在 bones 和 animations 旁边添加 clips 部分:
{ "bones": [ … ],
"animations": { … },
"clips": {
"idle": { "length": 2.0, "bones": { "head": { "position": { "0": [0, 0, 0], "1": [0, 0.6, 0], "2": [0, 0, 0] } } } },
"walk": { "length": 1.0, "bones": { "body": { "rotation": { "0": [0, 0, -6], "0.5": [0, 0, 6], "1": [0, 0, -6] } } } },
"roar": { "length": 1.5, "bones": {
"head": { "rotation": { "0": [0, 0, 0], "0.4": [-35, 0, 0], "1.1": [-35, 0, 0], "1.5": [0, 0, 0] },
"scale": { "0": 1, "0.4": 1.35, "1.1": 1.35, "1.5": 1 } },
"body": { "position": { "0": [0, 0, 0], "0.3": [0, 4, 0], "0.6": [0, 0, 0] } } } }
} }- 每个片段有以秒计的
length(时长),每根骨骼最多有三个通道:rotation(度)、position(像素,y 向上)和scale(一个数或[x, y, z])。 - 关键帧的键是以秒计的时间。值在关键帧之间按直线过渡;给片段加上
"interpolation": "smooth",则改为沿曲线穿过各关键帧。通道也可以只写一个值,用于整个片段。
| 片段 | 何时播放 |
|---|---|
walk |
行走时循环播放,与脚步同步。 |
idle |
站立不动时循环播放。 |
attack |
出击时播放。 |
| 其他任何名称 | 代码请求时播放:c.play_animation("roar")。附近装有 Crafting 的玩家能看到。 |
"idle": { "length": 1.2, "interpolation": "smooth", "bones": {
"left_wing": { "rotation": { "0": [0, 0, -20], "0.6": [0, 0, 25], "1.2": [0, 0, -20] } } } }由代码启动的片段会叠加在 walk、idle 和 attack 之上播放,而不是替换它们,并且效果会相加:生物可以一边行走一边咆哮。
拥有自己模型的生物,其幼崽按一半大小绘制。
纹理
没有模型时,纹理的布局与所选身体(僵尸、狼……)相同,所以你可以从该身体的模板开始在上面绘制。它放在模组内部,和物品、方块的纹理一样:
| 模组 | 位置 |
|---|---|
| CraftScript(文件夹) | mods/ghostmod/textures/entity/ghost.png |
| Kotlin 或 Java | src/main/resources/assets/ghostmod/textures/entity/ghost.png |