Skip to content
服务器插件与终端接口

事件系统 ​

事件就是"当某事发生时,执行你的代码"。例如玩家进入游戏、破坏方块、移动时,都会触发对应事件,你可以在处理器里插入逻辑。

如何使用事件 ​

  1. 让插件实现对应的事件接口;
  2. 在 Initialize() 中注册事件(XxxEventManager.AddObject(this));
  3. 在事件方法中写你的逻辑。

玩家进入/离开事件 ​

csharp
using Game.Server;
using Game.Server.PlayerEvent;

public class WelcomePlugin : ServerPlugin, IPlayerEnterGameEventHandle
{
    public override string Name => "Welcome";
    public override int Version => 1;
    public byte FirstLevel => 0;

    public override void Initialize()
    {
        PlayerEnterGameEventManager.AddObject(this);
    }

    void IPlayerEnterGameEventHandle.PlayerEnter(PlayerData player)
    {
        Console.WriteLine($"玩家 {player.Name} 进来了");
    }

    void IPlayerEnterGameEventHandle.PlayerLeave(PlayerData player)
    {
        Console.WriteLine($"{player.Name} 离开了");
    }

    public override void Load() { }
    public override void Save() { }
}

方块破坏/放置事件 ​

可以用来做区域保护:

csharp
using Engine;
using Game.Server;
using Game.Server.PlayerEvent;

public class ProtectPlugin : ServerPlugin, IPlayerBreakAndPlaceHandle
{
    public override string Name => "Protect";
    public override int Version => 1;
    public byte FirstLevel => 0;

    public override void Initialize()
    {
        PlayerBreakAndPlaceBlockEventManager.AddObject(this);
    }

    // 玩家破坏方块时调用
    // 返回 true = 允许破坏,false = 阻止破坏
    bool IPlayerBreakAndPlaceHandle.PlayerBreakEvent(
        ComponentPlayer player,
        Point3 point,      // 方块坐标
        int blockValue,    // 方块ID
        int toolLevel)     // 工具等级
    {
        if (IsProtected(point))
        {
            SendMessage(player, "这里是保护区,不能破坏");
            return false;
        }
        return true;
    }

    // 玩家放置方块时调用
    bool IPlayerBreakAndPlaceHandle.PlayerPlaceEvent(
        ComponentPlayer player,
        Point3 point,
        int blockValue)
    {
        if (IsProtected(point))
        {
            SendMessage(player, "这里是保护区,不能放置");
            return false;
        }
        return true;
    }

    bool IsProtected(Point3 pos)
    {
        return Math.Abs(pos.X) < 100 && Math.Abs(pos.Z) < 100;
    }

    void SendMessage(ComponentPlayer player, string msg)
    {
        var pkg = new Game.NetWork.Packages.MessagePackage(null, msg, 0, null);
        pkg.To = player.PlayerData.Client;
        Game.NetWork.CommonLib.Net.QueuePackage(pkg);
    }

    public override void Load() { }
    public override void Save() { }
}

玩家移动事件 ​

csharp
using Engine;
using Game.Server;
using Game.Server.PlayerEvent;

public class MovePlugin : ServerPlugin, IPlayerMoveHandle
{
    public override string Name => "MovePlugin";
    public override int Version => 1;
    public byte FirstLevel => 0;

    public override void Initialize()
    {
        PlayerMoveEventManager.AddObject(this);
    }

    // 返回 true = 允许移动,false = 阻止移动
    bool IPlayerMoveHandle.PlayerMoveEvent(ComponentPlayer player, Vector3 newPos)
    {
        if (newPos.X > 1000)
        {
            SendMessage(player, "前方是禁区");
            return false;
        }
        return true;
    }
}

所有事件接口一览 ​

接口注册管理器说明
IPlayerEnterGameEventHandlePlayerEnterGameEventManager玩家进入/离开
IPlayerBreakAndPlaceHandlePlayerBreakAndPlaceBlockEventManager方块破坏/放置
IPlayerMoveHandlePlayerMoveEventManager玩家移动
IPlayerInteractEventHandlePlayerInteractEventManager玩家交互

更完整的事件清单与签名(含聊天、封禁、生物、地形、终端等)见 接口参考 与 事件与命令路线图。

事件返回值 ​

很多事件方法返回 bool:

  • true = 允许操作继续;
  • false = 取消/阻止操作。
csharp
bool IPlayerBreakAndPlaceHandle.PlayerBreakEvent(...)
{
    if (某种条件)
        return false;  // 阻止破坏

    return true;  // 允许破坏
}

多个插件同时处理时,只要任意处理器返回 false,最终结果通常就是 false。默认允许时显式返回 true;阻止时记录原因、玩家和位置;确认插件卸载后不会留下永久锁定数据。不要用异常代替权限拒绝。

同时监听多个事件 ​

一个插件可以实现多个接口:

csharp
public class MyPlugin : ServerPlugin,
    IPlayerEnterGameEventHandle,
    IPlayerBreakAndPlaceHandle
{
    public override void Initialize()
    {
        PlayerEnterGameEventManager.AddObject(this);
        PlayerBreakAndPlaceBlockEventManager.AddObject(this);
    }

    void IPlayerEnterGameEventHandle.PlayerEnter(PlayerData player) { }
    void IPlayerEnterGameEventHandle.PlayerLeave(PlayerData player) { }

    bool IPlayerBreakAndPlaceHandle.PlayerBreakEvent(...) => true;
    bool IPlayerBreakAndPlaceHandle.PlayerPlaceEvent(...) => true;
}

小贴士 ​

  1. 记得注册:在 Initialize() 中调用 EventManager.AddObject(this)。
  2. 返回值很重要:返回 false 可以阻止操作。
  3. 不要做太重的操作:事件触发很频繁,代码要高效。
  4. 发送消息提醒玩家:阻止操作时告诉玩家原因。
参与共建发现错误或有建议?两种零门槛方式,无需本地环境

玩家共建文档 · 原版、插件版、联机版与插件联机版请注意区分