Minecraft基岩版开发Wiki:技术周报/21m02w04a

来自Minecraft基岩版开发Wiki
assignment 21m02w04a | event 2021/2/28 | confirmation_number 第三期

edit history refresh

navigate_before 21m02w03a | 21m02w04a | 21m03w01a navigate_next

技术更新[编辑]

官方Beta[编辑]

本周官方发布了Beta 1.16.210.61更新,其中并无技术更新。

技术茶馆[编辑]

本周主题:《中国版 Mod API 引擎系统构建》

文案:月光独奏

在上周的周报中,我们介绍了网易ModAPI引擎的基本结构以及如何初始化引擎,这次我们来讲如何构建一个系统。

系统是整个 Mod API 的核心基础,所有操作都必须基于系统之上进行。

导入库[编辑]

与当前的最新版本不同,网易使用的是 python2 。在整个脚本文件的开头,我们需要一行特殊的注释以保证文件能够在含中文的情况下正常运行。

# -*- coding: utf-8 -*-

接下来,使用 python 的 import 方法导入网易的 mod 库,以及任何你想使用的库(例如存放变量的文件)。

需要注意的一点是,服务端系统与客户端系统使用的是两套不同的库,导入时需要注意。若是在一端的系统内使用了另一端的 API ,很可能会导致严重的错误。

下为服务端的导入示例:

import mod.server.extraServerApi as serverApi
...

客户端:

import mod.client.extraClientApi as clientApi
...

构建 System 类[编辑]

在导入了所有需要的库之后,就可以开始构建系统类了。同样的,客户端和服务端的构建操作有着一些细微的差异。下面给出代码示例。

服务端:

ServerSystem = serverApi.GetServerSystemCls()
class ServerSystem(ServerSystem):
    def __init__(self, namespace, systemName):
        super(ServerSystem, self).__init__(namespace, systemName)

客户端:

ClientSystem = clientApi.GetClientSystemCls()
class ClientSystem(ClientSystem):
    def __init__(self, namespace, systemName):
        super(ClientSystem, self).__init__(namespace, systemName)

注意:此处类的名称(即class后面的字符)一定要与在Modmain中注册的类名称一致!否则会导致引擎无法找到类造成构建失败(以及一大堆红色字符!)(笑)

对游戏进行修改[编辑]

到此为止,我们的系统其实已经构建完成了。但是若想让它真正发挥作用,还必须通过监听事件以对游戏进行修改。下面给出一个完整服务端系统的代码示例进行解析。

# -*- coding: utf-8 -*-

import server.extraServerApi as serverApi
import modConfig as config
#获取System类以继承创建自己的类
ServerSystem = serverApi.GetServerSystemCls()

class ServerSystem(ServerSystem):

    def __init__(self, namespace, systemName):
        super(ServerSystem, self).__init__(namespace, systemName)
        #建议将监听事件和反监听事件单独写成函数,并将两个函数放在一起,这样方便增删事件。
        self.ListenEvent()

    def ListenEvent(self):
        #监听事件用函数ListenForEvent,参数分别为[事件来源Mod名][事件来源System][事件名称][回调函数所在类][回调函数]。
        #前两个参数处的函数是API中提供的快速获取Mod名和System名的函数,可以在监听内置事件时使用。
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "OnCarriedNewItemChangedServerEvent", self, self.book)
        #下面是监听自定义事件的一个示例,参数类型和上面相同,使用了config模块快速导入变量。
        self.ListenForEvent(config.modName, config.ClientSystemName, "GetName", self, self.GetName)

    def UnListenEvent(self):
        #反监听事件函数,内容基本和上面相同,除了多了几个字母以外(雾)
        self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "OnCarriedNewItemChangedServerEvent", self, self.book)
        self.UnListenForEvent(config.modName, config.ClientSystemName, "GetName", self, self.GetName)

    def book(self, args):
        #OnCarriedNewItemChangedServerEvent的回调函数,args为事件传递过来的字典,详细内容请见官方文档。
        #创建name组件,以达到获取或修改当前游戏内容的效果。详细内容请见官方文档。
        name = serverApi.CreateComponent(args["playerId"],"Minecraft","name")
        playerName = name.GetName()
        data = {"playerId": args["playerId"], "playerName": playerName}
        if args["newItemName"] == config.guideUiItem:
            self.NotifyToClient(args["playerId"], "bookRender", data)
        if args["oldItemName"] == config.guideUiItem:
            self.NotifyToClient(args["playerId"], "bookRenderDestroy", args["playerId"])

    def GetName(self, args):
        #自定义事件GetName的回调函数。
        name = serverApi.CreateComponent(args["playerId"],"Minecraft","name")
        playerName = name.GetName()
        data = {"playerId": args["playerId"], "playerName": playerName}
        #向指定客户端发送名为initRender的自定义事件,传入的值为data。
        self.NotifyToClient(args["playerId"], "initRender", data)

    def Destroy(self):
        #Destroy是系统内置方法,在引擎被摧毁时会自动调用,此时可以反监听事件。
        # 清楚system的时候调用取消监听事件
        self.UnListenEvent()

客户端系统的构建同理。

结语[编辑]

到此为止,Mod API 引擎的基本构建已经彻底完成了,接下来的步骤就是根据自己的想法,选择事件进行监听、修改来定义你心目中的那个 Minecraft 了。

内置事件和其传入值、内置组件可以查看官方文档获取。

当然,这些东西并不是脚本的全部————在脚本中,还有一个非常特殊的存在,那就是自定义 UI 。不过对于初学者来说,自定义 UI 是一项大挑战。如果要进行 UI 开发,建议在熟悉系统的工作方式之后解析官方示例进行学习。

最后,送给大家一个仅注册了一个空服务端和一个空客户端的脚本文件夹示例,以帮助大家更快地收拾这些极其麻烦的步骤【其实官方示例也不是完全空白,而是带有一些逻辑的,还要修改不少地方才能用。我在这里准备的是完全没有任何附加逻辑的空文件夹,解压到行为包里,修改注册名称之后就可以开始制作了】

下载地址:https://xmariohux.lanzous.com/inOOjlyiaud

编辑的时候记得先改文件夹名字啊!(笑)

别问我为什么,问就是把两个包打一起用的时候总是注册失败,然后折腾了几个小时才发现是因为文件夹名字重了,我先在这说一下,避免大家被坑到(

有缘再见!

你知道吗[编辑]

  • 这周 Mojang 的更新日志只有三个条目。
  • 这周 Mojang 依然没有更新任何脚本引擎相关的内容。