跳到主要内容

可使用物品 v2

下载

本包用于创建一个可右键使用的物品

在实际工程中,难免会遇到一些需要右键使用物品的情况。这时候我们希望物品右键使用之后能够有一些反应,例如运行函数。本包基于两种不同的原理,实现了右键物品执行函数的功能。正常情况下,我们强烈推荐使用第 1 种包。

  1. 国际版和中国版各自的脚本系统。
    • 优点:易于维护和自定义;限制少,可适用于原版物品;使用方法简单
    • 缺点:需要分别对两个版本做适配。
  2. 玩家动画控制器。
    • 优点:天生支持两个版本,理解门槛相对较低。
    • 缺点:因为修改了player.json,侵入性强,高版本兼容性会比较差;只能适用于真正的可使用物品,无法应用到原版的一切物品上;不易于维护和自定义。

本包为行为包资源包组合的包。

温馨提示

本文假定您已经能够独立编写属于自己的自定义物品。如果您还不能编写自定义物品,请阅读模块 3 的教程:1.1 数据驱动物品


文件架构

  • BP_usable_item_script基于脚本原理的自定义物品行为包
    • functions:函数
      • items:物品执行的函数
        • usable_item.mcfunction:对于namespace:id的物品,自动执行items/(id)函数
    • items:物品定义
      • template:分类(建议换名)
        • usable_item.item.json:自定义物品定义
    • scripts:脚本
      • main.js:(有冲突风险)国际版脚本,使用@minecraft/server@1.7.0版本
      • __init__.py:(有冲突风险)中国版脚本
      • modMain.py:(有冲突风险)中国版脚本入口文件
      • templateClient.py:(有冲突风险)中国版脚本客户端文件,目前暂时没用到
      • templateServer.py:(有冲突风险)中国版脚本服务端文件
    • manifest.json:(有冲突风险)清单文件,包含脚本信息
    • pack_icon.png:包图标
  • BP_usable_item_ac基于动画控制器原理的自定义物品行为包
    • animation_controllers:动画控制器
      • player.animation_controllers.json:(有冲突风险)玩家执行的动画控制器
    • entities:实体定义
      • vanilla:原版实体
        • player.json:(有冲突风险)玩家的实体定义,用于执行动画控制器
    • functions:同基于脚本原理
      • items:同基于脚本原理
        • usable_item.mcfunction:同基于脚本原理
    • items:同基于脚本原理
      • template:同基于脚本原理
        • usable_item.item.json:同基于脚本原理,但存在一定的差别
    • manifest.json:清单文件
    • pack_icon.png:包图标
  • RP_usable_item自定义物品资源包
    • texts:翻译文本
      • zh_CN.lang:(有冲突风险)中文翻译文本
      • en_US.lang:(有冲突风险)英文翻译文本
    • textures:贴图
      • items:物品贴图
        • usable_item.png:自定义物品贴图
      • item_texture.json:(有冲突风险)物品贴图定义
    • manifest.json:清单文件
    • pack_icon.png:包图标

合并到您的包中

如果您选择使用基于脚本原理的包,请合并BP_usable_item_scriptRP_usable_item到您的包中。

如果您选择使用基于动画控制器原理的包,请合并BP_usable_item_acRP_usable_item到您的包中。

其中可能会出现多个文件冲突。如果在粘贴过程中遇到冲突,请务必选择跳过这些文件而非覆盖您原有的文件,并按照下面可能需要修改的文件列表进行选择性粘贴。

合并时可能需要修改的文件(基于脚本原理的行为包)

以下文件可能和您已有的包产生冲突。在复制这些文件时,如果产生冲突,请注意以下文件不能直接复制,需要视情况手动粘贴其中的内容

  • BP/manifest.json,应当加入国际版脚本所对应的dependenciesmodules。如果不打算支持国际版,可忽略。使用@minecraft/server1.x.x版本原则上都不会出现问题。
  • BP/scripts/main.js,在您已经使用国际版脚本的情况下可能产生冲突,请自行将相关代码整合到您的包内。
  • BP/scripts/*.py,在您已经使用中国版脚本的情况下可能产生冲突,请自行将相关代码整合到您的包内。

以下文件中的自定义内容使用了字段template,然而我们不推荐您在您的作品中使用该字段。在正式使用本包之前,您应当将这些字段按您的需求进行改动。

  • BP/items/template/*,包括template文件夹在内的所有文件
  • BP/scripts/*.py,应当把文件内所有的template全部换成您专属的统一字段(例如命名空间),然后更改名称。
更改示例:将中国版脚本的所有template全部更换为adventureWorld

其中还有一些Tutorial的残留,虽然不碍事,但也请一并改掉。其中,15 行和 23 行的方法的第 3 个参数(比如scripts.adventureWorldServer.adventureWorldServerSystem)是文件路径,所以这里千万不要写错,不要遗漏什么东西。

modMain.py
# -*- coding: utf-8 -*-

from mod.common.mod import Mod
import mod.server.extraServerApi as serverApi
import mod.client.extraClientApi as clientApi

@Mod.Binding(name = "adventureWorldMod", version = "1.0.0")
class adventureWorldMod(object):

def __init__(self):
pass

@Mod.InitServer()
def AdventureWorldServerInit(self):
serverApi.RegisterSystem("adventureWorldMod", "adventureWorldServerSystem", "scripts.adventureWorldServer.adventureWorldServerSystem")

@Mod.DestroyServer()
def AdventureWorldServerDestroy(self):
pass

@Mod.InitClient()
def AdventureWorldClientInit(self):
clientApi.RegisterSystem("adventureWorldMod", "adventureWorldClientSystem", "scripts.adventureWorldClient.adventureWorldClientSystem")

@Mod.DestroyClient()
def AdventureWorldClientDestroy(self):
pass

客户端脚本。注意改文件名。

adventureWorldClient.py
# -*- coding: utf-8 -*-

import mod.client.extraClientApi as clientApi
ClientSystem = clientApi.GetClientSystemCls()

class adventureWorldClientSystem(ClientSystem):

def __init__(self, namespace, systemName):
super(adventureWorldClientSystem, self).__init__(namespace, systemName)

服务端脚本。注意改文件名。其中itemUse函数内的大段注释是对应的 SAPI 代码,可删去。

adventureWorldServer.py
# -*- coding: utf-8 -*-

import mod.server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()
compFactory = serverApi.GetEngineCompFactory()

usableItems = [ "template:usable_item" ]

class adventureWorldServerSystem(ServerSystem):

def __init__(self, namespace, systemName):
super(adventureWorldServerSystem, self).__init__(namespace, systemName)
self.levelId = serverApi.GetLevelId()
self.subscribe()

def subscribe(self):
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ItemUseAfterServerEvent", self, self.itemUse)

def unsubscribe(self):
pass

def itemUse(self, event):
source = event["entityId"]
itemStack = event["itemDict"]

# world.afterEvents.itemUse.subscribe( event => {
# if ( usableItems.includes( event.itemStack.typeId ) ) {
# event.source.runCommand( `function items/${event.itemStack.typeId.split(":")[1]}` );
# }
# } )

if itemStack["newItemName"] in usableItems:
compFactory.CreateCommand(self.levelId).SetCommand("/function items/{}".format(itemStack["newItemName"].split(":")[1]), source, False)

合并时可能需要修改的文件(基于动画控制器原理的行为包)

以下文件可能和您已有的包产生冲突。在复制这些文件时,如果产生冲突,请注意以下文件不能直接复制,需要视情况手动粘贴其中的内容

  • BP/animation_controllers/player.animation_controllers.json,在您已经使用玩家动画控制器的情况下可能产生冲突,请自行将相关代码整合到您的包内。
  • BP/entities/vanilla/player.json,在您已经更改玩家行为的情况下可能产生冲突,请自行将相关代码整合到您的包内。

以下文件中的自定义内容使用了字段template,然而我们不推荐您在您的作品中使用该字段。在正式使用本包之前,您应当将这些字段按您的需求进行改动。

  • BP/items/template/*,包括template文件夹在内的所有文件

合并时可能需要修改的文件(资源包)

以下文件可能和您已有的包产生冲突。在复制这些文件时,如果产生冲突,请注意以下文件不能直接复制,需要视情况手动粘贴其中的内容

  • RP/texts/*.lang
  • RP/textures/item_texture.json

以下文件中的自定义内容使用了字段template,然而我们不推荐您在您的作品中使用该字段。在正式使用本包之前,您应当将这些字段按您的需求进行改动。

  • RP/texts/*.lang

使用方法(基于脚本原理)

合并完成之后,按照下面的方法实现可使用的自定义物品。

基本原理

本包的基本原理

使用国际版的world类的后事件itemUse订阅玩家使用物品,以及中国版的ItemUseAfterServerEvent事件监听玩家使用物品,使其执行一个相同的函数,该函数路径由物品的 ID 决定。

基本注册步骤

  1. 在国际版脚本注册您要指定的可使用物品的 ID(带命名空间,可以指定原版物品),位于该文件第 6 行:
BP/scripts/main.js
/** 可执行命令的物品 */
const usableItems = [ "template:usable_item" ];
  1. 在中国版服务端脚本注册您要指定的可使用物品的 ID(带命名空间,可以指定原版物品),位于该文件第 7 行:
BP/scripts/(???)Server.js
usableItems = [ "template:usable_item" ]
  1. 然后,更改BP/functions/items/(物品ID,不带命名空间).mcfunction即可实现使用该物品调用该函数。
    • 例如,指定了可使用物品为minecraft:stick后,使用物品会执行items/stick函数。

其他自定义物品的适用性

其他自定义物品也可以使用类似的方法注册。使用本原理的自定义物品无需指定食物、投掷物等可用属性,只要定义其最基本的属性即可。

使用方法(基于玩家动画控制器原理)

合并完成之后,按照下面的方法实现可使用的自定义物品。

基本原理

本包的基本原理

修改玩家的实体定义player.json,使其执行到一个玩家行为包动画控制器上,通过 Molang 检测玩家手持物品是否为该物品,并且玩家是否正在使用物品,即可实现可使用物品的检测。

基本注册步骤

  1. 打开玩家动画控制器,将您要注册的可使用的物品(必须为食物、投掷物等可使用的物品类型)按照下面的方式注册:
BP/animation_controllers/player.animation_controllers.json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.player.item_using_test": {
"states": {
"default": {
"transitions": [
{ "is_using_usable_item": "query.is_item_name_any('slot.weapon.mainhand', 0, 'template:usable_item') && query.is_using_item" }
]
},
"is_using_usable_item": {
"on_entry": [ "/function items/usable_item" ],
"transitions": [
{ "default": "!query.is_item_name_any('slot.weapon.mainhand', 0, 'template:usable_item') || !query.is_using_item" }
]
}
}
}
}
}

举例:注册一个 ID 为mcdevdoc:settings的物品
BP/animation_controllers/player.animation_controllers.json
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.player.item_using_test": {
"states": {
"default": {
"transitions": [
{ "is_using_usable_item": "query.is_item_name_any('slot.weapon.mainhand', 0, 'template:usable_item') && query.is_using_item" },
{ "is_using_settings": "query.is_item_name_any('slot.weapon.mainhand', 0, 'mcdevdoc:settings') && query.is_using_item" }
]
},
"is_using_usable_item": {
"on_entry": [ "/function items/usable_item" ],
"transitions": [
{ "default": "!query.is_item_name_any('slot.weapon.mainhand', 0, 'template:usable_item') || !query.is_using_item" }
]
},
"is_using_settings": {
"on_entry": [ "/function items/settings" ],
"transitions": [
{ "default": "!query.is_item_name_any('slot.weapon.mainhand', 0, 'mcdevdoc:settings') || !query.is_using_item" }
]
}
}
}
}
}

  1. 然后,更改BP/functions/items/(物品ID,不带命名空间).mcfunction即可实现使用该物品调用该函数。
    • 函数路径由on_entry定义的路径决定。

其他自定义物品的适用性

其他自定义物品也可以使用类似的方法注册。使用本原理的自定义物品必须指定食物、投掷物等可用属性,因此不能指定原版物品中非食物、投掷物等不可使用物品。此外,它也导致该物品是可能会被消耗掉的,所以请使用minecraft:use_modifiers将该物品的使用时间设置得尽可能长。示例可以参见我们给出的例子。

实例

当玩家使用木棍时,如果玩家手里有 4 个以上木棍则给予其 2 个木板

该功能只能适用基于脚本原理的包实现。首先按照合并指南完成包合并。然后按照基本注册步骤完成物品注册,如下所示。

BP/scripts/main.js
/** 可执行命令的物品 */
const usableItems = [ "template:usable_item", "minecraft:stick" ];
BP/scripts/(???)Server.js
usableItems = [ "template:usable_item", "minecraft:stick" ]

最后,定义一个函数items/stick,写入下面的内容即可。

BP/functions/items/stick.mcfunction
execute if entity @s[hasitem={item=stick,quantity=4..}] run give @s oak_planks 2
execute if entity @s[hasitem={item=stick,quantity=4..}] run clear @s stick -1 4

更新日志

相比于 v1 版本,v2 版本主要进行了如下更改:

  • 提升了最低版本需求为 1.20.50。
  • 示例的自定义物品的格式版本升级到 1.20.50,以同时适用于国际版和中国版。
  • 加入了对双端脚本的支持。

过往版本下载

您可以在这里下载到过往版本。然而,我们已不再推荐使用这些旧版本。

下载 v1 版本