Skip to content

入口脚本

在游戏运行时,将自动扫描行为包(Behavior-Pack,简称 BH,请牢记此缩写)中的 modMain.py 文件,并将其作为入口脚本执行。

modMain入口

modMain.py 是入口模块,其具体位置并未被强制规定,但通常建议将其放置在 BH/<符合命名规范的项目名称>/modMain.py 路径,以便于管理和维护。

基本内容

通常来说一个官方的入口加载逻辑有以下内容

python
# -*- coding: utf-8 -*-
from mod.common.mod import Mod
import mod.server.extraServerApi as serverApi
import mod.client.extraClientApi as clientApi

@Mod.Binding(name = "<符合命名规范的MOD名称>", version = "1.0.0")
class MyMod(object):    # 类名是什么无所谓 网易历史遗留的加载器扫描方式
    @Mod.InitServer()
    def serverInit(self):
        pass

    @Mod.InitClient()
    def clientInit(self):
        pass

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

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

编码问题

由于网易采用的Python版本是2.7.18默认仅支持ASCII源代码字符,若需中文支持请在顶部使用声明语句。

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

模块解析

静态类 mod.common.mod.Mod,通常来说需要其中的@Mod.xxx装饰器,用来标记Mod加载逻辑。

python
from mod.common.mod import Mod

端侧API serverApi clientApi,包含服务端和客户端所需的游戏接口,如您所见 MC是网络游戏设计模式。

python
# 使用 as 语句重新命名别名 方便调用
import mod.server.extraServerApi as serverApi
import mod.client.extraClientApi as clientApi

MOD加载流程

1.扫描加载类

MOD加载器将自动搜索所有@Mod.Binding标记的类,并在对应的服务端客户端线程执行

python
@Mod.Binding(name = "...", version = "1.0.0")
class MyMod_1(object):
    # MOD加载器会自动构造该class
    ...

@Mod.Binding(name = "...", version = "1.0.0")
class MyMod_2(object):
    # 同上
    ...

class OtherCls(object):
    # 无@Mod.Binding修饰 不会被自动构造执行
    pass
...

2.线程环境执行

@Mod.InitServer用于标记是服务端的执行入口,@Mod.InitClient则是客户端的执行入口

python
@Mod.Binding(name = "...", version = "1.0.0")
class MyMod(object):
    # 标记为端侧的入口执行方法,用于初始化您的MOD业务
    @Mod.InitServer()
    def serverInit(self):
        # 服务端加载时执行
        pass

    @Mod.InitClient()
    def clientInit(self):
        # 客户端加载时执行
        pass

    # 同理,对应端侧关闭时的执行方法(析构),可用于作回收逻辑(若有需要)。
    @Mod.DestroyServer()
    def serverDestroy(self):
        pass

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

注意:类名/方法名取什么都无所谓,扫描器只识别特定标记(注解)。

游戏线程环境

环境类型描述
服务端处理游戏的真实数据,如生物血量、位置、属性数据、物理引擎等。
客户端负责画面渲染、用户操作、GUI 等逻辑,如渲染服务端传递的生物位置信息。
------------------------------------------------------------
单人模式房主同时加载服务端与客户端,模拟网络环境。
联机模式房主加载服务端与客户端,其他成员仅加载客户端。
网络游戏服务端由网易服务器运行,所有玩家仅加载客户端。

第一个MOD项目

在了解了以上信息后,接下来可以进入正式开发环节。此处我们假设项目所在路径: BH/TestMod/modMain.py

注册服务端业务

通俗点来说就是加载特定的业务文件

python
# 注意@Mod.Binding的参数,若有多个MOD持有相同的name只会加载版本号最高的一代
# 大多数情况下我们并不需要这个功能,因此请确保您的名称独一无二。
@Mod.Binding(name = "TestMod", version = "1.0.0")
class MyMod(object):

    # @Mod.InitServer 只有服务端环境的持有者会加载这部分
    @Mod.InitServer()
    def serverInit(self):
        # 使用serverApi注册(加载)一个系统类
        serverApi.RegisterSystem("test", "ser1", "TestMod.Server.MyServer")

参数说明:

  • serverApi.RegisterSystem("命名空间", "系统名", "模块路径.类名"):
    • 命名空间: 用于区分不同模块的标识,例如 minecraft:zombie 中的 minecraft
    • 系统名: 系统的唯一名称,用于标识注册的系统,例如 zombie
    • 模块路径.类名: 从 BH 目录开始,使用点号分隔的文件路径和类名。例如 TestMod.Server.MyServer

示例解析:

  • 模块路径: TestMod(文件夹).Server(文件).MyServer(类名)
    • 对应文件路径: TestMod/Server.py 中的 class MyServer
  • 命名空间: 早期用于模块隔离的设计,通过命名空间+名称组合减少重复的可能性。
    • 注意: 网易的 Python 环境未实现严格隔离,因此需要通过命名区分模块,避免多 MOD 冲突导致未定义行为。

编写服务端业务

根据我们的注册路径TestMod.Server.MyServer新建对应的文件并编写MyServer

python
# -*- coding: utf-8 -*-
# 文件:BH/TestMod/Server.py
import mod.server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()   # 获取服务端基类

# 定义MyServer类 正如注册参数上所写
class MyServer(ServerSystem):
    def __init__(self, namespace, systemName):
        ServerSystem.__init__(self, namespace, systemName)
        print("服务端业务初始化")
    
    # 系统类相关讲解请见后文
    ...

总结

MOD 加载器的核心流程如下:

  1. 加载器扫描 modMain.py 文件。
  2. 执行端侧初始化/销毁方法(服务端或客户端)。
  3. 加载具体业务逻辑(一般另外注册文件)。

如果对加载逻辑不熟悉,可以参考本文示例,逐步实现。

[MOD加载器] -> 扫描 -> modMain.py
modMain.py -> 提供 -> 不同端侧的处理方法
端侧处理方法 -> 加载 -> 具体业务文件

提示

使用QuModLibs框架可以简化开发流程,提升效率,但本篇仅讲解原版开发框架,稍后您可以单独了解。

Released under the BSD3 License