附加包教程:43.方块(九)
本帖最后由 Cat_Anchor 于 2024-2-3 08:32 编辑巧克力门https://pic.imgdb.cn/item/65a21598871b83018a508752.gif
稀有度常见
创造分类建筑
材料固体
合适挖掘工具镐
硬度0.8
爆炸抗性2
亮度0
窒息生物否
红石导体否
光照透明1
可被火破坏否
可被熔岩生成火否
可再生是
最大堆叠64
命名空间IDchocolate_door
前言
对于大部分人,门确实是一个难复刻的东西。它的难度不在于门的方向或者开关之类,而在于它是一个两格高的方块。门的这种性质注定了它需要一番功夫制作,“活板门”和“门”也花了我一天时间来研究。其中,有半天时间都在优化门的两格高带来的极差的体验。
https://klpbbs.com/static/image/hrline/line5.png
目标
制作一个尽可能与原版一样的门,可以打开/关闭。
https://klpbbs.com/static/image/hrline/line7.png
分析与解决
今天的任务比之前的门要更难,但也不是无法解决。首先,既然是门,那么它肯定有指定4个方向的状态,还有指定是否打开的状态。
门的4个方向是根据我们放置时的朝向决定的,所以使用minecraft:placement_direction实现。至于开关与否,就单独定义一个方块状态。
不过我们使用了方块特征,就把相关的触发器组件——例如minecraft:on_placed——给占用了,以后我们不能用这些组件了。不过根据我的测试,minecraft:on_player_placing似乎还可以使用,这是以后的关键。
现在我们来定义方块状态和一些基本的组件。
{
"format_version": "1.20.60", //格式版本
"minecraft:block": {
"description": {
"identifier": "supplementary:chocolate_door", //方块ID
"menu_category": { //定义菜单分类
"category": "construction", //在创造模式物品栏的“建材”类里
"group": "itemGroup.name.door" //在“门”物品组里
},
"traits": {
"minecraft:placement_direction": {
"enabled_states": [
"minecraft:cardinal_direction"
]
}
}, //定义方块特征,启用minecraft:cardinal_direction方块状态
"states": {
"supplementary:open_bit": [ //门是否打开
false,
true
],
"supplementary:upper_block_bit": [ //门是否为上半部分
false,
true
], ...
}
},
"components": {
"tag:door": {}, //门的标签
"minecraft:selection_box": { //定义判定箱和碰撞箱
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:destructible_by_mining": { //定义挖掘时间
"seconds_to_destroy": 0.8
},
"minecraft:on_player_placing": {
"event": "placed"
}, //定义触发器,当玩家放置时,触发placed事件
"minecraft:destructible_by_explosion": { //定义爆炸抗性
"explosion_resistance": 2
},
"minecraft:light_dampening": 0 //定义遮光量为0(完全透光)
}, ...
}
}
为了实现两格高方块的效果,我们放置门时只放置了下半部分,需要一个事件把上半部分也放置出来。
"events": {
"placed": { //刚才定义的事件
"set_block_at_pos": { //事件方法:在x y z位置放置方块
"block_type": "supplementary:chocolate_door", //放置巧克力门
"block_offset": [ //在上面一格的位置
0,
1,
0
]
}
}, ...
然后定义门旋转和开关相关的方块排列。给每个排列都加上一个标签,方便后续检测。
"permutations": [
{
"condition": "q.block_state('minecraft:cardinal_direction')=='north'",
"components": {
"tag:door_south": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
5
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
5
],
"size": [
16,
16,
3
]
},
"minecraft:geometry": "geometry.door_south"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='south'",
"components": {
"tag:door_north": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:geometry": "geometry.door_north"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='west'",
"components": {
"tag:door_east": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:geometry": "geometry.door_east"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='east'",
"components": {
"tag:door_west": {},
"minecraft:selection_box": {
"origin": [
5,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:collision_box": {
"origin": [
5,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:geometry": "geometry.door_west"
}
},
{
"condition": "q.block_state('supplementary:open_bit')==true", //门是开着的时...
"components": {
"tag:door_open": {},
"minecraft:transformation": {
"rotation": [
0,
-90,
0
]
},
"minecraft:on_interact": {
"event": "door_close"
} //点击触发事件door_close(关门)
}
},
{
"condition": "q.block_state('supplementary:open_bit')==false", //门是关着的时...
"components": {
"tag:door_close": {},
"minecraft:on_interact": {
"event": "door_open"
} //点击触发事件door_open(开门)
}
},
{
"condition": "q.block_state('supplementary:upper_block_bit')==false", //门是下半部分时...
"components": {
"tag:door_lower": {},
"minecraft:material_instances": {
"*": {
"texture": "chocolate_door_lower", //下半部分的纹理
"render_method": "blend"
}
}
}
},
{
"condition": "q.block_state('supplementary:upper_block_bit')==true", //门是上半部分时...
"components": {
"tag:door_upper": {},
"minecraft:loot": "", //不掉落物品
"minecraft:material_instances": {
"*": {
"texture": "chocolate_door_upper", //上半部分的纹理
"render_method": "blend"
}
},
"minecraft:placement_filter": { //仅允许放在(下半部分的)巧克力门上方
"conditions": [
{
"block_filter": [
"supplementary:chocolate_door"
],
"allowed_faces": [
"up"
]
}
]
}
}
}, ...
] ...
但现在有个问题,那就是点击门时只会开半扇门,不会开一整扇门。为了实现这个功能,我们要加上一个循环执行的事件,来不停地检测上面下面的门的状态,并将自身的状态与其同步。我们顺便把开门关门的事件写出来。
"set_door_states": { //检测
"sequence": [
{ //从这个开始,这8个事件方法都将门的方向进行同步
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'north'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'south'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'west'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'east'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'north'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'south'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'west'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'east'"
}
},
{ //从这个开始,这2个是将门的开关状态进行同步,防止只开半扇门的情况发生
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_open') || q.block_neighbor_has_all_tags(0,1,0,'door_open')",
"set_block_state": {
"supplementary:open_bit": true
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_close') || q.block_neighbor_has_all_tags(0,1,0,'door_close')",
"set_block_state": {
"supplementary:open_bit": false
}
}
]
},
"door_open": { //开门时...
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')" //将门的开关状态设为另一个(开设为关,关设为开)
},
"run_command": {
"command": "playsound open.wooden_door @a ~ ~ ~ 0.4 1.0" //发出声音
}
},
"door_close": { //关门时...
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')" //将门的开关状态设为另一个(开设为关,关设为开)
},
"run_command": {
"command": "playsound close.wooden_door @a ~ ~ ~ 0.4 1.0" //发出声音
}
}, ...
问题又来了,每次开关门有概率“失败”。具体情况是,我们如果开/关门,那么开门后有可能会被同步回没有开/关门的状态,所以视觉上就是门开了一瞬间又关上了。为了解决这个问题,我们需要定义新方块状态,决定门是否同步,一般是要同步的,点击门后设置为不同步,然后再设置回去。
"supplementary:should_update": [ //门是否同步
true,
false
]
{
"condition": "q.block_state('supplementary:should_update')==false",
"components": {
"minecraft:queued_ticking": {
"looping": true,
"interval_range": [
1,
1
],
"on_tick": {
"event": "update",
"target": "self"
}
}
}
}, //如果门不同步,那么等待1刻,然后继续同步
{
"condition": "q.block_state('supplementary:should_update')==true",
"components": {
"minecraft:queued_ticking": {
"looping": true,
"interval_range": [
1,
1
],
"on_tick": {
"event": "set_door_states",
"target": "self"
}
}
}
} //如果门同步,那么触发同步的事件set_door_states
"door_open": {
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
"supplementary:should_update": false //开门时,将门设为不同步
},
"run_command": {
"command": "playsound open.wooden_door @a ~ ~ ~ 0.4 1.0"
}
},
"door_close": {
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
"supplementary:should_update": false //关门时,将门设为不同步
},
"run_command": {
"command": "playsound close.wooden_door @a ~ ~ ~ 0.4 1.0"
}
}, ...
那么门方块就做好了,下面是我的chocolate_door.json中的代码。{
"format_version": "1.20.30",
"minecraft:block": {
"description": {
"identifier": "supplementary:chocolate_door",
"menu_category": {
"category": "construction",
"group": "itemGroup.name.door"
},
"traits": {
"minecraft:placement_direction": {
"enabled_states": [
"minecraft:cardinal_direction"
]
}
},
"states": {
"supplementary:open_bit": [
false,
true
],
"supplementary:upper_block_bit": [
false,
true
],
"supplementary:should_update": [
true,
false
]
}
},
"components": {
"tag:door": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 0.8
},
"minecraft:on_player_placing": {
"event": "placed"
},
"minecraft:destructible_by_explosion": {
"explosion_resistance": 2
},
"minecraft:light_dampening": 0
},
"events": {
"placed": {
"set_block_at_pos": {
"block_type": "supplementary:chocolate_door",
"block_offset": [
0,
1,
0
]
}
},
"set_door_states": {
"sequence": [
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'north'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'south'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'west'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_lower')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'east'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'north'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'south'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'west'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_upper')",
"set_block_state": {
"supplementary:upper_block_bit": true,
"minecraft:cardinal_direction": "'east'"
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_open') || q.block_neighbor_has_all_tags(0,1,0,'door_open')",
"set_block_state": {
"supplementary:open_bit": true
}
},
{
"condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_close') || q.block_neighbor_has_all_tags(0,1,0,'door_close')",
"set_block_state": {
"supplementary:open_bit": false
}
}
]
},
"door_open": {
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
"supplementary:should_update": false
},
"run_command": {
"command": "playsound open.wooden_door @a ~ ~ ~ 0.4 1.0"
}
},
"door_close": {
"set_block_state": {
"supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
"supplementary:should_update": false
},
"run_command": {
"command": "playsound close.wooden_door @a ~ ~ ~ 0.4 1.0"
}
},
"update": {
"set_block_state": {
"supplementary:should_update": true
}
}
},
"permutations": [
{
"condition": "q.block_state('minecraft:cardinal_direction')=='north'",
"components": {
"tag:door_south": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
5
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
5
],
"size": [
16,
16,
3
]
},
"minecraft:geometry": "geometry.door_south"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='south'",
"components": {
"tag:door_north": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
16,
16,
3
]
},
"minecraft:geometry": "geometry.door_north"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='west'",
"components": {
"tag:door_east": {},
"minecraft:selection_box": {
"origin": [
-8,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:collision_box": {
"origin": [
-8,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:geometry": "geometry.door_east"
}
},
{
"condition": "q.block_state('minecraft:cardinal_direction')=='east'",
"components": {
"tag:door_west": {},
"minecraft:selection_box": {
"origin": [
5,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:collision_box": {
"origin": [
5,
0,
-8
],
"size": [
3,
16,
16
]
},
"minecraft:geometry": "geometry.door_west"
}
},
{
"condition": "q.block_state('supplementary:open_bit')==true",
"components": {
"tag:door_open": {},
"minecraft:transformation": {
"rotation": [
0,
-90,
0
]
},
"minecraft:on_interact": {
"event": "door_close"
}
}
},
{
"condition": "q.block_state('supplementary:open_bit')==false",
"components": {
"tag:door_close": {},
"minecraft:on_interact": {
"event": "door_open"
}
}
},
{
"condition": "q.block_state('supplementary:upper_block_bit')==false",
"components": {
"tag:door_lower": {},
"minecraft:material_instances": {
"*": {
"texture": "chocolate_door_lower",
"render_method": "blend"
}
}
}
},
{
"condition": "q.block_state('supplementary:upper_block_bit')==true",
"components": {
"tag:door_upper": {},
"minecraft:loot": "",
"minecraft:material_instances": {
"*": {
"texture": "chocolate_door_upper",
"render_method": "blend"
}
},
"minecraft:placement_filter": {
"conditions": [
{
"block_filter": [
"supplementary:chocolate_door"
],
"allowed_faces": [
"up"
]
}
]
}
}
},
{
"condition": "q.block_state('supplementary:should_update')==false",
"components": {
"minecraft:queued_ticking": {
"looping": true,
"interval_range": [
1,
1
],
"on_tick": {
"event": "update",
"target": "self"
}
}
}
},
{
"condition": "q.block_state('supplementary:should_update')==true",
"components": {
"minecraft:queued_ticking": {
"looping": true,
"interval_range": [
1,
1
],
"on_tick": {
"event": "set_door_states",
"target": "self"
}
}
}
}
]
}
}
以下是模型文件。{"format_version":"1.16.0","minecraft:geometry":[{"description":{"identifier":"geometry.door_north","texture_width":16,"texture_height":16,"visible_bounds_width":2,"visible_bounds_height":2.5,"visible_bounds_offset":},"bones":[{"name":"half_door","pivot":,"cubes":[{"origin":[-8,0,-8],"size":,"uv":{"north":{"uv":,"uv_size":},"east":{"uv":,"uv_size":},"south":{"uv":,"uv_size":},"west":{"uv":,"uv_size":},"up":{"uv":,"uv_size":[-16,-3]},"down":{"uv":,"uv_size":[-16,-3]}}}]}]},{"description":{"identifier":"geometry.door_south","texture_width":16,"texture_height":16,"visible_bounds_width":3,"visible_bounds_height":2.5,"visible_bounds_offset":},"bones":[{"name":"half_door","pivot":,"cubes":[{"origin":[-8,0,5],"size":,"uv":{"north":{"uv":,"uv_size":},"east":{"uv":,"uv_size":},"south":{"uv":,"uv_size":},"west":{"uv":,"uv_size":},"up":{"uv":,"uv_size":[-16,-3]},"down":{"uv":,"uv_size":[-16,-3]}}}]}]},{"description":{"identifier":"geometry.door_east","texture_width":16,"texture_height":16,"visible_bounds_width":3,"visible_bounds_height":2.5,"visible_bounds_offset":},"bones":[{"name":"half_door","pivot":,"cubes":[{"origin":[-8,0,-8],"size":,"uv":{"north":{"uv":,"uv_size":},"east":{"uv":,"uv_size":},"south":{"uv":,"uv_size":},"west":{"uv":,"uv_size":},"up":{"uv":,"uv_size":[-3,-16]},"down":{"uv":,"uv_size":[-3,-16]}}}]}]},{"description":{"identifier":"geometry.door_west","texture_width":16,"texture_height":16,"visible_bounds_width":3,"visible_bounds_height":2.5,"visible_bounds_offset":},"bones":[{"name":"half_door","pivot":,"cubes":[{"origin":,"size":,"uv":{"north":{"uv":,"uv_size":},"east":{"uv":,"uv_size":},"south":{"uv":,"uv_size":},"west":{"uv":,"uv_size":},"up":{"uv":,"uv_size":[-3,-16]},"down":{"uv":,"uv_size":[-3,-16]}}}]}]}]}
但是这时,我发现原版门的物品使用了不同的纹理,不好看,实现起来也比较麻烦。于是,我打算做一个附着物,手持“门”时显示。之前我讲过这个,不再赘述。
首先制作模型。
{"format_version":"1.16.0","minecraft:geometry":[{"description":{"identifier":"geometry.door_render","texture_width":16,"texture_height":16,"visible_bounds_width":3,"visible_bounds_height":3.5,"visible_bounds_offset":},"bones":[{"name":"door_root","binding":"q.item_slot_to_bone_name(c.item_slot)"},{"name":"lower","parent":"door_root","pivot":,"cubes":[{"origin":[-8,-16,-8],"size":,"uv":{"north":{"uv":,"uv_size":},"east":{"uv":,"uv_size":},"south":{"uv":,"uv_size":},"west":{"uv":,"uv_size":},"down":{"uv":,"uv_size":[-16,-3]}}}]},{"name":"upper","parent":"door_root","pivot":,"texture_meshes":[{"position":,"rotation":,"local_pivot":,"scale":,"texture":"upper"},{"position":,"rotation":,"local_pivot":,"scale":,"texture":"upper"},{"position":,"rotation":,"local_pivot":,"scale":,"texture":"upper"}]}]}]}
然后是附着物和动画。
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "supplementary:chocolate_door",
"materials": {
"default": "entity_alphatest",
"enchanted": "entity_alphatest_glint"
},
"textures": {
"default": "textures/blocks/chocolate_door_bottom",
"upper": "textures/blocks/chocolate_door_top",
"lower": "textures/blocks/chocolate_door_bottom",
"enchanted": "textures/misc/enchanted_item_glint"
},
"geometry": {
"default": "geometry.door_render"
},
"animations": {
"hold_first_person": "animation.door.hold_first_person",
"hold_third_person": "animation.door.hold_third_person"
},
"scripts": {
"animate": [
{
"hold_first_person": "c.is_first_person"
},
{
"hold_third_person": "!c.is_first_person"
}
]
},
"render_controllers": [
"controller.render.item_default"
]
}
}
}
//以上是附着物,以下是动画。
{
"format_version": "1.10.0",
"animations": {
"animation.door.hold_first_person": {
"loop": true,
"bones": {
"door_root": {
"rotation": [
27,
-39,
-159
],
"position": [
0,
14.5,
2.4
]
}
}
},
"animation.door.hold_third_person": {
"loop": true,
"bones": {
"door_root": {
"rotation": [
-20,
-32.5,
0
],
"position": [
0,
19,
-4
],
"scale": 0.65
}
}
}
}
}
最后是纹理和文本。
//blocks.json
"chocolate_door": {
"sound": "mud_bricks"
}
//terrain_texture.json
"chocolate_door_upper": {
"textures": "textures/blocks/chocolate_door_top"
},
"chocolate_door_lower": {
"textures": "textures/blocks/chocolate_door_bottom"
}
//zh_CN.lang
tile.supplementary:chocolate_door.name=巧克力门
https://klpbbs.com/static/image/hrline/line3.png
总结
这一期,我们制作了一个与原版极其相似的门。
最后,我放出我为这个门做的纹理,以及所有的示例文档,可以参考一下。
第四十二期 第四十三期 第四十四期
页: [1]