
# 什么是 MODSDKSpring
MODSDKSpring 是一个非官方的,由魔灵工作室-创造者MC制作的,在网易我的世界 MODSDK 基础上开发的框架。目的是为了简化并规范网易我的世界 [MOD](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/1-Mod%E5%BC%80%E5%8F%91%E7%AE%80%E4%BB%8B/1-Mod%E7%AE%80%E4%BB%8B.html) 的开发。
# 为什么要用 MODSDKSpring
MODSDKSpring 定义了一系列的装饰器(就像您在 modMain.py 中看到的 @Mod.InitClient() 这种写法),避免了自己写 self.ListenForEvent 去监听事件。另外,MODSDKSpring 借鉴了 Java 语言中的知名框架 Spring 的相关概念,实现了针对 MODSDK 的控制反转和依赖注入。
具体而言,框架可以做到只注册一个客户端类和服务端类,就能像注册了多个客户端类和服务端类那样,每个模块(.py 文件)各司其职,自己监听需要监听的事件并在模块内处理。这样一来,我们可以设计出更合理的 Mod 结构,不必在单个 `.py` 文件中把所有功能都耦合到一起。
上面的描述如果没看懂也没关系,在接下来的快速入门中,您将直观的感受到使用 MODSDKSpring 所带来的便捷。
# Python 版本
因为网易我的世界 MODSDK 使用的是 [python 2.7.18](https://www.python.org/downloads/release/python-2718/),所以此框架也使用相同的版本。
# 框架下载
```shell
pip install mc-creatormc-sdkspring
```
如果您安装了 Python2 和 Python3,您可能需要使用下方的命令去下载。
```shell
pip2 install mc-creatormc-sdkspring
```
# 示例代码
本文档中的教程源码,均可在仓库中的 [example](https://github.com/CreatorMC/MODSDKSping/tree/example) 分支中查看。
# 快速入门
> 快速入门教程改造自网易我的世界开发者官网 DemoMod 中的 [TutorialMod](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/60-Demo%E7%A4%BA%E4%BE%8B.html#TutorialMod)。您在阅读本篇教程时,可与官方代码进行对照,感受 MODSDKSpring 的便捷。
> 教程开始前,请确保您已经下载并安装了 [python 2.7.18](https://www.python.org/downloads/release/python-2718/)、[MODSDKSpring](#%E6%A1%86%E6%9E%B6%E4%B8%8B%E8%BD%BD) 以及 [ModSDK 补全库](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E5%AE%89%E8%A3%85mod-sdk%E8%A1%A5%E5%85%A8%E5%BA%93)。
> 虽然 [ModSDK 补全库](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E5%AE%89%E8%A3%85mod-sdk%E8%A1%A5%E5%85%A8%E5%BA%93) 理论上不是必须的,但安装后可以帮助您的代码编辑器使用语法补全等功能。
> 本教程假设您对 MODSDK 已经有了基本的了解,理解基础的事件监听与回调机制。如果您还不了解,请参考 [官方教程](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1) 自行学习。
1. 创建文件夹
首先,创建一个如下所示的行为包结构。
```txt
TutorialMod
└── tutorialBehaviorPack
├── entities
└── manifest.json
```
其中,manifest.json 文件内的内容如下。
```json
{
"format_version": 2,
"header": {
"name": "MODSDKSpring教程行为包",
"description": "作者:创造者MC",
"uuid": "a44ca707-044d-47c4-ab75-d0568eef5d00",
"version": [1 ,0 ,0],
"min_engine_version": [1 ,18 ,0]
},
"modules": [
{
"description": "作者:创造者MC",
"uuid": "627b21f9-f6e5-44f1-82d3-4f3249606e20",
"version": [1,0,0],
"type": "data"
}
]
}
```
2. 自动生成 Mod 结构
MODSDKSpring 提供了命令行形式的自动生成工具,能够自动生成包含 MODSDKSpring 的初始的 Mod 结构。
如果您的电脑是 Windows 系统,在 `TutorialMod/tutorialBehaviorPack` 文件夹内的地址栏上输入 `cmd` 并按下 `Enter` 键,即可在当前位置打开一个命令行窗口。

接着输入以下命令:
```shell
modsdkspring init
```
您会在命令行窗口看到如下输出:
```shell
Start initializing your Mod...
Please enter the name of the Mod folder:
```
请注意,如果您看到的是:
```shell
'modsdkspring' 不是内部或外部命令,也不是可运行的程序或批处理文件。
```
说明您还没有下载并安装 MODSDKSpring。请查看本文档上方的 [框架下载](#%E6%A1%86%E6%9E%B6%E4%B8%8B%E8%BD%BD) 部分,然后重复此步骤。或者,您可能没有正确配置系统的环境变量,请自行搜索解决。
接下来按照提示 Please enter the name of the Mod folder(请输入 Mod 文件夹的名称),输入以下名称后按 `Enter` 键。
```shell
tutorialScripts
```
接着出现提示 Please enter the Mod name, which will serve as the namespace registered to the engine(请输入Mod名称,该名称将作为注册到引擎的命名空间),继续输入以下内容后按 `Enter` 键。
```shell
TutorialMod
```
接着出现提示 Please enter the client system name, which will serve as the class name for the client system(请输入客户端系统名称,该名称将作为客户端系统的类名),继续输入以下内容后按 `Enter` 键。
```shell
TutorialClientSystem
```
接着出现提示 Please enter the server system name, which will serve as the class name for the server system(请输入服务端系统名称,该名称将作为服务端系统的类名),继续输入以下内容后按 `Enter` 键。
```shell
TutorialServerSystem
```
最后出现提示 Created successfully!

此时查看文件夹结构,您应该得到了如下所示的结构:
```txt
TutorialMod
└── tutorialBehaviorPack
├── entities
├── tutorialScripts
│ ├── components
│ │ ├── client
│ │ │ └── __init__.py
│ │ ├── server
│ │ │ └── __init__.py
│ │ └── __init__.py
│ ├── modCommon
│ │ ├── __init__.py
│ │ └── modConfig.py
│ ├── plugins
│ │ ├── MODSDKSpring
│ │ │ └── ...
│ │ └── __init__.py
│ ├── __init__.py
│ ├── modMain.py
│ ├── TutorialClientSystem.py
│ └── TutorialServerSystem.py
└── manifest.json
```
现在,这个 Mod 已经可以直接放入游戏中运行了。
3. Mod 结构介绍
> 如果您已经会使用 MODSDK 了,那么这一部分快速浏览一遍即可。
- \_\_init\_\_.py
python2 中,每个包含 `.py` 文件的文件夹内都需要一个 `__init__.py` 文件。
- modMain.py
此文件是 Python 逻辑的入口文件,需要在这里定义哪个类是客户端,哪个类是服务端,以及 Mod 的名称和版本。
实际上,您可以在 `modMain.py` 中,创建多个 `class`,以此创建多个 Mod。但在 MODSDKSpring 中,我们不推荐这样做。因为 MODSDKSpring 的架构,已经解决了这样做所带来的“好处”。尽管如此,为了框架的灵活性和对现有项目的改造,MODSDKSpring 仍然兼容在同一个 `modMain.py` 中定义多个 Mod 的写法。在后面的部分中,您可以看到相关的写法。
更多关于此文件的详细说明,请参考 [官方文档](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#modmain-py%E6%98%AF%E4%BB%80%E4%B9%88)。
- TutorialClientSystem.py
此文件是 Mod 的客户端。每个玩家都拥有一个独立的客户端,但服务端是当前联机房间内所有玩家共享的。
更多关于此文件的详细说明,请参考 [官方文档](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8E%E5%AE%A2%E6%88%B7%E7%AB%AF)。
- TutorialServerSystem.py
此文件是 Mod 的服务端。每个玩家都拥有一个独立的客户端,但服务端是当前联机房间内所有玩家共享的。
更多关于此文件的详细说明,请参考 [官方文档](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8E%E5%AE%A2%E6%88%B7%E7%AB%AF)。
- components
存放“组件”的文件夹,此处的“组件”,是 MODSDKSpring 的一个概念。在后续的文档中会详细介绍。
其中,`client` 文件夹,存放能调用**客户端**相关 API 的组件。`server` 文件夹,存放能调用**服务端**相关 API 的组件。
- modCommon
存放 Mod 中一些通用的模块。其中,`modConfig.py` 文件中,默认存放了有关 Mod 本身信息的一些常量。
- plugins
插件文件夹,可存放一些额外的第三方模块(通常不是你自己编写的模块)。MODSDKSpring 框架本身被放置在此文件夹中。
4. 监听事件
打开 TutorialServerSystem.py 文件,添加以下代码:
```python
@ListenEvent.Server(eventName="ServerChatEvent")
def OnServerChat(self, args):
print "==== OnServerChat ==== ", args
# 生成掉落物品
# 当我们输入的信息等于右边这个值时,创建相应的物品
# 创建Component,用来完成特定的功能,这里是为了创建Item物品
playerId = args["playerId"]
comp = compFactory.CreateItem(playerId)
if args["message"] == "钻石剑":
# 调用SpawnItemToPlayerInv接口生成物品到玩家背包,参数参考《MODSDK文档》
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_sword", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石镐":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_pickaxe", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石头盔":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_helmet", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石胸甲":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_chestplate", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石护腿":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_leggings", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石靴子":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_boots", "count":1, 'auxValue': 0}, playerId)
else:
print "==== Sorry man ===="
```
最终,整个文件的代码如下:
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
ServerSystem = serverApi.GetServerSystemCls()
compFactory = serverApi.GetEngineCompFactory()
@ListenEvent.InitServer
class TutorialServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
pass
@ListenEvent.Server(eventName="ServerChatEvent")
def OnServerChat(self, args):
print "==== OnServerChat ==== ", args
# 生成掉落物品
# 当我们输入的信息等于右边这个值时,创建相应的物品
# 创建Component,用来完成特定的功能,这里是为了创建Item物品
playerId = args["playerId"]
comp = compFactory.CreateItem(playerId)
if args["message"] == "钻石剑":
# 调用SpawnItemToPlayerInv接口生成物品到玩家背包,参数参考《MODSDK文档》
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_sword", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石镐":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_pickaxe", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石头盔":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_helmet", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石胸甲":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_chestplate", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石护腿":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_leggings", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石靴子":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_boots", "count":1, 'auxValue': 0}, playerId)
else:
print "==== Sorry man ===="
```
上面的代码监听了 [ServerChatEvent](https://mc.163.com/dev/mcmanual/mc-dev/mcdocs/1-ModAPI/%E4%BA%8B%E4%BB%B6/%E4%B8%96%E7%95%8C.html#serverchatevent) 事件,和官方教程一样,当玩家在聊天框中输入指定的文字,就会给予玩家指定的物品。
看到这里,您可能会有几个疑问。不用担心,继续往下看,我马上会向您解释这一切。
5. 代码解释
针对 MODSDKSpring,解释上一步骤中的代码。对于新增装饰器的详细说明,可以查看此文档中的 [装饰器文档](#%E8%A3%85%E9%A5%B0%E5%99%A8%E6%96%87%E6%A1%A3) 部分。
- @ListenEvent.InitServer 是什么?
这是 MODSDKSpring 框架提供的一个装饰器,只能添加到**服务端类**的上方,标识此类是一个服务端。只有添加了这个装饰器,才能启用类内的其他 MODSDKSpring 中的装饰器。注意,使用时最后不要加括号。
类似的还有 @ListenEvent.InitClient。
- @ListenEvent.Server(eventName="ServerChatEvent") 是什么?
这是 MODSDKSpring 框架提供的一个装饰器,只能添加到**服务端类或组件**的方法上。它代替了 self.ListenForEvent,表示此方法要监听的事件,事件的回调方法即是此方法。
其中 `eventName` 表示要监听的事件的名称。除了监听 MODSDK 提供的事件,它还可以监听其他系统发送的自定义事件,详见 [监听自定义事件](#%E7%9B%91%E5%90%AC%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6) 部分。
类似的还有 @ListenEvent.Client。
- \_\_init\_\_ 方法内的 super(XXX, self).\_\_init\_\_(namespace, systemName) 去哪了?
对父类构造方法的调用,已经被封装进了 MODSDKSpring 内部。您不再需要,也不应该手动调用父类构造方法。
- Destroy 方法去哪了?
Destroy 方法已经被封装进了 MODSDKSpring 内部,并且会在系统销毁时自动取消系统中所有的监听。您不需要重写 Destroy 方法了,但是,如果您需要在 Destroy 方法中做除了取消监听以外的事情,您仍然可以重写 Destroy 方法,并且不会影响自动取消监听的功能。
6. 运行
恭喜你!现在可以把上面的行为包放入游戏了。如果您使用网易的我的世界开发者启动器,您应该会在进入游戏时看到如下内容。

在游戏的聊天窗口中输入 `钻石剑`,验证 Mod 是否生效。如果您遇到了问题,可以再仔细看看上面的步骤,或下载 example 分支内的示例。
> 如果您没有看到有关服务端系统的输出,可能是您的日志与调试工具没有及时打开。点击 `工具箱`,使用 `Mod PC开发包` 进入世界存档可解决此问题。
# 定义组件
这里的“组件”,是一个 MODSDKSpring 中的概念。通常情况下,我们会在一个客户端系统或服务端系统中监听很多事件,写很多的回调函数,这就导致我们的代码都耦合在一个文件内,添加和修改都很麻烦。这点在大项目中尤其明显。
针对上述情况,MODSDKSpring 提出了“组件”的概念。所谓“组件”,在功能上可以看作是一个独立的客户端/服务端,组件可以像独立的客户端/服务端那样,自己监听事件并进行处理。这样一来,您可以将一些具有共同特点的功能,单独写成一个 `.py` 文件,再也不用迷失在成百上千行的代码中了。
组件分为两种,一种是客户端组件,一种是服务端组件。无论是客户端组件还是服务端组件,它们都可以有多个。一个组件只属于一个系统。
上面说的这些暂时理解不了没关系,接下来我会带您改造快速入门中的示例,用组件的方式去实现相同的功能。
1. 复制文件夹
复制我们在快速入门中创建的文件夹 `TutorialMod`,并重命名为 `TutorialComponentMod`。
如果您没有跟着快速入门去做也没关系,在仓库的 example 分支中,可以下载快速入门中的代码。
将 `tutorialBehaviorPack` 中的 `tutorialScripts` 文件夹重命名为 `tutorialComponentScripts`。
2. 修改配置
打开 `manifest.json` 修改其中的 `uuid`。UUID 可以使用一些在线网站生成,具体请自行搜索。
打开 `modCommon` 文件夹下的 `modConfig.py` 文件,修改为如下内容:
```python
# -*- coding: utf-8 -*-
# Mod Version
MOD_NAMESPACE = "TutorialComponentMod"
MOD_VERSION = "0.0.1"
# Client System
CLIENT_SYSTEM_NAME = "TutorialClientSystem"
CLIENT_SYSTEM_CLS_PATH = "tutorialComponentScripts.TutorialClientSystem.TutorialClientSystem"
# Server System
SERVER_SYSTEM_NAME = "TutorialServerSystem"
SERVER_SYSTEM_CLS_PATH = "tutorialComponentScripts.TutorialServerSystem.TutorialServerSystem"
```
3. 创建服务端组件
回想一下,我们需要监听 `ServerChatEvent` 事件,此事件是一个服务端事件,所以只能用服务端去监听。因此,我们需要创建一个服务端组件,用来专门做这一件事情。
在 `components` 文件夹内的 `server` 文件夹内,创建一个叫做 `ChatServerComponent.py` 的文件。
文件内代码如下:
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
ServerSystem = serverApi.GetServerSystemCls()
compFactory = serverApi.GetEngineCompFactory()
@ListenEvent.InitComponentServer
class ChatServerComponent(object):
def __init__(self, server):
# 获取服务端系统对象,即 TutorialServerSystem 的对象
self.server = server
# 监听ServerChatEvent的回调函数
@ListenEvent.Server(eventName="ServerChatEvent")
def OnServerChat(self, args):
print "==== OnServerChat ==== ", args
# 生成掉落物品
# 当我们输入的信息等于右边这个值时,创建相应的物品
# 创建Component,用来完成特定的功能,这里是为了创建Item物品
playerId = args["playerId"]
comp = compFactory.CreateItem(playerId)
if args["message"] == "钻石剑":
# 调用SpawnItemToPlayerInv接口生成物品到玩家背包,参数参考《MODSDK文档》
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_sword", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石镐":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_pickaxe", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石头盔":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_helmet", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石胸甲":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_chestplate", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石护腿":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_leggings", "count":1, 'auxValue': 0}, playerId)
elif args["message"] == "钻石靴子":
comp.SpawnItemToPlayerInv({"itemName":"minecraft:diamond_boots", "count":1, 'auxValue': 0}, playerId)
else:
print "==== Sorry man ===="
```
创建组件时,无论是客户端组件还是服务端组件,都需要继承自 `object` 类,即上方代码中的 `class ChatServerComponent(object):`。
组件的 `__init__` 方法中的参数,必须有第二个变量(即上方代码中的 `__init__(self, server)` 中的 `server` 变量)。
如果是客户端组件,`__init__` 方法一般写为 `__init__(self, client)`。
如果创建的是**服务端组件**,需要在类的上方添加 `@ListenEvent.InitComponentServer` 装饰器。
如果创建的是**客户端组件**,需要在类的上方添加 `@ListenEvent.InitComponentClient` 装饰器。
4. 修改客户端和服务端文件
打开 `TutorialClientSystem.py` 文件,修改为以下内容:
```python
# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
# 因为文件夹名称改变,所以导入路径也改变了
from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
ClientSystem = clientApi.GetClientSystemCls()
compFactory = clientApi.GetEngineCompFactory()
@ListenEvent.InitClient
class TutorialClientSystem(ClientSystem):
def __init__(self, namespace, systemName):
pass
```
打开 `TutorialServerSystem.py` 文件,修改为以下内容:
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
# 因为文件夹名称改变,所以导入路径也改变了
from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
# 导入组件,尽管这里你没有显式使用它,也必须导入!
from tutorialComponentScripts.components.server.ChatServerComponent import ChatServerComponent
ServerSystem = serverApi.GetServerSystemCls()
compFactory = serverApi.GetEngineCompFactory()
@ListenEvent.InitServer
class TutorialServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
pass
```
需要特别注意的是,因为网易我的世界限制了 python 的 `os` 模块,MODSDKSpring 框架无法通过路径扫描自动导入所需要的组件,所以您必须在 `TutorialServerSystem.py` 文件中手动导入需要的服务端组件,即 `from tutorialComponentScripts.components.server.ChatServerComponent import ChatServerComponent`。
同理,如果您创建客户端组件,也需要在客户端系统文件中手动导入需要的客户端组件。
**通常情况下,这是您的组件不生效的首要原因,请务必牢记!**
> 有一种更加方便的导入组件的方式,并且 MODSDKSpring 框架提供了类似于 `modsdkspring init` 一样的控制台命令。强烈建议您阅读高级内容中的 [快速导入组件](#%E5%BF%AB%E9%80%9F%E5%AF%BC%E5%85%A5%E7%BB%84%E4%BB%B6) 部分。
5. 运行
至此,我们已经完成了对快速入门示例的改造。把在 `TutorialServerSystem.py` 中的监听,移到了 `ChatServerComponent.py` 中。现在您可以导入改造后的行为包,在聊天窗口中输入 `钻石剑` 验证 Mod 是否生效。
6. 代码解释
- @ListenEvent.InitComponentServer 是什么?
这是 MODSDKSpring 框架提供的一个装饰器,只能添加到**服务端组件**的上方,标识此类是一个服务端组件。只有添加了这个装饰器,才能启用类内的其他 MODSDKSpring 中的装饰器。注意,使用时最后不要加括号。
此装饰器还能具体指定该服务端组件属于哪个服务端,即组件的 `__init__` 方法中的参数 `server` 具体是哪个服务端系统。如果您在 `modMain.py` 中只注册了一个服务端,那么此处无需指定该组件属于哪个服务端。具体如何指定,详见装饰器文档部分。
类似的还有 @ListenEvent.InitComponentClient。
# 监听自定义事件
在实际开发中,我们经常会自定义事件,以此来进行客户端与服务端之间的相互通信。MODSDKSpring 也提供了监听自定义事件的方法。
- @ListenEvent.Client
用于**客户端系统/组件**监听事件,只能添加到**客户端系统/组件**的方法上方。
其拥有四个参数,参数名及含义如下:
- eventName (str): 监听的事件名称。
- namespace (str, 可选): 所监听事件的来源系统的 namespace。默认值为 clientApi.GetEngineNamespace()。
- systemName (str, 可选): 所监听事件的来源系统的 systemName。默认值为 clientApi.GetEngineSystemName()。
- priority (int, 可选): 回调函数的优先级。默认值为 0,这个数值越大表示被执行的优先级越高,最高为10。
- @ListenEvent.Server
用于**服务端系统/组件**监听事件,只能添加到**服务端系统/组件**的方法上方。
其拥有四个参数,参数名及含义如下:
- eventName (str): 监听的事件名称。
- namespace (str, 可选): 所监听事件的来源系统的 namespace。默认值为 clientApi.GetEngineNamespace()。
- systemName (str, 可选): 所监听事件的来源系统的 systemName。默认值为 clientApi.GetEngineSystemName()。
- priority (int, 可选): 回调函数的优先级。默认值为 0,这个数值越大表示被执行的优先级越高,最高为10。
客户端系统/组件监听自定义事件的方式如下:
```python
@ListenEvent.Client(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.SERVER_SYSTEM_NAME, eventName="DamageEventToClient")
def damageEvent(self, event):
pass
```
服务端系统/组件同理,只是替换为 `@ListenEvent.Server`。
在 [ParticleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/ParticleMod) 示例中,客户端组件 `HurtEntityClientComponent.py` 监听了服务端组件 `HurtEntityServerComponent.py` 发出的自定义事件 `DamageEventToClient`。您可以下载此示例,查看具体代码。
# 跨组件调用(依赖注入)
设想这样一个场景,您定义了一个专门用于播放粒子的客户端组件 `P`。您有另一个客户端组件 `A`。您想实现在客户端组件 `A` 中调用客户端组件 `P` 中的方法。这时候应该怎么办呢?
要想实现在 `A` 中调用 `P` 的方法,`A` 必须获取到 `P` 的对象 `p`,然后执行 `p.xxx()` 这样的语句。`A` 和 `P` 的这种关系,我们可以称为 `A` 依赖于 `P`。即,`P` 是 `A` 的依赖。
MODSDKSpring 框架可以管理上述的依赖关系。具体做法是,框架会在组件被创建时,将组件的对象放入“容器”(实际上就是一个字典)当中。当组件 `A` 需要另一个组件 `P` 时,框架可以从容器中拿到 `P`,并把 `P` 通过**某种方式**传递给 `A`。
这样,`A` 便可以调用 `P` 的方法,并且不会产生 `P` 这个类的新对象。实现了组件的单例模式,节约内存。
那么,**某种方式**具体是什么?MODSDKSpring 框架目前提供了两种从容器中获取组件对象的方法。这两种方法有它们各自的使用场景,具体细节请继续阅读。
## 组件类的对象在容器中的存储形式
所谓的容器,实际上就是一个 `dict` 类型的变量!千万不要想的太复杂,我不喜欢玩文字游戏,希望您也一样。
假设,有一个客户端组件类,类名是 `HurtEntityClientComponent`。当此类在框架中创建对象后,框架会给它起一个“名字”,叫做 `hurtEntityClientComponent`(类名首字母小写)。这个“名字”是容器中的 `key`,而这个 `key` 对应的 `value` 就是类 `HurtEntityClientComponent` 的对象!形式如下。
```python
{
'hurtEntityClientComponent': HurtEntityClientComponent()
# ...
}
```
了解了这些,您可以更好的理解下方的从容器中获取组件对象的方法。
## 构造方法注入
假设,有一个客户端组件 `HurtEntityClientComponent`,需要使用另一个客户端组件 `ParticleClientComponent`。
首先,在 `HurtEntityClientComponent` 的 `__init__` 方法的参数上,添加一个变量,名字为 `particleClientComponent`(对应组件类名的首字母小写,**名字不能变!**)。如果您有更多需要调用的组件,在 `__init__` 方法的参数中,可以继续添加更多类似形式的变量。
然后,在 `__init__` 方法的上方添加一个装饰器 `@Autowired`,开启依赖注入。
最后,框架会自动在 `HurtEntityClientComponent` 类的对象被创建时,通过 `__init__` 方法的参数,传入对应的 `ParticleClientComponent` 类的对象。
示例代码如下:
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from particleModScripts.plugins.MODSDKSpring.core.Autowired import Autowired
from particleModScripts.modCommon import modConfig
from particleModScripts.modCommon import eventConfig
@ListenEvent.InitComponentClient
class HurtEntityClientComponent(object):
@Autowired
def __init__(self, client, particleClientComponent):
self.client = client
self.particleClientComponent = particleClientComponent
```
上述代码来源于 example 分支中的 [ParticleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/ParticleMod) 示例,您可以自行下载查看。
注意,在 `__init__` 方法中,变量 `particleClientComponent` 不总是有值。如果有循环依赖的情况,可能变量 `particleClientComponent` 在执行完 `__init__` 方法后,才被赋值,所以变量 `particleClientComponent` 在 `__init__` 方法中可能为 `None`。
因此,我建议您永远不要在 `__init__` 方法中调用其他组件的方法!`__init__` 方法应该只做赋值操作!
至于循环依赖是什么情况,请查看 [解决循环依赖](#%E8%A7%A3%E5%86%B3%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96) 部分。
> `@Autowired` 也可以被添加到**客户端/服务端系统**的 `__init__` 方法上方,但通常情况下,您不应该这么做。
## getBean() 方法
方法在 `xxx.plugins.MODSDKSpring.core.BeanFactory` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
该方法能够直接从容器中获取组件对象
- 参数
|参数名|数据类型|说明|
|-----|--------|----|
|systemType|str|想要获取的组件的类型<br>值为 `SystemType.CLIENT` 或 `SystemType.SERVER`<br>`SystemType` 在 `xxx.plugins.MODSDKSpring.core.constant.SystemType` 中|
|beanName|str|存放组件的容器的 `key`<br>即类名首字母小写,比如你有一个类名为 `TestComponentClient` 的组件,那么它的 `key` 为 `testComponentClient`|
- 返回值
|数据类型|说明|
|-------|----|
|object \| None|返回容器中的组件对象<br>如果组件不存在,则返回 None|
- 示例
```python
from tutorialScripts.plugins.MODSDKSpring.core.BeanFactory import BeanFactory
import tutorialScripts.plugins.MODSDKSpring.core.constant.SystemType as SystemType
testComponentClient = BeanFactory.getBean(SystemType.CLIENT, 'testComponentClient')
```
> 该方法适用于在注册了多个客户端系统或服务端系统的情况下,某个系统的组件要调用另外一个系统的组件时使用。一般情况下,请使用 `@Autowired`。
> 该方法不会产生循环依赖问题。
> 永远不要在 `__init__` 方法中使用 `getBean()`,因为此时您需要的组件可能尚未创建。
# 解决循环依赖
设想这样一个场景,您有一个组件 `A`,还有一个组件 `B`。您想在组件 `A` 中调用组件 `B` 的方法,同时,您也想在组件 `B` 中调用组件 `A` 中的方法。这两个组件都想调用对方,就形成了所谓的循环依赖。
从代码逻辑上讲,当组件 `A` 被创建时,框架发现组件 `A` 需要一个组件 `B`,于是就先去创建组件 `B` 的对象。但是在创建组件 `B` 时,框架又发现组件 `B` 需要组件 `A`,于是又去创建组件 `A` 的对象,这就形成了一个循环。如果不做任何处理,最终会因为递归层数过多,抛出异常。
MODSDKSpring 框架目前提供了两种解决循环依赖的方法。一种是在需要调用另一个组件的地方,手动调用 `getBean()` 方法。需要注意的是,不要在 `__init__` 方法中使用 `getBean()`。
另外一种方法,是使用装饰器 `@Lazy`。这种方法应该是您的首选。
## 使用 @Lazy
假设组件 `A` 和 `B` 之间存在循环依赖,那么您只需要在 `A` 或者 `B` 中的 `__init__` 方法上的 `@Autowired` 上面添加 `@Lazy` 即可。注意,是 `A` 或者 `B`,在其中一个类的 `@Autowired` 上面加就行!
添加了 `@Lazy` 的 `__init__` 方法,会在创建对象时先用 `None` 填充方法内的组件的变量。在 `__init__` 方法执行完成,所有组件被创建之后,会再次执行依赖注入,给对象中的组件的变量赋值(如下方代码中的 `self.b`)。示例代码如下。
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from particleModScripts.plugins.MODSDKSpring.core.Autowired import Autowired
from particleModScripts.plugins.MODSDKSpring.core.Lazy import Lazy
from particleModScripts.modCommon import modConfig
from particleModScripts.modCommon import eventConfig
@ListenEvent.InitComponentClient
class A(object):
@Lazy
@Autowired
def __init__(self, client, b):
self.client = client
self.b = b # self.b 的值此时为 None,所有组件创建完成后,框架会自动为 self.b 赋值。
```
如果遇到了问题,您可以下载 example 分支中的 [CirculateMod](https://github.com/CreatorMC/MODSDKSping/tree/example/CirculateMod) 示例,此示例专门演示了如何解决循环依赖。
> `@Lazy` 只能写在 `@Autowired` 的上方!如果写在 `@Autowired` 下方,您会在网易我的世界开发者启动器的日志窗口中看到 `@Lazy 必须添加在 @Autowired 的上方。` 的异常提示。
> `@Lazy` 不能用于**客户端/服务端系统**的 `__init__` 方法上(这里指的是客户端或服务端系统,不是组件)。因为这完全没有必要,使用 `@Autowired` 已足够将组件注入到客户端/服务端系统中,并且不会与系统之间产生循环依赖。如果您对此仍有疑惑,请查看 [CirculateMod](https://github.com/CreatorMC/MODSDKSping/tree/example/CirculateMod) 示例。
# 高级内容
> 对您来说,这部分的内容不是使用框架所必须看的。但如果您了解了这些高级内容,可能在某些场景下会帮助您更方便的使用框架。
## 快速导入组件
假设您的 Addon 文件结构如下:
```txt
TutorialMod
└── tutorialBehaviorPack
├── entities
├── tutorialScripts
│ ├── components
│ │ ├── client
│ │ │ ├── __init__.py
│ │ │ ├── AClientComponent.py
│ │ │ ├── BClientComponent.py
│ │ │ └── CClientComponent.py
│ │ ├── server
│ │ │ ├── __init__.py
│ │ │ ├── AServerComponent.py
│ │ │ ├── BServerComponent.py
│ │ │ └── CServerComponent.py
│ │ └── __init__.py
│ ├── modCommon
│ │ ├── __init__.py
│ │ └── modConfig.py
│ ├── plugins
│ │ ├── MODSDKSpring
│ │ │ └── ...
│ │ └── __init__.py
│ ├── __init__.py
│ ├── modMain.py
│ ├── TutorialClientSystem.py
│ └── TutorialServerSystem.py
└── manifest.json
```
在 `TutorialMod/tutorialBehaviorPack/tutorialScripts/components/client/__init__.py` 文件中编写如下代码:
```python
# -*- coding: utf-8 -*-
# 此处假设模块名和模块中定义的类名相同,请根据您的实际情况进行导入
from AClientComponent import AClientComponent
from BClientComponent import BClientComponent
from CClientComponent import CClientComponent
```
在 `TutorialMod/tutorialBehaviorPack/tutorialScripts/components/server/__init__.py` 文件中编写如下代码:
```python
# -*- coding: utf-8 -*-
# 此处假设模块名和模块中定义的类名相同,请根据您的实际情况进行导入
from AServerComponent import AServerComponent
from BServerComponent import BServerComponent
from CServerComponent import CServerComponent
```
在 `TutorialMod/tutorialBehaviorPack/tutorialScripts/TutorialClientSystem.py` 文件顶部添加如下代码:
```python
from tutorialScripts.components.client import *
```
在 `TutorialMod/tutorialBehaviorPack/tutorialScripts/TutorialServerSystem.py` 文件顶部添加如下代码:
```python
from tutorialScripts.components.server import *
```
这样,每当您增加或删除组件时,不需要改动 `TutorialClientSystem.py` 和 `TutorialServerSystem.py` 文件,只需要改动 `client` 和 `server` 文件夹内的 `__init__.py` 文件即可。
您可能还是觉得很麻烦,还是要手动修改文件,称不上“快速”。针对这点,MODSDKSpring 提供了一个控制台命令,能够自动生成上述的 `__init__.py` 文件。
### 自动生成所需的 \_\_init\_\_.py 文件
打开您的命令行窗口,或者在您的代码编辑器中打开一个终端。然后将当前位置切换到 `.../components/client` 或 `.../components/server` 文件夹下。输入下方命令:
```shell
modsdkspring import
```
正常的话,您应该会看到以下输出:
```shell
Starting to create the __init__.py file.
Successfully created the __init__.py file!
```
然后在 `.../components/client` 或 `.../components/server` 文件夹内,就会自动生成一个 `__init__.py` 文件(如果此文件已存在,会自动覆盖文件中的内容)。其中导入了此文件夹及其子文件夹内所有的类。
很多时候,您在代码编辑器中打开一个终端,可能终端所在的默认位置并不是 `.../components/client` 或 `.../components/server`,并且您也不想手动切换位置。这时候,您可以使用 `modsdkspring import` 命令提供的参数 `--path`,指定路径。具体示例如下:
```shell
modsdkspring import --path "tutorialBehaviorPack/tutorialScripts/components/client"
```
上面的命令假设终端的当前位置在 `TutorialMod` 中。命令执行后,会在您指定的路径中生成一个 `__init__.py` 文件。
### 将命令配置为 Visual Studio Code 任务
尽管框架提供了相关命令,但每次添加或删除组件,您都要手动执行一次命令,这仍然比较麻烦,不够自动化。
如果您使用 Visual Studio Code 作为您的代码编辑器,您可以阅读此部分,按照步骤配置自动化任务。
最终实现的效果是,当您在 Visual Studio Code 中保存组件目录下的 `.py` 文件时,Visual Studio Code 将自动执行命令 `modsdkspring import --path "xxx"`。
> 此教程环境说明如下。<br>如果您的设备环境不符合下方的说明,您也可以按此教程尝试配置,如果您遇到了问题,可自行搜索解决。<br><br>操作系统:Windows 10<br>Visual Studio Code 版本:1.72.1
1. 安装扩展
在 Visual Studio Code 中的扩展中搜索 [Save and Run](https://marketplace.visualstudio.com/items?itemName=wk-j.save-and-run) 或直接点击链接,安装此扩展。本教程的 Save and Run 版本为 0.0.22。
2. 配置扩展
假设您有一个如下图所示的工作区:

您需要在 `settings` 中增加如下文本:
```json
"saveAndRun": {
"commands": [
{
"match": ".*\\\\components\\\\(client|server).*\\.py",
"cmd": "modsdkspring import --path \"${fileDirname}\"",
"useShortcut": false,
"silent": false
}
]
}
```
> 如果您有工作区文件 `XXX.code-workspace`,请按上方截图中的方式进行配置。如果您没有工作区文件,请在 `.vscode` 文件夹中的 `settings.json` 文件中添加配置。
> 您可以修改 `match` 中的正则表达式,以符合您的实际情况。
3. 测试效果
现在,请尝试修改 `.../components/client` 或 `.../components/server` 文件夹下的 `.py` 文件,在您按 `ctrl + s` 保存文件时,您可以看到 Visual Studio Code 将自动打开一个终端,并执行命令。

## 在 modMain.py 中创建多个客户端和服务端的情况
> 在 MODSDKSpring 框架中,我不推荐您这么做。但是,如果您仍要这么做,MODSDKSpring 也提供了方法。
假设您的 `modMain.py` 文件如下所示:
```python
# -*- coding: utf-8 -*-
from mod.common.mod import Mod
import mod.client.extraClientApi as clientApi
import mod.server.extraServerApi as serverApi
from modCommon import modConfig
from mod_log import logger
@Mod.Binding(name=modConfig.MOD_NAMESPACE, version=modConfig.MOD_VERSION)
class TMSMultipleMod(object):
def __init__(self):
logger.info("===== init %s mod =====", modConfig.MOD_NAMESPACE)
@Mod.InitServer()
def TMSMultipleModServerInit(self):
logger.info("===== init %s server =====", modConfig.SERVER_SYSTEM_NAME)
serverApi.RegisterSystem(modConfig.MOD_NAMESPACE, modConfig.SERVER_SYSTEM_NAME, modConfig.SERVER_SYSTEM_CLS_PATH)
@Mod.DestroyServer()
def TMSMultipleModServerDestroy(self):
logger.info("===== destroy %s server =====", modConfig.SERVER_SYSTEM_NAME)
@Mod.InitClient()
def TMSMultipleModClientInit(self):
logger.info("===== init %s client =====", modConfig.CLIENT_SYSTEM_NAME)
clientApi.RegisterSystem(modConfig.MOD_NAMESPACE, modConfig.CLIENT_SYSTEM_NAME, modConfig.CLIENT_SYSTEM_CLS_PATH)
@Mod.DestroyClient()
def TMSMultipleModClientDestroy(self):
logger.info("===== destroy %s client =====", modConfig.CLIENT_SYSTEM_NAME)
@Mod.Binding(name=modConfig.MOD_NAMESPACE_1, version=modConfig.MOD_VERSION_1)
class TMSCopyMod(object):
def __init__(self):
logger.info("===== init %s mod =====", modConfig.MOD_NAMESPACE_1)
@Mod.InitServer()
def TMSCopyModServerInit(self):
logger.info("===== init %s server =====", modConfig.SERVER_SYSTEM_NAME_1)
serverApi.RegisterSystem(modConfig.MOD_NAMESPACE_1, modConfig.SERVER_SYSTEM_NAME_1, modConfig.SERVER_SYSTEM_CLS_PATH_1)
@Mod.DestroyServer()
def TMSCopyModServerDestroy(self):
logger.info("===== destroy %s server =====", modConfig.SERVER_SYSTEM_NAME_1)
@Mod.InitClient()
def TMSCopyModClientInit(self):
logger.info("===== init %s client =====", modConfig.CLIENT_SYSTEM_NAME_1)
clientApi.RegisterSystem(modConfig.MOD_NAMESPACE_1, modConfig.CLIENT_SYSTEM_NAME_1, modConfig.CLIENT_SYSTEM_CLS_PATH_1)
@Mod.DestroyClient()
def TMSCopyModClientDestroy(self):
logger.info("===== destroy %s client =====", modConfig.CLIENT_SYSTEM_NAME_1)
```
`modConfig.py` 代码如下:
```python
# -*- coding: utf-8 -*-
# Mod Version
MOD_NAMESPACE = "TMSMultipleMod"
MOD_VERSION = "0.0.1"
# Client System
CLIENT_SYSTEM_NAME = "MultipleClientSystem"
CLIENT_SYSTEM_CLS_PATH = "multipleModScripts.MultipleClientSystem.MultipleClientSystem"
# Server System
SERVER_SYSTEM_NAME = "MultipleServerSystem"
SERVER_SYSTEM_CLS_PATH = "multipleModScripts.MultipleServerSystem.MultipleServerSystem"
# Mod Version
MOD_NAMESPACE_1 = "TMSCopyMod"
MOD_VERSION_1 = "0.0.1"
# Client System
CLIENT_SYSTEM_NAME_1 = "CopyClientSystem"
CLIENT_SYSTEM_CLS_PATH_1 = "multipleModScripts.CopyClientSystem.CopyClientSystem"
# Server System
SERVER_SYSTEM_NAME_1 = "CopyServerSystem"
SERVER_SYSTEM_CLS_PATH_1 = "multipleModScripts.CopyServerSystem.CopyServerSystem"
```
下方的代码定义了一个属于 `CopyClientSystem` 的组件:
```python
# -*- coding: utf-8 -*-
from multipleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from multipleModScripts.modCommon import modConfig
from multipleModScripts.plugins.MODSDKSpring.core.log.Log import logger
@ListenEvent.InitComponentClient(namespace=modConfig.MOD_NAMESPACE_1, systemName=modConfig.CLIENT_SYSTEM_NAME_1)
class ACopyClientComponent(object):
def __init__(self, client):
self.client = client
logger.info("ACopyClientComponent 获取到的系统:" + str(client))
```
下方的代码定义了一个属于 `CopyServerSystem` 的组件:
```python
# -*- coding: utf-8 -*-
from multipleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from multipleModScripts.modCommon import modConfig
from multipleModScripts.plugins.MODSDKSpring.core.log.Log import logger
@ListenEvent.InitComponentServer(namespace=modConfig.MOD_NAMESPACE_1, systemName=modConfig.SERVER_SYSTEM_NAME_1)
class ACopyServerComponent(object):
def __init__(self, server):
self.server = server
logger.info("ACopyServerComponent 获取到的系统:" + str(server))
```
需要明确一点的是,如果您的 `modMain.py` 中注册了多个系统,您需要在 `@ListenEvent.InitComponentClient` 或 `@ListenEvent.InitComponentServer` 当中填写 `namespace` 和 `systemName` 这两个参数,以此来指定此组件属于哪个系统。不可以省略不填!
如果您还有疑问,可以下载 example 分支中的 [MultipleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/MultipleMod) 示例。此示例还展示了如何实现不同系统的组件之间的调用。
## 自定义 Mod 生成模板(未来可能的功能)
实际上,现在已经能自定义生成模板了,只是模板被内置在框架当中,没有提供对外的标准方法。感兴趣的开发者,可以阅读相关源码,自行探索自定义生成模板的方法。或者,欢迎您对本框架的代码做出贡献!
# 可能遇到的问题
> 您在日志中可能会看到下方所列的这些提示信息,如果您看到了并且不知道怎么解决,可以查阅此部分。
>
> 下方标题或描述中提到的 `XXX`、`xxx` 和 `YYY` 均表示实际的类或方法。
## 没有找到带有 @InitComponentClient 或 @InitComponentServer 的类 XXX,将使用 None 进行注入。
- 原因
看到此日志可能是因为您真的没有在类 `XXX` 上添加 `@InitComponentClient` 或 `@InitComponentServer`,导致类 `XXX` 的对象不能被注入。
另一种情况是,当您在 `modMain.py` 中注册了多个系统时,您在某个系统中要想用 `@Autowired` 注入其他系统的组件对象。这种情况属于跨系统调用组件,请使用 [getBean()](#getbean-方法) 方法。
## 类 XXX 和 YYY 之间存在循环依赖,请使用 @Lazy 解决。
- 原因
当两个类彼此都需要注入对方的对象时,会出现此异常信息。可参考 [解决循环依赖](#解决循环依赖) 部分。
## 方法 xxx 不是 \_\_init\_\_,不能使用 @Autowired 装饰器。
- 原因
您将 `@Autowired` 加在了 `xxx` 方法的上方。`@Autowired` 只能加在组件或系统类的 `__init__` 方法上方。
## @Lazy 必须添加在 @Autowired 的上方。
- 原因
您写了如下所示的代码:
```python
@Autowired
@Lazy
def __init__(self, client, aClientComponent):
# ...
```
将代码调整为:
```python
@Lazy
@Autowired
def __init__(self, client, aClientComponent):
# ...
```
即可解决。
# 装饰器文档
> 这一部分解释了 MODSDKSpring 中各个装饰器的参数和含义。适合入门 MODSDKSpring 后快速查阅相关功能时使用。
## @ListenEvent.InitClient
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加在被 modMain.py 注册的客户端类的上方,开启框架相关功能
- 参数
无
- 示例
```python
# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
ClientSystem = clientApi.GetClientSystemCls()
compFactory = clientApi.GetEngineCompFactory()
@ListenEvent.InitClient
class TutorialClientSystem(ClientSystem):
def __init__(self, namespace, systemName):
pass
```
## @ListenEvent.InitServer
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加在被 modMain.py 注册的服务端类的上方,开启框架相关功能
- 参数
无
- 示例
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
ServerSystem = serverApi.GetServerSystemCls()
compFactory = serverApi.GetEngineCompFactory()
@ListenEvent.InitServer
class TutorialServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
pass
```
## @ListenEvent.InitComponentClient
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加到自定义的客户端 Component 类的上方,开启框架相关功能
- 参数
|参数名|数据类型|说明|
|------|-------|----|
|namespace|str|注入的客户端系统的命名空间,当 modMain.py 中只注册了一个客户端时不用填写此参数|
|systemName|str|注入的客户端系统的系统名称,当 modMain.py 中只注册了一个客户端时不用填写此参数|
- 示例
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
@ListenEvent.InitComponentClient
class HurtEntityClientComponent(object):
def __init__(self, client):
self.client = client
```
## @ListenEvent.InitComponentServer
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加到自定义的服务端 Component 类的上方,开启框架相关功能
- 参数
|参数名|数据类型|说明|
|------|-------|----|
|namespace|str|注入的服务端系统的命名空间,当 modMain.py 中只注册了一个服务端时不用填写此参数|
|systemName|str|注入的服务端系统的系统名称,当 modMain.py 中只注册了一个服务端时不用填写此参数|
- 示例
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
@ListenEvent.InitComponentServer
class HurtEntityServerComponent(object):
def __init__(self, server):
self.server = server
```
## @ListenEvent.Client
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
客户端监听事件
- 参数
|参数名|数据类型|说明|
|------|-------|----|
|eventName|str|监听的事件名称|
|namespace|str|所监听事件的来源系统的 namespace。默认值为 clientApi.GetEngineNamespace()|
|systemName|str|所监听事件的来源系统的 systemName。默认值为 clientApi.GetEngineSystemName()|
|priority|int|回调函数的优先级。默认值为 0,这个数值越大表示被执行的优先级越高,最高为10|
- 示例
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
@ListenEvent.Client(eventName="AddEntityClientEvent")
def addEntityClientEvent(self, args):
pass
```
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from particleModScripts.modCommon import modConfig
@ListenEvent.Client(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.SERVER_SYSTEM_NAME, eventName="DamageEventToClient")
def damageEvent(self, event):
pass
```
## @ListenEvent.Server
方法在 `xxx.plugins.MODSDKSpring.core.ListenEvent` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
服务端监听事件
- 参数
|参数名|数据类型|说明|
|------|-------|----|
|eventName|str|监听的事件名称|
|namespace|str|所监听事件的来源系统的 namespace。默认值为 clientApi.GetEngineNamespace()|
|systemName|str|所监听事件的来源系统的 systemName。默认值为 clientApi.GetEngineSystemName()|
|priority|int|回调函数的优先级。默认值为 0,这个数值越大表示被执行的优先级越高,最高为10|
- 示例
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
@ListenEvent.Server(eventName="AddEntityServerEvent")
def addEntityServerEvent(self, args):
pass
```
```python
# -*- coding: utf-8 -*-
from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from particleModScripts.modCommon import modConfig
@ListenEvent.Server(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.CLIENT_SYSTEM_NAME, eventName="PerspChangeClientEventToServer")
def perspChangeEvent(self, event):
pass
```
## @Autowired
方法在 `xxx.plugins.MODSDKSpring.core.Autowired` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加到 `__init__` 方法上的装饰器,表示此方法需要依赖注入
- 参数
无
- 示例
```python
# -*- coding: utf-8 -*-
from circulateModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from circulateModScripts.plugins.MODSDKSpring.core.Autowired import Autowired
@ListenEvent.InitComponentClient
class CClientComponent(object):
@Autowired
def __init__(self, client, aClientComponent, bClientComponent):
self.client = client
self.aClientComponent = aClientComponent
self.bClientComponent = bClientComponent
```
## @Lazy
方法在 `xxx.plugins.MODSDKSpring.core.Lazy` 中,`xxx` 应替换为您的行为包中的 Mod 文件夹名称,如 `tutorialScripts`。
- 描述
添加到 @Autowired 上的装饰器,表示此方法在进行依赖注入时先用 None 进行注入,对象创建之后再注入真正需要的依赖
此装饰器一般用于解决循环依赖
- 参数
无
- 示例
```python
# -*- coding: utf-8 -*-
from circulateModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent
from circulateModScripts.plugins.MODSDKSpring.core.Autowired import Autowired
from circulateModScripts.plugins.MODSDKSpring.core.Lazy import Lazy
@ListenEvent.InitComponentClient
class AClientComponent(object):
@Lazy
@Autowired
def __init__(self, client, bClientComponent, cClientComponent):
self.client = client
self.bClientComponent = bClientComponent
self.cClientComponent = cClientComponent
```
Raw data
{
"_id": null,
"home_page": "https://github.com/CreatorMC/MODSDKSping",
"name": "mc-creatormc-sdkspring",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "CreatorMC",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/3a/48/086b0d00d679b9790b8f22104083a8da970c2bc6ec9398b4f7e19b167f59/mc-creatormc-sdkspring-1.0.0.tar.gz",
"platform": "any",
"description": "\r\n\r\n# \u4ec0\u4e48\u662f MODSDKSpring\r\n\r\nMODSDKSpring \u662f\u4e00\u4e2a\u975e\u5b98\u65b9\u7684\uff0c\u7531\u9b54\u7075\u5de5\u4f5c\u5ba4-\u521b\u9020\u8005MC\u5236\u4f5c\u7684\uff0c\u5728\u7f51\u6613\u6211\u7684\u4e16\u754c MODSDK \u57fa\u7840\u4e0a\u5f00\u53d1\u7684\u6846\u67b6\u3002\u76ee\u7684\u662f\u4e3a\u4e86\u7b80\u5316\u5e76\u89c4\u8303\u7f51\u6613\u6211\u7684\u4e16\u754c [MOD](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/1-Mod%E5%BC%80%E5%8F%91%E7%AE%80%E4%BB%8B/1-Mod%E7%AE%80%E4%BB%8B.html) \u7684\u5f00\u53d1\u3002\r\n\r\n# \u4e3a\u4ec0\u4e48\u8981\u7528 MODSDKSpring\r\n\r\nMODSDKSpring \u5b9a\u4e49\u4e86\u4e00\u7cfb\u5217\u7684\u88c5\u9970\u5668\uff08\u5c31\u50cf\u60a8\u5728 modMain.py \u4e2d\u770b\u5230\u7684 @Mod.InitClient() \u8fd9\u79cd\u5199\u6cd5\uff09\uff0c\u907f\u514d\u4e86\u81ea\u5df1\u5199 self.ListenForEvent \u53bb\u76d1\u542c\u4e8b\u4ef6\u3002\u53e6\u5916\uff0cMODSDKSpring \u501f\u9274\u4e86 Java \u8bed\u8a00\u4e2d\u7684\u77e5\u540d\u6846\u67b6 Spring \u7684\u76f8\u5173\u6982\u5ff5\uff0c\u5b9e\u73b0\u4e86\u9488\u5bf9 MODSDK \u7684\u63a7\u5236\u53cd\u8f6c\u548c\u4f9d\u8d56\u6ce8\u5165\u3002\r\n\r\n\u5177\u4f53\u800c\u8a00\uff0c\u6846\u67b6\u53ef\u4ee5\u505a\u5230\u53ea\u6ce8\u518c\u4e00\u4e2a\u5ba2\u6237\u7aef\u7c7b\u548c\u670d\u52a1\u7aef\u7c7b\uff0c\u5c31\u80fd\u50cf\u6ce8\u518c\u4e86\u591a\u4e2a\u5ba2\u6237\u7aef\u7c7b\u548c\u670d\u52a1\u7aef\u7c7b\u90a3\u6837\uff0c\u6bcf\u4e2a\u6a21\u5757\uff08.py \u6587\u4ef6\uff09\u5404\u53f8\u5176\u804c\uff0c\u81ea\u5df1\u76d1\u542c\u9700\u8981\u76d1\u542c\u7684\u4e8b\u4ef6\u5e76\u5728\u6a21\u5757\u5185\u5904\u7406\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u6211\u4eec\u53ef\u4ee5\u8bbe\u8ba1\u51fa\u66f4\u5408\u7406\u7684 Mod \u7ed3\u6784\uff0c\u4e0d\u5fc5\u5728\u5355\u4e2a `.py` \u6587\u4ef6\u4e2d\u628a\u6240\u6709\u529f\u80fd\u90fd\u8026\u5408\u5230\u4e00\u8d77\u3002\r\n\r\n\u4e0a\u9762\u7684\u63cf\u8ff0\u5982\u679c\u6ca1\u770b\u61c2\u4e5f\u6ca1\u5173\u7cfb\uff0c\u5728\u63a5\u4e0b\u6765\u7684\u5feb\u901f\u5165\u95e8\u4e2d\uff0c\u60a8\u5c06\u76f4\u89c2\u7684\u611f\u53d7\u5230\u4f7f\u7528 MODSDKSpring \u6240\u5e26\u6765\u7684\u4fbf\u6377\u3002\r\n\r\n# Python \u7248\u672c\r\n\r\n\u56e0\u4e3a\u7f51\u6613\u6211\u7684\u4e16\u754c MODSDK \u4f7f\u7528\u7684\u662f [python 2.7.18](https://www.python.org/downloads/release/python-2718/)\uff0c\u6240\u4ee5\u6b64\u6846\u67b6\u4e5f\u4f7f\u7528\u76f8\u540c\u7684\u7248\u672c\u3002\r\n\r\n# \u6846\u67b6\u4e0b\u8f7d\r\n\r\n```shell\r\npip install mc-creatormc-sdkspring\r\n```\r\n\r\n\u5982\u679c\u60a8\u5b89\u88c5\u4e86 Python2 \u548c Python3\uff0c\u60a8\u53ef\u80fd\u9700\u8981\u4f7f\u7528\u4e0b\u65b9\u7684\u547d\u4ee4\u53bb\u4e0b\u8f7d\u3002\r\n\r\n```shell\r\npip2 install mc-creatormc-sdkspring\r\n```\r\n\r\n# \u793a\u4f8b\u4ee3\u7801\r\n\r\n\u672c\u6587\u6863\u4e2d\u7684\u6559\u7a0b\u6e90\u7801\uff0c\u5747\u53ef\u5728\u4ed3\u5e93\u4e2d\u7684 [example](https://github.com/CreatorMC/MODSDKSping/tree/example) \u5206\u652f\u4e2d\u67e5\u770b\u3002\r\n\r\n# \u5feb\u901f\u5165\u95e8\r\n\r\n> \u5feb\u901f\u5165\u95e8\u6559\u7a0b\u6539\u9020\u81ea\u7f51\u6613\u6211\u7684\u4e16\u754c\u5f00\u53d1\u8005\u5b98\u7f51 DemoMod \u4e2d\u7684 [TutorialMod](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/60-Demo%E7%A4%BA%E4%BE%8B.html#TutorialMod)\u3002\u60a8\u5728\u9605\u8bfb\u672c\u7bc7\u6559\u7a0b\u65f6\uff0c\u53ef\u4e0e\u5b98\u65b9\u4ee3\u7801\u8fdb\u884c\u5bf9\u7167\uff0c\u611f\u53d7 MODSDKSpring \u7684\u4fbf\u6377\u3002\r\n\r\n> \u6559\u7a0b\u5f00\u59cb\u524d\uff0c\u8bf7\u786e\u4fdd\u60a8\u5df2\u7ecf\u4e0b\u8f7d\u5e76\u5b89\u88c5\u4e86 [python 2.7.18](https://www.python.org/downloads/release/python-2718/)\u3001[MODSDKSpring](#%E6%A1%86%E6%9E%B6%E4%B8%8B%E8%BD%BD) \u4ee5\u53ca [ModSDK \u8865\u5168\u5e93](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E5%AE%89%E8%A3%85mod-sdk%E8%A1%A5%E5%85%A8%E5%BA%93)\u3002\r\n\r\n> \u867d\u7136 [ModSDK \u8865\u5168\u5e93](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E5%AE%89%E8%A3%85mod-sdk%E8%A1%A5%E5%85%A8%E5%BA%93) \u7406\u8bba\u4e0a\u4e0d\u662f\u5fc5\u987b\u7684\uff0c\u4f46\u5b89\u88c5\u540e\u53ef\u4ee5\u5e2e\u52a9\u60a8\u7684\u4ee3\u7801\u7f16\u8f91\u5668\u4f7f\u7528\u8bed\u6cd5\u8865\u5168\u7b49\u529f\u80fd\u3002\r\n\r\n> \u672c\u6559\u7a0b\u5047\u8bbe\u60a8\u5bf9 MODSDK \u5df2\u7ecf\u6709\u4e86\u57fa\u672c\u7684\u4e86\u89e3\uff0c\u7406\u89e3\u57fa\u7840\u7684\u4e8b\u4ef6\u76d1\u542c\u4e0e\u56de\u8c03\u673a\u5236\u3002\u5982\u679c\u60a8\u8fd8\u4e0d\u4e86\u89e3\uff0c\u8bf7\u53c2\u8003 [\u5b98\u65b9\u6559\u7a0b](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1) \u81ea\u884c\u5b66\u4e60\u3002\r\n\r\n1. \u521b\u5efa\u6587\u4ef6\u5939\r\n\r\n \u9996\u5148\uff0c\u521b\u5efa\u4e00\u4e2a\u5982\u4e0b\u6240\u793a\u7684\u884c\u4e3a\u5305\u7ed3\u6784\u3002\r\n\r\n ```txt\r\n TutorialMod\r\n \u2514\u2500\u2500 tutorialBehaviorPack\r\n \u251c\u2500\u2500 entities\r\n \u2514\u2500\u2500 manifest.json\r\n ```\r\n\r\n \u5176\u4e2d\uff0cmanifest.json \u6587\u4ef6\u5185\u7684\u5185\u5bb9\u5982\u4e0b\u3002\r\n\r\n ```json\r\n {\r\n \"format_version\": 2,\r\n \"header\": {\r\n \"name\": \"MODSDKSpring\u6559\u7a0b\u884c\u4e3a\u5305\",\r\n \"description\": \"\u4f5c\u8005:\u521b\u9020\u8005MC\",\r\n \"uuid\": \"a44ca707-044d-47c4-ab75-d0568eef5d00\",\r\n \"version\": [1 ,0 ,0],\r\n \"min_engine_version\": [1 ,18 ,0]\r\n },\r\n \"modules\": [\r\n {\r\n \"description\": \"\u4f5c\u8005:\u521b\u9020\u8005MC\",\r\n \"uuid\": \"627b21f9-f6e5-44f1-82d3-4f3249606e20\",\r\n \"version\": [1,0,0],\r\n \"type\": \"data\"\r\n }\r\n ]\r\n }\r\n ```\r\n\r\n2. \u81ea\u52a8\u751f\u6210 Mod \u7ed3\u6784\r\n\r\n MODSDKSpring \u63d0\u4f9b\u4e86\u547d\u4ee4\u884c\u5f62\u5f0f\u7684\u81ea\u52a8\u751f\u6210\u5de5\u5177\uff0c\u80fd\u591f\u81ea\u52a8\u751f\u6210\u5305\u542b MODSDKSpring \u7684\u521d\u59cb\u7684 Mod \u7ed3\u6784\u3002\r\n\r\n \u5982\u679c\u60a8\u7684\u7535\u8111\u662f Windows \u7cfb\u7edf\uff0c\u5728 `TutorialMod/tutorialBehaviorPack` \u6587\u4ef6\u5939\u5185\u7684\u5730\u5740\u680f\u4e0a\u8f93\u5165 `cmd` \u5e76\u6309\u4e0b `Enter` \u952e\uff0c\u5373\u53ef\u5728\u5f53\u524d\u4f4d\u7f6e\u6253\u5f00\u4e00\u4e2a\u547d\u4ee4\u884c\u7a97\u53e3\u3002\r\n\r\n \r\n\r\n \u63a5\u7740\u8f93\u5165\u4ee5\u4e0b\u547d\u4ee4\uff1a\r\n\r\n ```shell\r\n modsdkspring init\r\n ```\r\n\r\n \u60a8\u4f1a\u5728\u547d\u4ee4\u884c\u7a97\u53e3\u770b\u5230\u5982\u4e0b\u8f93\u51fa\uff1a\r\n\r\n ```shell\r\n Start initializing your Mod...\r\n Please enter the name of the Mod folder:\r\n ```\r\n\r\n \u8bf7\u6ce8\u610f\uff0c\u5982\u679c\u60a8\u770b\u5230\u7684\u662f\uff1a\r\n\r\n ```shell\r\n 'modsdkspring' \u4e0d\u662f\u5185\u90e8\u6216\u5916\u90e8\u547d\u4ee4\uff0c\u4e5f\u4e0d\u662f\u53ef\u8fd0\u884c\u7684\u7a0b\u5e8f\u6216\u6279\u5904\u7406\u6587\u4ef6\u3002\r\n ```\r\n\r\n \u8bf4\u660e\u60a8\u8fd8\u6ca1\u6709\u4e0b\u8f7d\u5e76\u5b89\u88c5 MODSDKSpring\u3002\u8bf7\u67e5\u770b\u672c\u6587\u6863\u4e0a\u65b9\u7684 [\u6846\u67b6\u4e0b\u8f7d](#%E6%A1%86%E6%9E%B6%E4%B8%8B%E8%BD%BD) \u90e8\u5206\uff0c\u7136\u540e\u91cd\u590d\u6b64\u6b65\u9aa4\u3002\u6216\u8005\uff0c\u60a8\u53ef\u80fd\u6ca1\u6709\u6b63\u786e\u914d\u7f6e\u7cfb\u7edf\u7684\u73af\u5883\u53d8\u91cf\uff0c\u8bf7\u81ea\u884c\u641c\u7d22\u89e3\u51b3\u3002\r\n\r\n \u63a5\u4e0b\u6765\u6309\u7167\u63d0\u793a Please enter the name of the Mod folder\uff08\u8bf7\u8f93\u5165 Mod \u6587\u4ef6\u5939\u7684\u540d\u79f0\uff09\uff0c\u8f93\u5165\u4ee5\u4e0b\u540d\u79f0\u540e\u6309 `Enter` \u952e\u3002\r\n\r\n ```shell\r\n tutorialScripts\r\n ```\r\n\r\n \u63a5\u7740\u51fa\u73b0\u63d0\u793a Please enter the Mod name, which will serve as the namespace registered to the engine\uff08\u8bf7\u8f93\u5165Mod\u540d\u79f0\uff0c\u8be5\u540d\u79f0\u5c06\u4f5c\u4e3a\u6ce8\u518c\u5230\u5f15\u64ce\u7684\u547d\u540d\u7a7a\u95f4\uff09\uff0c\u7ee7\u7eed\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u540e\u6309 `Enter` \u952e\u3002\r\n\r\n ```shell\r\n TutorialMod\r\n ```\r\n\r\n \u63a5\u7740\u51fa\u73b0\u63d0\u793a Please enter the client system name, which will serve as the class name for the client system\uff08\u8bf7\u8f93\u5165\u5ba2\u6237\u7aef\u7cfb\u7edf\u540d\u79f0\uff0c\u8be5\u540d\u79f0\u5c06\u4f5c\u4e3a\u5ba2\u6237\u7aef\u7cfb\u7edf\u7684\u7c7b\u540d\uff09\uff0c\u7ee7\u7eed\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u540e\u6309 `Enter` \u952e\u3002\r\n\r\n ```shell\r\n TutorialClientSystem\r\n ```\r\n\r\n \u63a5\u7740\u51fa\u73b0\u63d0\u793a Please enter the server system name, which will serve as the class name for the server system\uff08\u8bf7\u8f93\u5165\u670d\u52a1\u7aef\u7cfb\u7edf\u540d\u79f0\uff0c\u8be5\u540d\u79f0\u5c06\u4f5c\u4e3a\u670d\u52a1\u7aef\u7cfb\u7edf\u7684\u7c7b\u540d\uff09\uff0c\u7ee7\u7eed\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u540e\u6309 `Enter` \u952e\u3002\r\n\r\n ```shell\r\n TutorialServerSystem\r\n ```\r\n\r\n \u6700\u540e\u51fa\u73b0\u63d0\u793a Created successfully!\r\n\r\n \r\n\r\n \u6b64\u65f6\u67e5\u770b\u6587\u4ef6\u5939\u7ed3\u6784\uff0c\u60a8\u5e94\u8be5\u5f97\u5230\u4e86\u5982\u4e0b\u6240\u793a\u7684\u7ed3\u6784\uff1a\r\n\r\n ```txt\r\n TutorialMod\r\n \u2514\u2500\u2500 tutorialBehaviorPack\r\n \u251c\u2500\u2500 entities\r\n \u251c\u2500\u2500 tutorialScripts\r\n \u2502 \u251c\u2500\u2500 components\r\n \u2502 \u2502 \u251c\u2500\u2500 client\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u251c\u2500\u2500 server\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 modCommon\r\n \u2502 \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u2514\u2500\u2500 modConfig.py\r\n \u2502 \u251c\u2500\u2500 plugins\r\n \u2502 \u2502 \u251c\u2500\u2500 MODSDKSpring\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 ...\r\n \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 modMain.py\r\n \u2502 \u251c\u2500\u2500 TutorialClientSystem.py\r\n \u2502 \u2514\u2500\u2500 TutorialServerSystem.py\r\n \u2514\u2500\u2500 manifest.json\r\n ```\r\n\r\n \u73b0\u5728\uff0c\u8fd9\u4e2a Mod \u5df2\u7ecf\u53ef\u4ee5\u76f4\u63a5\u653e\u5165\u6e38\u620f\u4e2d\u8fd0\u884c\u4e86\u3002\r\n\r\n3. Mod \u7ed3\u6784\u4ecb\u7ecd\r\n\r\n > \u5982\u679c\u60a8\u5df2\u7ecf\u4f1a\u4f7f\u7528 MODSDK \u4e86\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u5feb\u901f\u6d4f\u89c8\u4e00\u904d\u5373\u53ef\u3002\r\n\r\n - \\_\\_init\\_\\_.py\r\n\r\n python2 \u4e2d\uff0c\u6bcf\u4e2a\u5305\u542b `.py` \u6587\u4ef6\u7684\u6587\u4ef6\u5939\u5185\u90fd\u9700\u8981\u4e00\u4e2a `__init__.py` \u6587\u4ef6\u3002\r\n\r\n - modMain.py\r\n\r\n \u6b64\u6587\u4ef6\u662f Python \u903b\u8f91\u7684\u5165\u53e3\u6587\u4ef6\uff0c\u9700\u8981\u5728\u8fd9\u91cc\u5b9a\u4e49\u54ea\u4e2a\u7c7b\u662f\u5ba2\u6237\u7aef\uff0c\u54ea\u4e2a\u7c7b\u662f\u670d\u52a1\u7aef\uff0c\u4ee5\u53ca Mod \u7684\u540d\u79f0\u548c\u7248\u672c\u3002\r\n\r\n \u5b9e\u9645\u4e0a\uff0c\u60a8\u53ef\u4ee5\u5728 `modMain.py` \u4e2d\uff0c\u521b\u5efa\u591a\u4e2a `class`\uff0c\u4ee5\u6b64\u521b\u5efa\u591a\u4e2a Mod\u3002\u4f46\u5728 MODSDKSpring \u4e2d\uff0c\u6211\u4eec\u4e0d\u63a8\u8350\u8fd9\u6837\u505a\u3002\u56e0\u4e3a MODSDKSpring \u7684\u67b6\u6784\uff0c\u5df2\u7ecf\u89e3\u51b3\u4e86\u8fd9\u6837\u505a\u6240\u5e26\u6765\u7684\u201c\u597d\u5904\u201d\u3002\u5c3d\u7ba1\u5982\u6b64\uff0c\u4e3a\u4e86\u6846\u67b6\u7684\u7075\u6d3b\u6027\u548c\u5bf9\u73b0\u6709\u9879\u76ee\u7684\u6539\u9020\uff0cMODSDKSpring \u4ecd\u7136\u517c\u5bb9\u5728\u540c\u4e00\u4e2a `modMain.py` \u4e2d\u5b9a\u4e49\u591a\u4e2a Mod \u7684\u5199\u6cd5\u3002\u5728\u540e\u9762\u7684\u90e8\u5206\u4e2d\uff0c\u60a8\u53ef\u4ee5\u770b\u5230\u76f8\u5173\u7684\u5199\u6cd5\u3002\r\n\r\n \u66f4\u591a\u5173\u4e8e\u6b64\u6587\u4ef6\u7684\u8be6\u7ec6\u8bf4\u660e\uff0c\u8bf7\u53c2\u8003 [\u5b98\u65b9\u6587\u6863](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#modmain-py%E6%98%AF%E4%BB%80%E4%B9%88)\u3002\r\n\r\n - TutorialClientSystem.py\r\n\r\n \u6b64\u6587\u4ef6\u662f Mod \u7684\u5ba2\u6237\u7aef\u3002\u6bcf\u4e2a\u73a9\u5bb6\u90fd\u62e5\u6709\u4e00\u4e2a\u72ec\u7acb\u7684\u5ba2\u6237\u7aef\uff0c\u4f46\u670d\u52a1\u7aef\u662f\u5f53\u524d\u8054\u673a\u623f\u95f4\u5185\u6240\u6709\u73a9\u5bb6\u5171\u4eab\u7684\u3002\r\n\r\n \u66f4\u591a\u5173\u4e8e\u6b64\u6587\u4ef6\u7684\u8be6\u7ec6\u8bf4\u660e\uff0c\u8bf7\u53c2\u8003 [\u5b98\u65b9\u6587\u6863](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8E%E5%AE%A2%E6%88%B7%E7%AB%AF)\u3002\r\n\r\n - TutorialServerSystem.py\r\n\r\n \u6b64\u6587\u4ef6\u662f Mod \u7684\u670d\u52a1\u7aef\u3002\u6bcf\u4e2a\u73a9\u5bb6\u90fd\u62e5\u6709\u4e00\u4e2a\u72ec\u7acb\u7684\u5ba2\u6237\u7aef\uff0c\u4f46\u670d\u52a1\u7aef\u662f\u5f53\u524d\u8054\u673a\u623f\u95f4\u5185\u6240\u6709\u73a9\u5bb6\u5171\u4eab\u7684\u3002\r\n\r\n \u66f4\u591a\u5173\u4e8e\u6b64\u6587\u4ef6\u7684\u8be6\u7ec6\u8bf4\u660e\uff0c\u8bf7\u53c2\u8003 [\u5b98\u65b9\u6587\u6863](https://mc.163.com/dev/mcmanual/mc-dev/mcguide/20-%E7%8E%A9%E6%B3%95%E5%BC%80%E5%8F%91/13-%E6%A8%A1%E7%BB%84SDK%E7%BC%96%E7%A8%8B/2-Python%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91/0-%E8%84%9A%E6%9C%AC%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8.html?catalog=1#%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8E%E5%AE%A2%E6%88%B7%E7%AB%AF)\u3002\r\n\r\n - components\r\n\r\n \u5b58\u653e\u201c\u7ec4\u4ef6\u201d\u7684\u6587\u4ef6\u5939\uff0c\u6b64\u5904\u7684\u201c\u7ec4\u4ef6\u201d\uff0c\u662f MODSDKSpring \u7684\u4e00\u4e2a\u6982\u5ff5\u3002\u5728\u540e\u7eed\u7684\u6587\u6863\u4e2d\u4f1a\u8be6\u7ec6\u4ecb\u7ecd\u3002\r\n\r\n \u5176\u4e2d\uff0c`client` \u6587\u4ef6\u5939\uff0c\u5b58\u653e\u80fd\u8c03\u7528**\u5ba2\u6237\u7aef**\u76f8\u5173 API \u7684\u7ec4\u4ef6\u3002`server` \u6587\u4ef6\u5939\uff0c\u5b58\u653e\u80fd\u8c03\u7528**\u670d\u52a1\u7aef**\u76f8\u5173 API \u7684\u7ec4\u4ef6\u3002\r\n\r\n - modCommon\r\n\r\n \u5b58\u653e Mod \u4e2d\u4e00\u4e9b\u901a\u7528\u7684\u6a21\u5757\u3002\u5176\u4e2d\uff0c`modConfig.py` \u6587\u4ef6\u4e2d\uff0c\u9ed8\u8ba4\u5b58\u653e\u4e86\u6709\u5173 Mod \u672c\u8eab\u4fe1\u606f\u7684\u4e00\u4e9b\u5e38\u91cf\u3002\r\n\r\n - plugins\r\n\r\n \u63d2\u4ef6\u6587\u4ef6\u5939\uff0c\u53ef\u5b58\u653e\u4e00\u4e9b\u989d\u5916\u7684\u7b2c\u4e09\u65b9\u6a21\u5757\uff08\u901a\u5e38\u4e0d\u662f\u4f60\u81ea\u5df1\u7f16\u5199\u7684\u6a21\u5757\uff09\u3002MODSDKSpring \u6846\u67b6\u672c\u8eab\u88ab\u653e\u7f6e\u5728\u6b64\u6587\u4ef6\u5939\u4e2d\u3002\r\n\r\n4. \u76d1\u542c\u4e8b\u4ef6\r\n\r\n \u6253\u5f00 TutorialServerSystem.py \u6587\u4ef6\uff0c\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a\r\n\r\n ```python\r\n @ListenEvent.Server(eventName=\"ServerChatEvent\")\r\n def OnServerChat(self, args):\r\n print \"==== OnServerChat ==== \", args\r\n # \u751f\u6210\u6389\u843d\u7269\u54c1\r\n # \u5f53\u6211\u4eec\u8f93\u5165\u7684\u4fe1\u606f\u7b49\u4e8e\u53f3\u8fb9\u8fd9\u4e2a\u503c\u65f6\uff0c\u521b\u5efa\u76f8\u5e94\u7684\u7269\u54c1\r\n # \u521b\u5efaComponent\uff0c\u7528\u6765\u5b8c\u6210\u7279\u5b9a\u7684\u529f\u80fd\uff0c\u8fd9\u91cc\u662f\u4e3a\u4e86\u521b\u5efaItem\u7269\u54c1\r\n playerId = args[\"playerId\"]\r\n comp = compFactory.CreateItem(playerId)\r\n if args[\"message\"] == \"\u94bb\u77f3\u5251\": \r\n # \u8c03\u7528SpawnItemToPlayerInv\u63a5\u53e3\u751f\u6210\u7269\u54c1\u5230\u73a9\u5bb6\u80cc\u5305\uff0c\u53c2\u6570\u53c2\u8003\u300aMODSDK\u6587\u6863\u300b\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_sword\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9550\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_pickaxe\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u5934\u76d4\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_helmet\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u80f8\u7532\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_chestplate\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u62a4\u817f\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_leggings\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9774\u5b50\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_boots\", \"count\":1, 'auxValue': 0}, playerId)\r\n else:\r\n print \"==== Sorry man ====\"\r\n ```\r\n\r\n \u6700\u7ec8\uff0c\u6574\u4e2a\u6587\u4ef6\u7684\u4ee3\u7801\u5982\u4e0b\uff1a\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n\r\n import mod.server.extraServerApi as serverApi\r\n from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n ServerSystem = serverApi.GetServerSystemCls()\r\n compFactory = serverApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitServer\r\n class TutorialServerSystem(ServerSystem):\r\n\r\n def __init__(self, namespace, systemName):\r\n pass\r\n\r\n @ListenEvent.Server(eventName=\"ServerChatEvent\")\r\n def OnServerChat(self, args):\r\n print \"==== OnServerChat ==== \", args\r\n # \u751f\u6210\u6389\u843d\u7269\u54c1\r\n # \u5f53\u6211\u4eec\u8f93\u5165\u7684\u4fe1\u606f\u7b49\u4e8e\u53f3\u8fb9\u8fd9\u4e2a\u503c\u65f6\uff0c\u521b\u5efa\u76f8\u5e94\u7684\u7269\u54c1\r\n # \u521b\u5efaComponent\uff0c\u7528\u6765\u5b8c\u6210\u7279\u5b9a\u7684\u529f\u80fd\uff0c\u8fd9\u91cc\u662f\u4e3a\u4e86\u521b\u5efaItem\u7269\u54c1\r\n playerId = args[\"playerId\"]\r\n comp = compFactory.CreateItem(playerId)\r\n if args[\"message\"] == \"\u94bb\u77f3\u5251\": \r\n # \u8c03\u7528SpawnItemToPlayerInv\u63a5\u53e3\u751f\u6210\u7269\u54c1\u5230\u73a9\u5bb6\u80cc\u5305\uff0c\u53c2\u6570\u53c2\u8003\u300aMODSDK\u6587\u6863\u300b\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_sword\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9550\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_pickaxe\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u5934\u76d4\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_helmet\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u80f8\u7532\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_chestplate\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u62a4\u817f\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_leggings\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9774\u5b50\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_boots\", \"count\":1, 'auxValue': 0}, playerId)\r\n else:\r\n print \"==== Sorry man ====\"\r\n\r\n ```\r\n\r\n \u4e0a\u9762\u7684\u4ee3\u7801\u76d1\u542c\u4e86 [ServerChatEvent](https://mc.163.com/dev/mcmanual/mc-dev/mcdocs/1-ModAPI/%E4%BA%8B%E4%BB%B6/%E4%B8%96%E7%95%8C.html#serverchatevent) \u4e8b\u4ef6\uff0c\u548c\u5b98\u65b9\u6559\u7a0b\u4e00\u6837\uff0c\u5f53\u73a9\u5bb6\u5728\u804a\u5929\u6846\u4e2d\u8f93\u5165\u6307\u5b9a\u7684\u6587\u5b57\uff0c\u5c31\u4f1a\u7ed9\u4e88\u73a9\u5bb6\u6307\u5b9a\u7684\u7269\u54c1\u3002\r\n\r\n \u770b\u5230\u8fd9\u91cc\uff0c\u60a8\u53ef\u80fd\u4f1a\u6709\u51e0\u4e2a\u7591\u95ee\u3002\u4e0d\u7528\u62c5\u5fc3\uff0c\u7ee7\u7eed\u5f80\u4e0b\u770b\uff0c\u6211\u9a6c\u4e0a\u4f1a\u5411\u60a8\u89e3\u91ca\u8fd9\u4e00\u5207\u3002\r\n\r\n5. \u4ee3\u7801\u89e3\u91ca\r\n\r\n \u9488\u5bf9 MODSDKSpring\uff0c\u89e3\u91ca\u4e0a\u4e00\u6b65\u9aa4\u4e2d\u7684\u4ee3\u7801\u3002\u5bf9\u4e8e\u65b0\u589e\u88c5\u9970\u5668\u7684\u8be6\u7ec6\u8bf4\u660e\uff0c\u53ef\u4ee5\u67e5\u770b\u6b64\u6587\u6863\u4e2d\u7684 [\u88c5\u9970\u5668\u6587\u6863](#%E8%A3%85%E9%A5%B0%E5%99%A8%E6%96%87%E6%A1%A3) \u90e8\u5206\u3002\r\n\r\n - @ListenEvent.InitServer \u662f\u4ec0\u4e48\uff1f\r\n\r\n \u8fd9\u662f MODSDKSpring \u6846\u67b6\u63d0\u4f9b\u7684\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u53ea\u80fd\u6dfb\u52a0\u5230**\u670d\u52a1\u7aef\u7c7b**\u7684\u4e0a\u65b9\uff0c\u6807\u8bc6\u6b64\u7c7b\u662f\u4e00\u4e2a\u670d\u52a1\u7aef\u3002\u53ea\u6709\u6dfb\u52a0\u4e86\u8fd9\u4e2a\u88c5\u9970\u5668\uff0c\u624d\u80fd\u542f\u7528\u7c7b\u5185\u7684\u5176\u4ed6 MODSDKSpring \u4e2d\u7684\u88c5\u9970\u5668\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u65f6\u6700\u540e\u4e0d\u8981\u52a0\u62ec\u53f7\u3002\r\n\r\n \u7c7b\u4f3c\u7684\u8fd8\u6709 @ListenEvent.InitClient\u3002\r\n\r\n - @ListenEvent.Server(eventName=\"ServerChatEvent\") \u662f\u4ec0\u4e48\uff1f\r\n\r\n \u8fd9\u662f MODSDKSpring \u6846\u67b6\u63d0\u4f9b\u7684\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u53ea\u80fd\u6dfb\u52a0\u5230**\u670d\u52a1\u7aef\u7c7b\u6216\u7ec4\u4ef6**\u7684\u65b9\u6cd5\u4e0a\u3002\u5b83\u4ee3\u66ff\u4e86 self.ListenForEvent\uff0c\u8868\u793a\u6b64\u65b9\u6cd5\u8981\u76d1\u542c\u7684\u4e8b\u4ef6\uff0c\u4e8b\u4ef6\u7684\u56de\u8c03\u65b9\u6cd5\u5373\u662f\u6b64\u65b9\u6cd5\u3002\r\n\r\n \u5176\u4e2d `eventName` \u8868\u793a\u8981\u76d1\u542c\u7684\u4e8b\u4ef6\u7684\u540d\u79f0\u3002\u9664\u4e86\u76d1\u542c MODSDK \u63d0\u4f9b\u7684\u4e8b\u4ef6\uff0c\u5b83\u8fd8\u53ef\u4ee5\u76d1\u542c\u5176\u4ed6\u7cfb\u7edf\u53d1\u9001\u7684\u81ea\u5b9a\u4e49\u4e8b\u4ef6\uff0c\u8be6\u89c1 [\u76d1\u542c\u81ea\u5b9a\u4e49\u4e8b\u4ef6](#%E7%9B%91%E5%90%AC%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6) \u90e8\u5206\u3002\r\n\r\n \u7c7b\u4f3c\u7684\u8fd8\u6709 @ListenEvent.Client\u3002\r\n\r\n - \\_\\_init\\_\\_ \u65b9\u6cd5\u5185\u7684 super(XXX, self).\\_\\_init\\_\\_(namespace, systemName) \u53bb\u54ea\u4e86\uff1f\r\n\r\n \u5bf9\u7236\u7c7b\u6784\u9020\u65b9\u6cd5\u7684\u8c03\u7528\uff0c\u5df2\u7ecf\u88ab\u5c01\u88c5\u8fdb\u4e86 MODSDKSpring \u5185\u90e8\u3002\u60a8\u4e0d\u518d\u9700\u8981\uff0c\u4e5f\u4e0d\u5e94\u8be5\u624b\u52a8\u8c03\u7528\u7236\u7c7b\u6784\u9020\u65b9\u6cd5\u3002\r\n\r\n - Destroy \u65b9\u6cd5\u53bb\u54ea\u4e86\uff1f\r\n\r\n Destroy \u65b9\u6cd5\u5df2\u7ecf\u88ab\u5c01\u88c5\u8fdb\u4e86 MODSDKSpring \u5185\u90e8\uff0c\u5e76\u4e14\u4f1a\u5728\u7cfb\u7edf\u9500\u6bc1\u65f6\u81ea\u52a8\u53d6\u6d88\u7cfb\u7edf\u4e2d\u6240\u6709\u7684\u76d1\u542c\u3002\u60a8\u4e0d\u9700\u8981\u91cd\u5199 Destroy \u65b9\u6cd5\u4e86\uff0c\u4f46\u662f\uff0c\u5982\u679c\u60a8\u9700\u8981\u5728 Destroy \u65b9\u6cd5\u4e2d\u505a\u9664\u4e86\u53d6\u6d88\u76d1\u542c\u4ee5\u5916\u7684\u4e8b\u60c5\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u91cd\u5199 Destroy \u65b9\u6cd5\uff0c\u5e76\u4e14\u4e0d\u4f1a\u5f71\u54cd\u81ea\u52a8\u53d6\u6d88\u76d1\u542c\u7684\u529f\u80fd\u3002\r\n\r\n6. \u8fd0\u884c\r\n\r\n \u606d\u559c\u4f60\uff01\u73b0\u5728\u53ef\u4ee5\u628a\u4e0a\u9762\u7684\u884c\u4e3a\u5305\u653e\u5165\u6e38\u620f\u4e86\u3002\u5982\u679c\u60a8\u4f7f\u7528\u7f51\u6613\u7684\u6211\u7684\u4e16\u754c\u5f00\u53d1\u8005\u542f\u52a8\u5668\uff0c\u60a8\u5e94\u8be5\u4f1a\u5728\u8fdb\u5165\u6e38\u620f\u65f6\u770b\u5230\u5982\u4e0b\u5185\u5bb9\u3002\r\n\r\n \r\n\r\n \u5728\u6e38\u620f\u7684\u804a\u5929\u7a97\u53e3\u4e2d\u8f93\u5165 `\u94bb\u77f3\u5251`\uff0c\u9a8c\u8bc1 Mod \u662f\u5426\u751f\u6548\u3002\u5982\u679c\u60a8\u9047\u5230\u4e86\u95ee\u9898\uff0c\u53ef\u4ee5\u518d\u4ed4\u7ec6\u770b\u770b\u4e0a\u9762\u7684\u6b65\u9aa4\uff0c\u6216\u4e0b\u8f7d example \u5206\u652f\u5185\u7684\u793a\u4f8b\u3002\r\n\r\n > \u5982\u679c\u60a8\u6ca1\u6709\u770b\u5230\u6709\u5173\u670d\u52a1\u7aef\u7cfb\u7edf\u7684\u8f93\u51fa\uff0c\u53ef\u80fd\u662f\u60a8\u7684\u65e5\u5fd7\u4e0e\u8c03\u8bd5\u5de5\u5177\u6ca1\u6709\u53ca\u65f6\u6253\u5f00\u3002\u70b9\u51fb `\u5de5\u5177\u7bb1`\uff0c\u4f7f\u7528 `Mod PC\u5f00\u53d1\u5305` \u8fdb\u5165\u4e16\u754c\u5b58\u6863\u53ef\u89e3\u51b3\u6b64\u95ee\u9898\u3002\r\n\r\n# \u5b9a\u4e49\u7ec4\u4ef6\r\n\r\n\u8fd9\u91cc\u7684\u201c\u7ec4\u4ef6\u201d\uff0c\u662f\u4e00\u4e2a MODSDKSpring \u4e2d\u7684\u6982\u5ff5\u3002\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u4f1a\u5728\u4e00\u4e2a\u5ba2\u6237\u7aef\u7cfb\u7edf\u6216\u670d\u52a1\u7aef\u7cfb\u7edf\u4e2d\u76d1\u542c\u5f88\u591a\u4e8b\u4ef6\uff0c\u5199\u5f88\u591a\u7684\u56de\u8c03\u51fd\u6570\uff0c\u8fd9\u5c31\u5bfc\u81f4\u6211\u4eec\u7684\u4ee3\u7801\u90fd\u8026\u5408\u5728\u4e00\u4e2a\u6587\u4ef6\u5185\uff0c\u6dfb\u52a0\u548c\u4fee\u6539\u90fd\u5f88\u9ebb\u70e6\u3002\u8fd9\u70b9\u5728\u5927\u9879\u76ee\u4e2d\u5c24\u5176\u660e\u663e\u3002\r\n\r\n\u9488\u5bf9\u4e0a\u8ff0\u60c5\u51b5\uff0cMODSDKSpring \u63d0\u51fa\u4e86\u201c\u7ec4\u4ef6\u201d\u7684\u6982\u5ff5\u3002\u6240\u8c13\u201c\u7ec4\u4ef6\u201d\uff0c\u5728\u529f\u80fd\u4e0a\u53ef\u4ee5\u770b\u4f5c\u662f\u4e00\u4e2a\u72ec\u7acb\u7684\u5ba2\u6237\u7aef/\u670d\u52a1\u7aef\uff0c\u7ec4\u4ef6\u53ef\u4ee5\u50cf\u72ec\u7acb\u7684\u5ba2\u6237\u7aef/\u670d\u52a1\u7aef\u90a3\u6837\uff0c\u81ea\u5df1\u76d1\u542c\u4e8b\u4ef6\u5e76\u8fdb\u884c\u5904\u7406\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u60a8\u53ef\u4ee5\u5c06\u4e00\u4e9b\u5177\u6709\u5171\u540c\u7279\u70b9\u7684\u529f\u80fd\uff0c\u5355\u72ec\u5199\u6210\u4e00\u4e2a `.py` \u6587\u4ef6\uff0c\u518d\u4e5f\u4e0d\u7528\u8ff7\u5931\u5728\u6210\u767e\u4e0a\u5343\u884c\u7684\u4ee3\u7801\u4e2d\u4e86\u3002\r\n\r\n\u7ec4\u4ef6\u5206\u4e3a\u4e24\u79cd\uff0c\u4e00\u79cd\u662f\u5ba2\u6237\u7aef\u7ec4\u4ef6\uff0c\u4e00\u79cd\u662f\u670d\u52a1\u7aef\u7ec4\u4ef6\u3002\u65e0\u8bba\u662f\u5ba2\u6237\u7aef\u7ec4\u4ef6\u8fd8\u662f\u670d\u52a1\u7aef\u7ec4\u4ef6\uff0c\u5b83\u4eec\u90fd\u53ef\u4ee5\u6709\u591a\u4e2a\u3002\u4e00\u4e2a\u7ec4\u4ef6\u53ea\u5c5e\u4e8e\u4e00\u4e2a\u7cfb\u7edf\u3002\r\n\r\n\u4e0a\u9762\u8bf4\u7684\u8fd9\u4e9b\u6682\u65f6\u7406\u89e3\u4e0d\u4e86\u6ca1\u5173\u7cfb\uff0c\u63a5\u4e0b\u6765\u6211\u4f1a\u5e26\u60a8\u6539\u9020\u5feb\u901f\u5165\u95e8\u4e2d\u7684\u793a\u4f8b\uff0c\u7528\u7ec4\u4ef6\u7684\u65b9\u5f0f\u53bb\u5b9e\u73b0\u76f8\u540c\u7684\u529f\u80fd\u3002\r\n\r\n1. \u590d\u5236\u6587\u4ef6\u5939\r\n\r\n \u590d\u5236\u6211\u4eec\u5728\u5feb\u901f\u5165\u95e8\u4e2d\u521b\u5efa\u7684\u6587\u4ef6\u5939 `TutorialMod`\uff0c\u5e76\u91cd\u547d\u540d\u4e3a `TutorialComponentMod`\u3002\r\n\r\n \u5982\u679c\u60a8\u6ca1\u6709\u8ddf\u7740\u5feb\u901f\u5165\u95e8\u53bb\u505a\u4e5f\u6ca1\u5173\u7cfb\uff0c\u5728\u4ed3\u5e93\u7684 example \u5206\u652f\u4e2d\uff0c\u53ef\u4ee5\u4e0b\u8f7d\u5feb\u901f\u5165\u95e8\u4e2d\u7684\u4ee3\u7801\u3002\r\n\r\n \u5c06 `tutorialBehaviorPack` \u4e2d\u7684 `tutorialScripts` \u6587\u4ef6\u5939\u91cd\u547d\u540d\u4e3a `tutorialComponentScripts`\u3002\r\n\r\n2. \u4fee\u6539\u914d\u7f6e\r\n\r\n \u6253\u5f00 `manifest.json` \u4fee\u6539\u5176\u4e2d\u7684 `uuid`\u3002UUID \u53ef\u4ee5\u4f7f\u7528\u4e00\u4e9b\u5728\u7ebf\u7f51\u7ad9\u751f\u6210\uff0c\u5177\u4f53\u8bf7\u81ea\u884c\u641c\u7d22\u3002\r\n\r\n \u6253\u5f00 `modCommon` \u6587\u4ef6\u5939\u4e0b\u7684 `modConfig.py` \u6587\u4ef6\uff0c\u4fee\u6539\u4e3a\u5982\u4e0b\u5185\u5bb9\uff1a\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n\r\n # Mod Version\r\n MOD_NAMESPACE = \"TutorialComponentMod\"\r\n MOD_VERSION = \"0.0.1\"\r\n\r\n # Client System\r\n CLIENT_SYSTEM_NAME = \"TutorialClientSystem\"\r\n CLIENT_SYSTEM_CLS_PATH = \"tutorialComponentScripts.TutorialClientSystem.TutorialClientSystem\"\r\n\r\n # Server System\r\n SERVER_SYSTEM_NAME = \"TutorialServerSystem\"\r\n SERVER_SYSTEM_CLS_PATH = \"tutorialComponentScripts.TutorialServerSystem.TutorialServerSystem\"\r\n ```\r\n\r\n3. \u521b\u5efa\u670d\u52a1\u7aef\u7ec4\u4ef6\r\n\r\n \u56de\u60f3\u4e00\u4e0b\uff0c\u6211\u4eec\u9700\u8981\u76d1\u542c `ServerChatEvent` \u4e8b\u4ef6\uff0c\u6b64\u4e8b\u4ef6\u662f\u4e00\u4e2a\u670d\u52a1\u7aef\u4e8b\u4ef6\uff0c\u6240\u4ee5\u53ea\u80fd\u7528\u670d\u52a1\u7aef\u53bb\u76d1\u542c\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u7aef\u7ec4\u4ef6\uff0c\u7528\u6765\u4e13\u95e8\u505a\u8fd9\u4e00\u4ef6\u4e8b\u60c5\u3002\r\n\r\n \u5728 `components` \u6587\u4ef6\u5939\u5185\u7684 `server` \u6587\u4ef6\u5939\u5185\uff0c\u521b\u5efa\u4e00\u4e2a\u53eb\u505a `ChatServerComponent.py` \u7684\u6587\u4ef6\u3002\r\n\r\n \u6587\u4ef6\u5185\u4ee3\u7801\u5982\u4e0b\uff1a\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n import mod.server.extraServerApi as serverApi\r\n from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n ServerSystem = serverApi.GetServerSystemCls()\r\n compFactory = serverApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitComponentServer\r\n class ChatServerComponent(object):\r\n\r\n def __init__(self, server):\r\n # \u83b7\u53d6\u670d\u52a1\u7aef\u7cfb\u7edf\u5bf9\u8c61\uff0c\u5373 TutorialServerSystem \u7684\u5bf9\u8c61\r\n self.server = server\r\n\r\n # \u76d1\u542cServerChatEvent\u7684\u56de\u8c03\u51fd\u6570\r\n @ListenEvent.Server(eventName=\"ServerChatEvent\")\r\n def OnServerChat(self, args):\r\n print \"==== OnServerChat ==== \", args\r\n # \u751f\u6210\u6389\u843d\u7269\u54c1\r\n # \u5f53\u6211\u4eec\u8f93\u5165\u7684\u4fe1\u606f\u7b49\u4e8e\u53f3\u8fb9\u8fd9\u4e2a\u503c\u65f6\uff0c\u521b\u5efa\u76f8\u5e94\u7684\u7269\u54c1\r\n # \u521b\u5efaComponent\uff0c\u7528\u6765\u5b8c\u6210\u7279\u5b9a\u7684\u529f\u80fd\uff0c\u8fd9\u91cc\u662f\u4e3a\u4e86\u521b\u5efaItem\u7269\u54c1\r\n playerId = args[\"playerId\"]\r\n comp = compFactory.CreateItem(playerId)\r\n if args[\"message\"] == \"\u94bb\u77f3\u5251\": \r\n # \u8c03\u7528SpawnItemToPlayerInv\u63a5\u53e3\u751f\u6210\u7269\u54c1\u5230\u73a9\u5bb6\u80cc\u5305\uff0c\u53c2\u6570\u53c2\u8003\u300aMODSDK\u6587\u6863\u300b\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_sword\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9550\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_pickaxe\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u5934\u76d4\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_helmet\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u80f8\u7532\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_chestplate\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u62a4\u817f\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_leggings\", \"count\":1, 'auxValue': 0}, playerId)\r\n elif args[\"message\"] == \"\u94bb\u77f3\u9774\u5b50\":\r\n comp.SpawnItemToPlayerInv({\"itemName\":\"minecraft:diamond_boots\", \"count\":1, 'auxValue': 0}, playerId)\r\n else:\r\n print \"==== Sorry man ====\"\r\n ```\r\n\r\n \u521b\u5efa\u7ec4\u4ef6\u65f6\uff0c\u65e0\u8bba\u662f\u5ba2\u6237\u7aef\u7ec4\u4ef6\u8fd8\u662f\u670d\u52a1\u7aef\u7ec4\u4ef6\uff0c\u90fd\u9700\u8981\u7ee7\u627f\u81ea `object` \u7c7b\uff0c\u5373\u4e0a\u65b9\u4ee3\u7801\u4e2d\u7684 `class ChatServerComponent(object):`\u3002\r\n\r\n \u7ec4\u4ef6\u7684 `__init__` \u65b9\u6cd5\u4e2d\u7684\u53c2\u6570\uff0c\u5fc5\u987b\u6709\u7b2c\u4e8c\u4e2a\u53d8\u91cf\uff08\u5373\u4e0a\u65b9\u4ee3\u7801\u4e2d\u7684 `__init__(self, server)` \u4e2d\u7684 `server` \u53d8\u91cf\uff09\u3002\r\n\r\n \u5982\u679c\u662f\u5ba2\u6237\u7aef\u7ec4\u4ef6\uff0c`__init__` \u65b9\u6cd5\u4e00\u822c\u5199\u4e3a `__init__(self, client)`\u3002\r\n\r\n \u5982\u679c\u521b\u5efa\u7684\u662f**\u670d\u52a1\u7aef\u7ec4\u4ef6**\uff0c\u9700\u8981\u5728\u7c7b\u7684\u4e0a\u65b9\u6dfb\u52a0 `@ListenEvent.InitComponentServer` \u88c5\u9970\u5668\u3002\r\n\r\n \u5982\u679c\u521b\u5efa\u7684\u662f**\u5ba2\u6237\u7aef\u7ec4\u4ef6**\uff0c\u9700\u8981\u5728\u7c7b\u7684\u4e0a\u65b9\u6dfb\u52a0 `@ListenEvent.InitComponentClient` \u88c5\u9970\u5668\u3002\r\n\r\n4. \u4fee\u6539\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef\u6587\u4ef6\r\n\r\n \u6253\u5f00 `TutorialClientSystem.py` \u6587\u4ef6\uff0c\u4fee\u6539\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff1a\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n\r\n import mod.client.extraClientApi as clientApi\r\n # \u56e0\u4e3a\u6587\u4ef6\u5939\u540d\u79f0\u6539\u53d8\uff0c\u6240\u4ee5\u5bfc\u5165\u8def\u5f84\u4e5f\u6539\u53d8\u4e86\r\n from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n ClientSystem = clientApi.GetClientSystemCls()\r\n compFactory = clientApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitClient\r\n class TutorialClientSystem(ClientSystem):\r\n\r\n def __init__(self, namespace, systemName):\r\n pass\r\n\r\n ```\r\n\r\n \u6253\u5f00 `TutorialServerSystem.py` \u6587\u4ef6\uff0c\u4fee\u6539\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff1a\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n\r\n import mod.server.extraServerApi as serverApi\r\n # \u56e0\u4e3a\u6587\u4ef6\u5939\u540d\u79f0\u6539\u53d8\uff0c\u6240\u4ee5\u5bfc\u5165\u8def\u5f84\u4e5f\u6539\u53d8\u4e86\r\n from tutorialComponentScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n # \u5bfc\u5165\u7ec4\u4ef6\uff0c\u5c3d\u7ba1\u8fd9\u91cc\u4f60\u6ca1\u6709\u663e\u5f0f\u4f7f\u7528\u5b83\uff0c\u4e5f\u5fc5\u987b\u5bfc\u5165\uff01\r\n from tutorialComponentScripts.components.server.ChatServerComponent import ChatServerComponent\r\n ServerSystem = serverApi.GetServerSystemCls()\r\n compFactory = serverApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitServer\r\n class TutorialServerSystem(ServerSystem):\r\n\r\n def __init__(self, namespace, systemName):\r\n pass\r\n\r\n ```\r\n\r\n \u9700\u8981\u7279\u522b\u6ce8\u610f\u7684\u662f\uff0c\u56e0\u4e3a\u7f51\u6613\u6211\u7684\u4e16\u754c\u9650\u5236\u4e86 python \u7684 `os` \u6a21\u5757\uff0cMODSDKSpring \u6846\u67b6\u65e0\u6cd5\u901a\u8fc7\u8def\u5f84\u626b\u63cf\u81ea\u52a8\u5bfc\u5165\u6240\u9700\u8981\u7684\u7ec4\u4ef6\uff0c\u6240\u4ee5\u60a8\u5fc5\u987b\u5728 `TutorialServerSystem.py` \u6587\u4ef6\u4e2d\u624b\u52a8\u5bfc\u5165\u9700\u8981\u7684\u670d\u52a1\u7aef\u7ec4\u4ef6\uff0c\u5373 `from tutorialComponentScripts.components.server.ChatServerComponent import ChatServerComponent`\u3002\r\n\r\n \u540c\u7406\uff0c\u5982\u679c\u60a8\u521b\u5efa\u5ba2\u6237\u7aef\u7ec4\u4ef6\uff0c\u4e5f\u9700\u8981\u5728\u5ba2\u6237\u7aef\u7cfb\u7edf\u6587\u4ef6\u4e2d\u624b\u52a8\u5bfc\u5165\u9700\u8981\u7684\u5ba2\u6237\u7aef\u7ec4\u4ef6\u3002\r\n\r\n **\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u8fd9\u662f\u60a8\u7684\u7ec4\u4ef6\u4e0d\u751f\u6548\u7684\u9996\u8981\u539f\u56e0\uff0c\u8bf7\u52a1\u5fc5\u7262\u8bb0\uff01**\r\n\r\n > \u6709\u4e00\u79cd\u66f4\u52a0\u65b9\u4fbf\u7684\u5bfc\u5165\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff0c\u5e76\u4e14 MODSDKSpring \u6846\u67b6\u63d0\u4f9b\u4e86\u7c7b\u4f3c\u4e8e `modsdkspring init` \u4e00\u6837\u7684\u63a7\u5236\u53f0\u547d\u4ee4\u3002\u5f3a\u70c8\u5efa\u8bae\u60a8\u9605\u8bfb\u9ad8\u7ea7\u5185\u5bb9\u4e2d\u7684 [\u5feb\u901f\u5bfc\u5165\u7ec4\u4ef6](#%E5%BF%AB%E9%80%9F%E5%AF%BC%E5%85%A5%E7%BB%84%E4%BB%B6) \u90e8\u5206\u3002\r\n\r\n5. \u8fd0\u884c\r\n\r\n \u81f3\u6b64\uff0c\u6211\u4eec\u5df2\u7ecf\u5b8c\u6210\u4e86\u5bf9\u5feb\u901f\u5165\u95e8\u793a\u4f8b\u7684\u6539\u9020\u3002\u628a\u5728 `TutorialServerSystem.py` \u4e2d\u7684\u76d1\u542c\uff0c\u79fb\u5230\u4e86 `ChatServerComponent.py` \u4e2d\u3002\u73b0\u5728\u60a8\u53ef\u4ee5\u5bfc\u5165\u6539\u9020\u540e\u7684\u884c\u4e3a\u5305\uff0c\u5728\u804a\u5929\u7a97\u53e3\u4e2d\u8f93\u5165 `\u94bb\u77f3\u5251` \u9a8c\u8bc1 Mod \u662f\u5426\u751f\u6548\u3002\r\n\r\n6. \u4ee3\u7801\u89e3\u91ca\r\n\r\n - @ListenEvent.InitComponentServer \u662f\u4ec0\u4e48\uff1f\r\n\r\n \u8fd9\u662f MODSDKSpring \u6846\u67b6\u63d0\u4f9b\u7684\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u53ea\u80fd\u6dfb\u52a0\u5230**\u670d\u52a1\u7aef\u7ec4\u4ef6**\u7684\u4e0a\u65b9\uff0c\u6807\u8bc6\u6b64\u7c7b\u662f\u4e00\u4e2a\u670d\u52a1\u7aef\u7ec4\u4ef6\u3002\u53ea\u6709\u6dfb\u52a0\u4e86\u8fd9\u4e2a\u88c5\u9970\u5668\uff0c\u624d\u80fd\u542f\u7528\u7c7b\u5185\u7684\u5176\u4ed6 MODSDKSpring \u4e2d\u7684\u88c5\u9970\u5668\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u65f6\u6700\u540e\u4e0d\u8981\u52a0\u62ec\u53f7\u3002\r\n\r\n \u6b64\u88c5\u9970\u5668\u8fd8\u80fd\u5177\u4f53\u6307\u5b9a\u8be5\u670d\u52a1\u7aef\u7ec4\u4ef6\u5c5e\u4e8e\u54ea\u4e2a\u670d\u52a1\u7aef\uff0c\u5373\u7ec4\u4ef6\u7684 `__init__` \u65b9\u6cd5\u4e2d\u7684\u53c2\u6570 `server` \u5177\u4f53\u662f\u54ea\u4e2a\u670d\u52a1\u7aef\u7cfb\u7edf\u3002\u5982\u679c\u60a8\u5728 `modMain.py` \u4e2d\u53ea\u6ce8\u518c\u4e86\u4e00\u4e2a\u670d\u52a1\u7aef\uff0c\u90a3\u4e48\u6b64\u5904\u65e0\u9700\u6307\u5b9a\u8be5\u7ec4\u4ef6\u5c5e\u4e8e\u54ea\u4e2a\u670d\u52a1\u7aef\u3002\u5177\u4f53\u5982\u4f55\u6307\u5b9a\uff0c\u8be6\u89c1\u88c5\u9970\u5668\u6587\u6863\u90e8\u5206\u3002\r\n\r\n \u7c7b\u4f3c\u7684\u8fd8\u6709 @ListenEvent.InitComponentClient\u3002\r\n\r\n# \u76d1\u542c\u81ea\u5b9a\u4e49\u4e8b\u4ef6\r\n\r\n\u5728\u5b9e\u9645\u5f00\u53d1\u4e2d\uff0c\u6211\u4eec\u7ecf\u5e38\u4f1a\u81ea\u5b9a\u4e49\u4e8b\u4ef6\uff0c\u4ee5\u6b64\u6765\u8fdb\u884c\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u7aef\u4e4b\u95f4\u7684\u76f8\u4e92\u901a\u4fe1\u3002MODSDKSpring \u4e5f\u63d0\u4f9b\u4e86\u76d1\u542c\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u7684\u65b9\u6cd5\u3002\r\n\r\n- @ListenEvent.Client\r\n\r\n \u7528\u4e8e**\u5ba2\u6237\u7aef\u7cfb\u7edf/\u7ec4\u4ef6**\u76d1\u542c\u4e8b\u4ef6\uff0c\u53ea\u80fd\u6dfb\u52a0\u5230**\u5ba2\u6237\u7aef\u7cfb\u7edf/\u7ec4\u4ef6**\u7684\u65b9\u6cd5\u4e0a\u65b9\u3002\r\n\r\n \u5176\u62e5\u6709\u56db\u4e2a\u53c2\u6570\uff0c\u53c2\u6570\u540d\u53ca\u542b\u4e49\u5982\u4e0b\uff1a\r\n\r\n - eventName (str): \u76d1\u542c\u7684\u4e8b\u4ef6\u540d\u79f0\u3002\r\n - namespace (str, \u53ef\u9009): \u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 namespace\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineNamespace()\u3002\r\n - systemName (str, \u53ef\u9009): \u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 systemName\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineSystemName()\u3002\r\n - priority (int, \u53ef\u9009): \u56de\u8c03\u51fd\u6570\u7684\u4f18\u5148\u7ea7\u3002\u9ed8\u8ba4\u503c\u4e3a 0\uff0c\u8fd9\u4e2a\u6570\u503c\u8d8a\u5927\u8868\u793a\u88ab\u6267\u884c\u7684\u4f18\u5148\u7ea7\u8d8a\u9ad8\uff0c\u6700\u9ad8\u4e3a10\u3002\r\n\r\n- @ListenEvent.Server\r\n\r\n \u7528\u4e8e**\u670d\u52a1\u7aef\u7cfb\u7edf/\u7ec4\u4ef6**\u76d1\u542c\u4e8b\u4ef6\uff0c\u53ea\u80fd\u6dfb\u52a0\u5230**\u670d\u52a1\u7aef\u7cfb\u7edf/\u7ec4\u4ef6**\u7684\u65b9\u6cd5\u4e0a\u65b9\u3002\r\n\r\n \u5176\u62e5\u6709\u56db\u4e2a\u53c2\u6570\uff0c\u53c2\u6570\u540d\u53ca\u542b\u4e49\u5982\u4e0b\uff1a\r\n\r\n - eventName (str): \u76d1\u542c\u7684\u4e8b\u4ef6\u540d\u79f0\u3002\r\n - namespace (str, \u53ef\u9009): \u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 namespace\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineNamespace()\u3002\r\n - systemName (str, \u53ef\u9009): \u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 systemName\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineSystemName()\u3002\r\n - priority (int, \u53ef\u9009): \u56de\u8c03\u51fd\u6570\u7684\u4f18\u5148\u7ea7\u3002\u9ed8\u8ba4\u503c\u4e3a 0\uff0c\u8fd9\u4e2a\u6570\u503c\u8d8a\u5927\u8868\u793a\u88ab\u6267\u884c\u7684\u4f18\u5148\u7ea7\u8d8a\u9ad8\uff0c\u6700\u9ad8\u4e3a10\u3002\r\n\r\n\u5ba2\u6237\u7aef\u7cfb\u7edf/\u7ec4\u4ef6\u76d1\u542c\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u7684\u65b9\u5f0f\u5982\u4e0b\uff1a\r\n\r\n```python\r\n@ListenEvent.Client(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.SERVER_SYSTEM_NAME, eventName=\"DamageEventToClient\")\r\ndef damageEvent(self, event):\r\n pass\r\n```\r\n\r\n\u670d\u52a1\u7aef\u7cfb\u7edf/\u7ec4\u4ef6\u540c\u7406\uff0c\u53ea\u662f\u66ff\u6362\u4e3a `@ListenEvent.Server`\u3002\r\n\r\n\u5728 [ParticleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/ParticleMod) \u793a\u4f8b\u4e2d\uff0c\u5ba2\u6237\u7aef\u7ec4\u4ef6 `HurtEntityClientComponent.py` \u76d1\u542c\u4e86\u670d\u52a1\u7aef\u7ec4\u4ef6 `HurtEntityServerComponent.py` \u53d1\u51fa\u7684\u81ea\u5b9a\u4e49\u4e8b\u4ef6 `DamageEventToClient`\u3002\u60a8\u53ef\u4ee5\u4e0b\u8f7d\u6b64\u793a\u4f8b\uff0c\u67e5\u770b\u5177\u4f53\u4ee3\u7801\u3002\r\n\r\n# \u8de8\u7ec4\u4ef6\u8c03\u7528\uff08\u4f9d\u8d56\u6ce8\u5165\uff09\r\n\r\n\u8bbe\u60f3\u8fd9\u6837\u4e00\u4e2a\u573a\u666f\uff0c\u60a8\u5b9a\u4e49\u4e86\u4e00\u4e2a\u4e13\u95e8\u7528\u4e8e\u64ad\u653e\u7c92\u5b50\u7684\u5ba2\u6237\u7aef\u7ec4\u4ef6 `P`\u3002\u60a8\u6709\u53e6\u4e00\u4e2a\u5ba2\u6237\u7aef\u7ec4\u4ef6 `A`\u3002\u60a8\u60f3\u5b9e\u73b0\u5728\u5ba2\u6237\u7aef\u7ec4\u4ef6 `A` \u4e2d\u8c03\u7528\u5ba2\u6237\u7aef\u7ec4\u4ef6 `P` \u4e2d\u7684\u65b9\u6cd5\u3002\u8fd9\u65f6\u5019\u5e94\u8be5\u600e\u4e48\u529e\u5462\uff1f\r\n\r\n\u8981\u60f3\u5b9e\u73b0\u5728 `A` \u4e2d\u8c03\u7528 `P` \u7684\u65b9\u6cd5\uff0c`A` \u5fc5\u987b\u83b7\u53d6\u5230 `P` \u7684\u5bf9\u8c61 `p`\uff0c\u7136\u540e\u6267\u884c `p.xxx()` \u8fd9\u6837\u7684\u8bed\u53e5\u3002`A` \u548c `P` \u7684\u8fd9\u79cd\u5173\u7cfb\uff0c\u6211\u4eec\u53ef\u4ee5\u79f0\u4e3a `A` \u4f9d\u8d56\u4e8e `P`\u3002\u5373\uff0c`P` \u662f `A` \u7684\u4f9d\u8d56\u3002\r\n\r\nMODSDKSpring \u6846\u67b6\u53ef\u4ee5\u7ba1\u7406\u4e0a\u8ff0\u7684\u4f9d\u8d56\u5173\u7cfb\u3002\u5177\u4f53\u505a\u6cd5\u662f\uff0c\u6846\u67b6\u4f1a\u5728\u7ec4\u4ef6\u88ab\u521b\u5efa\u65f6\uff0c\u5c06\u7ec4\u4ef6\u7684\u5bf9\u8c61\u653e\u5165\u201c\u5bb9\u5668\u201d\uff08\u5b9e\u9645\u4e0a\u5c31\u662f\u4e00\u4e2a\u5b57\u5178\uff09\u5f53\u4e2d\u3002\u5f53\u7ec4\u4ef6 `A` \u9700\u8981\u53e6\u4e00\u4e2a\u7ec4\u4ef6 `P` \u65f6\uff0c\u6846\u67b6\u53ef\u4ee5\u4ece\u5bb9\u5668\u4e2d\u62ff\u5230 `P`\uff0c\u5e76\u628a `P` \u901a\u8fc7**\u67d0\u79cd\u65b9\u5f0f**\u4f20\u9012\u7ed9 `A`\u3002\r\n\r\n\u8fd9\u6837\uff0c`A` \u4fbf\u53ef\u4ee5\u8c03\u7528 `P` \u7684\u65b9\u6cd5\uff0c\u5e76\u4e14\u4e0d\u4f1a\u4ea7\u751f `P` \u8fd9\u4e2a\u7c7b\u7684\u65b0\u5bf9\u8c61\u3002\u5b9e\u73b0\u4e86\u7ec4\u4ef6\u7684\u5355\u4f8b\u6a21\u5f0f\uff0c\u8282\u7ea6\u5185\u5b58\u3002\r\n\r\n\u90a3\u4e48\uff0c**\u67d0\u79cd\u65b9\u5f0f**\u5177\u4f53\u662f\u4ec0\u4e48\uff1fMODSDKSpring \u6846\u67b6\u76ee\u524d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4ece\u5bb9\u5668\u4e2d\u83b7\u53d6\u7ec4\u4ef6\u5bf9\u8c61\u7684\u65b9\u6cd5\u3002\u8fd9\u4e24\u79cd\u65b9\u6cd5\u6709\u5b83\u4eec\u5404\u81ea\u7684\u4f7f\u7528\u573a\u666f\uff0c\u5177\u4f53\u7ec6\u8282\u8bf7\u7ee7\u7eed\u9605\u8bfb\u3002\r\n\r\n## \u7ec4\u4ef6\u7c7b\u7684\u5bf9\u8c61\u5728\u5bb9\u5668\u4e2d\u7684\u5b58\u50a8\u5f62\u5f0f\r\n\r\n\u6240\u8c13\u7684\u5bb9\u5668\uff0c\u5b9e\u9645\u4e0a\u5c31\u662f\u4e00\u4e2a `dict` \u7c7b\u578b\u7684\u53d8\u91cf\uff01\u5343\u4e07\u4e0d\u8981\u60f3\u7684\u592a\u590d\u6742\uff0c\u6211\u4e0d\u559c\u6b22\u73a9\u6587\u5b57\u6e38\u620f\uff0c\u5e0c\u671b\u60a8\u4e5f\u4e00\u6837\u3002\r\n\r\n\u5047\u8bbe\uff0c\u6709\u4e00\u4e2a\u5ba2\u6237\u7aef\u7ec4\u4ef6\u7c7b\uff0c\u7c7b\u540d\u662f `HurtEntityClientComponent`\u3002\u5f53\u6b64\u7c7b\u5728\u6846\u67b6\u4e2d\u521b\u5efa\u5bf9\u8c61\u540e\uff0c\u6846\u67b6\u4f1a\u7ed9\u5b83\u8d77\u4e00\u4e2a\u201c\u540d\u5b57\u201d\uff0c\u53eb\u505a `hurtEntityClientComponent`\uff08\u7c7b\u540d\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\u3002\u8fd9\u4e2a\u201c\u540d\u5b57\u201d\u662f\u5bb9\u5668\u4e2d\u7684 `key`\uff0c\u800c\u8fd9\u4e2a `key` \u5bf9\u5e94\u7684 `value` \u5c31\u662f\u7c7b `HurtEntityClientComponent` \u7684\u5bf9\u8c61\uff01\u5f62\u5f0f\u5982\u4e0b\u3002\r\n\r\n```python\r\n{\r\n 'hurtEntityClientComponent': HurtEntityClientComponent()\r\n # ...\r\n}\r\n```\r\n\r\n\u4e86\u89e3\u4e86\u8fd9\u4e9b\uff0c\u60a8\u53ef\u4ee5\u66f4\u597d\u7684\u7406\u89e3\u4e0b\u65b9\u7684\u4ece\u5bb9\u5668\u4e2d\u83b7\u53d6\u7ec4\u4ef6\u5bf9\u8c61\u7684\u65b9\u6cd5\u3002\r\n\r\n## \u6784\u9020\u65b9\u6cd5\u6ce8\u5165\r\n\r\n\u5047\u8bbe\uff0c\u6709\u4e00\u4e2a\u5ba2\u6237\u7aef\u7ec4\u4ef6 `HurtEntityClientComponent`\uff0c\u9700\u8981\u4f7f\u7528\u53e6\u4e00\u4e2a\u5ba2\u6237\u7aef\u7ec4\u4ef6 `ParticleClientComponent`\u3002\r\n\r\n\u9996\u5148\uff0c\u5728 `HurtEntityClientComponent` \u7684 `__init__` \u65b9\u6cd5\u7684\u53c2\u6570\u4e0a\uff0c\u6dfb\u52a0\u4e00\u4e2a\u53d8\u91cf\uff0c\u540d\u5b57\u4e3a `particleClientComponent`\uff08\u5bf9\u5e94\u7ec4\u4ef6\u7c7b\u540d\u7684\u9996\u5b57\u6bcd\u5c0f\u5199\uff0c**\u540d\u5b57\u4e0d\u80fd\u53d8\uff01**\uff09\u3002\u5982\u679c\u60a8\u6709\u66f4\u591a\u9700\u8981\u8c03\u7528\u7684\u7ec4\u4ef6\uff0c\u5728 `__init__` \u65b9\u6cd5\u7684\u53c2\u6570\u4e2d\uff0c\u53ef\u4ee5\u7ee7\u7eed\u6dfb\u52a0\u66f4\u591a\u7c7b\u4f3c\u5f62\u5f0f\u7684\u53d8\u91cf\u3002\r\n\r\n\u7136\u540e\uff0c\u5728 `__init__` \u65b9\u6cd5\u7684\u4e0a\u65b9\u6dfb\u52a0\u4e00\u4e2a\u88c5\u9970\u5668 `@Autowired`\uff0c\u5f00\u542f\u4f9d\u8d56\u6ce8\u5165\u3002\r\n\r\n\u6700\u540e\uff0c\u6846\u67b6\u4f1a\u81ea\u52a8\u5728 `HurtEntityClientComponent` \u7c7b\u7684\u5bf9\u8c61\u88ab\u521b\u5efa\u65f6\uff0c\u901a\u8fc7 `__init__` \u65b9\u6cd5\u7684\u53c2\u6570\uff0c\u4f20\u5165\u5bf9\u5e94\u7684 `ParticleClientComponent` \u7c7b\u7684\u5bf9\u8c61\u3002\r\n\r\n\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\nfrom particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\nfrom particleModScripts.plugins.MODSDKSpring.core.Autowired import Autowired\r\nfrom particleModScripts.modCommon import modConfig\r\nfrom particleModScripts.modCommon import eventConfig\r\n\r\n@ListenEvent.InitComponentClient\r\nclass HurtEntityClientComponent(object):\r\n\r\n @Autowired\r\n def __init__(self, client, particleClientComponent):\r\n self.client = client\r\n self.particleClientComponent = particleClientComponent\r\n```\r\n\r\n\u4e0a\u8ff0\u4ee3\u7801\u6765\u6e90\u4e8e example \u5206\u652f\u4e2d\u7684 [ParticleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/ParticleMod) \u793a\u4f8b\uff0c\u60a8\u53ef\u4ee5\u81ea\u884c\u4e0b\u8f7d\u67e5\u770b\u3002\r\n\r\n\u6ce8\u610f\uff0c\u5728 `__init__` \u65b9\u6cd5\u4e2d\uff0c\u53d8\u91cf `particleClientComponent` \u4e0d\u603b\u662f\u6709\u503c\u3002\u5982\u679c\u6709\u5faa\u73af\u4f9d\u8d56\u7684\u60c5\u51b5\uff0c\u53ef\u80fd\u53d8\u91cf `particleClientComponent` \u5728\u6267\u884c\u5b8c `__init__` \u65b9\u6cd5\u540e\uff0c\u624d\u88ab\u8d4b\u503c\uff0c\u6240\u4ee5\u53d8\u91cf `particleClientComponent` \u5728 `__init__` \u65b9\u6cd5\u4e2d\u53ef\u80fd\u4e3a `None`\u3002\r\n\r\n\u56e0\u6b64\uff0c\u6211\u5efa\u8bae\u60a8\u6c38\u8fdc\u4e0d\u8981\u5728 `__init__` \u65b9\u6cd5\u4e2d\u8c03\u7528\u5176\u4ed6\u7ec4\u4ef6\u7684\u65b9\u6cd5\uff01`__init__` \u65b9\u6cd5\u5e94\u8be5\u53ea\u505a\u8d4b\u503c\u64cd\u4f5c\uff01\r\n\r\n\u81f3\u4e8e\u5faa\u73af\u4f9d\u8d56\u662f\u4ec0\u4e48\u60c5\u51b5\uff0c\u8bf7\u67e5\u770b [\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56](#%E8%A7%A3%E5%86%B3%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96) \u90e8\u5206\u3002\r\n\r\n> `@Autowired` \u4e5f\u53ef\u4ee5\u88ab\u6dfb\u52a0\u5230**\u5ba2\u6237\u7aef/\u670d\u52a1\u7aef\u7cfb\u7edf**\u7684 `__init__` \u65b9\u6cd5\u4e0a\u65b9\uff0c\u4f46\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u60a8\u4e0d\u5e94\u8be5\u8fd9\u4e48\u505a\u3002\r\n\r\n## getBean() \u65b9\u6cd5\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.BeanFactory` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u8be5\u65b9\u6cd5\u80fd\u591f\u76f4\u63a5\u4ece\u5bb9\u5668\u4e2d\u83b7\u53d6\u7ec4\u4ef6\u5bf9\u8c61\r\n\r\n- \u53c2\u6570\r\n\r\n |\u53c2\u6570\u540d|\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |-----|--------|----|\r\n |systemType|str|\u60f3\u8981\u83b7\u53d6\u7684\u7ec4\u4ef6\u7684\u7c7b\u578b<br>\u503c\u4e3a `SystemType.CLIENT` \u6216 `SystemType.SERVER`<br>`SystemType` \u5728 `xxx.plugins.MODSDKSpring.core.constant.SystemType` \u4e2d|\r\n |beanName|str|\u5b58\u653e\u7ec4\u4ef6\u7684\u5bb9\u5668\u7684 `key`<br>\u5373\u7c7b\u540d\u9996\u5b57\u6bcd\u5c0f\u5199\uff0c\u6bd4\u5982\u4f60\u6709\u4e00\u4e2a\u7c7b\u540d\u4e3a `TestComponentClient` \u7684\u7ec4\u4ef6\uff0c\u90a3\u4e48\u5b83\u7684 `key` \u4e3a `testComponentClient`|\r\n\r\n- \u8fd4\u56de\u503c\r\n\r\n |\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |-------|----|\r\n |object \\| None|\u8fd4\u56de\u5bb9\u5668\u4e2d\u7684\u7ec4\u4ef6\u5bf9\u8c61<br>\u5982\u679c\u7ec4\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u8fd4\u56de None|\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n from tutorialScripts.plugins.MODSDKSpring.core.BeanFactory import BeanFactory\r\n import tutorialScripts.plugins.MODSDKSpring.core.constant.SystemType as SystemType\r\n\r\n testComponentClient = BeanFactory.getBean(SystemType.CLIENT, 'testComponentClient')\r\n ```\r\n\r\n> \u8be5\u65b9\u6cd5\u9002\u7528\u4e8e\u5728\u6ce8\u518c\u4e86\u591a\u4e2a\u5ba2\u6237\u7aef\u7cfb\u7edf\u6216\u670d\u52a1\u7aef\u7cfb\u7edf\u7684\u60c5\u51b5\u4e0b\uff0c\u67d0\u4e2a\u7cfb\u7edf\u7684\u7ec4\u4ef6\u8981\u8c03\u7528\u53e6\u5916\u4e00\u4e2a\u7cfb\u7edf\u7684\u7ec4\u4ef6\u65f6\u4f7f\u7528\u3002\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u8bf7\u4f7f\u7528 `@Autowired`\u3002\r\n\r\n> \u8be5\u65b9\u6cd5\u4e0d\u4f1a\u4ea7\u751f\u5faa\u73af\u4f9d\u8d56\u95ee\u9898\u3002\r\n\r\n> \u6c38\u8fdc\u4e0d\u8981\u5728 `__init__` \u65b9\u6cd5\u4e2d\u4f7f\u7528 `getBean()`\uff0c\u56e0\u4e3a\u6b64\u65f6\u60a8\u9700\u8981\u7684\u7ec4\u4ef6\u53ef\u80fd\u5c1a\u672a\u521b\u5efa\u3002\r\n\r\n# \u89e3\u51b3\u5faa\u73af\u4f9d\u8d56\r\n\r\n\u8bbe\u60f3\u8fd9\u6837\u4e00\u4e2a\u573a\u666f\uff0c\u60a8\u6709\u4e00\u4e2a\u7ec4\u4ef6 `A`\uff0c\u8fd8\u6709\u4e00\u4e2a\u7ec4\u4ef6 `B`\u3002\u60a8\u60f3\u5728\u7ec4\u4ef6 `A` \u4e2d\u8c03\u7528\u7ec4\u4ef6 `B` \u7684\u65b9\u6cd5\uff0c\u540c\u65f6\uff0c\u60a8\u4e5f\u60f3\u5728\u7ec4\u4ef6 `B` \u4e2d\u8c03\u7528\u7ec4\u4ef6 `A` \u4e2d\u7684\u65b9\u6cd5\u3002\u8fd9\u4e24\u4e2a\u7ec4\u4ef6\u90fd\u60f3\u8c03\u7528\u5bf9\u65b9\uff0c\u5c31\u5f62\u6210\u4e86\u6240\u8c13\u7684\u5faa\u73af\u4f9d\u8d56\u3002\r\n\r\n\u4ece\u4ee3\u7801\u903b\u8f91\u4e0a\u8bb2\uff0c\u5f53\u7ec4\u4ef6 `A` \u88ab\u521b\u5efa\u65f6\uff0c\u6846\u67b6\u53d1\u73b0\u7ec4\u4ef6 `A` \u9700\u8981\u4e00\u4e2a\u7ec4\u4ef6 `B`\uff0c\u4e8e\u662f\u5c31\u5148\u53bb\u521b\u5efa\u7ec4\u4ef6 `B` \u7684\u5bf9\u8c61\u3002\u4f46\u662f\u5728\u521b\u5efa\u7ec4\u4ef6 `B` \u65f6\uff0c\u6846\u67b6\u53c8\u53d1\u73b0\u7ec4\u4ef6 `B` \u9700\u8981\u7ec4\u4ef6 `A`\uff0c\u4e8e\u662f\u53c8\u53bb\u521b\u5efa\u7ec4\u4ef6 `A` \u7684\u5bf9\u8c61\uff0c\u8fd9\u5c31\u5f62\u6210\u4e86\u4e00\u4e2a\u5faa\u73af\u3002\u5982\u679c\u4e0d\u505a\u4efb\u4f55\u5904\u7406\uff0c\u6700\u7ec8\u4f1a\u56e0\u4e3a\u9012\u5f52\u5c42\u6570\u8fc7\u591a\uff0c\u629b\u51fa\u5f02\u5e38\u3002\r\n\r\nMODSDKSpring \u6846\u67b6\u76ee\u524d\u63d0\u4f9b\u4e86\u4e24\u79cd\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56\u7684\u65b9\u6cd5\u3002\u4e00\u79cd\u662f\u5728\u9700\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u7ec4\u4ef6\u7684\u5730\u65b9\uff0c\u624b\u52a8\u8c03\u7528 `getBean()` \u65b9\u6cd5\u3002\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u4e0d\u8981\u5728 `__init__` \u65b9\u6cd5\u4e2d\u4f7f\u7528 `getBean()`\u3002\r\n\r\n\u53e6\u5916\u4e00\u79cd\u65b9\u6cd5\uff0c\u662f\u4f7f\u7528\u88c5\u9970\u5668 `@Lazy`\u3002\u8fd9\u79cd\u65b9\u6cd5\u5e94\u8be5\u662f\u60a8\u7684\u9996\u9009\u3002\r\n\r\n## \u4f7f\u7528 @Lazy\r\n\r\n\u5047\u8bbe\u7ec4\u4ef6 `A` \u548c `B` \u4e4b\u95f4\u5b58\u5728\u5faa\u73af\u4f9d\u8d56\uff0c\u90a3\u4e48\u60a8\u53ea\u9700\u8981\u5728 `A` \u6216\u8005 `B` \u4e2d\u7684 `__init__` \u65b9\u6cd5\u4e0a\u7684 `@Autowired` \u4e0a\u9762\u6dfb\u52a0 `@Lazy` \u5373\u53ef\u3002\u6ce8\u610f\uff0c\u662f `A` \u6216\u8005 `B`\uff0c\u5728\u5176\u4e2d\u4e00\u4e2a\u7c7b\u7684 `@Autowired` \u4e0a\u9762\u52a0\u5c31\u884c\uff01\r\n\r\n\u6dfb\u52a0\u4e86 `@Lazy` \u7684 `__init__` \u65b9\u6cd5\uff0c\u4f1a\u5728\u521b\u5efa\u5bf9\u8c61\u65f6\u5148\u7528 `None` \u586b\u5145\u65b9\u6cd5\u5185\u7684\u7ec4\u4ef6\u7684\u53d8\u91cf\u3002\u5728 `__init__` \u65b9\u6cd5\u6267\u884c\u5b8c\u6210\uff0c\u6240\u6709\u7ec4\u4ef6\u88ab\u521b\u5efa\u4e4b\u540e\uff0c\u4f1a\u518d\u6b21\u6267\u884c\u4f9d\u8d56\u6ce8\u5165\uff0c\u7ed9\u5bf9\u8c61\u4e2d\u7684\u7ec4\u4ef6\u7684\u53d8\u91cf\u8d4b\u503c\uff08\u5982\u4e0b\u65b9\u4ee3\u7801\u4e2d\u7684 `self.b`\uff09\u3002\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\u3002\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\nfrom particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\nfrom particleModScripts.plugins.MODSDKSpring.core.Autowired import Autowired\r\nfrom particleModScripts.plugins.MODSDKSpring.core.Lazy import Lazy\r\nfrom particleModScripts.modCommon import modConfig\r\nfrom particleModScripts.modCommon import eventConfig\r\n\r\n@ListenEvent.InitComponentClient\r\nclass A(object):\r\n\r\n @Lazy\r\n @Autowired\r\n def __init__(self, client, b):\r\n self.client = client\r\n self.b = b # self.b \u7684\u503c\u6b64\u65f6\u4e3a None\uff0c\u6240\u6709\u7ec4\u4ef6\u521b\u5efa\u5b8c\u6210\u540e\uff0c\u6846\u67b6\u4f1a\u81ea\u52a8\u4e3a self.b \u8d4b\u503c\u3002\r\n```\r\n\r\n\u5982\u679c\u9047\u5230\u4e86\u95ee\u9898\uff0c\u60a8\u53ef\u4ee5\u4e0b\u8f7d example \u5206\u652f\u4e2d\u7684 [CirculateMod](https://github.com/CreatorMC/MODSDKSping/tree/example/CirculateMod) \u793a\u4f8b\uff0c\u6b64\u793a\u4f8b\u4e13\u95e8\u6f14\u793a\u4e86\u5982\u4f55\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56\u3002\r\n\r\n> `@Lazy` \u53ea\u80fd\u5199\u5728 `@Autowired` \u7684\u4e0a\u65b9\uff01\u5982\u679c\u5199\u5728 `@Autowired` \u4e0b\u65b9\uff0c\u60a8\u4f1a\u5728\u7f51\u6613\u6211\u7684\u4e16\u754c\u5f00\u53d1\u8005\u542f\u52a8\u5668\u7684\u65e5\u5fd7\u7a97\u53e3\u4e2d\u770b\u5230 `@Lazy \u5fc5\u987b\u6dfb\u52a0\u5728 @Autowired \u7684\u4e0a\u65b9\u3002` \u7684\u5f02\u5e38\u63d0\u793a\u3002\r\n\r\n> `@Lazy` \u4e0d\u80fd\u7528\u4e8e**\u5ba2\u6237\u7aef/\u670d\u52a1\u7aef\u7cfb\u7edf**\u7684 `__init__` \u65b9\u6cd5\u4e0a\uff08\u8fd9\u91cc\u6307\u7684\u662f\u5ba2\u6237\u7aef\u6216\u670d\u52a1\u7aef\u7cfb\u7edf\uff0c\u4e0d\u662f\u7ec4\u4ef6\uff09\u3002\u56e0\u4e3a\u8fd9\u5b8c\u5168\u6ca1\u6709\u5fc5\u8981\uff0c\u4f7f\u7528 `@Autowired` \u5df2\u8db3\u591f\u5c06\u7ec4\u4ef6\u6ce8\u5165\u5230\u5ba2\u6237\u7aef/\u670d\u52a1\u7aef\u7cfb\u7edf\u4e2d\uff0c\u5e76\u4e14\u4e0d\u4f1a\u4e0e\u7cfb\u7edf\u4e4b\u95f4\u4ea7\u751f\u5faa\u73af\u4f9d\u8d56\u3002\u5982\u679c\u60a8\u5bf9\u6b64\u4ecd\u6709\u7591\u60d1\uff0c\u8bf7\u67e5\u770b [CirculateMod](https://github.com/CreatorMC/MODSDKSping/tree/example/CirculateMod) \u793a\u4f8b\u3002\r\n\r\n# \u9ad8\u7ea7\u5185\u5bb9\r\n\r\n> \u5bf9\u60a8\u6765\u8bf4\uff0c\u8fd9\u90e8\u5206\u7684\u5185\u5bb9\u4e0d\u662f\u4f7f\u7528\u6846\u67b6\u6240\u5fc5\u987b\u770b\u7684\u3002\u4f46\u5982\u679c\u60a8\u4e86\u89e3\u4e86\u8fd9\u4e9b\u9ad8\u7ea7\u5185\u5bb9\uff0c\u53ef\u80fd\u5728\u67d0\u4e9b\u573a\u666f\u4e0b\u4f1a\u5e2e\u52a9\u60a8\u66f4\u65b9\u4fbf\u7684\u4f7f\u7528\u6846\u67b6\u3002\r\n\r\n## \u5feb\u901f\u5bfc\u5165\u7ec4\u4ef6\r\n\r\n\u5047\u8bbe\u60a8\u7684 Addon \u6587\u4ef6\u7ed3\u6784\u5982\u4e0b\uff1a\r\n\r\n```txt\r\nTutorialMod\r\n\u2514\u2500\u2500 tutorialBehaviorPack\r\n \u251c\u2500\u2500 entities\r\n \u251c\u2500\u2500 tutorialScripts\r\n \u2502 \u251c\u2500\u2500 components\r\n \u2502 \u2502 \u251c\u2500\u2500 client\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 AClientComponent.py\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 BClientComponent.py\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 CClientComponent.py\r\n \u2502 \u2502 \u251c\u2500\u2500 server\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 AServerComponent.py\r\n \u2502 \u2502 \u2502 \u251c\u2500\u2500 BServerComponent.py\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 CServerComponent.py\r\n \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 modCommon\r\n \u2502 \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u2502 \u2514\u2500\u2500 modConfig.py\r\n \u2502 \u251c\u2500\u2500 plugins\r\n \u2502 \u2502 \u251c\u2500\u2500 MODSDKSpring\r\n \u2502 \u2502 \u2502 \u2514\u2500\u2500 ...\r\n \u2502 \u2502 \u2514\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 __init__.py\r\n \u2502 \u251c\u2500\u2500 modMain.py\r\n \u2502 \u251c\u2500\u2500 TutorialClientSystem.py\r\n \u2502 \u2514\u2500\u2500 TutorialServerSystem.py\r\n \u2514\u2500\u2500 manifest.json\r\n```\r\n\r\n\u5728 `TutorialMod/tutorialBehaviorPack/tutorialScripts/components/client/__init__.py` \u6587\u4ef6\u4e2d\u7f16\u5199\u5982\u4e0b\u4ee3\u7801\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\n# \u6b64\u5904\u5047\u8bbe\u6a21\u5757\u540d\u548c\u6a21\u5757\u4e2d\u5b9a\u4e49\u7684\u7c7b\u540d\u76f8\u540c\uff0c\u8bf7\u6839\u636e\u60a8\u7684\u5b9e\u9645\u60c5\u51b5\u8fdb\u884c\u5bfc\u5165\r\nfrom AClientComponent import AClientComponent\r\nfrom BClientComponent import BClientComponent\r\nfrom CClientComponent import CClientComponent\r\n```\r\n\r\n\u5728 `TutorialMod/tutorialBehaviorPack/tutorialScripts/components/server/__init__.py` \u6587\u4ef6\u4e2d\u7f16\u5199\u5982\u4e0b\u4ee3\u7801\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\n# \u6b64\u5904\u5047\u8bbe\u6a21\u5757\u540d\u548c\u6a21\u5757\u4e2d\u5b9a\u4e49\u7684\u7c7b\u540d\u76f8\u540c\uff0c\u8bf7\u6839\u636e\u60a8\u7684\u5b9e\u9645\u60c5\u51b5\u8fdb\u884c\u5bfc\u5165\r\nfrom AServerComponent import AServerComponent\r\nfrom BServerComponent import BServerComponent\r\nfrom CServerComponent import CServerComponent\r\n```\r\n\r\n\u5728 `TutorialMod/tutorialBehaviorPack/tutorialScripts/TutorialClientSystem.py` \u6587\u4ef6\u9876\u90e8\u6dfb\u52a0\u5982\u4e0b\u4ee3\u7801\uff1a\r\n\r\n```python\r\nfrom tutorialScripts.components.client import *\r\n```\r\n\r\n\u5728 `TutorialMod/tutorialBehaviorPack/tutorialScripts/TutorialServerSystem.py` \u6587\u4ef6\u9876\u90e8\u6dfb\u52a0\u5982\u4e0b\u4ee3\u7801\uff1a\r\n\r\n```python\r\nfrom tutorialScripts.components.server import *\r\n```\r\n\r\n\u8fd9\u6837\uff0c\u6bcf\u5f53\u60a8\u589e\u52a0\u6216\u5220\u9664\u7ec4\u4ef6\u65f6\uff0c\u4e0d\u9700\u8981\u6539\u52a8 `TutorialClientSystem.py` \u548c `TutorialServerSystem.py` \u6587\u4ef6\uff0c\u53ea\u9700\u8981\u6539\u52a8 `client` \u548c `server` \u6587\u4ef6\u5939\u5185\u7684 `__init__.py` \u6587\u4ef6\u5373\u53ef\u3002\r\n\r\n\u60a8\u53ef\u80fd\u8fd8\u662f\u89c9\u5f97\u5f88\u9ebb\u70e6\uff0c\u8fd8\u662f\u8981\u624b\u52a8\u4fee\u6539\u6587\u4ef6\uff0c\u79f0\u4e0d\u4e0a\u201c\u5feb\u901f\u201d\u3002\u9488\u5bf9\u8fd9\u70b9\uff0cMODSDKSpring \u63d0\u4f9b\u4e86\u4e00\u4e2a\u63a7\u5236\u53f0\u547d\u4ee4\uff0c\u80fd\u591f\u81ea\u52a8\u751f\u6210\u4e0a\u8ff0\u7684 `__init__.py` \u6587\u4ef6\u3002\r\n\r\n### \u81ea\u52a8\u751f\u6210\u6240\u9700\u7684 \\_\\_init\\_\\_.py \u6587\u4ef6\r\n\r\n\u6253\u5f00\u60a8\u7684\u547d\u4ee4\u884c\u7a97\u53e3\uff0c\u6216\u8005\u5728\u60a8\u7684\u4ee3\u7801\u7f16\u8f91\u5668\u4e2d\u6253\u5f00\u4e00\u4e2a\u7ec8\u7aef\u3002\u7136\u540e\u5c06\u5f53\u524d\u4f4d\u7f6e\u5207\u6362\u5230 `.../components/client` \u6216 `.../components/server` \u6587\u4ef6\u5939\u4e0b\u3002\u8f93\u5165\u4e0b\u65b9\u547d\u4ee4\uff1a\r\n\r\n```shell\r\nmodsdkspring import\r\n```\r\n\r\n\u6b63\u5e38\u7684\u8bdd\uff0c\u60a8\u5e94\u8be5\u4f1a\u770b\u5230\u4ee5\u4e0b\u8f93\u51fa\uff1a\r\n\r\n```shell\r\nStarting to create the __init__.py file.\r\nSuccessfully created the __init__.py file!\r\n```\r\n\r\n\u7136\u540e\u5728 `.../components/client` \u6216 `.../components/server` \u6587\u4ef6\u5939\u5185\uff0c\u5c31\u4f1a\u81ea\u52a8\u751f\u6210\u4e00\u4e2a `__init__.py` \u6587\u4ef6\uff08\u5982\u679c\u6b64\u6587\u4ef6\u5df2\u5b58\u5728\uff0c\u4f1a\u81ea\u52a8\u8986\u76d6\u6587\u4ef6\u4e2d\u7684\u5185\u5bb9\uff09\u3002\u5176\u4e2d\u5bfc\u5165\u4e86\u6b64\u6587\u4ef6\u5939\u53ca\u5176\u5b50\u6587\u4ef6\u5939\u5185\u6240\u6709\u7684\u7c7b\u3002\r\n\r\n\u5f88\u591a\u65f6\u5019\uff0c\u60a8\u5728\u4ee3\u7801\u7f16\u8f91\u5668\u4e2d\u6253\u5f00\u4e00\u4e2a\u7ec8\u7aef\uff0c\u53ef\u80fd\u7ec8\u7aef\u6240\u5728\u7684\u9ed8\u8ba4\u4f4d\u7f6e\u5e76\u4e0d\u662f `.../components/client` \u6216 `.../components/server`\uff0c\u5e76\u4e14\u60a8\u4e5f\u4e0d\u60f3\u624b\u52a8\u5207\u6362\u4f4d\u7f6e\u3002\u8fd9\u65f6\u5019\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 `modsdkspring import` \u547d\u4ee4\u63d0\u4f9b\u7684\u53c2\u6570 `--path`\uff0c\u6307\u5b9a\u8def\u5f84\u3002\u5177\u4f53\u793a\u4f8b\u5982\u4e0b\uff1a\r\n\r\n```shell\r\nmodsdkspring import --path \"tutorialBehaviorPack/tutorialScripts/components/client\"\r\n```\r\n\r\n\u4e0a\u9762\u7684\u547d\u4ee4\u5047\u8bbe\u7ec8\u7aef\u7684\u5f53\u524d\u4f4d\u7f6e\u5728 `TutorialMod` \u4e2d\u3002\u547d\u4ee4\u6267\u884c\u540e\uff0c\u4f1a\u5728\u60a8\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u751f\u6210\u4e00\u4e2a `__init__.py` \u6587\u4ef6\u3002\r\n\r\n### \u5c06\u547d\u4ee4\u914d\u7f6e\u4e3a Visual Studio Code \u4efb\u52a1\r\n\r\n\u5c3d\u7ba1\u6846\u67b6\u63d0\u4f9b\u4e86\u76f8\u5173\u547d\u4ee4\uff0c\u4f46\u6bcf\u6b21\u6dfb\u52a0\u6216\u5220\u9664\u7ec4\u4ef6\uff0c\u60a8\u90fd\u8981\u624b\u52a8\u6267\u884c\u4e00\u6b21\u547d\u4ee4\uff0c\u8fd9\u4ecd\u7136\u6bd4\u8f83\u9ebb\u70e6\uff0c\u4e0d\u591f\u81ea\u52a8\u5316\u3002\r\n\r\n\u5982\u679c\u60a8\u4f7f\u7528 Visual Studio Code \u4f5c\u4e3a\u60a8\u7684\u4ee3\u7801\u7f16\u8f91\u5668\uff0c\u60a8\u53ef\u4ee5\u9605\u8bfb\u6b64\u90e8\u5206\uff0c\u6309\u7167\u6b65\u9aa4\u914d\u7f6e\u81ea\u52a8\u5316\u4efb\u52a1\u3002\r\n\r\n\u6700\u7ec8\u5b9e\u73b0\u7684\u6548\u679c\u662f\uff0c\u5f53\u60a8\u5728 Visual Studio Code \u4e2d\u4fdd\u5b58\u7ec4\u4ef6\u76ee\u5f55\u4e0b\u7684 `.py` \u6587\u4ef6\u65f6\uff0cVisual Studio Code \u5c06\u81ea\u52a8\u6267\u884c\u547d\u4ee4 `modsdkspring import --path \"xxx\"`\u3002\r\n\r\n> \u6b64\u6559\u7a0b\u73af\u5883\u8bf4\u660e\u5982\u4e0b\u3002<br>\u5982\u679c\u60a8\u7684\u8bbe\u5907\u73af\u5883\u4e0d\u7b26\u5408\u4e0b\u65b9\u7684\u8bf4\u660e\uff0c\u60a8\u4e5f\u53ef\u4ee5\u6309\u6b64\u6559\u7a0b\u5c1d\u8bd5\u914d\u7f6e\uff0c\u5982\u679c\u60a8\u9047\u5230\u4e86\u95ee\u9898\uff0c\u53ef\u81ea\u884c\u641c\u7d22\u89e3\u51b3\u3002<br><br>\u64cd\u4f5c\u7cfb\u7edf\uff1aWindows 10<br>Visual Studio Code \u7248\u672c\uff1a1.72.1\r\n\r\n1. \u5b89\u88c5\u6269\u5c55\r\n\r\n \u5728 Visual Studio Code \u4e2d\u7684\u6269\u5c55\u4e2d\u641c\u7d22 [Save and Run](https://marketplace.visualstudio.com/items?itemName=wk-j.save-and-run) \u6216\u76f4\u63a5\u70b9\u51fb\u94fe\u63a5\uff0c\u5b89\u88c5\u6b64\u6269\u5c55\u3002\u672c\u6559\u7a0b\u7684 Save and Run \u7248\u672c\u4e3a 0.0.22\u3002\r\n\r\n2. \u914d\u7f6e\u6269\u5c55\r\n\r\n \u5047\u8bbe\u60a8\u6709\u4e00\u4e2a\u5982\u4e0b\u56fe\u6240\u793a\u7684\u5de5\u4f5c\u533a\uff1a\r\n\r\n \r\n\r\n \u60a8\u9700\u8981\u5728 `settings` \u4e2d\u589e\u52a0\u5982\u4e0b\u6587\u672c\uff1a\r\n\r\n ```json\r\n \"saveAndRun\": {\r\n \"commands\": [\r\n {\r\n \"match\": \".*\\\\\\\\components\\\\\\\\(client|server).*\\\\.py\",\r\n \"cmd\": \"modsdkspring import --path \\\"${fileDirname}\\\"\",\r\n \"useShortcut\": false,\r\n \"silent\": false\r\n }\r\n ]\r\n }\r\n ```\r\n\r\n > \u5982\u679c\u60a8\u6709\u5de5\u4f5c\u533a\u6587\u4ef6 `XXX.code-workspace`\uff0c\u8bf7\u6309\u4e0a\u65b9\u622a\u56fe\u4e2d\u7684\u65b9\u5f0f\u8fdb\u884c\u914d\u7f6e\u3002\u5982\u679c\u60a8\u6ca1\u6709\u5de5\u4f5c\u533a\u6587\u4ef6\uff0c\u8bf7\u5728 `.vscode` \u6587\u4ef6\u5939\u4e2d\u7684 `settings.json` \u6587\u4ef6\u4e2d\u6dfb\u52a0\u914d\u7f6e\u3002\r\n\r\n > \u60a8\u53ef\u4ee5\u4fee\u6539 `match` \u4e2d\u7684\u6b63\u5219\u8868\u8fbe\u5f0f\uff0c\u4ee5\u7b26\u5408\u60a8\u7684\u5b9e\u9645\u60c5\u51b5\u3002\r\n\r\n3. \u6d4b\u8bd5\u6548\u679c\r\n\r\n \u73b0\u5728\uff0c\u8bf7\u5c1d\u8bd5\u4fee\u6539 `.../components/client` \u6216 `.../components/server` \u6587\u4ef6\u5939\u4e0b\u7684 `.py` \u6587\u4ef6\uff0c\u5728\u60a8\u6309 `ctrl + s` \u4fdd\u5b58\u6587\u4ef6\u65f6\uff0c\u60a8\u53ef\u4ee5\u770b\u5230 Visual Studio Code \u5c06\u81ea\u52a8\u6253\u5f00\u4e00\u4e2a\u7ec8\u7aef\uff0c\u5e76\u6267\u884c\u547d\u4ee4\u3002\r\n\r\n \r\n\r\n## \u5728 modMain.py \u4e2d\u521b\u5efa\u591a\u4e2a\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef\u7684\u60c5\u51b5\r\n\r\n> \u5728 MODSDKSpring \u6846\u67b6\u4e2d\uff0c\u6211\u4e0d\u63a8\u8350\u60a8\u8fd9\u4e48\u505a\u3002\u4f46\u662f\uff0c\u5982\u679c\u60a8\u4ecd\u8981\u8fd9\u4e48\u505a\uff0cMODSDKSpring \u4e5f\u63d0\u4f9b\u4e86\u65b9\u6cd5\u3002\r\n\r\n\u5047\u8bbe\u60a8\u7684 `modMain.py` \u6587\u4ef6\u5982\u4e0b\u6240\u793a\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\n\r\nfrom mod.common.mod import Mod\r\nimport mod.client.extraClientApi as clientApi\r\nimport mod.server.extraServerApi as serverApi\r\nfrom modCommon import modConfig\r\nfrom mod_log import logger\r\n\r\n@Mod.Binding(name=modConfig.MOD_NAMESPACE, version=modConfig.MOD_VERSION)\r\nclass TMSMultipleMod(object):\r\n\r\n def __init__(self):\r\n logger.info(\"===== init %s mod =====\", modConfig.MOD_NAMESPACE)\r\n\r\n @Mod.InitServer()\r\n def TMSMultipleModServerInit(self):\r\n logger.info(\"===== init %s server =====\", modConfig.SERVER_SYSTEM_NAME)\r\n serverApi.RegisterSystem(modConfig.MOD_NAMESPACE, modConfig.SERVER_SYSTEM_NAME, modConfig.SERVER_SYSTEM_CLS_PATH)\r\n\r\n @Mod.DestroyServer()\r\n def TMSMultipleModServerDestroy(self):\r\n logger.info(\"===== destroy %s server =====\", modConfig.SERVER_SYSTEM_NAME)\r\n\r\n @Mod.InitClient()\r\n def TMSMultipleModClientInit(self):\r\n logger.info(\"===== init %s client =====\", modConfig.CLIENT_SYSTEM_NAME)\r\n clientApi.RegisterSystem(modConfig.MOD_NAMESPACE, modConfig.CLIENT_SYSTEM_NAME, modConfig.CLIENT_SYSTEM_CLS_PATH)\r\n\r\n @Mod.DestroyClient()\r\n def TMSMultipleModClientDestroy(self):\r\n logger.info(\"===== destroy %s client =====\", modConfig.CLIENT_SYSTEM_NAME)\r\n\r\n@Mod.Binding(name=modConfig.MOD_NAMESPACE_1, version=modConfig.MOD_VERSION_1)\r\nclass TMSCopyMod(object):\r\n\r\n def __init__(self):\r\n logger.info(\"===== init %s mod =====\", modConfig.MOD_NAMESPACE_1)\r\n\r\n @Mod.InitServer()\r\n def TMSCopyModServerInit(self):\r\n logger.info(\"===== init %s server =====\", modConfig.SERVER_SYSTEM_NAME_1)\r\n serverApi.RegisterSystem(modConfig.MOD_NAMESPACE_1, modConfig.SERVER_SYSTEM_NAME_1, modConfig.SERVER_SYSTEM_CLS_PATH_1)\r\n\r\n @Mod.DestroyServer()\r\n def TMSCopyModServerDestroy(self):\r\n logger.info(\"===== destroy %s server =====\", modConfig.SERVER_SYSTEM_NAME_1)\r\n\r\n @Mod.InitClient()\r\n def TMSCopyModClientInit(self):\r\n logger.info(\"===== init %s client =====\", modConfig.CLIENT_SYSTEM_NAME_1)\r\n clientApi.RegisterSystem(modConfig.MOD_NAMESPACE_1, modConfig.CLIENT_SYSTEM_NAME_1, modConfig.CLIENT_SYSTEM_CLS_PATH_1)\r\n\r\n @Mod.DestroyClient()\r\n def TMSCopyModClientDestroy(self):\r\n logger.info(\"===== destroy %s client =====\", modConfig.CLIENT_SYSTEM_NAME_1)\r\n```\r\n\r\n`modConfig.py` \u4ee3\u7801\u5982\u4e0b\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\n\r\n# Mod Version\r\nMOD_NAMESPACE = \"TMSMultipleMod\"\r\nMOD_VERSION = \"0.0.1\"\r\n\r\n# Client System\r\nCLIENT_SYSTEM_NAME = \"MultipleClientSystem\"\r\nCLIENT_SYSTEM_CLS_PATH = \"multipleModScripts.MultipleClientSystem.MultipleClientSystem\"\r\n\r\n# Server System\r\nSERVER_SYSTEM_NAME = \"MultipleServerSystem\"\r\nSERVER_SYSTEM_CLS_PATH = \"multipleModScripts.MultipleServerSystem.MultipleServerSystem\"\r\n\r\n# Mod Version\r\nMOD_NAMESPACE_1 = \"TMSCopyMod\"\r\nMOD_VERSION_1 = \"0.0.1\"\r\n\r\n# Client System\r\nCLIENT_SYSTEM_NAME_1 = \"CopyClientSystem\"\r\nCLIENT_SYSTEM_CLS_PATH_1 = \"multipleModScripts.CopyClientSystem.CopyClientSystem\"\r\n\r\n# Server System\r\nSERVER_SYSTEM_NAME_1 = \"CopyServerSystem\"\r\nSERVER_SYSTEM_CLS_PATH_1 = \"multipleModScripts.CopyServerSystem.CopyServerSystem\"\r\n```\r\n\r\n\u4e0b\u65b9\u7684\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5c5e\u4e8e `CopyClientSystem` \u7684\u7ec4\u4ef6\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\nfrom multipleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\nfrom multipleModScripts.modCommon import modConfig\r\nfrom multipleModScripts.plugins.MODSDKSpring.core.log.Log import logger\r\n\r\n@ListenEvent.InitComponentClient(namespace=modConfig.MOD_NAMESPACE_1, systemName=modConfig.CLIENT_SYSTEM_NAME_1)\r\nclass ACopyClientComponent(object):\r\n\r\n def __init__(self, client):\r\n self.client = client\r\n logger.info(\"ACopyClientComponent \u83b7\u53d6\u5230\u7684\u7cfb\u7edf\uff1a\" + str(client))\r\n```\r\n\r\n\u4e0b\u65b9\u7684\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5c5e\u4e8e `CopyServerSystem` \u7684\u7ec4\u4ef6\uff1a\r\n\r\n```python\r\n# -*- coding: utf-8 -*-\r\nfrom multipleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\nfrom multipleModScripts.modCommon import modConfig\r\nfrom multipleModScripts.plugins.MODSDKSpring.core.log.Log import logger\r\n\r\n@ListenEvent.InitComponentServer(namespace=modConfig.MOD_NAMESPACE_1, systemName=modConfig.SERVER_SYSTEM_NAME_1)\r\nclass ACopyServerComponent(object):\r\n\r\n def __init__(self, server):\r\n self.server = server\r\n logger.info(\"ACopyServerComponent \u83b7\u53d6\u5230\u7684\u7cfb\u7edf\uff1a\" + str(server))\r\n```\r\n\r\n\u9700\u8981\u660e\u786e\u4e00\u70b9\u7684\u662f\uff0c\u5982\u679c\u60a8\u7684 `modMain.py` \u4e2d\u6ce8\u518c\u4e86\u591a\u4e2a\u7cfb\u7edf\uff0c\u60a8\u9700\u8981\u5728 `@ListenEvent.InitComponentClient` \u6216 `@ListenEvent.InitComponentServer` \u5f53\u4e2d\u586b\u5199 `namespace` \u548c `systemName` \u8fd9\u4e24\u4e2a\u53c2\u6570\uff0c\u4ee5\u6b64\u6765\u6307\u5b9a\u6b64\u7ec4\u4ef6\u5c5e\u4e8e\u54ea\u4e2a\u7cfb\u7edf\u3002\u4e0d\u53ef\u4ee5\u7701\u7565\u4e0d\u586b\uff01\r\n\r\n\u5982\u679c\u60a8\u8fd8\u6709\u7591\u95ee\uff0c\u53ef\u4ee5\u4e0b\u8f7d example \u5206\u652f\u4e2d\u7684 [MultipleMod](https://github.com/CreatorMC/MODSDKSping/tree/example/MultipleMod) \u793a\u4f8b\u3002\u6b64\u793a\u4f8b\u8fd8\u5c55\u793a\u4e86\u5982\u4f55\u5b9e\u73b0\u4e0d\u540c\u7cfb\u7edf\u7684\u7ec4\u4ef6\u4e4b\u95f4\u7684\u8c03\u7528\u3002\r\n\r\n## \u81ea\u5b9a\u4e49 Mod \u751f\u6210\u6a21\u677f\uff08\u672a\u6765\u53ef\u80fd\u7684\u529f\u80fd\uff09\r\n\r\n\u5b9e\u9645\u4e0a\uff0c\u73b0\u5728\u5df2\u7ecf\u80fd\u81ea\u5b9a\u4e49\u751f\u6210\u6a21\u677f\u4e86\uff0c\u53ea\u662f\u6a21\u677f\u88ab\u5185\u7f6e\u5728\u6846\u67b6\u5f53\u4e2d\uff0c\u6ca1\u6709\u63d0\u4f9b\u5bf9\u5916\u7684\u6807\u51c6\u65b9\u6cd5\u3002\u611f\u5174\u8da3\u7684\u5f00\u53d1\u8005\uff0c\u53ef\u4ee5\u9605\u8bfb\u76f8\u5173\u6e90\u7801\uff0c\u81ea\u884c\u63a2\u7d22\u81ea\u5b9a\u4e49\u751f\u6210\u6a21\u677f\u7684\u65b9\u6cd5\u3002\u6216\u8005\uff0c\u6b22\u8fce\u60a8\u5bf9\u672c\u6846\u67b6\u7684\u4ee3\u7801\u505a\u51fa\u8d21\u732e\uff01\r\n\r\n# \u53ef\u80fd\u9047\u5230\u7684\u95ee\u9898\r\n\r\n> \u60a8\u5728\u65e5\u5fd7\u4e2d\u53ef\u80fd\u4f1a\u770b\u5230\u4e0b\u65b9\u6240\u5217\u7684\u8fd9\u4e9b\u63d0\u793a\u4fe1\u606f\uff0c\u5982\u679c\u60a8\u770b\u5230\u4e86\u5e76\u4e14\u4e0d\u77e5\u9053\u600e\u4e48\u89e3\u51b3\uff0c\u53ef\u4ee5\u67e5\u9605\u6b64\u90e8\u5206\u3002\r\n>\r\n> \u4e0b\u65b9\u6807\u9898\u6216\u63cf\u8ff0\u4e2d\u63d0\u5230\u7684 `XXX`\u3001`xxx` \u548c `YYY` \u5747\u8868\u793a\u5b9e\u9645\u7684\u7c7b\u6216\u65b9\u6cd5\u3002\r\n\r\n## \u6ca1\u6709\u627e\u5230\u5e26\u6709 @InitComponentClient \u6216 @InitComponentServer \u7684\u7c7b XXX\uff0c\u5c06\u4f7f\u7528 None \u8fdb\u884c\u6ce8\u5165\u3002\r\n\r\n- \u539f\u56e0\r\n\r\n \u770b\u5230\u6b64\u65e5\u5fd7\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u771f\u7684\u6ca1\u6709\u5728\u7c7b `XXX` \u4e0a\u6dfb\u52a0 `@InitComponentClient` \u6216 `@InitComponentServer`\uff0c\u5bfc\u81f4\u7c7b `XXX` \u7684\u5bf9\u8c61\u4e0d\u80fd\u88ab\u6ce8\u5165\u3002\r\n\r\n \u53e6\u4e00\u79cd\u60c5\u51b5\u662f\uff0c\u5f53\u60a8\u5728 `modMain.py` \u4e2d\u6ce8\u518c\u4e86\u591a\u4e2a\u7cfb\u7edf\u65f6\uff0c\u60a8\u5728\u67d0\u4e2a\u7cfb\u7edf\u4e2d\u8981\u60f3\u7528 `@Autowired` \u6ce8\u5165\u5176\u4ed6\u7cfb\u7edf\u7684\u7ec4\u4ef6\u5bf9\u8c61\u3002\u8fd9\u79cd\u60c5\u51b5\u5c5e\u4e8e\u8de8\u7cfb\u7edf\u8c03\u7528\u7ec4\u4ef6\uff0c\u8bf7\u4f7f\u7528 [getBean()](#getbean-\u65b9\u6cd5) \u65b9\u6cd5\u3002\r\n\r\n## \u7c7b XXX \u548c YYY \u4e4b\u95f4\u5b58\u5728\u5faa\u73af\u4f9d\u8d56\uff0c\u8bf7\u4f7f\u7528 @Lazy \u89e3\u51b3\u3002\r\n\r\n- \u539f\u56e0\r\n\r\n \u5f53\u4e24\u4e2a\u7c7b\u5f7c\u6b64\u90fd\u9700\u8981\u6ce8\u5165\u5bf9\u65b9\u7684\u5bf9\u8c61\u65f6\uff0c\u4f1a\u51fa\u73b0\u6b64\u5f02\u5e38\u4fe1\u606f\u3002\u53ef\u53c2\u8003 [\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56](#\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56) \u90e8\u5206\u3002\r\n\r\n## \u65b9\u6cd5 xxx \u4e0d\u662f \\_\\_init\\_\\_\uff0c\u4e0d\u80fd\u4f7f\u7528 @Autowired \u88c5\u9970\u5668\u3002\r\n\r\n- \u539f\u56e0\r\n\r\n \u60a8\u5c06 `@Autowired` \u52a0\u5728\u4e86 `xxx` \u65b9\u6cd5\u7684\u4e0a\u65b9\u3002`@Autowired` \u53ea\u80fd\u52a0\u5728\u7ec4\u4ef6\u6216\u7cfb\u7edf\u7c7b\u7684 `__init__` \u65b9\u6cd5\u4e0a\u65b9\u3002\r\n\r\n## @Lazy \u5fc5\u987b\u6dfb\u52a0\u5728 @Autowired \u7684\u4e0a\u65b9\u3002\r\n\r\n- \u539f\u56e0\r\n\r\n \u60a8\u5199\u4e86\u5982\u4e0b\u6240\u793a\u7684\u4ee3\u7801\uff1a\r\n\r\n ```python\r\n @Autowired\r\n @Lazy\r\n def __init__(self, client, aClientComponent):\r\n # ...\r\n ```\r\n\r\n \u5c06\u4ee3\u7801\u8c03\u6574\u4e3a\uff1a\r\n\r\n ```python\r\n @Lazy\r\n @Autowired\r\n def __init__(self, client, aClientComponent):\r\n # ...\r\n ```\r\n\r\n \u5373\u53ef\u89e3\u51b3\u3002\r\n\r\n# \u88c5\u9970\u5668\u6587\u6863\r\n\r\n> \u8fd9\u4e00\u90e8\u5206\u89e3\u91ca\u4e86 MODSDKSpring \u4e2d\u5404\u4e2a\u88c5\u9970\u5668\u7684\u53c2\u6570\u548c\u542b\u4e49\u3002\u9002\u5408\u5165\u95e8 MODSDKSpring \u540e\u5feb\u901f\u67e5\u9605\u76f8\u5173\u529f\u80fd\u65f6\u4f7f\u7528\u3002\r\n\r\n## @ListenEvent.InitClient\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5728\u88ab modMain.py \u6ce8\u518c\u7684\u5ba2\u6237\u7aef\u7c7b\u7684\u4e0a\u65b9\uff0c\u5f00\u542f\u6846\u67b6\u76f8\u5173\u529f\u80fd\r\n\r\n- \u53c2\u6570\r\n\r\n \u65e0\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n import mod.client.extraClientApi as clientApi\r\n from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n ClientSystem = clientApi.GetClientSystemCls()\r\n compFactory = clientApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitClient\r\n class TutorialClientSystem(ClientSystem):\r\n\r\n def __init__(self, namespace, systemName):\r\n pass\r\n ```\r\n\r\n## @ListenEvent.InitServer\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5728\u88ab modMain.py \u6ce8\u518c\u7684\u670d\u52a1\u7aef\u7c7b\u7684\u4e0a\u65b9\uff0c\u5f00\u542f\u6846\u67b6\u76f8\u5173\u529f\u80fd\r\n\r\n- \u53c2\u6570\r\n\r\n \u65e0\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n import mod.server.extraServerApi as serverApi\r\n from tutorialScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n ServerSystem = serverApi.GetServerSystemCls()\r\n compFactory = serverApi.GetEngineCompFactory()\r\n\r\n @ListenEvent.InitServer\r\n class TutorialServerSystem(ServerSystem):\r\n\r\n def __init__(self, namespace, systemName):\r\n pass\r\n ```\r\n\r\n## @ListenEvent.InitComponentClient\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5230\u81ea\u5b9a\u4e49\u7684\u5ba2\u6237\u7aef Component \u7c7b\u7684\u4e0a\u65b9\uff0c\u5f00\u542f\u6846\u67b6\u76f8\u5173\u529f\u80fd\r\n\r\n- \u53c2\u6570\r\n\r\n |\u53c2\u6570\u540d|\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |------|-------|----|\r\n |namespace|str|\u6ce8\u5165\u7684\u5ba2\u6237\u7aef\u7cfb\u7edf\u7684\u547d\u540d\u7a7a\u95f4\uff0c\u5f53 modMain.py \u4e2d\u53ea\u6ce8\u518c\u4e86\u4e00\u4e2a\u5ba2\u6237\u7aef\u65f6\u4e0d\u7528\u586b\u5199\u6b64\u53c2\u6570|\r\n |systemName|str|\u6ce8\u5165\u7684\u5ba2\u6237\u7aef\u7cfb\u7edf\u7684\u7cfb\u7edf\u540d\u79f0\uff0c\u5f53 modMain.py \u4e2d\u53ea\u6ce8\u518c\u4e86\u4e00\u4e2a\u5ba2\u6237\u7aef\u65f6\u4e0d\u7528\u586b\u5199\u6b64\u53c2\u6570|\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n\r\n @ListenEvent.InitComponentClient\r\n class HurtEntityClientComponent(object):\r\n\r\n def __init__(self, client):\r\n self.client = client\r\n ```\r\n\r\n## @ListenEvent.InitComponentServer\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5230\u81ea\u5b9a\u4e49\u7684\u670d\u52a1\u7aef Component \u7c7b\u7684\u4e0a\u65b9\uff0c\u5f00\u542f\u6846\u67b6\u76f8\u5173\u529f\u80fd\r\n\r\n- \u53c2\u6570\r\n\r\n |\u53c2\u6570\u540d|\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |------|-------|----|\r\n |namespace|str|\u6ce8\u5165\u7684\u670d\u52a1\u7aef\u7cfb\u7edf\u7684\u547d\u540d\u7a7a\u95f4\uff0c\u5f53 modMain.py \u4e2d\u53ea\u6ce8\u518c\u4e86\u4e00\u4e2a\u670d\u52a1\u7aef\u65f6\u4e0d\u7528\u586b\u5199\u6b64\u53c2\u6570|\r\n |systemName|str|\u6ce8\u5165\u7684\u670d\u52a1\u7aef\u7cfb\u7edf\u7684\u7cfb\u7edf\u540d\u79f0\uff0c\u5f53 modMain.py \u4e2d\u53ea\u6ce8\u518c\u4e86\u4e00\u4e2a\u670d\u52a1\u7aef\u65f6\u4e0d\u7528\u586b\u5199\u6b64\u53c2\u6570|\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n\r\n @ListenEvent.InitComponentServer\r\n class HurtEntityServerComponent(object):\r\n\r\n def __init__(self, server):\r\n self.server = server\r\n ```\r\n\r\n## @ListenEvent.Client\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u5ba2\u6237\u7aef\u76d1\u542c\u4e8b\u4ef6\r\n\r\n- \u53c2\u6570\r\n\r\n |\u53c2\u6570\u540d|\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |------|-------|----|\r\n |eventName|str|\u76d1\u542c\u7684\u4e8b\u4ef6\u540d\u79f0|\r\n |namespace|str|\u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 namespace\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineNamespace()|\r\n |systemName|str|\u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 systemName\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineSystemName()|\r\n |priority|int|\u56de\u8c03\u51fd\u6570\u7684\u4f18\u5148\u7ea7\u3002\u9ed8\u8ba4\u503c\u4e3a 0\uff0c\u8fd9\u4e2a\u6570\u503c\u8d8a\u5927\u8868\u793a\u88ab\u6267\u884c\u7684\u4f18\u5148\u7ea7\u8d8a\u9ad8\uff0c\u6700\u9ad8\u4e3a10|\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n\r\n @ListenEvent.Client(eventName=\"AddEntityClientEvent\")\r\n def addEntityClientEvent(self, args):\r\n pass\r\n ```\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n from particleModScripts.modCommon import modConfig\r\n\r\n @ListenEvent.Client(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.SERVER_SYSTEM_NAME, eventName=\"DamageEventToClient\")\r\n def damageEvent(self, event):\r\n pass\r\n ```\r\n\r\n## @ListenEvent.Server\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.ListenEvent` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u670d\u52a1\u7aef\u76d1\u542c\u4e8b\u4ef6\r\n\r\n- \u53c2\u6570\r\n\r\n |\u53c2\u6570\u540d|\u6570\u636e\u7c7b\u578b|\u8bf4\u660e|\r\n |------|-------|----|\r\n |eventName|str|\u76d1\u542c\u7684\u4e8b\u4ef6\u540d\u79f0|\r\n |namespace|str|\u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 namespace\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineNamespace()|\r\n |systemName|str|\u6240\u76d1\u542c\u4e8b\u4ef6\u7684\u6765\u6e90\u7cfb\u7edf\u7684 systemName\u3002\u9ed8\u8ba4\u503c\u4e3a clientApi.GetEngineSystemName()|\r\n |priority|int|\u56de\u8c03\u51fd\u6570\u7684\u4f18\u5148\u7ea7\u3002\u9ed8\u8ba4\u503c\u4e3a 0\uff0c\u8fd9\u4e2a\u6570\u503c\u8d8a\u5927\u8868\u793a\u88ab\u6267\u884c\u7684\u4f18\u5148\u7ea7\u8d8a\u9ad8\uff0c\u6700\u9ad8\u4e3a10|\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n\r\n @ListenEvent.Server(eventName=\"AddEntityServerEvent\")\r\n def addEntityServerEvent(self, args):\r\n pass\r\n ```\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from particleModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n from particleModScripts.modCommon import modConfig\r\n\r\n @ListenEvent.Server(namespace=modConfig.MOD_NAMESPACE, systemName=modConfig.CLIENT_SYSTEM_NAME, eventName=\"PerspChangeClientEventToServer\")\r\n def perspChangeEvent(self, event):\r\n pass\r\n ```\r\n\r\n## @Autowired\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.Autowired` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5230 `__init__` \u65b9\u6cd5\u4e0a\u7684\u88c5\u9970\u5668\uff0c\u8868\u793a\u6b64\u65b9\u6cd5\u9700\u8981\u4f9d\u8d56\u6ce8\u5165\r\n\r\n- \u53c2\u6570\r\n\r\n \u65e0\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from circulateModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n from circulateModScripts.plugins.MODSDKSpring.core.Autowired import Autowired\r\n\r\n @ListenEvent.InitComponentClient\r\n class CClientComponent(object):\r\n\r\n @Autowired\r\n def __init__(self, client, aClientComponent, bClientComponent):\r\n self.client = client\r\n self.aClientComponent = aClientComponent\r\n self.bClientComponent = bClientComponent\r\n ```\r\n\r\n## @Lazy\r\n\r\n\u65b9\u6cd5\u5728 `xxx.plugins.MODSDKSpring.core.Lazy` \u4e2d\uff0c`xxx` \u5e94\u66ff\u6362\u4e3a\u60a8\u7684\u884c\u4e3a\u5305\u4e2d\u7684 Mod \u6587\u4ef6\u5939\u540d\u79f0\uff0c\u5982 `tutorialScripts`\u3002\r\n\r\n- \u63cf\u8ff0\r\n\r\n \u6dfb\u52a0\u5230 @Autowired \u4e0a\u7684\u88c5\u9970\u5668\uff0c\u8868\u793a\u6b64\u65b9\u6cd5\u5728\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165\u65f6\u5148\u7528 None \u8fdb\u884c\u6ce8\u5165\uff0c\u5bf9\u8c61\u521b\u5efa\u4e4b\u540e\u518d\u6ce8\u5165\u771f\u6b63\u9700\u8981\u7684\u4f9d\u8d56\r\n\r\n \u6b64\u88c5\u9970\u5668\u4e00\u822c\u7528\u4e8e\u89e3\u51b3\u5faa\u73af\u4f9d\u8d56\r\n\r\n- \u53c2\u6570\r\n\r\n \u65e0\r\n\r\n- \u793a\u4f8b\r\n\r\n ```python\r\n # -*- coding: utf-8 -*-\r\n from circulateModScripts.plugins.MODSDKSpring.core.ListenEvent import ListenEvent\r\n from circulateModScripts.plugins.MODSDKSpring.core.Autowired import Autowired\r\n from circulateModScripts.plugins.MODSDKSpring.core.Lazy import Lazy\r\n\r\n @ListenEvent.InitComponentClient\r\n class AClientComponent(object):\r\n\r\n @Lazy\r\n @Autowired\r\n def __init__(self, client, bClientComponent, cClientComponent):\r\n self.client = client\r\n self.bClientComponent = bClientComponent\r\n self.cClientComponent = cClientComponent\r\n ```\r\n\r\n\r\n\r\n",
"bugtrack_url": null,
"license": null,
"summary": "\u4e00\u4e2a\u57fa\u4e8e\u7f51\u6613\u6211\u7684\u4e16\u754c MODSDK \u5f00\u53d1\u7684\u6846\u67b6\uff0c\u53ef\u4ee5\u8ba9\u5f00\u53d1\u8005\u66f4\u65b9\u4fbf\u7684\u4f7f\u7528 MODSDK\u3002",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/CreatorMC/MODSDKSping"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6766cf667e8be3616e38f04375639f85551318ab414366786f5b4fcc8fb31241",
"md5": "00fafbd475e9c1b80b6b72003963fc37",
"sha256": "1a214d1f0f0a86e8bf65fdcdbaf399dcd560562e8737e6c55abdf340e6dd29cf"
},
"downloads": -1,
"filename": "mc_creatormc_sdkspring-1.0.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "00fafbd475e9c1b80b6b72003963fc37",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 30929,
"upload_time": "2024-09-07T08:21:41",
"upload_time_iso_8601": "2024-09-07T08:21:41.071201Z",
"url": "https://files.pythonhosted.org/packages/67/66/cf667e8be3616e38f04375639f85551318ab414366786f5b4fcc8fb31241/mc_creatormc_sdkspring-1.0.0-py2-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3a48086b0d00d679b9790b8f22104083a8da970c2bc6ec9398b4f7e19b167f59",
"md5": "eeacc1993052dd059d88a2bfb43d15bc",
"sha256": "1c5812d31bab6520cc00461b6b1debf9f1b56cdfd0276769dfef0fc97021ba7d"
},
"downloads": -1,
"filename": "mc-creatormc-sdkspring-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "eeacc1993052dd059d88a2bfb43d15bc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 52243,
"upload_time": "2024-09-07T08:21:43",
"upload_time_iso_8601": "2024-09-07T08:21:43.276087Z",
"url": "https://files.pythonhosted.org/packages/3a/48/086b0d00d679b9790b8f22104083a8da970c2bc6ec9398b4f7e19b167f59/mc-creatormc-sdkspring-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-07 08:21:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "CreatorMC",
"github_project": "MODSDKSping",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "mc-creatormc-sdkspring"
}