--- front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg hard: 进阶 time: 20分钟 --- # 监听事件并创建组件逻辑 现在我们已经创建好了一个服务端系统,我们来尝试向这个系统中添加逻辑。 在添加逻辑之前,我们需要手动将系统在主模组文件中注册。我们仿照之前看到的示例,将额外API的`RegisterSystem`函数写在`@Mod.InitServer()`装饰器下的方法中。 ```python @Mod.InitServer() def DemoTutorialModServerInit(self): serverApi.RegisterSystem("DemoTutorialMod", "Server", "Script_DemoTutorialMod.DemoTutorialServerSystem.DemoTutorialServerSystem") ``` ## 监听实体受伤事件 我们回到服务端系统文件`DemoTutorialServerSystem.py`中。我们一起尝试做一个简单的事件监听,比如,监听实体(活动对象)收到伤害的事件。 通过查阅API文档,我们得到了控制实体受到伤害的事件`ActorHurtServerEvent`,其字面意思为“活动对象受伤服务端事件”。我们通过该系统本身的`ListenForEvent`方法来注册这个事件监听。我们在`__init__`方法的末尾加入我们的监听注册函数,同时在该类中定义一个新的方法,比如名为`OnActorHurtServer`,将该方法作为回调函数绑定到事件上。 ```python def __init__(self, namespace, systemName): ServerSystem.__init__(self, namespace, systemName) self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ActorHurtServerEvent", self, self.OnActorHurtServer) ``` 这样,我们便完成了实体受伤的监听。当实体受到伤害时,`DemoTutorialServerSystem`实例的`OnActorHurtServer`方法将会运行。 ## 在事件内触发击退逻辑 我们希望不仅仅是监听该事件,更要在事件发生时执行一些逻辑,比如更改受击实体的击退属性。 我们通过查阅API文档得知,`action`组件(`mod.server.component.actionCompServer`)具备更改击退逻辑的方法`SetMobKnockback`。所以我们使用引擎组件工厂创建一个`action`引擎组件,然后调用它的设置击退的方法做到一些逻辑,比如我们想增加击退的威力。我们在`OnActorHurtServer`中写入如下内容。 ```python def OnActorHurtServer(self, args): comp = serverApi.GetEngineCompFactory().CreateAction(args["entityId"]) comp.SetMobKnockback(0.1, 0.1, 10.0, 1.0, 1.0) ``` ![](./images/11.4_set_knockback.png) 这样,我们便成功更改了击退的威力。我们将完整的修改过的代码展示在此处。首先是`modMain.py`: ```python # -*- coding: utf-8 -*- from mod.common.mod import Mod import mod.server.extraServerApi as serverApi import mod.client.extraClientApi as clientApi @Mod.Binding(name="DemoTutorialMod", version="0.0.1") class DemoTutorialMod(object): def __init__(self): @Mod.InitServer() def DemoTutorialModServerInit(self): serverApi.RegisterSystem("DemoTutorialMod", "Server", "Script_DemoTutorialMod.DemoTutorialServerSystem.DemoTutorialServerSystem") @Mod.DestroyServer() def DemoTutorialModServerDestroy(self): pass @Mod.InitClient() def DemoTutorialModClientInit(self): pass @Mod.DestroyClient() def DemoTutorialModClientDestroy(self): pass ``` 然后是`DemoTutorialServerSystem.py`: ```python # -*- coding: utf-8 -*- import mod.server.extraServerApi as serverApi ServerSystem = serverApi.GetServerSystemCls() class DemoTutorialServerSystem(ServerSystem): def __init__(self, namespace, systemName): ServerSystem.__init__(self, namespace, systemName) self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ActorHurtServerEvent", self, self.OnActorHurtServer) def OnActorHurtServer(self, args): comp = serverApi.GetEngineCompFactory().CreateAction(args["entityId"]) comp.SetMobKnockback(0.1, 0.1, 10.0, 1.0, 1.0) # ScriptTickServerEvent的回调函数,会在引擎tick的时候调用,1秒30帧(被调用30次) def OnTickServer(self): """ Driven by event, One tick way """ pass # 这个Update函数是基类的方法,同样会在引擎tick的时候被调用,1秒30帧(被调用30次) def Update(self): """ Driven by system manager, Two tick way """ pass def Destroy(self): self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ActorHurtServerEvent", self, self.OnActorHurtServer) ``` ![](./images/11.4_in-game.gif) 进入游戏测试,便可以发现`SetMobKnockback`更改击退属性“诚不我欺”。