diff --git a/Api/OpenEntityAdapter/OpenItemAdapter.cs b/Api/OpenEntityAdapter/OpenItemAdapter.cs index e671743..66674ed 100644 --- a/Api/OpenEntityAdapter/OpenItemAdapter.cs +++ b/Api/OpenEntityAdapter/OpenItemAdapter.cs @@ -12,7 +12,10 @@ namespace Milimoe.FunGame.Core.Api.OpenEntityAdapter if (config[key] is Item prev) { Item next = prev.Copy(); - if (next is T t) config[key] = t; + if (next is T t) + { + config[key] = t; + } } } } diff --git a/Api/Transmittal/MailSender.cs b/Api/Transmittal/MailSender.cs index 0cdd70b..d2cdca1 100644 --- a/Api/Transmittal/MailSender.cs +++ b/Api/Transmittal/MailSender.cs @@ -38,47 +38,47 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// /// 创建邮件服务 /// - /// - /// - /// - /// - /// - /// - public MailSender(string SenderMailAddress, string SenderName, string SenderPassword, string Host, int Port, bool OpenSSL) + /// + /// + /// + /// + /// + /// + public MailSender(string senderMailAddress, string senderName, string senderPassword, string host, int port, bool ssl) { MailSenderID = Guid.NewGuid(); - _SmtpClientInfo = new SmtpClientInfo(SenderMailAddress, SenderName, SenderPassword, Host, Port, OpenSSL); + _SmtpClientInfo = new SmtpClientInfo(senderMailAddress, senderName, senderPassword, host, port, ssl); if (!MailManager.MailSenders.ContainsKey(MailSenderID)) MailManager.MailSenders.Add(MailSenderID, this); } /// /// 创建完整邮件对象 /// - /// - /// - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// + /// + /// /// - public MailObject CreateMail(string Subject, string Body, MailPriority Priority, bool HTML, string[] ToList, string[]? CCList = null, string[]? BCCList = null) + public MailObject CreateMail(string subject, string body, MailPriority priority, bool html, string[] toList, string[]? ccList = null, string[]? bccList = null) { - return new MailObject(this, Subject, Body, Priority, HTML, ToList, CCList, BCCList); + return new MailObject(this, subject, body, priority, html, toList, ccList, bccList); } /// /// 发送邮件 /// - /// + /// /// - public MailSendResult Send(MailObject Mail) + public MailSendResult Send(MailObject mail) { - _LastestResult = MailManager.Send(this, Mail, out _ErrorMsg); + _LastestResult = MailManager.Send(this, mail, out _ErrorMsg); return _LastestResult; } - private bool IsDisposed = false; + private bool _isDisposed = false; /// /// 关闭邮件服务 @@ -92,17 +92,17 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// /// 关闭邮件服务 /// - /// - protected void Dispose(bool Disposing) + /// + protected void Dispose(bool disposing) { - if (!IsDisposed) + if (!_isDisposed) { - if (Disposing) + if (disposing) { MailManager.Dispose(this); } } - IsDisposed = true; + _isDisposed = true; } } } diff --git a/Api/Transmittal/SQLHelper.cs b/Api/Transmittal/SQLHelper.cs index 3aa15ec..7f8efe2 100644 --- a/Api/Transmittal/SQLHelper.cs +++ b/Api/Transmittal/SQLHelper.cs @@ -8,7 +8,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// /// 需要在Server中继承此类实现 /// - public abstract class SQLHelper : ISQLHelper + public abstract class SQLHelper : ISQLHelper, IDisposable { public abstract FunGameInfo.FunGame FunGameType { get; } public abstract SQLMode Mode { get; } @@ -29,9 +29,9 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// /// 执行一个指定的命令 /// - /// 命令 + /// 命令 /// 影响的行数 - public abstract int Execute(string Script); + public abstract int Execute(string script); /// /// 查询DataSet @@ -42,9 +42,9 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// /// 执行指定的命令查询DataSet /// - /// 命令 + /// 命令 /// 结果集 - public abstract DataSet ExecuteDataSet(string Script); + public abstract DataSet ExecuteDataSet(string script); /// /// 执行指定的命令查询DataRow(可选实现) @@ -52,16 +52,21 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// 结果行 public virtual DataRow? ExecuteDataRow() { - return null; + return ExecuteDataRow(Script); } /// /// 执行指定的命令查询DataRow(可选实现) /// - /// 命令 + /// 命令 /// 结果行 - public virtual DataRow? ExecuteDataRow(string Script) + public virtual DataRow? ExecuteDataRow(string script) { + DataSet dataSet = ExecuteDataSet(script); + if (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0) + { + return dataSet.Tables[0].Rows[0]; + } return null; } @@ -84,5 +89,10 @@ namespace Milimoe.FunGame.Core.Api.Transmittal /// 回滚事务 /// public abstract void Rollback(); + + /// + /// 释放资源 + /// + public abstract void Dispose(); } } diff --git a/Api/Utility/Factory.cs b/Api/Utility/Factory.cs index f71e575..ff08525 100644 --- a/Api/Utility/Factory.cs +++ b/Api/Utility/Factory.cs @@ -1,8 +1,10 @@ using System.Data; using Milimoe.FunGame.Core.Api.EntityFactory; using Milimoe.FunGame.Core.Api.OpenEntityAdapter; +using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Library.Exception; using Milimoe.FunGame.Core.Library.SQLScript.Entity; namespace Milimoe.FunGame.Core.Api.Utility @@ -81,9 +83,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in CharacterFactories) { - if (d.Invoke(id, name, args) is T character) + try { - return character; + if (d.Invoke(id, name, args) is T character) + { + return character; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetCharacter(); @@ -92,9 +101,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in InventoryFactories) { - if (d.Invoke(id, name, args) is T inventory) + try { - return inventory; + if (d.Invoke(id, name, args) is T inventory) + { + return inventory; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetInventory(); @@ -103,9 +119,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in SkillFactories) { - if (d.Invoke(id, name, args) is T skill) + try { - return skill; + if (d.Invoke(id, name, args) is T skill) + { + return skill; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)new OpenSkill(id, name, args); @@ -114,9 +137,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in EffectFactories) { - if (d.Invoke(id, name, args) is T effect) + try { - return effect; + if (d.Invoke(id, name, args) is T effect) + { + return effect; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetEffect(); @@ -125,9 +155,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in ItemFactories) { - if (d.Invoke(id, name, args) is T item) + try { - return item; + if (d.Invoke(id, name, args) is T item) + { + return item; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetItem(); @@ -136,9 +173,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in RoomFactories) { - if (d.Invoke(id, name, args) is T room) + try { - return room; + if (d.Invoke(id, name, args) is T room) + { + return room; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetRoom(); @@ -147,9 +191,16 @@ namespace Milimoe.FunGame.Core.Api.Utility { foreach (EntityFactoryDelegate d in UserFactories) { - if (d.Invoke(id, name, args) is T user) + try { - return user; + if (d.Invoke(id, name, args) is T user) + { + return user; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); } } return (T)(object)GetUser(); @@ -197,6 +248,78 @@ namespace Milimoe.FunGame.Core.Api.Utility config.SaveConfig(); } + internal HashSet SQLHelperFactories { get; } = []; + + public delegate SQLHelper? SQLHelperFactoryDelegate(); + + /// + /// 注册工厂方法 [SQLHelper] + /// + /// + public void RegisterFactory(SQLHelperFactoryDelegate d) + { + SQLHelperFactories.Add(d); + } + + /// + /// 构造一个 SQLHelper 实例 + /// + /// + public SQLHelper? GetSQLHelper() + { + foreach (SQLHelperFactoryDelegate d in SQLHelperFactories) + { + try + { + if (d.Invoke() is SQLHelper helper) + { + return helper; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); + } + } + return null; + } + + internal HashSet MailSenderFactories { get; } = []; + + public delegate MailSender? MailSenderFactoryDelegate(); + + /// + /// 注册工厂方法 [MailSender] + /// + /// + public void RegisterFactory(MailSenderFactoryDelegate d) + { + MailSenderFactories.Add(d); + } + + /// + /// 构造一个 MailSender 实例 + /// + /// + public MailSender? GetMailSender() + { + foreach (MailSenderFactoryDelegate d in MailSenderFactories) + { + try + { + if (d.Invoke() is MailSender sender) + { + return sender; + } + } + catch (Exception e) + { + TXTHelper.AppendErrorLog(e.GetErrorInfo()); + } + } + return null; + } + private readonly static CharacterFactory CharacterFactory = new(); private readonly static InventoryFactory InventoryFactory = new(); private readonly static SkillFactory SkillFactory = new(); diff --git a/Api/Utility/General.cs b/Api/Utility/General.cs index a31505d..159d35b 100644 --- a/Api/Utility/General.cs +++ b/Api/Utility/General.cs @@ -398,6 +398,27 @@ namespace Milimoe.FunGame.Core.Api.Utility return $"{month}. {day}, {lastWriteTime.Year} {time}"; } + + /// + /// 获取下一次可交易的时间 + /// + /// + public static DateTime GetTradableTime(DateTime? date = null) + { + date ??= DateTime.Now; + if (date is DateTime d) + { + if (d.Hour < 15) + { + return d.Date.AddDays(1).AddHours(15); + } + else + { + return d.Date.AddDays(2).AddHours(9); + } + } + return DateTime.MinValue; + } } #endregion diff --git a/Api/Utility/TextReader.cs b/Api/Utility/TextReader.cs index ef1ff27..8768534 100644 --- a/Api/Utility/TextReader.cs +++ b/Api/Utility/TextReader.cs @@ -125,7 +125,7 @@ namespace Milimoe.FunGame.Core.Api.Utility WriteINI("Mailer", "Password", ""); WriteINI("Mailer", "Host", ""); WriteINI("Mailer", "Port", "587"); - WriteINI("Mailer", "OpenSSL", "true"); + WriteINI("Mailer", "SSL", "true"); break; } } diff --git a/Controller/AddonController.cs b/Controller/AddonController.cs index 14a76dd..f34aa07 100644 --- a/Controller/AddonController.cs +++ b/Controller/AddonController.cs @@ -5,7 +5,7 @@ using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Controller { /// - /// 这个控制器在Base的基础上添加了DataRequest + /// 这个控制器在 Base 的基础上添加了 DataRequest /// /// public class AddonController : BaseAddonController where T : IAddon @@ -105,10 +105,10 @@ namespace Milimoe.FunGame.Core.Controller /// public AddonController(IAddon addon, Dictionary delegates) : base(addon, delegates) { - if (delegates.ContainsKey("NewDataRequest")) MaskMethod_NewDataRequest = delegates["NewDataRequest"] != null ? (Func)delegates["NewDataRequest"]! : new(DefaultNewDataRequest); - if (delegates.ContainsKey("NewLongRunningDataRequest")) MaskMethod_NewLongRunningDataRequest = delegates["NewLongRunningDataRequest"] != null ? (Func)delegates["NewLongRunningDataRequest"]! : new(DefaultNewDataRequest); - if (delegates.ContainsKey("NewGamingRequest")) MaskMethod_NewGamingRequest = delegates["NewGamingRequest"] != null ? (Func)delegates["NewGamingRequest"]! : new(DefaultNewDataRequest); - if (delegates.ContainsKey("NewLongRunningGamingRequest")) MaskMethod_NewLongRunningGamingRequest = delegates["NewLongRunningGamingRequest"] != null ? (Func)delegates["NewLongRunningGamingRequest"]! : new(DefaultNewDataRequest); + if (delegates.TryGetValue("NewDataRequest", out object? value)) MaskMethod_NewDataRequest = value != null ? (Func)value : new(DefaultNewDataRequest); + if (delegates.TryGetValue("NewLongRunningDataRequest", out value)) MaskMethod_NewLongRunningDataRequest = value != null ? (Func)value : new(DefaultNewDataRequest); + if (delegates.TryGetValue("NewGamingRequest", out value)) MaskMethod_NewGamingRequest = value != null ? (Func)value : new(DefaultNewDataRequest); + if (delegates.TryGetValue("NewLongRunningGamingRequest", out value)) MaskMethod_NewLongRunningGamingRequest = value != null ? (Func)value : new(DefaultNewDataRequest); MaskMethod_NewDataRequest ??= new(DefaultNewDataRequest); MaskMethod_NewLongRunningDataRequest ??= new(DefaultNewDataRequest); MaskMethod_NewGamingRequest ??= new(DefaultNewDataRequest); diff --git a/Controller/ServerAddonController.cs b/Controller/ServerAddonController.cs new file mode 100644 index 0000000..2f0eb62 --- /dev/null +++ b/Controller/ServerAddonController.cs @@ -0,0 +1,111 @@ +using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Interface.Addons; +using Milimoe.FunGame.Core.Library.SQLScript.Common; + +namespace Milimoe.FunGame.Core.Controller +{ + /// + /// 这个控制器在 Base 的基础上添加了 SQLHelper 和 MailSender + /// + /// + /// + /// 新建一个ServerAddonController + /// + /// + /// + public class ServerAddonController(IAddon addon, Dictionary delegates) : BaseAddonController(addon, delegates), IServerAddon where T : IAddon + { + /// + /// 数据库连接器 + /// + public SQLHelper? SQLHelper => _sqlHelper; + + /// + /// 邮件发送器 + /// + public MailSender? MailSender => _mailSender; + + private SQLHelper? _sqlHelper = null; + private MailSender? _mailSender = null; + private Task? _sqlPolling = null; + private CancellationTokenSource? _cts = null; + + /// + /// 新建 SQLHelper + /// + public void NewSQLHelper() + { + if (_sqlHelper is null) + { + // 创建持久化 SQLHelper + _sqlHelper = Factory.OpenFactory.GetSQLHelper(); + if (_sqlHelper != null) + { + _cts = new(); + _sqlPolling = Task.Run(async () => + { + await Task.Delay(30); + while (true) + { + 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) + { + Error(e); + } + } + }, _cts.Token); + } + } + else + { + WriteLine("已经创建过 SQLHelper 实例。"); + } + } + + /// + /// 新建 MailSender + /// + public void NewMailSender() + { + if (_mailSender is null) + { + _mailSender = Factory.OpenFactory.GetMailSender(); + } + else + { + WriteLine("已经创建过 MailSender 实例。"); + } + } + + /// + /// 关闭插件的服务 + /// + public async void Close() + { + _mailSender?.Dispose(); + _mailSender = null; + _cts?.Cancel(); + if (_sqlPolling != null) + { + await _sqlPolling; + _sqlPolling.Dispose(); + _sqlPolling = null; + } + _cts?.Dispose(); + } + } +} diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index 02cf40c..5d919c1 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -1,5 +1,4 @@ -using System.IO; -using System.Text; +using System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; diff --git a/Entity/Character/MagicResistance.cs b/Entity/Character/MagicResistance.cs index d832085..4c10770 100644 --- a/Entity/Character/MagicResistance.cs +++ b/Entity/Character/MagicResistance.cs @@ -48,6 +48,23 @@ } } + /// + /// 增加所有抗性,传入负数来减少 + /// + /// + public void AddAllValue(double value) + { + None += value; + Particle += value; + Fleabane += value; + Element += value; + Shadow += value; + Bright += value; + PurityContemporary += value; + PurityNatural += value; + Starmark += value; + } + /// /// 复制一个魔法抗性对象 /// diff --git a/Entity/Item/Item.cs b/Entity/Item/Item.cs index 5e897fe..fa15a08 100644 --- a/Entity/Item/Item.cs +++ b/Entity/Item/Item.cs @@ -1,5 +1,4 @@ -using System.Net.NetworkInformation; -using System.Text; +using System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Base; using Milimoe.FunGame.Core.Interface.Entity; @@ -140,6 +139,14 @@ namespace Milimoe.FunGame.Core.Entity e.Source = _character; } } + foreach (Skill skill in Skills.Magics) + { + skill.Character = _character; + foreach (Effect e in skill.Effects) + { + e.Source = _character; + } + } } } @@ -153,6 +160,11 @@ namespace Milimoe.FunGame.Core.Entity /// public SkillGroup Skills { get; set; } = new(); + /// + /// 其他内容 + /// + public Dictionary Others { get; set; } = []; + /// /// 当装备物品时 /// @@ -175,6 +187,13 @@ namespace Milimoe.FunGame.Core.Entity } } } + foreach (Skill skill in Skills.Magics) + { + if (Character != null && skill.IsMagic && skill.Level > 0) + { + Character.Skills.Add(skill); + } + } if (Character != null) OnItemEquipped(Character, this, type); } @@ -185,15 +204,6 @@ namespace Milimoe.FunGame.Core.Entity { if (Character != null) { - if (Skills.Active != null) - { - List effects = Character.Effects.Where(e => e.Skill == Skills.Active && e.Level > 0).ToList(); - foreach (Effect e in effects) - { - Character.Effects.Remove(e); - e.OnEffectLost(Character); - } - } foreach (Skill skill in Skills.Passives) { List effects = Character.Effects.Where(e => e.Skill == skill && e.Level > 0).ToList(); @@ -203,6 +213,10 @@ namespace Milimoe.FunGame.Core.Entity e.OnEffectLost(Character); } } + foreach (Skill skill in Skills.Magics) + { + Character.Skills.Remove(skill); + } switch (type) { case EquipSlotType.MagicCardPack: @@ -241,6 +255,10 @@ namespace Milimoe.FunGame.Core.Entity { skill.GamingQueue = queue; } + foreach (Skill skill in Skills.Magics) + { + skill.GamingQueue = queue; + } } /// @@ -346,38 +364,73 @@ namespace Milimoe.FunGame.Core.Entity /// 显示物品的详细信息 /// /// 是否显示通用描述,而不是描述 + /// 是否在商店中显示 /// - public string ToString(bool isShowGeneralDescription) + public string ToString(bool isShowGeneralDescription, bool isShowInStore = false) { StringBuilder builder = new(); builder.AppendLine($"【{Name}】"); - builder.AppendLine($"{ItemSet.GetItemTypeName(ItemType) + (ItemType == ItemType.Weapon && WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(WeaponType) : "")}" + (IsPurchasable && Price > 0 ? $" 售价:{Price}" : "")); + + string itemquality = ItemSet.GetQualityTypeName(QualityType); + string itemtype = ItemSet.GetItemTypeName(ItemType) + (ItemType == ItemType.Weapon && WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(WeaponType) : ""); + if (itemtype != "") itemtype = $" {itemtype}"; + + builder.AppendLine($"{itemquality + itemtype}"); + + if (isShowInStore && Price > 0) + { + builder.AppendLine($"售价:{Price} {General.GameplayEquilibriumConstant.InGameCurrency}"); + } if (RemainUseTimes > 0) { - builder.AppendLine($"剩余可用次数:{RemainUseTimes}"); + builder.AppendLine($"{(isShowInStore ? "" : "剩余")}可用次数:{RemainUseTimes}"); } - List sellandtrade = [""]; - if (IsSellable) + if (isShowInStore) { - sellandtrade.Add("可出售"); + if (IsSellable) + { + builder.AppendLine($"购买此物品后可立即出售"); + } + if (IsTradable) + { + DateTime date = DateTimeUtility.GetTradableTime(); + builder.AppendLine($"购买此物品后将在 {date.ToString(General.GeneralDateTimeFormatChinese)} 后可交易"); + } } - if (IsTradable) + else { - sellandtrade.Add("可交易"); - } - builder.AppendLine(string.Join(" ", sellandtrade).Trim()); + List sellandtrade = [""]; + if (IsSellable) + { + sellandtrade.Add("可出售"); + } + if (IsTradable) + { + sellandtrade.Add("可交易"); + } - if (!IsSellable && NextSellableTime != DateTime.MinValue) - { - builder.AppendLine($"此物品将在 {NextSellableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可出售"); - } + if (!IsSellable && NextSellableTime != DateTime.MinValue) + { + builder.AppendLine($"此物品将在 {NextSellableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可出售"); + } + else if (!IsSellable) + { + sellandtrade.Add("不可出售"); + } - if (!IsTradable && NextTradableTime != DateTime.MinValue) - { - builder.AppendLine($"此物品将在 {NextTradableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可交易"); + if (!IsTradable && NextTradableTime != DateTime.MinValue) + { + builder.AppendLine($"此物品将在 {NextTradableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可交易"); + } + else if (!IsTradable) + { + sellandtrade.Add("不可交易"); + } + + builder.AppendLine(string.Join(" ", sellandtrade).Trim()); } if (isShowGeneralDescription && GeneralDescription != "") @@ -388,6 +441,12 @@ namespace Milimoe.FunGame.Core.Entity { builder.AppendLine("物品描述:" + Description); } + if (ItemType == ItemType.MagicCardPack && Skills.Magics.Count > 0) + { + builder.AppendLine("== 魔法卡 ==\r\n" + string.Join("\r\n", Skills.Magics.Select(m => m.ToString().Trim()))); + } + + builder.AppendLine("== 物品技能 =="); if (Skills.Active != null) builder.AppendLine($"{Skills.Active.ToString().Trim()}"); foreach (Skill skill in Skills.Passives) @@ -461,17 +520,24 @@ namespace Milimoe.FunGame.Core.Entity item.NextTradableTime = NextTradableTime; item.RemainUseTimes = RemainUseTimes; item.Skills.Active = Skills.Active?.Copy(); - if (item.Skills.Active != null && copyLevel) + if (item.Skills.Active != null) { - item.Skills.Active.Level = Skills.Active?.Level ?? 0; + item.Skills.Active.Level = copyLevel ? (Skills.Active?.Level ?? 1) : 1; } foreach (Skill skill in Skills.Passives) { Skill newskill = skill.Copy(); newskill.Item = item; - newskill.Level = copyLevel ? skill.Level : 0; + newskill.Level = copyLevel ? skill.Level : 1; item.Skills.Passives.Add(newskill); } + foreach (Skill skill in Skills.Magics) + { + Skill newskill = skill.Copy(); + newskill.Item = item; + newskill.Level = copyLevel ? skill.Level : 1; + item.Skills.Magics.Add(newskill); + } return item; } @@ -491,6 +557,22 @@ namespace Milimoe.FunGame.Core.Entity } } + /// + /// 设置所有魔法的等级 + /// + /// + public void SetMagicsLevel(int level) + { + if (Skills.Active != null) + { + Skills.Active.Level = level; + } + foreach (Skill skill in Skills.Magics) + { + skill.Level = level; + } + } + /// /// 所属的角色 /// diff --git a/Entity/Item/SkillGroup.cs b/Entity/Item/SkillGroup.cs index 7eb4649..cd40325 100644 --- a/Entity/Item/SkillGroup.cs +++ b/Entity/Item/SkillGroup.cs @@ -2,6 +2,7 @@ { /// /// 物品只有一个主动技能,但是可以有很多个被动技能 + /// 魔法卡包具有很多个魔法技能 /// public class SkillGroup { @@ -14,5 +15,10 @@ /// 被动技能组 /// public HashSet Passives { get; set; } = []; + + /// + /// 魔法技能组 + /// + public HashSet Magics { get; set; } = []; } } diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs index 468e1ab..c6e0ce9 100644 --- a/Entity/Skill/Skill.cs +++ b/Entity/Skill/Skill.cs @@ -334,7 +334,7 @@ namespace Milimoe.FunGame.Core.Entity LastCostMP = RealMPCost; LastCostEP = RealEPCost; } - + /// /// 触发技能效果 /// diff --git a/Entity/System/RoundRecord.cs b/Entity/System/RoundRecord.cs index 7cb08b0..11e96f6 100644 --- a/Entity/System/RoundRecord.cs +++ b/Entity/System/RoundRecord.cs @@ -79,7 +79,7 @@ namespace Milimoe.FunGame.Core.Entity { builder.AppendLine($"[ {character} ] 进入复活倒计时:{RespawnCountdowns[character]:0.##}"); } - + foreach (Character character in Respawns) { builder.AppendLine($"[ {character} ] 复活了"); diff --git a/Interface/Base/Addons/IGameModuleServer.cs b/Interface/Base/Addons/IGameModuleServer.cs index c5033e1..0ee4fca 100644 --- a/Interface/Base/Addons/IGameModuleServer.cs +++ b/Interface/Base/Addons/IGameModuleServer.cs @@ -4,7 +4,7 @@ using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Interface.Addons { - public interface IGameModuleServer : IAddon, IServerAddon, IAddonController, IGameModuleDepend + public interface IGameModuleServer : IAddon, IAddonController, IGameModuleDepend { public bool StartServer(string GameModule, Room Room, List Users, IServerModel RoomMasterServerModel, Dictionary ServerModels, params object[] args); diff --git a/Library/Common/Addon/GameModuleServer.cs b/Library/Common/Addon/GameModuleServer.cs index 8ec102b..c96541f 100644 --- a/Library/Common/Addon/GameModuleServer.cs +++ b/Library/Common/Addon/GameModuleServer.cs @@ -1,5 +1,3 @@ -using Milimoe.FunGame.Core.Api.Transmittal; -using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Interface.Addons; @@ -44,26 +42,25 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// /// 包含了一些常用方法的控制器 /// - public BaseAddonController Controller + public ServerAddonController Controller { get => _Controller ?? throw new NotImplementedException(); - set => _Controller = value; + internal set => _Controller = value; + } + + /// + /// base控制器 + /// + BaseAddonController IAddonController.Controller + { + get => Controller; + set => _Controller = (ServerAddonController?)value; } /// /// 控制器内部变量 /// - private BaseAddonController? _Controller; - - /// - /// 全局数据库连接器 - /// - public SQLHelper? SQLHelper => Singleton.Get(); - - /// - /// 全局邮件发送器 - /// - public MailSender? MailSender => Singleton.Get(); + private ServerAddonController? _Controller; /// /// 启动服务器监听 请在此处实现服务器逻辑 diff --git a/Library/Common/Addon/ServerPlugin.cs b/Library/Common/Addon/ServerPlugin.cs index 8db1831..843f36b 100644 --- a/Library/Common/Addon/ServerPlugin.cs +++ b/Library/Common/Addon/ServerPlugin.cs @@ -1,13 +1,11 @@ -using Milimoe.FunGame.Core.Api.Transmittal; -using Milimoe.FunGame.Core.Api.Utility; -using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface; using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Library.Common.Event; namespace Milimoe.FunGame.Core.Library.Common.Addon { - public abstract class ServerPlugin : IPlugin, IServerAddon + public abstract class ServerPlugin : IPlugin { /// /// 插件名称 @@ -32,26 +30,25 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// /// 包含了一些常用方法的控制器 /// - public BaseAddonController Controller + public ServerAddonController Controller { get => _Controller ?? throw new NotImplementedException(); - set => _Controller = value; + internal set => _Controller = value; } /// - /// 全局数据库连接器 + /// base控制器 /// - public SQLHelper? SQLHelper => Singleton.Get(); - - /// - /// 全局邮件发送器 - /// - public MailSender? MailSender => Singleton.Get(); + BaseAddonController IAddonController.Controller + { + get => Controller; + set => _Controller = (ServerAddonController?)value; + } /// /// 控制器内部变量 /// - private BaseAddonController? _Controller; + private ServerAddonController? _Controller; /// /// 加载标记 diff --git a/Library/Common/Addon/WebAPIPlugin.cs b/Library/Common/Addon/WebAPIPlugin.cs index c6c5d86..a8dc9a8 100644 --- a/Library/Common/Addon/WebAPIPlugin.cs +++ b/Library/Common/Addon/WebAPIPlugin.cs @@ -1,11 +1,9 @@ -using Milimoe.FunGame.Core.Api.Transmittal; -using Milimoe.FunGame.Core.Api.Utility; -using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface.Addons; namespace Milimoe.FunGame.Core.Library.Common.Addon { - public abstract class WebAPIPlugin : IAddon, IServerAddon, IAddonController + public abstract class WebAPIPlugin : IAddon, IAddonController { /// /// 插件名称 @@ -30,38 +28,37 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// /// 包含了一些常用方法的控制器 /// - public BaseAddonController Controller + public ServerAddonController Controller { get => _Controller ?? throw new NotImplementedException(); - set => _Controller = value; + internal set => _Controller = value; + } + + /// + /// base控制器 + /// + BaseAddonController IAddonController.Controller + { + get => Controller; + set => _Controller = (ServerAddonController?)value; } /// /// 控制器内部变量 /// - private BaseAddonController? _Controller; - - /// - /// 全局数据库连接器 - /// - public SQLHelper? SQLHelper => Singleton.Get(); - - /// - /// 全局邮件发送器 - /// - public MailSender? MailSender => Singleton.Get(); + private ServerAddonController? _Controller; /// /// 加载标记 /// - private bool IsLoaded = false; + private bool _isLoaded = false; /// /// 加载插件 /// public bool Load(params object[] objs) { - if (IsLoaded) + if (_isLoaded) { return false; } @@ -69,9 +66,9 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon if (BeforeLoad(objs)) { // 插件加载后,不允许再次加载此插件 - IsLoaded = true; + _isLoaded = true; } - return IsLoaded; + return _isLoaded; } /// diff --git a/Library/Common/JsonConverter/ItemConverter.cs b/Library/Common/JsonConverter/ItemConverter.cs index eec8e43..b3bc088 100644 --- a/Library/Common/JsonConverter/ItemConverter.cs +++ b/Library/Common/JsonConverter/ItemConverter.cs @@ -94,6 +94,14 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter SkillGroup skills = NetworkUtility.JsonDeserialize(ref reader, options) ?? new(); result.Skills.Active = skills.Active; result.Skills.Passives = skills.Passives; + result.Skills.Magics = skills.Magics; + break; + case nameof(Item.Others): + Dictionary values = NetworkUtility.JsonDeserialize>(ref reader, options) ?? []; + foreach (string key in values.Keys) + { + result.Others.Add(key, values[key]); + } break; } } @@ -129,6 +137,8 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter } writer.WritePropertyName(nameof(Item.Skills)); JsonSerializer.Serialize(writer, value.Skills, options); + writer.WritePropertyName(nameof(Item.Others)); + JsonSerializer.Serialize(writer, value.Others, options); writer.WriteEndObject(); } diff --git a/Library/Common/Network/MailObject.cs b/Library/Common/Network/MailObject.cs index a6b59c2..379a2b0 100644 --- a/Library/Common/Network/MailObject.cs +++ b/Library/Common/Network/MailObject.cs @@ -39,17 +39,17 @@ namespace Milimoe.FunGame.Core.Library.Common.Network /// /// 收件人列表 /// - public List ToList { get; } = new(); + public List ToList { get; } = []; /// /// 抄送列表 /// - public List CCList { get; } = new(); + public List CCList { get; } = []; /// /// 密送列表 /// - public List BCCList { get; } = new(); + public List BCCList { get; } = []; public MailObject() { @@ -59,80 +59,80 @@ namespace Milimoe.FunGame.Core.Library.Common.Network /// /// 使用MailSender工具类创建邮件对象 /// - /// - public MailObject(MailSender Sender) + /// + public MailObject(MailSender sender) { - this.Sender = Sender.SmtpClientInfo.SenderMailAddress; - this.SenderName = Sender.SmtpClientInfo.SenderName; + this.Sender = sender.SmtpClientInfo.SenderMailAddress; + this.SenderName = sender.SmtpClientInfo.SenderName; } /// /// 使用地址和名称创建邮件对象 /// - /// - /// - public MailObject(string Sender, string SenderName) + /// + /// + public MailObject(string sender, string senderName) { - this.Sender = Sender; - this.SenderName = SenderName; + this.Sender = sender; + this.SenderName = senderName; } /// /// 使用地址和名称创建邮件对象,同时写主题、内容、单个收件人 /// - /// - /// - /// - /// - public MailObject(MailSender Sender, string Subject, string Body, string To) + /// + /// + /// + /// + public MailObject(MailSender sender, string subject, string body, string to) { - this.Sender = Sender.SmtpClientInfo.SenderMailAddress; - this.SenderName = Sender.SmtpClientInfo.SenderName; - this.Subject = Subject; - this.Body = Body; - ToList.Add(To); + this.Sender = sender.SmtpClientInfo.SenderMailAddress; + this.SenderName = sender.SmtpClientInfo.SenderName; + this.Subject = subject; + this.Body = body; + ToList.Add(to); } /// /// 使用地址和名称创建邮件对象,同时写主题、内容、单个收件人、单个抄送 /// - /// - /// - /// - /// - /// - public MailObject(MailSender Sender, string Subject, string Body, string To, string CC) + /// + /// + /// + /// + /// + public MailObject(MailSender sender, string subject, string body, string to, string cc) { - this.Sender = Sender.SmtpClientInfo.SenderMailAddress; - this.SenderName = Sender.SmtpClientInfo.SenderName; - this.Subject = Subject; - this.Body = Body; - ToList.Add(To); - CCList.Add(CC); + this.Sender = sender.SmtpClientInfo.SenderMailAddress; + this.SenderName = sender.SmtpClientInfo.SenderName; + this.Subject = subject; + this.Body = body; + ToList.Add(to); + CCList.Add(cc); } /// /// 完整的创建邮件对象 /// - /// - /// - /// - /// - /// - /// - /// - /// - public MailObject(MailSender Sender, string Subject, string Body, MailPriority Priority, bool HTML, string[] ToList, string[]? CCList = null, string[]? BCCList = null) + /// + /// + /// + /// + /// + /// + /// + /// + public MailObject(MailSender sender, string subject, string body, MailPriority priority, bool html, string[] toList, string[]? ccList = null, string[]? bccList = null) { - this.Sender = Sender.SmtpClientInfo.SenderMailAddress; - this.SenderName = Sender.SmtpClientInfo.SenderName; - this.Subject = Subject; - this.Body = Body; - this.Priority = Priority; - this.HTML = HTML; - AddTo(ToList); - if (CCList != null) AddCC(CCList); - if (BCCList != null) AddBCC(BCCList); + Sender = sender.SmtpClientInfo.SenderMailAddress; + SenderName = sender.SmtpClientInfo.SenderName; + Subject = subject; + Body = body; + Priority = priority; + HTML = html; + AddTo(toList); + if (ccList != null) AddCC(ccList); + if (bccList != null) AddBCC(bccList); } /// diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs index aef6bef..5241663 100644 --- a/Library/Constant/ConstantSet.cs +++ b/Library/Constant/ConstantSet.cs @@ -482,6 +482,34 @@ namespace Milimoe.FunGame.Core.Library.Constant _ => EquipSlotType.None }; } + + public static string GetQualityTypeName(QualityType type) + { + return type switch + { + QualityType.Green => "优秀", + QualityType.Blue => "稀有", + QualityType.Purple => "史诗", + QualityType.Orange => "传说", + QualityType.Red => "神话", + QualityType.Gold => "不朽", + _ => "普通" + }; + } + + public static QualityType GetQualityTypeFromName(string name) + { + return name switch + { + "优秀" => QualityType.Green, + "稀有" => QualityType.Blue, + "史诗" => QualityType.Purple, + "传说" => QualityType.Orange, + "神话" => QualityType.Red, + "不朽" => QualityType.Gold, + _ => QualityType.White + }; + } } public class SkillSet diff --git a/Library/Constant/FunGameInfo.cs b/Library/Constant/FunGameInfo.cs index 058d759..bfab102 100644 --- a/Library/Constant/FunGameInfo.cs +++ b/Library/Constant/FunGameInfo.cs @@ -28,6 +28,19 @@ public const string FunGame_Version = "v1.0"; public const string FunGame_VersionPatch = ""; + public const string FunGameCoreTitle = @" _____ _ _ _ _ ____ _ __ __ _____ ____ ___ ____ _____ + | ___| | | | \ | |/ ___| / \ | \/ | ____| / ___/ _ \| _ \| ____| + | |_ | | | | \| | | _ / _ \ | |\/| | _| | | | | | | |_) | _| + | _| | |_| | |\ | |_| |/ ___ \| | | | |___ | |__| |_| | _ <| |___ + |_| \___/|_| \_|\____/_/ \_\_| |_|_____| \____\___/|_| \_\_____| + "; + + public const string FunGameServerTitle = @" _____ _ _ _ _ ____ _ __ __ _____ ____ _____ ______ _______ ____ + | ___| | | | \ | |/ ___| / \ | \/ | ____| / ___|| ____| _ \ \ / / ____| _ \ + | |_ | | | | \| | | _ / _ \ | |\/| | _| \___ \| _| | |_) \ \ / /| _| | |_) | + | _| | |_| | |\ | |_| |/ ___ \| | | | |___ ___) | |___| _ < \ V / | |___| _ < + |_| \___/|_| \_|\____/_/ \_\_| |_|_____| |____/|_____|_| \_\ \_/ |_____|_| \_\ + "; public static string GetInfo(FunGame FunGameType) { string type = FunGameType switch diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs index 7cd1291..67f9941 100644 --- a/Library/Constant/TypeEnum.cs +++ b/Library/Constant/TypeEnum.cs @@ -753,7 +753,8 @@ namespace Milimoe.FunGame.Core.Library.Constant Blue, Purple, Orange, - Red + Red, + Gold } public enum RarityType diff --git a/Model/ActionQueue.cs b/Model/ActionQueue.cs index 261b306..afb70cc 100644 --- a/Model/ActionQueue.cs +++ b/Model/ActionQueue.cs @@ -19,7 +19,7 @@ namespace Milimoe.FunGame.Core.Model /// 原始的角色字典 /// public Dictionary Original => _original; - + /// /// 当前的行动顺序 /// @@ -60,13 +60,13 @@ namespace Milimoe.FunGame.Core.Model /// 第一滴血获得者 /// public Character? FirstKiller { get; set; } = null; - + /// /// 最大复活次数 /// 0:不复活 / -1:无限复活 /// public int MaxRespawnTimes { get; set; } = 0; - + /// /// 复活次数统计 /// @@ -87,7 +87,7 @@ namespace Milimoe.FunGame.Core.Model /// 上回合记录 /// public RoundRecord LastRound { get; set; } = new(0); - + /// /// 所有回合的记录 /// @@ -97,7 +97,7 @@ namespace Milimoe.FunGame.Core.Model /// 原始的角色字典 /// protected readonly Dictionary _original = []; - + /// /// 当前的行动顺序 /// @@ -137,7 +137,7 @@ namespace Milimoe.FunGame.Core.Model /// 角色最高连杀数 /// protected readonly Dictionary _maxContinuousKilling = []; - + /// /// 角色目前的连杀数 /// @@ -167,7 +167,7 @@ namespace Milimoe.FunGame.Core.Model /// 复活次数统计 /// protected readonly Dictionary _respawnTimes = []; - + /// /// 复活倒计时 /// diff --git a/Model/EquilibriumConstant.cs b/Model/EquilibriumConstant.cs index 4c36a82..7f8cef7 100644 --- a/Model/EquilibriumConstant.cs +++ b/Model/EquilibriumConstant.cs @@ -224,12 +224,12 @@ /// 每 1 点智力增加魔法回复力 /// public double INTtoMRFactor { get; set; } = 0.1; - + /// /// 每 1 点智力减少魔法消耗 /// public double INTtoCastMPReduce { get; set; } = 0.00125; - + /// /// 每 1 点智力减少能量消耗 /// diff --git a/Model/SmtpClientInfo.cs b/Model/SmtpClientInfo.cs index e10de85..6c69ac7 100644 --- a/Model/SmtpClientInfo.cs +++ b/Model/SmtpClientInfo.cs @@ -4,28 +4,21 @@ namespace Milimoe.FunGame.Core.Model { public class SmtpClientInfo : IMailSender { - public string Host => _Host; - public int Port => _Port; - public bool OpenSSL => _OpenSSL; - public string SenderMailAddress => _SenderMailAddress; - public string SenderName => _SenderName; - public string SenderPassword => _SenderPassword; + public string SenderMailAddress { get; set; } = ""; + public string SenderName { get; set; } = ""; + public string SenderPassword { get; set; } = ""; + public string Host { get; set; } = ""; + public int Port { get; set; } = 587; + public bool SSL { get; set; } = false; - private string _Host = ""; - private int _Port = 587; - private bool _OpenSSL = true; - private string _SenderMailAddress = ""; - private string _SenderName = ""; - private string _SenderPassword = ""; - - internal SmtpClientInfo(string SenderMailAddress, string SenderName, string SenderPassword, string Host, int Port, bool OpenSSL) + internal SmtpClientInfo(string senderMailAddress, string senderName, string senderPassword, string host, int port, bool ssl) { - _Host = Host; - _Port = Port; - _OpenSSL = OpenSSL; - _SenderMailAddress = SenderMailAddress; - _SenderName = SenderName; - _SenderPassword = SenderPassword; + SenderMailAddress = senderMailAddress; + SenderName = senderName; + SenderPassword = senderPassword; + Host = host; + Port = port; + SSL = ssl; } } } diff --git a/Service/MailManager.cs b/Service/MailManager.cs index a1824d9..314f868 100644 --- a/Service/MailManager.cs +++ b/Service/MailManager.cs @@ -25,11 +25,11 @@ namespace Milimoe.FunGame.Core.Service /// /// 获取某个已经保存过的邮件服务 /// - /// + /// /// - internal static MailSender? GetSender(Guid MailSenderID) + internal static MailSender? GetSender(Guid mailSenderID) { - if (MailSenders.TryGetValue(MailSenderID, out MailSender? value)) + if (MailSenders.TryGetValue(mailSenderID, out MailSender? value)) { return value; } @@ -39,60 +39,60 @@ namespace Milimoe.FunGame.Core.Service /// /// 统一调用此方法发送邮件 /// - /// - /// - /// + /// + /// + /// /// - internal static MailSendResult Send(MailSender Sender, MailObject Mail, out string ErrorMsg) + internal static MailSendResult Send(MailSender sender, MailObject mail, out string errorMsg) { - ErrorMsg = ""; + errorMsg = ""; try { - SmtpClientInfo Info = Sender.SmtpClientInfo; - SmtpClient Smtp; - Guid MailSenderID = Sender.MailSenderID; - if (!SmtpClients.TryGetValue(MailSenderID, out SmtpClient? value)) + SmtpClientInfo info = sender.SmtpClientInfo; + SmtpClient smtp; + Guid senderID = sender.MailSenderID; + if (!SmtpClients.TryGetValue(senderID, out SmtpClient? value)) { - Smtp = new() + smtp = new() { - Host = Info.Host, - Port = Info.Port, - EnableSsl = Info.OpenSSL, + Host = info.Host, + Port = info.Port, + EnableSsl = info.SSL, DeliveryMethod = SmtpDeliveryMethod.Network, - Credentials = new NetworkCredential(Info.SenderMailAddress, Info.SenderPassword) + Credentials = new NetworkCredential(info.SenderMailAddress, info.SenderPassword) }; - SmtpClients.Add(MailSenderID, Smtp); + SmtpClients.Add(senderID, smtp); } - else Smtp = value; + else smtp = value; MailMessage Msg = new() { - Subject = Mail.Subject, + Subject = mail.Subject, SubjectEncoding = General.DefaultEncoding, - Body = Mail.Body, + Body = mail.Body, BodyEncoding = General.DefaultEncoding, - From = new MailAddress(Mail.Sender, Mail.SenderName, General.DefaultEncoding), - IsBodyHtml = Mail.HTML, - Priority = Mail.Priority + From = new MailAddress(mail.Sender, mail.SenderName, General.DefaultEncoding), + IsBodyHtml = mail.HTML, + Priority = mail.Priority }; - foreach (string To in Mail.ToList) + foreach (string To in mail.ToList) { if (To.Trim() != "") Msg.To.Add(To); } - foreach (string CC in Mail.CCList) + foreach (string CC in mail.CCList) { if (CC.Trim() != "") Msg.CC.Add(CC); } - foreach (string BCC in Mail.BCCList) + foreach (string BCC in mail.BCCList) { if (BCC.Trim() != "") Msg.Bcc.Add(BCC); } - Smtp.SendMailAsync(Msg); + smtp.SendMailAsync(Msg); return MailSendResult.Success; } catch (Exception e) { - ErrorMsg = e.GetErrorInfo(); - Api.Utility.TXTHelper.AppendErrorLog(ErrorMsg); + errorMsg = e.GetErrorInfo(); + Api.Utility.TXTHelper.AppendErrorLog(errorMsg); return MailSendResult.Fail; } } @@ -100,18 +100,18 @@ namespace Milimoe.FunGame.Core.Service /// /// 关闭邮件服务 /// - /// + /// /// - internal static bool Dispose(MailSender Sender) + internal static bool Dispose(MailSender sender) { try { - Guid MailSenderID = Sender.MailSenderID; - if (SmtpClients.TryGetValue(MailSenderID, out SmtpClient? value)) + Guid senderID = sender.MailSenderID; + if (SmtpClients.TryGetValue(senderID, out SmtpClient? value)) { value.Dispose(); - SmtpClients.Remove(MailSenderID); - MailSenders.Remove(MailSenderID); + SmtpClients.Remove(senderID); + MailSenders.Remove(senderID); return true; } return false;