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

玩家管理 ​

服务端插件最常做的事就是操作玩家:查找、发消息、传送、给物品、踢出等。本节给出常用片段。

关于日志

示例里多处用 Console.WriteLine 调试。真实服务端里更推荐用 Log.Information(...) / Log.Warning(...)(来自服务端日志框架),便于在服务器终端统一管理输出。

获取玩家 ​

按名字查找玩家 ​

csharp
using System;
using GameEntitySystem;

ComponentPlayer FindPlayer(string name)
{
    var players = GameManager.Project.FindSubsystem<SubsystemPlayers>();
    foreach (var p in players.ComponentPlayers)
    {
        if (p.PlayerData.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
            return p;
    }
    return null;
}

获取所有在线玩家 ​

csharp
using System.Collections.Generic;

List<ComponentPlayer> GetAllPlayers()
{
    var list = new List<ComponentPlayer>();
    var players = GameManager.Project.FindSubsystem<SubsystemPlayers>();
    foreach (var p in players.ComponentPlayers)
    {
        list.Add(p);
    }
    return list;
}

PlayerData 玩家数据 ​

PlayerData 包含玩家的基本信息:

csharp
void OnPlayerEnter(PlayerData player)
{
    string name = player.Name;           // 玩家名
    Client client = player.Client;       // 网络连接
    ComponentPlayer cp = player.ComponentPlayer;  // 玩家组件
}

ComponentPlayer 玩家组件 ​

这是操作玩家的核心对象:

csharp
// 从 PlayerData 获取
ComponentPlayer player = playerData.ComponentPlayer;

// 获取位置
Vector3 pos = player.ComponentBody.Position;

// 获取生命值组件
ComponentHealth health = player.ComponentHealth;

// 获取背包
ComponentInventory inventory = player.Entity.FindComponent<ComponentInventory>();

发送消息 ​

csharp
using Game.NetWork;
using Game.NetWork.Packages;

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

// 使用示例
SendMessage(player, "欢迎来到服务器!");

命令类里可直接用 SendMessage("系统", "消息") 这个便捷重载(来自 AbstractProcessCmd),无需自己拼 MessagePackage。

传送玩家 ​

csharp
using Engine;
using Game.NetWork;
using Game.NetWork.Packages;

void Teleport(ComponentPlayer player, float x, float y, float z)
{
    // 设置位置
    player.ComponentBody.Position = new Vector3(x, y, z);

    // 通知客户端(PlayerAction.12 = 传送)
    CommonLib.Net.QueuePackage(new ComponentPlayerPackage(player, (PlayerAction)12));
}

// 传送到另一个玩家
void TeleportToPlayer(ComponentPlayer source, ComponentPlayer target)
{
    var targetPos = target.ComponentBody.Position;
    Teleport(source, targetPos.X, targetPos.Y, targetPos.Z);
}

给予物品 ​

csharp
bool GiveItem(ComponentPlayer player, int itemId, int count)
{
    var inventory = ((Component)player).Entity.FindComponent<ComponentInventory>();

    // 找空格子
    for (int i = 0; i < inventory.SlotsCount; i++)
    {
        int slotValue = inventory.GetSlotValue(i);
        int slotCount = inventory.GetSlotCount(i);

        // 空格子或相同物品
        if (slotCount == 0 || slotValue == itemId)
        {
            inventory.AddSlotItems(i, itemId, count);
            return true;
        }
    }
    return false;  // 背包满了
}

踢出玩家 ​

csharp
using Game.NetWork;

void KickPlayer(PlayerData player, string reason)
{
    CommonLib.Net.RemoveClient(player.Client, reason);
}

// 使用示例
KickPlayer(player, "行为不当");

获取玩家位置 ​

csharp
using Engine;

Vector3 GetPosition(ComponentPlayer player)
{
    return player.ComponentBody.Position;
}

// 获取坐标
Vector3 pos = GetPosition(player);
float x = pos.X;
float y = pos.Y;
float z = pos.Z;

设置无敌 ​

csharp
void SetInvulnerable(ComponentPlayer player, bool invulnerable)
{
    player.ComponentHealth.IsInvulnerable = invulnerable;
}

常用代码片段 ​

广播消息给所有玩家 ​

csharp
void Broadcast(string message)
{
    var players = GameManager.Project.FindSubsystem<SubsystemPlayers>();
    foreach (var p in players.ComponentPlayers)
    {
        var pkg = new MessagePackage(null, message, 0, null);
        pkg.To = p.PlayerData.Client;
        CommonLib.Net.QueuePackage(pkg);
    }
}

检查玩家是否在线 ​

csharp
bool IsOnline(string name)
{
    return FindPlayer(name) != null;
}

获取玩家 IP ​

csharp
string GetIP(PlayerData player)
{
    string endPoint = player.Client.Peer.EndPoint.ToString();
    // 格式通常是 "IP:端口"
    return endPoint.Split(':')[0];
}

小贴士 ​

  1. 先检查是否为空:使用 FindPlayer 后要检查返回值。
  2. 游戏是否加载:操作玩家前检查 GameManager.Project != null。
  3. 异常处理:网络操作可能出错,用 try-catch 包裹。
参与共建发现错误或有建议?两种零门槛方式,无需本地环境

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