教程:开发模组API/构建系统与监听事件

From Minecraft基岩版开发Wiki

< 编辑、调试、打包与作品上传 | 在事件下使用组件 >

导读[edit]

在建立了基本的环境之后,便可以着手开始构建系统了。

本章将会介绍模组API引擎最基本的用法。

注册系统[edit]

系统需要一个名为 modMain.py 的文件进行注册。该文件应在脚本文件夹的第一层,且不可缺少。modMain 是 Python 逻辑的入口文件,需要包含 mod 初始化与退出时的处理函数。

下面是一个 modMain 实例,对该文件的结构进行解释。

Mod 属于 SDK 的内部类,用于绑定

from mod.common.mod import Mod

# 分别导入服务端与客户端的API进行绑定

import mod.server.extraServerApi as serverApi

import mod.client.extraClientApi as clientApi

# 将引擎的方法绑定到类上用于识别

@Mod.Binding(name = "testMod", version = "0.0.1")

class testMod(object):

    def __init__(self):

        pass

    # 服务端脚本初始化的入口函数
    #当然,如果您不需要服务端,您可以直接pass掉它

    @Mod.InitServer()

    def testServerInit(self):

        serverApi.RegisterSystem("testMod", "testModServer", "Scripts.ServerSystem.ServerSystem")
    #RegisterSystem的三个参数分别是[Mod名称][System名称][System类路径](路径从行为包根目录开始计算,中间以“.”隔开而不是“/”。下面客户端注册同理)

    # 服务端脚本在退出时执行的析构函数

    @Mod.DestroyServer()

    def testServerDestroy(self):

        pass

    # 客户端脚本初始化的入口函数

    @Mod.InitClient()

    def testClientInit(self):

        clientApi.RegisterSystem("testMod", "testModClient", "Scripts.ClientSystem.ClientSystem")

    # 客户端脚本在退出时执行的析构函数

    @Mod.DestroyClient():

    def testClientDestroy(self):

        pass

#备注:建议将Mod名称、版本号等需要在多处地方使用的量保存在一个单独的模块文件里,以便将来维护修改。

构建系统[edit]

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

构建系统时必须确保该系统在ModMain中被正确注册,否则会导致报错或未被启用。

导入库[edit]

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

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

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

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

下为服务端的导入示例:

import mod.server.extraServerApi as serverApi
...

客户端:

import mod.client.extraClientApi as clientApi
...

构建 System 类[edit]

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

服务端:

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中注册的类名称一致!否则会导致引擎无法找到类造成构建失败(以及一大堆红色字符!)

对游戏进行修改[edit]

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

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

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

class ServerSystem(ServerSystem):

      #类的init函数,会在类初始化时自动执行。
    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()

客户端系统的构建同理。

结语[edit]

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

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

因为官方的脚本模板并非完全空白,删去多余功能很浪费时间,所以这里附赠一个完全空白的脚本文件夹模板。

下载地址:https://pan.baidu.com/s/1XjOTj116IDNFs-abM5Tjdg (提取码:ogms)

你知道吗[edit]

  • 脚本文件夹名称的重复会导致严重错误,所以请尽量使用更加独特的名称(如 工作室名+Mod名+"Scripts")
  • 上面示例中的Config模块其实是一个自定义文件,通过Python导入,其中可以存放任何你想要存放的变量(如系统名称和路径),方便统一修改。

< 编辑、调试、打包与作品上传 | 在事件下使用组件 >