mirror of
https://github.com/project-redbud/FunGame-Server.git
synced 2025-04-20 19:19:39 +08:00
302 lines
11 KiB
C#
302 lines
11 KiB
C#
using System.Collections;
|
||
using Milimoe.FunGame;
|
||
using Milimoe.FunGame.Core.Api.Utility;
|
||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||
using Milimoe.FunGame.Core.Library.Common.Network;
|
||
using Milimoe.FunGame.Core.Library.Constant;
|
||
using Milimoe.FunGame.Server.Model;
|
||
using Milimoe.FunGame.Server.Others;
|
||
using Milimoe.FunGame.Server.Utility;
|
||
|
||
Console.Title = Config.ServerName;
|
||
Console.WriteLine(FunGameInfo.GetInfo(Config.FunGameType));
|
||
|
||
bool Running = true;
|
||
ServerSocket? ListeningSocket = null;
|
||
|
||
StartServer();
|
||
|
||
while (Running)
|
||
{
|
||
string order = Console.ReadLine() ?? "";
|
||
ServerHelper.Type();
|
||
if (order != "" && Running)
|
||
{
|
||
order = order.ToLower();
|
||
switch (order)
|
||
{
|
||
case OrderDictionary.Quit:
|
||
case OrderDictionary.Exit:
|
||
case OrderDictionary.Close:
|
||
Running = false;
|
||
break;
|
||
case OrderDictionary.Restart:
|
||
if (ListeningSocket == null)
|
||
{
|
||
ServerHelper.WriteLine("重启服务器");
|
||
StartServer();
|
||
}
|
||
else ServerHelper.WriteLine("服务器正在运行,拒绝重启!");
|
||
break;
|
||
default:
|
||
ConsoleModel.Order(ListeningSocket, order);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
ServerHelper.WriteLine("服务器已关闭,按任意键退出程序。");
|
||
Console.ReadKey();
|
||
|
||
void StartServer()
|
||
{
|
||
Task t = Task.Factory.StartNew(() =>
|
||
{
|
||
try
|
||
{
|
||
ServerHelper.WriteLine("正在读取配置文件并初始化服务 . . .");
|
||
// 初始化命令菜单
|
||
ServerHelper.InitOrderList();
|
||
|
||
// 读取游戏模组
|
||
if (!GetGameModeList())
|
||
{
|
||
ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。");
|
||
}
|
||
|
||
// 检查是否存在配置文件
|
||
if (!INIHelper.ExistINIFile())
|
||
{
|
||
ServerHelper.WriteLine("未检测到配置文件,将自动创建配置文件 . . .");
|
||
INIHelper.Init(Config.FunGameType);
|
||
ServerHelper.WriteLine("配置文件FunGame.ini创建成功,请修改该配置文件,然后重启服务器。");
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
ServerHelper.GetServerSettings();
|
||
Console.Title = Config.ServerName + " - FunGame Server Port: " + Config.ServerPort;
|
||
}
|
||
ServerHelper.WriteLine("请输入 help 来获取帮助,输入 quit 关闭服务器。");
|
||
|
||
// 创建全局SQLHelper
|
||
Config.InitSQLHelper();
|
||
|
||
// 创建监听
|
||
ListeningSocket = ServerSocket.StartListening();
|
||
|
||
// 开始监听连接
|
||
AddBannedList(ListeningSocket);
|
||
ServerHelper.WriteLine("Listen -> " + Config.ServerPort);
|
||
ServerHelper.WriteLine("服务器启动成功,开始监听 . . .");
|
||
|
||
if (Config.ServerNotice != "")
|
||
ServerHelper.WriteLine("\n\n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n");
|
||
else
|
||
ServerHelper.WriteLine("无法读取服务器公告");
|
||
|
||
while (Running)
|
||
{
|
||
ClientSocket socket;
|
||
string clientip = "";
|
||
try
|
||
{
|
||
Guid token = Guid.NewGuid();
|
||
socket = ListeningSocket.Accept(token);
|
||
clientip = socket.ClientIP;
|
||
Config.ConnectingPlayerCount++;
|
||
// 开始处理客户端连接请求
|
||
bool isDebugMode = false;
|
||
if (Connect(socket, token, clientip, ref isDebugMode))
|
||
{
|
||
ServerModel ClientModel = new(ListeningSocket, socket, Running, isDebugMode);
|
||
Task t = Task.Factory.StartNew(() =>
|
||
{
|
||
ClientModel.Start();
|
||
});
|
||
ClientModel.SetClientName(clientip);
|
||
}
|
||
else
|
||
{
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 连接失败。", InvokeMessageType.Core);
|
||
}
|
||
Config.ConnectingPlayerCount--;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
if (--Config.ConnectingPlayerCount < 0) Config.ConnectingPlayerCount = 0;
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 中断连接!", InvokeMessageType.Core);
|
||
ServerHelper.Error(e);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
if (e.Message.Equals(new ServerErrorException().Message))
|
||
{
|
||
if (ListeningSocket != null)
|
||
{
|
||
ListeningSocket.Close();
|
||
ListeningSocket = null;
|
||
}
|
||
}
|
||
ServerHelper.Error(e);
|
||
}
|
||
finally
|
||
{
|
||
if (ListeningSocket != null)
|
||
{
|
||
ListeningSocket.Close();
|
||
ListeningSocket = null;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
bool GetGameModeList()
|
||
{
|
||
// 同时读取Implement预设的模组和gamemods目录下的模组,最后合成一个总的列表
|
||
List<string> supported = [];
|
||
// 构建AddonController
|
||
Hashtable delegates = [];
|
||
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.GameMode)));
|
||
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
|
||
// 开始读取
|
||
Config.GameModeLoader = GameModeLoader.LoadGameModes(Config.FunGameType, delegates);
|
||
string[] mods = (string[]?)Implement.GetFunGameImplValue(InterfaceType.IServer, InterfaceMethod.GameModeList, false) ?? [];
|
||
if (mods.Length > 0)
|
||
{
|
||
supported.AddRange(mods);
|
||
// 检查已安装的模组中是否在Implement预设的模组中存在
|
||
foreach (string mod in mods)
|
||
{
|
||
if (!Config.GameModeLoader.ServerModes.ContainsKey(mod))
|
||
{
|
||
ServerHelper.WriteLine("[GameMode] Load Failed: " + mod + " 不存在或未正确安装");
|
||
supported.Remove(mod);
|
||
}
|
||
}
|
||
}
|
||
// 检查模组是否有相对应的地图
|
||
foreach (GameModeServer mode in Config.GameModeLoader.ServerModes.Values)
|
||
{
|
||
string modename = mode.Name;
|
||
if (Config.GameModeLoader.Maps.ContainsKey(mode.DefaultMap))
|
||
{
|
||
supported.Add(modename);
|
||
}
|
||
else
|
||
{
|
||
ServerHelper.WriteLine("[GameMode] Load Failed: " + modename + " 没有找到相对应的地图,加载失败");
|
||
Config.GameModeLoader.ServerModes.Remove(modename);
|
||
supported.Remove(modename);
|
||
}
|
||
}
|
||
|
||
// 设置全局
|
||
Config.GameModeSupported = supported.Distinct().ToArray();
|
||
foreach (string modename in Config.GameModeSupported)
|
||
{
|
||
ServerHelper.WriteLine("[GameMode] Loaded: " + modename);
|
||
}
|
||
|
||
return Config.GameModeSupported.Length > 0;
|
||
}
|
||
|
||
bool Connect(ClientSocket socket, Guid token, string clientip, ref bool isDebugMode)
|
||
{
|
||
// 接收客户端消息
|
||
foreach (SocketObject read in socket.ReceiveArray())
|
||
{
|
||
if (read.SocketType == SocketMessageType.Connect)
|
||
{
|
||
if (Config.ConnectingPlayerCount + Config.OnlinePlayerCount > Config.MaxPlayers)
|
||
{
|
||
SendRefuseConnect(socket, "服务器可接受的连接数量已上限!");
|
||
ServerHelper.WriteLine("服务器可接受的连接数量已上限!", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 正在连接服务器 . . .", InvokeMessageType.Core);
|
||
if (IsIPBanned(ListeningSocket, clientip))
|
||
{
|
||
SendRefuseConnect(socket, "服务器已拒绝黑名单用户连接。");
|
||
ServerHelper.WriteLine("检测到 " + ServerHelper.MakeClientName(clientip) + " 为黑名单用户,已禁止其连接!", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
|
||
ServerHelper.WriteLine("[" + SocketSet.GetTypeString(read.SocketType) + "] " + ServerHelper.MakeClientName(socket.ClientIP), InvokeMessageType.Core);
|
||
|
||
// 读取参数
|
||
// 参数1:客户端的游戏模组列表,没有服务器的需要拒绝
|
||
string[] modes = read.GetParam<string[]>(0) ?? [];
|
||
// 参数2:客户端是否开启了开发者模式,开启开发者模式部分功能不可用
|
||
isDebugMode = read.GetParam<bool>(1);
|
||
if (isDebugMode) ServerHelper.WriteLine("客户端已开启开发者模式");
|
||
|
||
string msg = "";
|
||
List<string> ClientDontHave = [];
|
||
string strDontHave = string.Join("\r\n", Config.GameModeSupported.Where(mode => !modes.Contains(mode)));
|
||
if (strDontHave != "")
|
||
{
|
||
strDontHave = "客户端缺少服务器所需的模组:" + strDontHave;
|
||
ServerHelper.WriteLine(strDontHave, InvokeMessageType.Core);
|
||
msg += strDontHave;
|
||
}
|
||
|
||
if (msg == "" && socket.Send(SocketMessageType.Connect, true, msg, token, Config.ServerName, Config.ServerNotice) == SocketResult.Success)
|
||
{
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "已确认连接", InvokeMessageType.Core);
|
||
return true;
|
||
}
|
||
else if (msg != "" && socket.Send(SocketMessageType.Connect, false, msg) == SocketResult.Success)
|
||
{
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "拒绝连接", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
ServerHelper.WriteLine("无法传输数据,与客户端的连接可能丢失。", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
SendRefuseConnect(socket, "服务器已拒绝连接。");
|
||
ServerHelper.WriteLine("客户端发送了不符合FunGame规定的字符,拒绝连接。", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
|
||
bool SendRefuseConnect(ClientSocket socket, string msg)
|
||
{
|
||
// 发送消息给客户端
|
||
msg = "连接被拒绝,如有疑问请联系服务器管理员:" + msg;
|
||
if (socket.Send(SocketMessageType.Connect, false, msg) == SocketResult.Success)
|
||
{
|
||
ServerHelper.WriteLine(ServerHelper.MakeClientName(socket.ClientIP) + " <- " + "已拒绝连接", InvokeMessageType.Core);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
ServerHelper.WriteLine("无法传输数据,与客户端的连接可能丢失。", InvokeMessageType.Core);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
void AddBannedList(ServerSocket server)
|
||
{
|
||
string[] bans = Config.ServerBannedList.Split(',');
|
||
foreach (string banned in bans)
|
||
{
|
||
server.BannedList.Add(banned.Trim());
|
||
}
|
||
}
|
||
|
||
bool IsIPBanned(ServerSocket server, string ip)
|
||
{
|
||
string[] strs = ip.Split(":");
|
||
if (strs.Length == 2 && server.BannedList.Contains(strs[0]))
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
} |