取消将 SQLHelper 和 MailSender 添加在 Singleton 中;添加了艺术字标题的输出;MySQLHelper 代码重构

This commit is contained in:
milimoe 2024-11-11 22:36:00 +08:00
parent c060c06d1c
commit d19d8f5e95
Signed by: milimoe
GPG Key ID: 05D280912DA6C69E
10 changed files with 497 additions and 617 deletions

View File

@ -66,19 +66,19 @@ void StartServer()
ServerHelper.InitOrderList(); ServerHelper.InitOrderList();
// 创建全局SQLHelper // 创建全局SQLHelper
Config.InitSQLHelper(); FunGameSystem.InitSQLHelper();
// 创建全局MailSender // 创建全局MailSender
Config.InitMailSender(); FunGameSystem.InitMailSender();
// 读取游戏模组 // 读取游戏模组
if (!Config.GetGameModuleList()) if (!FunGameSystem.GetGameModuleList())
{ {
ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。"); ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。");
} }
// 读取Server插件 // 读取Server插件
Config.GetServerPlugins(); FunGameSystem.GetServerPlugins();
// 检查是否存在配置文件 // 检查是否存在配置文件
if (!INIHelper.ExistINIFile()) if (!INIHelper.ExistINIFile())
@ -95,6 +95,8 @@ void StartServer()
} }
ServerHelper.WriteLine("请输入 help 来获取帮助,输入 quit 关闭服务器。"); ServerHelper.WriteLine("请输入 help 来获取帮助,输入 quit 关闭服务器。");
ServerHelper.PrintFunGameTitle();
// 使用Socket还是WebSocket // 使用Socket还是WebSocket
bool useWebSocket = Config.UseWebSocket; bool useWebSocket = Config.UseWebSocket;

View File

@ -6,6 +6,7 @@ using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Common.Network; using Milimoe.FunGame.Core.Library.Common.Network;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Common;
using Milimoe.FunGame.Core.Library.SQLScript.Entity; using Milimoe.FunGame.Core.Library.SQLScript.Entity;
using Milimoe.FunGame.Server.Controller; using Milimoe.FunGame.Server.Controller;
using Milimoe.FunGame.Server.Others; using Milimoe.FunGame.Server.Others;
@ -49,11 +50,8 @@ namespace Milimoe.FunGame.Server.Model
Socket = socket; Socket = socket;
DataRequestController = new(this); DataRequestController = new(this);
IsDebugMode = isDebugMode; IsDebugMode = isDebugMode;
if (Config.SQLMode != SQLMode.None) _sqlHelper = Factory.OpenFactory.GetSQLHelper();
{ _mailer = SmtpHelper.GetMailSender();
_sqlHelper = Config.SQLHelper;
}
_mailer = Config.MailSender;
} }
public virtual async Task<bool> SocketMessageHandler(ISocketMessageProcessor socket, SocketObject obj) public virtual async Task<bool> SocketMessageHandler(ISocketMessageProcessor socket, SocketObject obj)
@ -465,6 +463,33 @@ namespace Milimoe.FunGame.Server.Model
protected async Task CreateStreamReader() protected async Task CreateStreamReader()
{ {
CancellationTokenSource cts = new();
Task sqlPolling = Task.Run(async () =>
{
await Task.Delay(30);
ServerHelper.WriteLine("Creating: SQLPolling -> " + GetClientName() + " ...OK");
while (Running)
{
if (cts.Token.IsCancellationRequested)
{
break;
}
// 每两小时触发一次SQL服务器的心跳查询防止SQL服务器掉线
try
{
await Task.Delay(2 * 1000 * 3600);
SQLHelper?.ExecuteDataSet(ServerLoginLogs.Select_GetLastLoginTime());
}
catch (OperationCanceledException)
{
break;
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
}, cts.Token);
await Task.Delay(20); await Task.Delay(20);
ServerHelper.WriteLine("Creating: StreamReader -> " + GetClientName() + " ...OK"); ServerHelper.WriteLine("Creating: StreamReader -> " + GetClientName() + " ...OK");
while (Running) while (Running)
@ -494,6 +519,9 @@ namespace Milimoe.FunGame.Server.Model
break; break;
} }
} }
cts.Cancel();
await sqlPolling;
cts.Dispose();
} }
protected async Task Close() protected async Task Close()

View File

@ -1,14 +1,8 @@
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Common;
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
using Milimoe.FunGame.Core.Model; using Milimoe.FunGame.Core.Model;
using Milimoe.FunGame.Server.Utility;
using Milimoe.FunGame.Server.Utility.DataUtility;
namespace Milimoe.FunGame.Server.Others namespace Milimoe.FunGame.Server.Others
{ {
@ -143,213 +137,6 @@ namespace Milimoe.FunGame.Server.Others
/// 未Loadmodules时此属性表示至少需要安装的模组 /// 未Loadmodules时此属性表示至少需要安装的模组
/// </summary> /// </summary>
public static string[] GameModuleSupported { get; set; } = []; public static string[] GameModuleSupported { get; set; } = [];
/// <summary>
/// 全局数据库连接器
/// </summary>
public static SQLHelper SQLHelper
{
get
{
if (_SQLHelper is null) throw new SQLServiceException();
return _SQLHelper;
}
}
/// <summary>
/// 全局邮件发送器
/// </summary>
public static MailSender? MailSender => _MailSender;
private static SQLHelper? _SQLHelper;
private static MailSender? _MailSender;
/// <summary>
/// 初始化数据库连接器
/// </summary>
public static void InitSQLHelper()
{
try
{
if (INIHelper.ExistINIFile())
{
if (INIHelper.ReadINI("MySQL", "UseMySQL").Trim() == "true")
{
_SQLHelper = new MySQLHelper("", false);
if (((MySQLHelper)_SQLHelper).Connection != null)
{
AfterCreateSQLService(_SQLHelper);
}
}
else if (INIHelper.ReadINI("SQLite", "UseSQLite").Trim() == "true")
{
_SQLHelper = new SQLiteHelper();
AfterCreateSQLService(_SQLHelper);
}
else
{
SQLMode = SQLMode.None;
ServerHelper.WriteLine("未开启 SQL 服务,某些请求将无法处理。", InvokeMessageType.Warning);
}
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
/// <summary>
/// 初始化邮件发送器
/// </summary>
public static void InitMailSender()
{
try
{
_MailSender = SmtpHelper.GetMailSender();
}
catch (Exception e)
{
ServerHelper.Error(e);
}
if (_MailSender != null)
{
Singleton.AddOrUpdate(_MailSender);
}
}
public static bool GetGameModuleList()
{
List<string> supported = [];
// 构建AddonController
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.GameModule)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
// 读取modules目录下的模组
try
{
GameModuleLoader = GameModuleLoader.LoadGameModules(FunGameType, delegates);
foreach (GameModuleServer module in GameModuleLoader.ModuleServers.Values)
{
try
{
bool check = true;
// 检查模组是否有相对应的地图
if (!GameModuleLoader.Maps.ContainsKey(module.DefaultMap))
{
ServerHelper.WriteLine("GameModule Load Failed: " + module + " 没有找到相对应的地图,加载失败", InvokeMessageType.Error);
check = false;
}
if (check)
{
supported.Add(module.Name);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
}
catch (Exception e2)
{
ServerHelper.Error(e2);
}
// 设置全局
GameModuleSupported = supported.Distinct().ToArray();
foreach (string modename in GameModuleSupported)
{
ServerHelper.WriteLine("Loaded: " + modename, InvokeMessageType.GameModule);
}
return GameModuleSupported.Length > 0;
}
public static void GetServerPlugins()
{
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.Plugin)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
try
{
// 读取plugins目录下的插件
ServerPluginLoader = ServerPluginLoader.LoadPlugins(delegates);
foreach (ServerPlugin plugin in ServerPluginLoader.Plugins.Values)
{
ServerHelper.WriteLine("Loaded: " + plugin.Name, InvokeMessageType.Plugin);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
public static void GetWebAPIPlugins()
{
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.Plugin)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
try
{
// 读取plugins目录下的插件
WebAPIPluginLoader = WebAPIPluginLoader.LoadPlugins(delegates);
foreach (WebAPIPlugin plugin in WebAPIPluginLoader.Plugins.Values)
{
ServerHelper.WriteLine("Loaded: " + plugin.Name, InvokeMessageType.Plugin);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
/// <summary>
/// 服务器启动登记
/// </summary>
public static void ServerLogin()
{
if (SQLMode != SQLMode.None)
{
SQLHelper.Execute(ServerLoginLogs.Insert_ServerLoginLogs(ServerName, ServerKey));
}
}
/// <summary>
/// 重启服务器后,所有房间都会被删除
/// </summary>
public static void ClearRoomList()
{
if (SQLMode != SQLMode.None)
{
SQLHelper.Execute(RoomQuery.Delete_Rooms());
}
}
public static void AfterCreateSQLService(SQLHelper sqlHelper)
{
SQLMode = sqlHelper.Mode;
Singleton.AddOrUpdate(sqlHelper, true);
ServerLogin();
ClearRoomList();
Task t = Task.Run(async () =>
{
while (true)
{
// 每两小时触发一次SQL服务器的心跳查询防止SQL服务器掉线
try
{
await Task.Delay(2 * 1000 * 3600);
SQLHelper?.ExecuteDataSet(ServerLoginLogs.Select_GetLastLoginTime());
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
});
}
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,198 @@
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Common;
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
using Milimoe.FunGame.Server.Utility;
using Milimoe.FunGame.Server.Utility.DataUtility;
namespace Milimoe.FunGame.Server.Others
{
public class FunGameSystem
{
/// <summary>
/// 初始化数据库连接器
/// </summary>
public static void InitSQLHelper()
{
try
{
Factory.OpenFactory.RegisterFactory(() => Config.SQLMode switch
{
SQLMode.MySQL => new MySQLHelper(),
SQLMode.SQLite => new SQLiteHelper(),
_ => null,
});
if (INIHelper.ExistINIFile())
{
string useMySQL = INIHelper.ReadINI("MySQL", "UseMySQL").Trim();
string useSQLite = INIHelper.ReadINI("SQLite", "UseSQLite").Trim();
// 根据配置文件选择适当的 SQLHelper 实例
SQLHelper? sqlHelper = useMySQL == "true" ? new MySQLHelper() : (useSQLite == "true" ? new SQLiteHelper() : null);
if (sqlHelper != null)
{
Config.SQLMode = sqlHelper.Mode;
switch (Config.SQLMode)
{
case SQLMode.MySQL:
ServerHelper.WriteLine("Connect -> MySQL://" + sqlHelper.ServerInfo.SQLServerIP + ":" + sqlHelper.ServerInfo.SQLServerPort);
break;
case SQLMode.SQLite:
ServerHelper.WriteLine("Connect -> SQLite://" + sqlHelper.ServerInfo.SQLServerDataBase);
break;
}
AfterCreateSQLService(sqlHelper);
}
else
{
Config.SQLMode = SQLMode.None;
ServerHelper.WriteLine("未开启 SQL 服务,某些请求将无法处理。", InvokeMessageType.Warning);
}
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
/// <summary>
/// 初始化邮件发送器
/// </summary>
public static void InitMailSender()
{
MailSender? sender = null;
try
{
sender = SmtpHelper.GetMailSender();
if (sender != null)
{
ServerHelper.WriteLine("SMTP 服务已启动!");
sender.Dispose();
}
else
{
ServerHelper.WriteLine("SMTP 服务处于关闭状态", InvokeMessageType.Warning);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
public static bool GetGameModuleList()
{
List<string> supported = [];
// 构建AddonController
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.GameModule)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
// 读取modules目录下的模组
try
{
Config.GameModuleLoader = GameModuleLoader.LoadGameModules(Config.FunGameType, delegates);
foreach (GameModuleServer module in Config.GameModuleLoader.ModuleServers.Values)
{
try
{
bool check = true;
// 检查模组是否有相对应的地图
if (!Config.GameModuleLoader.Maps.ContainsKey(module.DefaultMap))
{
ServerHelper.WriteLine("GameModule Load Failed: " + module + " 没有找到相对应的地图,加载失败", InvokeMessageType.Error);
check = false;
}
if (check)
{
supported.Add(module.Name);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
}
catch (Exception e2)
{
ServerHelper.Error(e2);
}
// 设置全局
Config.GameModuleSupported = supported.Distinct().ToArray();
foreach (string modename in Config.GameModuleSupported)
{
ServerHelper.WriteLine("Loaded: " + modename, InvokeMessageType.GameModule);
}
return Config.GameModuleSupported.Length > 0;
}
public static void GetServerPlugins()
{
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.Plugin)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
try
{
// 读取plugins目录下的插件
Config.ServerPluginLoader = ServerPluginLoader.LoadPlugins(delegates);
foreach (ServerPlugin plugin in Config.ServerPluginLoader.Plugins.Values)
{
ServerHelper.WriteLine("Loaded: " + plugin.Name, InvokeMessageType.Plugin);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
public static void GetWebAPIPlugins()
{
Dictionary<string, object> delegates = [];
delegates.Add("WriteLine", new Action<string>(msg => ServerHelper.WriteLine(msg, InvokeMessageType.Plugin)));
delegates.Add("Error", new Action<Exception>(ServerHelper.Error));
try
{
// 读取plugins目录下的插件
Config.WebAPIPluginLoader = WebAPIPluginLoader.LoadPlugins(delegates);
foreach (WebAPIPlugin plugin in Config.WebAPIPluginLoader.Plugins.Values)
{
ServerHelper.WriteLine("Loaded: " + plugin.Name, InvokeMessageType.Plugin);
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
}
/// <summary>
/// 服务器启动登记
/// </summary>
public static void ServerLogin(SQLHelper sqlHelper)
{
sqlHelper.Execute(ServerLoginLogs.Insert_ServerLoginLogs(Config.ServerName, Config.ServerKey));
}
/// <summary>
/// 重启服务器后,所有房间都会被删除
/// </summary>
public static void ClearRoomList(SQLHelper sqlHelper)
{
sqlHelper.Execute(RoomQuery.Delete_Rooms());
}
public static void AfterCreateSQLService(SQLHelper sqlHelper)
{
Config.SQLMode = sqlHelper.Mode;
ServerLogin(sqlHelper);
ClearRoomList(sqlHelper);
sqlHelper.Dispose();
}
}
}

View File

@ -9,6 +9,14 @@ namespace Milimoe.FunGame.Server.Utility
{ {
public class ServerHelper public class ServerHelper
{ {
public static void PrintFunGameTitle()
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\r ");
Console.WriteLine(FunGameInfo.FunGameServerTitle);
Console.ResetColor();
}
public static string GetPrefix(InvokeMessageType type) public static string GetPrefix(InvokeMessageType type)
{ {
string prefix; string prefix;
@ -191,7 +199,7 @@ namespace Milimoe.FunGame.Server.Utility
public static string SenderPassword { get; set; } = ""; public static string SenderPassword { get; set; } = "";
public static string SmtpHost { get; set; } = ""; public static string SmtpHost { get; set; } = "";
public static int SmtpPort { get; set; } = 587; public static int SmtpPort { get; set; } = 587;
public static bool OpenSSL { get; set; } = true; public static bool SSL { get; set; } = true;
public static MailSender? GetMailSender() public static MailSender? GetMailSender()
{ {
@ -211,21 +219,19 @@ namespace Milimoe.FunGame.Server.Utility
SmtpHost = INIHelper.ReadINI("Mailer", "Host"); SmtpHost = INIHelper.ReadINI("Mailer", "Host");
if (int.TryParse(INIHelper.ReadINI("Mailer", "Port"), out int Port)) if (int.TryParse(INIHelper.ReadINI("Mailer", "Port"), out int Port))
SmtpPort = Port; SmtpPort = Port;
if (bool.TryParse(INIHelper.ReadINI("Mailer", "OpenSSL").ToLower(), out bool SSL)) if (bool.TryParse(INIHelper.ReadINI("Mailer", "SSL").ToLower(), out bool ssl))
OpenSSL = SSL; SSL = ssl;
if (SmtpPort > 0) if (SmtpPort > 0)
{ {
ServerHelper.WriteLine("SMTP 服务已启动!"); return new MailSender(SenderMailAddress, SenderName, SenderPassword, SmtpHost, SmtpPort, SSL);
return new MailSender(SenderMailAddress, SenderName, SenderPassword, SmtpHost, SmtpPort, OpenSSL);
} }
} }
} }
ServerHelper.WriteLine("SMTP 服务处于关闭状态", InvokeMessageType.Warning);
return null; return null;
} }
throw new SmtpHelperException(); throw new SmtpHelperException();
} }
return new MailSender(SenderMailAddress, SenderName, SenderPassword, SmtpHost, SmtpPort, OpenSSL); return new MailSender(SenderMailAddress, SenderName, SenderPassword, SmtpHost, SmtpPort, SSL);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -1,87 +0,0 @@
using Milimoe.FunGame.Core.Model;
using MySql.Data.MySqlClient;
namespace Milimoe.FunGame.Server.Utility.DataUtility
{
public class MySQLConnection
{
public MySqlConnection? Connection
{
get
{
return _Connection;
}
}
public SQLServerInfo ServerInfo
{
get
{
return _ServerInfo ?? SQLServerInfo.Create();
}
}
private MySqlConnection? _Connection;
private SQLServerInfo? _ServerInfo;
/// <summary>
/// 创建SQL连接
/// </summary>
/// <param name="serverInfo"></param>
public MySQLConnection(out SQLServerInfo? serverInfo)
{
_Connection = Connect(out serverInfo);
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
if (_Connection != null && _Connection.State == System.Data.ConnectionState.Open)
{
_Connection.Close();
}
_Connection = null;
}
/// <summary>
/// 连接MySQL服务器
/// </summary>
/// <param name="serverInfo">服务器信息</param>
/// <returns>连接对象</returns>
/// <exception cref="MySQLConfigException">MySQL服务启动失败无法找到MySQL配置文件</exception>
private MySqlConnection? Connect(out SQLServerInfo? serverInfo)
{
try
{
string connectionString = ConnectProperties.GetConnectPropertiesForMySQL();
if (connectionString != null)
{
string[] strings = connectionString.Split(";");
if (strings.Length > 1 && strings[0].Length > 14 && strings[1].Length > 8)
{
ServerHelper.WriteLine("Connect -> MySQL://" + strings[0][14..] + ":" + strings[1][8..]);
}
_Connection = new MySqlConnection(connectionString);
_Connection.Open();
if (_Connection.State == System.Data.ConnectionState.Open)
{
_ServerInfo = SQLServerInfo.Create(ConnectProperties.Name, ConnectProperties.DataSource, ConnectProperties.Port, ConnectProperties.DataBase, ConnectProperties.User, ConnectProperties.Password);
ServerHelper.WriteLine("Connected: MySQL服务器连接成功");
}
}
else
{
throw new MySQLConfigException();
}
}
catch (Exception e)
{
ServerHelper.Error(e);
}
serverInfo = _ServerInfo;
return _Connection;
}
}
}

View File

@ -1,136 +1,170 @@
using System.Data; using System.Data;
using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model; using Milimoe.FunGame.Core.Model;
using Milimoe.FunGame.Server.Others;
using Milimoe.FunGame.Server.Utility.DataUtility;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
namespace Milimoe.FunGame.Server.Utility namespace Milimoe.FunGame.Server.Utility.DataUtility
{ {
public class MySQLHelper : SQLHelper public class MySQLHelper : SQLHelper
{ {
public override FunGameInfo.FunGame FunGameType => Config.FunGameType; public override FunGameInfo.FunGame FunGameType { get; } = FunGameInfo.FunGame.FunGame_Server;
public override SQLMode Mode => SQLMode.MySQL; public override SQLMode Mode { get; } = SQLMode.MySQL;
public override string Script { get; set; } = ""; public override string Script { get; set; } = "";
public override CommandType CommandType { get; set; } = CommandType.Text; public override CommandType CommandType { get; set; } = CommandType.Text;
public override SQLResult Result => _Result; public override SQLResult Result => _result;
public override SQLServerInfo ServerInfo => _ServerInfo ?? SQLServerInfo.Create(); public override SQLServerInfo ServerInfo => _serverInfo ?? SQLServerInfo.Create();
public override int UpdateRows => _UpdateRows; public override int UpdateRows => _updateRows;
public override DataSet DataSet => _DataSet; public override DataSet DataSet => _dataSet;
public MySqlParameter[] Parameters { get; set; }
public MySQLConnection? Connection => _Connection;
private SQLResult _Result = SQLResult.Success; private readonly string _connectionString = "";
private SQLServerInfo? _ServerInfo; private MySqlConnection? _connection;
private int _UpdateRows = 0; private MySqlTransaction? _transaction;
private DataSet _DataSet = new(); private DataSet _dataSet = new();
private MySQLConnection? _Connection; private SQLResult _result = SQLResult.NotFound;
private MySqlTransaction? _Transaction; private readonly SQLServerInfo? _serverInfo;
private readonly IServerModel? ServerModel; private int _updateRows = 0;
private readonly bool _IsOneTime = false;
public MySQLHelper(string script = "", CommandType type = CommandType.Text)
{
Script = script;
CommandType = type;
_connectionString = ConnectProperties.GetConnectPropertiesForMySQL();
string[] strings = _connectionString.Split(";");
if (strings.Length > 1 && strings[0].Length > 14 && strings[1].Length > 8)
{
string ip = strings[0][14..];
string port = strings[1][8..];
_serverInfo = SQLServerInfo.Create(ip: ip, port: port);
}
}
/// <summary>
/// 打开数据库连接
/// </summary>
private void OpenConnection()
{
_connection ??= new MySqlConnection(_connectionString);
if (_connection.State != ConnectionState.Open)
{
_connection.Open();
}
}
/// <summary>
/// 关闭数据库连接
/// </summary>
public override void Close()
{
_transaction?.Dispose();
_transaction = null;
if (_connection?.State != ConnectionState.Closed)
{
_connection?.Close();
}
_connection?.Dispose();
_connection = null;
}
/// <summary> /// <summary>
/// 执行一个命令 /// 执行一个命令
/// </summary> /// </summary>
/// <param name="Result">执行结果</param> /// <returns></returns>
/// <returns>影响的行数</returns>
public override int Execute() public override int Execute()
{ {
// _IsOneTime = true需要手动创建连接和关闭 return Execute(Script);
ServerHelper.WriteLine("SQLQuery -> " + Script, InvokeMessageType.Api);
_DataSet = new DataSet();
_UpdateRows = MySQLManager.Execute(this, out _Result);
if (_IsOneTime) Close();
return _UpdateRows;
} }
/// <summary> /// <summary>
/// 执行一个指定的命令 /// 执行一个指定的命令
/// </summary> /// </summary>
/// <param name="Script">命令</param> /// <param name="script"></param>
/// <param name="Result">执行结果</param> /// <returns></returns>
/// <returns>影响的行数</returns> /// <exception cref="Exception"></exception>
public override int Execute(string Script) public override int Execute(string script)
{ {
// _IsOneTime = true需要手动创建连接和关闭 bool localTransaction = _transaction == null;
ServerHelper.WriteLine("SQLQuery -> " + Script, InvokeMessageType.Api);
this.Script = Script; try
_DataSet = new DataSet(); {
_UpdateRows = MySQLManager.Execute(this, out _Result); if (localTransaction)
if (_IsOneTime) Close(); {
return _UpdateRows; NewTransaction();
}
OpenConnection();
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using MySqlCommand command = new(script, _connection);
command.CommandType = CommandType;
if (_transaction != null) command.Transaction = _transaction;
_updateRows = command.ExecuteNonQuery();
_result = SQLResult.Success;
if (localTransaction) Commit();
}
catch (Exception e)
{
if (localTransaction) Rollback();
_result = SQLResult.Fail;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
}
return UpdateRows;
} }
/// <summary> /// <summary>
/// 查询DataSet /// 查询DataSet
/// </summary> /// </summary>
/// <param name="Result">执行结果</param> /// <returns></returns>
/// <returns>结果集</returns>
public override DataSet ExecuteDataSet() public override DataSet ExecuteDataSet()
{ {
// _IsOneTime = true需要手动创建连接和关闭 return ExecuteDataSet(Script);
ServerHelper.WriteLine("SQLQuery -> " + Script, InvokeMessageType.Api);
_DataSet = MySQLManager.ExecuteDataSet(this, out _Result, out _UpdateRows);
if (_IsOneTime) Close();
return DataSet;
} }
/// <summary> /// <summary>
/// 执行指定的命令查询DataSet /// 执行指定的命令查询DataSet
/// </summary> /// </summary>
/// <param name="Script">命令</param> /// <param name="script"></param>
/// <param name="Result">执行结果</param> /// <returns></returns>
/// <returns>结果集</returns> public override DataSet ExecuteDataSet(string script)
public override DataSet ExecuteDataSet(string Script)
{ {
// _IsOneTime = true需要手动创建连接和关闭 bool localTransaction = _transaction == null;
ServerHelper.WriteLine("SQLQuery -> " + Script, InvokeMessageType.Api);
this.Script = Script;
_DataSet = MySQLManager.ExecuteDataSet(this, out _Result, out _UpdateRows);
if (_IsOneTime) Close();
return DataSet;
}
/// <summary> try
/// 关闭连接 如有事务会自动提交事务 {
/// </summary> if (localTransaction)
public override void Close() {
{ NewTransaction();
// _IsOneTime = false需要手动调用此方法 }
Commit(); OpenConnection();
_Connection?.Close(); ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
ServerHelper.WriteLine($"{(GetClientName() == string.Empty ? "" : GetClientName())}已释放MySQL连接");
}
/// <summary> using MySqlCommand command = new(script, _connection)
/// 创建SQLHelper {
/// </summary> CommandType = CommandType
/// <param name="IsOneTime">是否是单次使用(执行完毕会自动Close连接)</param> };
/// <param name="script">存储过程名称或者script语句</param>
/// <param name="type">存储过程, 文本, 等等</param>
/// <param name="parameters">执行命令所用参数的集合</param>
public MySQLHelper(string script = "", bool IsOneTime = true, CommandType type = CommandType.Text, params MySqlParameter[] parameters)
{
Script = script;
_IsOneTime = IsOneTime;
CommandType = type;
Parameters = parameters;
_Connection = new MySQLConnection(out _ServerInfo);
}
/// <summary> MySqlDataAdapter adapter = new()
/// 创建为SocketModel服务的SQLHelper {
/// </summary> SelectCommand = command
/// <param name="ServerModel">SocketModel</param> };
public MySQLHelper(IServerModel ServerModel) adapter.Fill(_dataSet);
{
this.ServerModel = ServerModel; if (localTransaction) Commit();
Script = ""; }
CommandType = CommandType.Text; catch (Exception e)
Parameters = []; {
_Connection = new MySQLConnection(out _ServerInfo); if (localTransaction) Rollback();
_result = SQLResult.Fail;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
}
return _dataSet;
} }
/// <summary> /// <summary>
@ -138,7 +172,11 @@ namespace Milimoe.FunGame.Server.Utility
/// </summary> /// </summary>
public override void NewTransaction() public override void NewTransaction()
{ {
_Transaction ??= _Connection?.Connection?.BeginTransaction(); OpenConnection();
if (_connection != null)
{
_transaction = _connection.BeginTransaction();
}
} }
/// <summary> /// <summary>
@ -146,8 +184,16 @@ namespace Milimoe.FunGame.Server.Utility
/// </summary> /// </summary>
public override void Commit() public override void Commit()
{ {
_Transaction?.Commit(); try
_Transaction = null; {
_transaction?.Commit();
_result = SQLResult.Success;
}
catch (Exception e)
{
_result = SQLResult.Fail;
ServerHelper.Error(e);
}
} }
/// <summary> /// <summary>
@ -155,17 +201,43 @@ namespace Milimoe.FunGame.Server.Utility
/// </summary> /// </summary>
public override void Rollback() public override void Rollback()
{ {
_Transaction?.Rollback(); try
_Transaction = null; {
_transaction?.Rollback();
_result = SQLResult.Success;
}
catch (Exception e)
{
_result = SQLResult.Fail;
ServerHelper.Error(e);
}
} }
private bool _isDisposed = false;
/// <summary> /// <summary>
/// 获取客户端名称 /// 资源清理
/// </summary> /// </summary>
/// <returns></returns> public void Dispose(bool disposing)
private string GetClientName()
{ {
return ServerModel?.GetClientName() ?? string.Empty; if (!_isDisposed)
{
if (disposing)
{
_transaction?.Dispose();
_transaction = null;
_connection?.Close();
_connection?.Dispose();
_connection = null;
}
}
_isDisposed = true;
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} }
} }
} }

View File

@ -1,140 +0,0 @@
using System.Data;
using Milimoe.FunGame.Core.Library.Constant;
using MySql.Data.MySqlClient;
namespace Milimoe.FunGame.Server.Utility
{
public class MySQLManager
{
/// <summary>
/// 执行Script命令
/// </summary>
/// <param name="Helper">MySQLHelper</param>
/// <param name="Result">执行结果</param>
/// <returns>影响的行数</returns>
public static int Execute(MySQLHelper Helper, out SQLResult Result)
{
MySqlCommand cmd = new();
int updaterow;
try
{
PrepareCommand(Helper, cmd);
updaterow = cmd.ExecuteNonQuery();
if (updaterow > 0)
{
Result = SQLResult.Success;
}
else Result = SQLResult.NotFound;
}
catch (Exception e)
{
ServerHelper.Error(e);
updaterow = -1;
Result = SQLResult.Fail;
}
return updaterow;
}
/// <summary>
/// 返回DataSet
/// </summary>
/// <param name="Helper">MySQLHelper</param>
/// <param name="Result">执行结果</param>
/// <returns>结果集</returns>
public static DataSet ExecuteDataSet(MySQLHelper Helper, out SQLResult Result, out int Rows)
{
MySqlCommand cmd = new();
DataSet ds = new();
Rows = 0;
try
{
PrepareCommand(Helper, cmd);
MySqlDataAdapter adapter = new()
{
SelectCommand = cmd
};
adapter.Fill(ds);
//清除参数
cmd.Parameters.Clear();
Rows = ds.Tables[0].Rows.Count;
if (Rows > 0) Result = SQLResult.Success;
else Result = SQLResult.NotFound;
}
catch (Exception e)
{
ServerHelper.Error(e);
Result = SQLResult.Fail;
}
return ds;
}
/// <summary>
/// 返回插入值ID
/// </summary>
/// <param name="Helper">MySQLHelper</param>
/// <param name="Result">执行结果</param>
/// <returns>插入值ID</returns>
public static long ExecuteAndGetLastInsertedID(MySQLHelper Helper, out SQLResult Result)
{
MySqlCommand cmd = new();
int updaterow;
try
{
PrepareCommand(Helper, cmd);
updaterow = cmd.ExecuteNonQuery();
if (updaterow > 0)
{
Result = SQLResult.Success;
}
else Result = SQLResult.NotFound;
}
catch (Exception e)
{
ServerHelper.Error(e);
Result = SQLResult.Fail;
}
return cmd.LastInsertedId;
}
/// <summary>
/// 准备执行一个命令
/// </summary>
/// <param name="Helper">MySQLHelper</param>
/// <param name="cmd">命令对象</param>
public static void PrepareCommand(MySQLHelper Helper, MySqlCommand cmd)
{
if (Helper.Connection != null)
{
MySqlConnection? conn = Helper.Connection.Connection;
if (conn != null)
{
if (conn.State != ConnectionState.Open) conn.Open();
cmd.Connection = conn;
cmd.CommandText = Helper.Script;
cmd.CommandType = Helper.CommandType;
if (Helper.Parameters != null)
{
foreach (MySqlParameter parm in Helper.Parameters)
{
cmd.Parameters.Add(parm);
}
}
}
}
}
}
}

View File

@ -17,13 +17,13 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
public override int UpdateRows => _updateRows; public override int UpdateRows => _updateRows;
public override DataSet DataSet => _dataSet; public override DataSet DataSet => _dataSet;
private readonly SqliteConnection _connection; private readonly string _connectionString = "";
private SqliteConnection? _connection;
private SqliteTransaction? _transaction; private SqliteTransaction? _transaction;
private DataSet _dataSet = new(); private DataSet _dataSet = new();
private SQLResult _result = SQLResult.NotFound; private SQLResult _result = SQLResult.NotFound;
private readonly SQLServerInfo? _serverInfo; private readonly SQLServerInfo? _serverInfo;
private int _updateRows = 0; private int _updateRows = 0;
private readonly string _connectionString = "";
public SQLiteHelper(string script = "", CommandType type = CommandType.Text) public SQLiteHelper(string script = "", CommandType type = CommandType.Text)
{ {
@ -33,10 +33,8 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
string[] strings = _connectionString.Split("="); string[] strings = _connectionString.Split("=");
if (strings.Length > 1) if (strings.Length > 1)
{ {
ServerHelper.WriteLine("Connect -> SQLite://" + strings[1]);
_serverInfo = SQLServerInfo.Create(database: strings[1]); _serverInfo = SQLServerInfo.Create(database: strings[1]);
} }
_connection = new SqliteConnection(_connectionString);
} }
/// <summary> /// <summary>
@ -44,6 +42,7 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
/// </summary> /// </summary>
private void OpenConnection() private void OpenConnection()
{ {
_connection ??= new SqliteConnection(_connectionString);
if (_connection.State != ConnectionState.Open) if (_connection.State != ConnectionState.Open)
{ {
_connection.Open(); _connection.Open();
@ -56,10 +55,13 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
public override void Close() public override void Close()
{ {
_transaction?.Dispose(); _transaction?.Dispose();
if (_connection.State != ConnectionState.Closed) _transaction = null;
if (_connection?.State != ConnectionState.Closed)
{ {
_connection.Close(); _connection?.Close();
} }
_connection?.Dispose();
_connection = null;
} }
/// <summary> /// <summary>
@ -79,27 +81,35 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public override int Execute(string script) public override int Execute(string script)
{ {
bool localTransaction = _transaction == null;
try try
{ {
if (localTransaction)
{
NewTransaction();
}
OpenConnection(); OpenConnection();
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api); ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using SqliteCommand command = new(script, _connection); using SqliteCommand command = new(script, _connection);
command.CommandType = CommandType; command.CommandType = CommandType;
if (_transaction != null) if (_transaction != null) command.Transaction = _transaction;
{
command.Transaction = _transaction;
}
_updateRows = command.ExecuteNonQuery(); _updateRows = command.ExecuteNonQuery();
_result = SQLResult.Success; _result = SQLResult.Success;
Close(); if (localTransaction) Commit();
return UpdateRows;
} }
catch (Exception ex) catch (Exception e)
{ {
if (localTransaction) Rollback();
_result = SQLResult.Fail; _result = SQLResult.Fail;
throw new Exception($"SQL execution failed: {ex.Message}", ex); ServerHelper.Error(e);
} }
finally
{
if (localTransaction) Close();
}
return UpdateRows;
} }
/// <summary> /// <summary>
@ -119,8 +129,14 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public override DataSet ExecuteDataSet(string script) public override DataSet ExecuteDataSet(string script)
{ {
bool localTransaction = _transaction == null;
try try
{ {
if (localTransaction)
{
NewTransaction();
}
OpenConnection(); OpenConnection();
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api); ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using SqliteCommand command = new(script, _connection) using SqliteCommand command = new(script, _connection)
@ -132,42 +148,19 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
DataTable table = new(); DataTable table = new();
table.Load(reader); table.Load(reader);
_dataSet.Tables.Add(table); _dataSet.Tables.Add(table);
Close(); if (localTransaction) Commit();
return _dataSet;
} }
catch (Exception ex) catch (Exception e)
{ {
if (localTransaction) Rollback();
_result = SQLResult.Fail; _result = SQLResult.Fail;
throw new Exception($"SQL execution failed: {ex.Message}", ex); ServerHelper.Error(e);
} }
} finally
/// <summary>
/// 执行指定的命令查询DataRow
/// </summary>
/// <returns></returns>
public override DataRow? ExecuteDataRow()
{
return ExecuteDataRow(Script);
}
/// <summary>
/// 执行指定的命令查询DataRow
/// </summary>
/// <param name="script"></param>
/// <returns></returns>
public override DataRow? ExecuteDataRow(string script)
{
OpenConnection();
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
DataSet dataSet = ExecuteDataSet(script);
if (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0)
{ {
Close(); if (localTransaction) Close();
return dataSet.Tables[0].Rows[0];
} }
Close(); return _dataSet;
return null;
} }
/// <summary> /// <summary>
@ -176,7 +169,10 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
public override void NewTransaction() public override void NewTransaction()
{ {
OpenConnection(); OpenConnection();
_transaction = _connection.BeginTransaction(); if (_connection != null)
{
_transaction = _connection.BeginTransaction();
}
} }
/// <summary> /// <summary>
@ -188,13 +184,12 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
try try
{ {
_transaction?.Commit(); _transaction?.Commit();
Close();
_result = SQLResult.Success; _result = SQLResult.Success;
} }
catch (Exception ex) catch (Exception e)
{ {
_result = SQLResult.Fail; _result = SQLResult.Fail;
throw new Exception($"Transaction commit failed: {ex.Message}", ex); ServerHelper.Error(e);
} }
} }
@ -207,23 +202,40 @@ namespace Milimoe.FunGame.Server.Utility.DataUtility
try try
{ {
_transaction?.Rollback(); _transaction?.Rollback();
Close();
_result = SQLResult.Success; _result = SQLResult.Success;
} }
catch (Exception ex) catch (Exception e)
{ {
_result = SQLResult.Fail; _result = SQLResult.Fail;
throw new Exception($"Transaction rollback failed: {ex.Message}", ex); ServerHelper.Error(e);
} }
} }
private bool _isDisposed = false;
/// <summary> /// <summary>
/// 资源清理 /// 资源清理
/// </summary> /// </summary>
public void Dispose() public void Dispose(bool disposing)
{ {
_transaction?.Dispose(); if (!_isDisposed)
_connection.Dispose(); {
if (disposing)
{
_transaction?.Dispose();
_transaction = null;
_connection?.Close();
_connection?.Dispose();
_connection = null;
}
}
_isDisposed = true;
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} }
} }
} }

View File

@ -33,22 +33,22 @@ try
ServerHelper.InitOrderList(); ServerHelper.InitOrderList();
// 创建全局SQLHelper // 创建全局SQLHelper
Config.InitSQLHelper(); FunGameSystem.InitSQLHelper();
// 创建全局MailSender // 创建全局MailSender
Config.InitMailSender(); FunGameSystem.InitMailSender();
// 读取游戏模组 // 读取游戏模组
if (!Config.GetGameModuleList()) if (!FunGameSystem.GetGameModuleList())
{ {
ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。"); ServerHelper.WriteLine("服务器似乎未安装任何游戏模组,请检查是否正确安装它们。");
} }
// 读取Server插件 // 读取Server插件
Config.GetServerPlugins(); FunGameSystem.GetServerPlugins();
// 读取Web API插件 // 读取Web API插件
Config.GetWebAPIPlugins(); FunGameSystem.GetWebAPIPlugins();
// 检查是否存在配置文件 // 检查是否存在配置文件
if (!INIHelper.ExistINIFile()) if (!INIHelper.ExistINIFile())
@ -70,6 +70,8 @@ try
ServerHelper.WriteLine("请输入 help 来获取帮助,输入 quit 关闭服务器。"); ServerHelper.WriteLine("请输入 help 来获取帮助,输入 quit 关闭服务器。");
ServerHelper.PrintFunGameTitle();
if (Config.ServerNotice != "") if (Config.ServerNotice != "")
Console.WriteLine("\r \n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n"); Console.WriteLine("\r \n********** 服务器公告 **********\n\n" + Config.ServerNotice + "\n");
else else