外观
玩家管理
服务端插件最常做的事就是操作玩家:查找、发消息、传送、给物品、踢出等。本节给出常用片段。
关于日志
示例里多处用 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];
}小贴士
- 先检查是否为空:使用
FindPlayer后要检查返回值。 - 游戏是否加载:操作玩家前检查
GameManager.Project != null。 - 异常处理:网络操作可能出错,用 try-catch 包裹。
IyDnjqnlrrbnrqHnkIYKCuacjeWKoeerr+aPkuS7tuacgOW4uOWBmueahOS6i+WwseaYr+aTjeS9nOeOqeWutu+8muafpeaJvuOAgeWPkea2iOaBr+OAgeS8oOmAgeOAgee7meeJqeWTgeOAgei4ouWHuuetieOAguacrOiKgue7meWHuuW4uOeUqOeJh+auteOAggoKOjo6IHRpcCDlhbPkuo7ml6Xlv5cK56S65L6L6YeM5aSa5aSE55SoIGBDb25zb2xlLldyaXRlTGluZWAg6LCD6K+V44CC55yf5a6e5pyN5Yqh56uv6YeM5pu05o6o6I2Q55SoIGBMb2cuSW5mb3JtYXRpb24oLi4uKWAgLyBgTG9nLldhcm5pbmcoLi4uKWDvvIjmnaXoh6rmnI3liqHnq6/ml6Xlv5fmoYbmnrbvvInvvIzkvr/kuo7lnKjmnI3liqHlmajnu4jnq6/nu5/kuIDnrqHnkIbovpPlh7rjgIIKOjo6CgojIyDojrflj5bnjqnlrrYKCiMjIyDmjInlkI3lrZfmn6Xmib7njqnlrrYKCmBgYGNzaGFycAp1c2luZyBTeXN0ZW07CnVzaW5nIEdhbWVFbnRpdHlTeXN0ZW07CgpDb21wb25lbnRQbGF5ZXIgRmluZFBsYXllcihzdHJpbmcgbmFtZSkKewogICAgdmFyIHBsYXllcnMgPSBHYW1lTWFuYWdlci5Qcm9qZWN0LkZpbmRTdWJzeXN0ZW08U3Vic3lzdGVtUGxheWVycz4oKTsKICAgIGZvcmVhY2ggKHZhciBwIGluIHBsYXllcnMuQ29tcG9uZW50UGxheWVycykKICAgIHsKICAgICAgICBpZiAocC5QbGF5ZXJEYXRhLk5hbWUuRXF1YWxzKG5hbWUsIFN0cmluZ0NvbXBhcmlzb24uT3JkaW5hbElnbm9yZUNhc2UpKQogICAgICAgICAgICByZXR1cm4gcDsKICAgIH0KICAgIHJldHVybiBudWxsOwp9CmBgYAoKIyMjIOiOt+WPluaJgOacieWcqOe6v+eOqeWutgoKYGBgY3NoYXJwCnVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOwoKTGlzdDxDb21wb25lbnRQbGF5ZXI+IEdldEFsbFBsYXllcnMoKQp7CiAgICB2YXIgbGlzdCA9IG5ldyBMaXN0PENvbXBvbmVudFBsYXllcj4oKTsKICAgIHZhciBwbGF5ZXJzID0gR2FtZU1hbmFnZXIuUHJvamVjdC5GaW5kU3Vic3lzdGVtPFN1YnN5c3RlbVBsYXllcnM+KCk7CiAgICBmb3JlYWNoICh2YXIgcCBpbiBwbGF5ZXJzLkNvbXBvbmVudFBsYXllcnMpCiAgICB7CiAgICAgICAgbGlzdC5BZGQocCk7CiAgICB9CiAgICByZXR1cm4gbGlzdDsKfQpgYGAKCiMjIFBsYXllckRhdGEg546p5a625pWw5o2uCgpgUGxheWVyRGF0YWAg5YyF5ZCr546p5a6255qE5Z+65pys5L+h5oGv77yaCgpgYGBjc2hhcnAKdm9pZCBPblBsYXllckVudGVyKFBsYXllckRhdGEgcGxheWVyKQp7CiAgICBzdHJpbmcgbmFtZSA9IHBsYXllci5OYW1lOyAgICAgICAgICAgLy8g546p5a625ZCNCiAgICBDbGllbnQgY2xpZW50ID0gcGxheWVyLkNsaWVudDsgICAgICAgLy8g572R57uc6L+e5o6lCiAgICBDb21wb25lbnRQbGF5ZXIgY3AgPSBwbGF5ZXIuQ29tcG9uZW50UGxheWVyOyAgLy8g546p5a6257uE5Lu2Cn0KYGBgCgojIyBDb21wb25lbnRQbGF5ZXIg546p5a6257uE5Lu2Cgrov5nmmK/mk43kvZznjqnlrrbnmoTmoLjlv4Plr7nosaHvvJoKCmBgYGNzaGFycAovLyDku44gUGxheWVyRGF0YSDojrflj5YKQ29tcG9uZW50UGxheWVyIHBsYXllciA9IHBsYXllckRhdGEuQ29tcG9uZW50UGxheWVyOwoKLy8g6I635Y+W5L2N572uClZlY3RvcjMgcG9zID0gcGxheWVyLkNvbXBvbmVudEJvZHkuUG9zaXRpb247CgovLyDojrflj5bnlJ/lkb3lgLznu4Tku7YKQ29tcG9uZW50SGVhbHRoIGhlYWx0aCA9IHBsYXllci5Db21wb25lbnRIZWFsdGg7CgovLyDojrflj5bog4zljIUKQ29tcG9uZW50SW52ZW50b3J5IGludmVudG9yeSA9IHBsYXllci5FbnRpdHkuRmluZENvbXBvbmVudDxDb21wb25lbnRJbnZlbnRvcnk+KCk7CmBgYAoKIyMg5Y+R6YCB5raI5oGvCgpgYGBjc2hhcnAKdXNpbmcgR2FtZS5OZXRXb3JrOwp1c2luZyBHYW1lLk5ldFdvcmsuUGFja2FnZXM7Cgp2b2lkIFNlbmRNZXNzYWdlKFBsYXllckRhdGEgcGxheWVyLCBzdHJpbmcgbWVzc2FnZSkKewogICAgdmFyIHBrZyA9IG5ldyBNZXNzYWdlUGFja2FnZShudWxsLCBtZXNzYWdlLCAwLCBudWxsKTsKICAgIHBrZy5UbyA9IHBsYXllci5DbGllbnQ7CiAgICBDb21tb25MaWIuTmV0LlF1ZXVlUGFja2FnZShwa2cpOwp9CgovLyDkvb/nlKjnpLrkvosKU2VuZE1lc3NhZ2UocGxheWVyLCAi5qyi6L+O5p2l5Yiw5pyN5Yqh5Zmo77yBIik7CmBgYAoKPiDlkb3ku6Tnsbvph4zlj6/nm7TmjqXnlKggYFNlbmRNZXNzYWdlKCLns7vnu58iLCAi5raI5oGvIilgIOi/meS4quS+v+aNt+mHjei9ve+8iOadpeiHqiBgQWJzdHJhY3RQcm9jZXNzQ21kYO+8ie+8jOaXoOmcgOiHquW3seaLvCBgTWVzc2FnZVBhY2thZ2Vg44CCCgojIyDkvKDpgIHnjqnlrrYKCmBgYGNzaGFycAp1c2luZyBFbmdpbmU7CnVzaW5nIEdhbWUuTmV0V29yazsKdXNpbmcgR2FtZS5OZXRXb3JrLlBhY2thZ2VzOwoKdm9pZCBUZWxlcG9ydChDb21wb25lbnRQbGF5ZXIgcGxheWVyLCBmbG9hdCB4LCBmbG9hdCB5LCBmbG9hdCB6KQp7CiAgICAvLyDorr7nva7kvY3nva4KICAgIHBsYXllci5Db21wb25lbnRCb2R5LlBvc2l0aW9uID0gbmV3IFZlY3RvcjMoeCwgeSwgeik7CgogICAgLy8g6YCa55+l5a6i5oi356uv77yIUGxheWVyQWN0aW9uLjEyID0g5Lyg6YCB77yJCiAgICBDb21tb25MaWIuTmV0LlF1ZXVlUGFja2FnZShuZXcgQ29tcG9uZW50UGxheWVyUGFja2FnZShwbGF5ZXIsIChQbGF5ZXJBY3Rpb24pMTIpKTsKfQoKLy8g5Lyg6YCB5Yiw5Y+m5LiA5Liq546p5a62CnZvaWQgVGVsZXBvcnRUb1BsYXllcihDb21wb25lbnRQbGF5ZXIgc291cmNlLCBDb21wb25lbnRQbGF5ZXIgdGFyZ2V0KQp7CiAgICB2YXIgdGFyZ2V0UG9zID0gdGFyZ2V0LkNvbXBvbmVudEJvZHkuUG9zaXRpb247CiAgICBUZWxlcG9ydChzb3VyY2UsIHRhcmdldFBvcy5YLCB0YXJnZXRQb3MuWSwgdGFyZ2V0UG9zLlopOwp9CmBgYAoKIyMg57uZ5LqI54mp5ZOBCgpgYGBjc2hhcnAKYm9vbCBHaXZlSXRlbShDb21wb25lbnRQbGF5ZXIgcGxheWVyLCBpbnQgaXRlbUlkLCBpbnQgY291bnQpCnsKICAgIHZhciBpbnZlbnRvcnkgPSAoKENvbXBvbmVudClwbGF5ZXIpLkVudGl0eS5GaW5kQ29tcG9uZW50PENvbXBvbmVudEludmVudG9yeT4oKTsKCiAgICAvLyDmib7nqbrmoLzlrZAKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgaW52ZW50b3J5LlNsb3RzQ291bnQ7IGkrKykKICAgIHsKICAgICAgICBpbnQgc2xvdFZhbHVlID0gaW52ZW50b3J5LkdldFNsb3RWYWx1ZShpKTsKICAgICAgICBpbnQgc2xvdENvdW50ID0gaW52ZW50b3J5LkdldFNsb3RDb3VudChpKTsKCiAgICAgICAgLy8g56m65qC85a2Q5oiW55u45ZCM54mp5ZOBCiAgICAgICAgaWYgKHNsb3RDb3VudCA9PSAwIHx8IHNsb3RWYWx1ZSA9PSBpdGVtSWQpCiAgICAgICAgewogICAgICAgICAgICBpbnZlbnRvcnkuQWRkU2xvdEl0ZW1zKGksIGl0ZW1JZCwgY291bnQpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7ICAvLyDog4zljIXmu6HkuoYKfQpgYGAKCiMjIOi4ouWHuueOqeWutgoKYGBgY3NoYXJwCnVzaW5nIEdhbWUuTmV0V29yazsKCnZvaWQgS2lja1BsYXllcihQbGF5ZXJEYXRhIHBsYXllciwgc3RyaW5nIHJlYXNvbikKewogICAgQ29tbW9uTGliLk5ldC5SZW1vdmVDbGllbnQocGxheWVyLkNsaWVudCwgcmVhc29uKTsKfQoKLy8g5L2/55So56S65L6LCktpY2tQbGF5ZXIocGxheWVyLCAi6KGM5Li65LiN5b2TIik7CmBgYAoKIyMg6I635Y+W546p5a625L2N572uCgpgYGBjc2hhcnAKdXNpbmcgRW5naW5lOwoKVmVjdG9yMyBHZXRQb3NpdGlvbihDb21wb25lbnRQbGF5ZXIgcGxheWVyKQp7CiAgICByZXR1cm4gcGxheWVyLkNvbXBvbmVudEJvZHkuUG9zaXRpb247Cn0KCi8vIOiOt+WPluWdkOaghwpWZWN0b3IzIHBvcyA9IEdldFBvc2l0aW9uKHBsYXllcik7CmZsb2F0IHggPSBwb3MuWDsKZmxvYXQgeSA9IHBvcy5ZOwpmbG9hdCB6ID0gcG9zLlo7CmBgYAoKIyMg6K6+572u5peg5pWMCgpgYGBjc2hhcnAKdm9pZCBTZXRJbnZ1bG5lcmFibGUoQ29tcG9uZW50UGxheWVyIHBsYXllciwgYm9vbCBpbnZ1bG5lcmFibGUpCnsKICAgIHBsYXllci5Db21wb25lbnRIZWFsdGguSXNJbnZ1bG5lcmFibGUgPSBpbnZ1bG5lcmFibGU7Cn0KYGBgCgojIyDluLjnlKjku6PnoIHniYfmrrUKCiMjIyDlub/mkq3mtojmga/nu5nmiYDmnInnjqnlrrYKCmBgYGNzaGFycAp2b2lkIEJyb2FkY2FzdChzdHJpbmcgbWVzc2FnZSkKewogICAgdmFyIHBsYXllcnMgPSBHYW1lTWFuYWdlci5Qcm9qZWN0LkZpbmRTdWJzeXN0ZW08U3Vic3lzdGVtUGxheWVycz4oKTsKICAgIGZvcmVhY2ggKHZhciBwIGluIHBsYXllcnMuQ29tcG9uZW50UGxheWVycykKICAgIHsKICAgICAgICB2YXIgcGtnID0gbmV3IE1lc3NhZ2VQYWNrYWdlKG51bGwsIG1lc3NhZ2UsIDAsIG51bGwpOwogICAgICAgIHBrZy5UbyA9IHAuUGxheWVyRGF0YS5DbGllbnQ7CiAgICAgICAgQ29tbW9uTGliLk5ldC5RdWV1ZVBhY2thZ2UocGtnKTsKICAgIH0KfQpgYGAKCiMjIyDmo4Dmn6XnjqnlrrbmmK/lkKblnKjnur8KCmBgYGNzaGFycApib29sIElzT25saW5lKHN0cmluZyBuYW1lKQp7CiAgICByZXR1cm4gRmluZFBsYXllcihuYW1lKSAhPSBudWxsOwp9CmBgYAoKIyMjIOiOt+WPlueOqeWutiBJUAoKYGBgY3NoYXJwCnN0cmluZyBHZXRJUChQbGF5ZXJEYXRhIHBsYXllcikKewogICAgc3RyaW5nIGVuZFBvaW50ID0gcGxheWVyLkNsaWVudC5QZWVyLkVuZFBvaW50LlRvU3RyaW5nKCk7CiAgICAvLyDmoLzlvI/pgJrluLjmmK8gIklQOuerr+WPoyIKICAgIHJldHVybiBlbmRQb2ludC5TcGxpdCgnOicpWzBdOwp9CmBgYAoKIyMg5bCP6LS05aOrCgoxLiAqKuWFiOajgOafpeaYr+WQpuS4uuepuioq77ya5L2/55SoIGBGaW5kUGxheWVyYCDlkI7opoHmo4Dmn6Xov5Tlm57lgLzjgIIKMi4gKirmuLjmiI/mmK/lkKbliqDovb0qKu+8muaTjeS9nOeOqeWutuWJjeajgOafpSBgR2FtZU1hbmFnZXIuUHJvamVjdCAhPSBudWxsYOOAggozLiAqKuW8guW4uOWkhOeQhioq77ya572R57uc5pON5L2c5Y+v6IO95Ye66ZSZ77yM55SoIHRyeS1jYXRjaCDljIXoo7njgIIK
