Files
netease-modsdk-wiki/docs/mcguide/20-玩法开发/14-预设玩法编程/9-第一个预设Mod/6-使用零件编程.md
2025-03-18 14:46:12 +08:00

233 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 使用零件编程
## 内置函数
现在我们已经把零件通过挂接到预设的方式,在场景中实例化了,下面我们可以进行零件的编程了。
当然,你也可以先进行零件的编程,再进行他的挂接和实例化。
我们找到上一步创建的零件的文件夹然后双击打开ChatPart.py这里把他的代码粘贴在下方。
你可以发现在零件的代码中我们已经为你生成了总计6个内置函数这些函数就是零件代码的逻辑入口。
```python
# -*- coding: utf-8 -*-
from Preset.Model.PartBase import PartBase
from Preset.Model.GameObject import registerGenericClass
@registerGenericClass("ChatPart")
class ChatPart(PartBase):
def __init__(self):
super(ChatPart, self).__init__()
self.name = "Chat"
def InitClient(self):
pass
def InitServer(self):
pass
def TickClient(self):
pass
def TickServer(self):
pass
def DestroyClient(self):
pass
def DestroyServer(self):
pass
```
他们分别是这些逻辑的入口:
- \_init\_零件初始化时一般仅在此声明变量
- InitClient零件实例的客户端初始化时
- InitServer零件实例的服务端初始化时
- TickClient零件实例的客户端每帧调用
- TickServer零件实例的服务端每帧调用
- DestroyClient零件实例的客户端销毁时
- DestroyServer零件实例的服务端销毁时
直接在脚本里重写这些函数就可以在这些时机执行对应的逻辑。
## 零件python编程
接下来,我们使用零件来实现一个简单的逻辑,我们在聊天栏输入“摧毁”时,摧毁这个零件的父预设实例。
当一个实例被摧毁时,挂接在他下面的所有实例也会跟着摧毁,所以,在这种情况下展览台预设下的。
代码如下,由于我们只用到服务端的初始化和销毁时,所以我们可以把其他的内置函数删除。
可以看到我们在InitServer里监听了ServerChatEvent事件当系统我的世界里发生玩家的聊天框输入时会调用零件的OnServerChat函数。
然后我们在OnServerChat函数中判断如果玩家输入的是摧毁就摧毁父预设。
```python
def InitServer(self):
import mod.server.extraServerApi as serverApi
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerChatEvent", self, self.OnServerChat)
def DestroyServer(self):
import mod.server.extraServerApi as serverApi
self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerChatEvent", self, self.OnServerChat)
def OnServerChat(self, args):
# 生成掉落物品
# 当我们输入的信息等于摧毁时,摧毁父节点
if args["message"] == "摧毁":
self.GetParent().Destroy()
```
> 当前我们已经支持在文件头 import 大部分库/文件。
>
> 如果产生了报错,可以在使用时 import。
## 使用Mod开发包测试结果
点击编辑器右上角的运行,进行本作品的开发测试。
![instance008](./images/instance008.png)
> 使用0.16.127月15日更新或者更高版本的MC Studio新建的作品只能使用1.23或更高版本的开发包进行开发测试
在运行的开发包中可以看到场景中的2个实例。
![coding007](./images/coding007.png)
按回车调出指令窗,输入:摧毁,此时只有一个展览台实例被摧毁了,但两个展览台是都应该被摧毁的。
MC的事件机制是当一个事件的函数执行完毕时才会发送下一个事件而我们在执行的过程中进行了事件的反监听导致了这一问题。
所以我们修改一下代码,让删除父节点的行为在事件触发的下一帧执行。
在资源管理器里找到Chat零件的文件夹然后右键空白处选择打开当前文件夹我们在Windows的资源管理器内创建一个新的python文件命名为coroutineMgrGas.py然后将如下代码复制进去此部分代码涉及的知识点较深可以先按步骤操作
```python
# -*- coding: utf-8 -*-
import time
# 这个类的作用是延迟执行给定的函数
# 使用参考每个具体使用的地方yield 正数为时间,负数为帧数
class CoroutineMgr(object):
coroutines = {}
globalEnd = []
addCoroutines = {}
@classmethod
def StartCoroutine(cls, iter):
cls.addCoroutines[iter] = 0
return iter
@classmethod
def StopCoroutine(cls, iter):
cls.globalEnd.append(iter)
@classmethod
def Tick(cls):
if cls.addCoroutines:
for c,v in cls.addCoroutines.iteritems():
cls.coroutines[c] = v
cls.addCoroutines = {}
if cls.globalEnd:
for c in cls.globalEnd:
if cls.coroutines.get(c):
del cls.coroutines[c]
cls.globalEnd = []
ended = []
for c, v in cls.coroutines.iteritems():
try:
if v < 0:
v += 1
cls.coroutines[c] = v
if v == 0 or (v > 0 and time.time() >= v):
newv = c.next()
if newv > 0:
newv = newv + time.time()
cls.coroutines[c] = newv
except StopIteration:
ended.append(c)
for c in ended:
del cls.coroutines[c]
```
然后修改ChatPart.py的代码如下
```python
from coroutineMgrGas import CoroutineMgr
def TickServer(self):
CoroutineMgr.Tick()
def OnServerChat(self, args):
# 生成掉落物品
# 当我们输入的信息等于摧毁时,摧毁父节点
if args["message"] == "摧毁":
CoroutineMgr.StartCoroutine(self.DelayDestroy())
def DelayDestroy(self):
yield -1
self.GetParent().Destroy()
```
现在我们再进行开发测试,可以看到现象正常了!
![coding008](./images/coding008.png)
## 使用属性面板修改零件
我们在资源管理器中点击Chat.part可以在他的属性面板中发现它的两个配套文件。除了在ChatPart.py里编程之外我们还可以利用ChatPartMeta.py将ChatPart.py中的变量暴露到编辑器的属性面板中。
点击配套文件右侧的小图标可以直接打开它。
![coding003](./images/coding003.png)
首先我们先改造一下ChatPart.py将“摧毁”作为一个变量使用。
```python
def __init__(self):
super(ChatPart, self).__init__()
self.name = "Chat"
self.message = "摧毁"
def OnServerChat(self, args):
if args["message"] == self.message:
......
```
改造后的零件在使用上与之前没有什么区别接下来我们打开ChatPartMeta.py这里面已经自动帮我们写好了一些必要的代码我们在这个文件中键入1行代码整体效果如下
```python
@sunshine_class_meta
class ChatPartMeta(PartBaseMeta):
CLASS_NAME = "ChatPart"
PROPERTIES = {
"message": PStr(group="默认", text="信息"),
}
```
然后返回编辑器我们可以发现Chat.part的属性面板中增加了我们自己定义的“信息”变量。
![coding004](./images/coding004.png)
接下来我们在舞台上找到Chat零件分别把两个展览台预设的Chat零件的信息更改为“左”和“右”然后保存并重新点击运行进行开发测试。
![image-20210710145051437](./images/coding005.png)
我们打开聊天窗口,输入:右。
这次,只有右边的展览台实例被删除了!
![coding006](./images/coding006.png)