diff --git a/src/NosCore.Core/NosCore.Core.csproj b/src/NosCore.Core/NosCore.Core.csproj
index 13c37b249..2d92dc0cb 100644
--- a/src/NosCore.Core/NosCore.Core.csproj
+++ b/src/NosCore.Core/NosCore.Core.csproj
@@ -37,7 +37,7 @@
-
+
diff --git a/src/NosCore.Data/CommandPackets/CommandPacketHeaderAttribute.cs b/src/NosCore.Data/CommandPackets/CommandPacketHeaderAttribute.cs
index f8b684511..04a6257e5 100644
--- a/src/NosCore.Data/CommandPackets/CommandPacketHeaderAttribute.cs
+++ b/src/NosCore.Data/CommandPackets/CommandPacketHeaderAttribute.cs
@@ -23,7 +23,7 @@
namespace NosCore.Data.CommandPackets
{
- public class CommandPacketHeaderAttribute(string identification, AuthorityType authority) : PacketHeaderAttribute(identification, Scope.InGame | Scope.InGame)
+ public class CommandPacketHeaderAttribute(string identification, AuthorityType authority) : PacketHeaderAttribute(identification, Scope.InGame)
{
public AuthorityType Authority { get; } = authority;
}
diff --git a/src/NosCore.Data/SkillPacket.cs b/src/NosCore.Data/SkillPacket.cs
index dab970316..577b2684a 100644
--- a/src/NosCore.Data/SkillPacket.cs
+++ b/src/NosCore.Data/SkillPacket.cs
@@ -1,10 +1,6 @@
using NosCore.Packets.Attributes;
using NosCore.Packets;
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using NosCore.Packets.Enumerations;
//todo move to NosCore.Packets
diff --git a/src/NosCore.Data/WebApi/WarehouseLink.cs b/src/NosCore.Data/WebApi/WarehouseLink.cs
index f0a0742b8..3d423c0e1 100644
--- a/src/NosCore.Data/WebApi/WarehouseLink.cs
+++ b/src/NosCore.Data/WebApi/WarehouseLink.cs
@@ -25,6 +25,8 @@ public class WarehouseLink
{
public WarehouseDto? Warehouse { get; set; }
+ public short Slot { get; set; }
+
//todo move this to a generic ItemInstance with a converter
public ItemInstanceDto? ItemInstance { get; set; }
}
diff --git a/src/NosCore.GameObject/Character.cs b/src/NosCore.GameObject/ComponentEntities/Entities/Character.cs
similarity index 86%
rename from src/NosCore.GameObject/Character.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/Character.cs
index 2f11880eb..83cc89bc6 100644
--- a/src/NosCore.GameObject/Character.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/Character.cs
@@ -33,10 +33,11 @@
using NosCore.Data.StaticEntities;
using NosCore.GameObject.ComponentEntities.Extensions;
using NosCore.GameObject.ComponentEntities.Interfaces;
-using NosCore.GameObject.Networking;
using NosCore.GameObject.Networking.ClientSession;
using NosCore.GameObject.Services.ExchangeService;
+using NosCore.GameObject.Services.GroupService;
using NosCore.GameObject.Services.InventoryService;
+using NosCore.GameObject.Services.ShopService;
using NosCore.GameObject.Services.ItemGenerationService;
using NosCore.GameObject.Services.MapInstanceGenerationService;
using NosCore.GameObject.Services.NRunService;
@@ -61,7 +62,6 @@
using NosCore.GameObject.Services.BattleService;
using NosCore.GameObject.Services.BroadcastService;
using NosCore.GameObject.Services.MapChangeService;
-using NosCore.GameObject.Services.SkillService;
using NosCore.GameObject.Services.SpeedCalculationService;
using NosCore.Core.I18N;
using NosCore.Networking;
@@ -69,7 +69,7 @@
using NosCore.Networking.SessionGroup.ChannelMatcher;
using MailData = NosCore.GameObject.InterChannelCommunication.Messages.MailData;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class Character(IInventoryService inventory, IExchangeService exchangeService,
IItemGenerationService itemProvider,
@@ -243,19 +243,19 @@ public async Task SetHeroLevelAsync(byte level)
{
HeroLevel = level;
HeroXp = 0;
- await GenerateLevelupPacketsAsync().ConfigureAwait(false);
+ await GenerateLevelupPacketsAsync();
await SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.HeroLevelIncreased
- }).ConfigureAwait(false);
+ });
}
public async Task SetJobLevelAsync(byte jobLevel)
{
JobLevel = (byte)((Class == CharacterClassType.Adventurer) && (jobLevel > 20) ? 20 : jobLevel);
JobLevelXp = 0;
- await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService)).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService));
var mapSessions = sessionRegistry.GetCharacters(s => s.MapInstance == MapInstance);
await Task.WhenAll(mapSessions.Select(s =>
{
@@ -265,12 +265,12 @@ await Task.WhenAll(mapSessions.Select(s =>
//}
return s.SendPacketAsync(this.GenerateEff(8));
- })).ConfigureAwait(false);
+ }));
await SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.JobLevelIncreased
- }).ConfigureAwait(false);
+ });
}
public void JoinGroup(Group group)
@@ -294,16 +294,16 @@ public async Task LeaveGroupAsync()
if (Group.Count == 1)
{
- await groupMember.LeaveGroupAsync().ConfigureAwait(false);
- await groupMember.SendPacketAsync(Group.GeneratePidx(groupMember)).ConfigureAwait(false);
+ await groupMember.LeaveGroupAsync();
+ await groupMember.SendPacketAsync(Group.GeneratePidx(groupMember));
await groupMember.SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.PartyDisbanded
- }).ConfigureAwait(false);
+ });
}
- await groupMember.SendPacketAsync(groupMember.Group!.GeneratePinit()).ConfigureAwait(false);
+ await groupMember.SendPacketAsync(groupMember.Group!.GeneratePinit());
}
Group = new Group(GroupType.Group, sessionGroupFactory);
@@ -321,14 +321,14 @@ await SendPacketAsync(new SayiPacket
VisualId = CharacterId,
Type = SayColorType.Yellow,
Message = Game18NConstString.RemoveEquipment
- }).ConfigureAwait(false);
+ });
return;
}
JobLevel = 1;
JobLevelXp = 0;
- await SendPacketAsync(new NpInfoPacket()).ConfigureAwait(false);
- await SendPacketAsync(new PclearPacket()).ConfigureAwait(false);
+ await SendPacketAsync(new NpInfoPacket());
+ await SendPacketAsync(new PclearPacket());
if (classType == CharacterClassType.Adventurer)
{
@@ -360,22 +360,22 @@ await SendPacketAsync(new SayiPacket
.Where(inv => inv != null))
{
await SendPacketsAsync(
- inv!.Select(invItem => invItem.GeneratePocketChange((PocketType)invItem.Type, invItem.Slot))).ConfigureAwait(false);
+ inv!.Select(invItem => invItem.GeneratePocketChange((PocketType)invItem.Type, invItem.Slot)));
}
- await SendPacketAsync(this.GenerateTit()).ConfigureAwait(false);
- await SendPacketAsync(GenerateStat()).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GenerateEq()).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GenerateEff(8)).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateTit());
+ await SendPacketAsync(GenerateStat());
+ await MapInstance.SendPacketAsync(this.GenerateEq());
+ await MapInstance.SendPacketAsync(this.GenerateEff(8));
//TODO: Faction
- await SendPacketAsync(this.GenerateCond()).ConfigureAwait(false);
- await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService)).ConfigureAwait(false);
- await SendPacketAsync(this.GenerateCMode()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateCond());
+ await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService));
+ await SendPacketAsync(this.GenerateCMode());
await SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.ClassChanged
- }).ConfigureAwait(false);
+ });
QuicklistEntries = new List
{
@@ -391,10 +391,10 @@ await SendPacketAsync(new MsgiPacket
}
};
- await MapInstance.SendPacketAsync(this.GenerateIn(Prefix ?? ""), new EveryoneBut(Channel!.Id)).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(Group!.GeneratePidx(this)).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GenerateEff(6)).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GenerateEff(198)).ConfigureAwait(false);
+ await MapInstance.SendPacketAsync(this.GenerateIn(Prefix ?? ""), new EveryoneBut(Channel!.Id));
+ await MapInstance.SendPacketAsync(Group!.GeneratePidx(this));
+ await MapInstance.SendPacketAsync(this.GenerateEff(6));
+ await MapInstance.SendPacketAsync(this.GenerateEff(198));
}
public Task AddGoldAsync(long gold)
@@ -422,19 +422,19 @@ public void RemoveBankGold(long bankGold)
public async Task SetGoldAsync(long gold)
{
Gold = gold;
- await SendPacketAsync(this.GenerateGold()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateGold());
await SendPacketAsync(this.GenerateSay(
GetMessageFromKey(LanguageKey.UPDATE_GOLD),
- SayColorType.Red)).ConfigureAwait(false);
+ SayColorType.Red));
}
public async Task SetReputationAsync(long reput)
{
Reput = reput;
- await SendPacketAsync(this.GenerateFd()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateFd());
await SendPacketAsync(this.GenerateSay(
GetMessageFromKey(LanguageKey.REPUTATION_CHANGED),
- SayColorType.Red)).ConfigureAwait(false);
+ SayColorType.Red));
}
//todo move this
@@ -446,22 +446,22 @@ public async Task GenerateMailAsync(IEnumerable mails)
{
if (mail.ItemInstance != null)
{
- await SendPacketAsync(mail.GeneratePost(0)).ConfigureAwait(false);
+ await SendPacketAsync(mail.GeneratePost(0));
}
else
{
- await SendPacketAsync(mail.GeneratePost(1)).ConfigureAwait(false);
+ await SendPacketAsync(mail.GeneratePost(1));
}
}
else
{
if (mail.ItemInstance != null)
{
- await SendPacketAsync(mail.GeneratePost(3)).ConfigureAwait(false);
+ await SendPacketAsync(mail.GeneratePost(3));
}
else
{
- await SendPacketAsync(mail.GeneratePost(2)).ConfigureAwait(false);
+ await SendPacketAsync(mail.GeneratePost(2));
}
}
}
@@ -481,24 +481,41 @@ public async Task CloseShopAsync()
{
Shop = null;
- await MapInstance.SendPacketAsync(this.GenerateShop(AccountLanguage)).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GeneratePFlag()).ConfigureAwait(false);
+ await MapInstance.SendPacketAsync(this.GenerateShop(AccountLanguage));
+ await MapInstance.SendPacketAsync(this.GeneratePFlag());
IsSitting = false;
- await SendPacketAsync(this.GenerateCond()).ConfigureAwait(false);
- await MapInstance.SendPacketAsync(this.GenerateRest()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateCond());
+ await MapInstance.SendPacketAsync(this.GenerateRest());
}
public async Task BuyAsync(Shop shop, short slot, short amount)
{
+ if (amount <= 0)
+ {
+ return;
+ }
+
var item = shop.ShopItems.Values.FirstOrDefault(it => it.Slot == slot);
if (item == null)
{
return;
}
- var price = item.Price ?? item.ItemInstance!.Item.Price * amount;
- var reputprice = item.Price == null ? item.ItemInstance!.Item.ReputPrice * amount : 0;
+ var itemPrice = item.Price ?? item.ItemInstance!.Item.Price;
+ if (itemPrice < 0 || itemPrice > long.MaxValue / amount)
+ {
+ return;
+ }
+ var price = itemPrice * amount;
+
+ var itemReputPrice = item.Price == null ? item.ItemInstance!.Item.ReputPrice : 0;
+ if (itemReputPrice < 0 || itemReputPrice > long.MaxValue / amount)
+ {
+ return;
+ }
+ var reputprice = itemReputPrice * amount;
+
var percent = DignityIcon switch
{
DignityType.Dreadful => 1.1,
@@ -519,7 +536,7 @@ await SendPacketAsync(new SMemoiPacket
{
Type = SMemoType.FailNpc,
Message = Game18NConstString.NotEnoughGold5
- }).ConfigureAwait(false);
+ });
return;
}
@@ -529,7 +546,7 @@ await SendPacketAsync(new SMemoiPacket
{
Type = SMemoType.FailNpc,
Message = Game18NConstString.ReputationNotHighEnough
- }).ConfigureAwait(false);
+ });
return;
}
@@ -548,7 +565,7 @@ await SendPacketAsync(new SMemoPacket
{
Type = SMemoType.FailPlayer,
Message = GetMessageFromKey(LanguageKey.TOO_RICH_SELLER)
- }).ConfigureAwait(false);
+ });
return;
}
@@ -567,28 +584,28 @@ await SendPacketAsync(new SMemoPacket
if (inv?.Count > 0)
{
inv.ForEach(it => it.CharacterId = CharacterId);
- var packet = await (shop.OwnerCharacter == null ? Task.FromResult((NInvPacket?)null) : shop.OwnerCharacter.BuyFromAsync(item, amount, slotChar)).ConfigureAwait(false);
+ var packet = await (shop.OwnerCharacter == null ? Task.FromResult((NInvPacket?)null) : shop.OwnerCharacter.BuyFromAsync(item, amount, slotChar));
if (packet != null)
{
- await SendPacketAsync(packet).ConfigureAwait(false);
+ await SendPacketAsync(packet);
}
- await SendPacketsAsync(inv.Select(invItem => invItem.GeneratePocketChange((PocketType)invItem.Type, invItem.Slot))).ConfigureAwait(false);
+ await SendPacketsAsync(inv.Select(invItem => invItem.GeneratePocketChange((PocketType)invItem.Type, invItem.Slot)));
await SendPacketAsync(new SMemoiPacket
{
Type = SMemoType.SuccessNpc,
Message = Game18NConstString.TradeSuccessfull
- }).ConfigureAwait(false);
+ });
if (reputprice == 0)
{
Gold -= (long)(price * percent);
- await SendPacketAsync(this.GenerateGold()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateGold());
}
else
{
Reput -= reputprice;
- await SendPacketAsync(this.GenerateFd()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateFd());
await SendPacketAsync(new SayiPacket
{
VisualType = VisualType.Player,
@@ -597,7 +614,7 @@ await SendPacketAsync(new SayiPacket
Message = Game18NConstString.ReputationReduced,
ArgumentType = 4,
Game18NArguments = { reputprice }
- }).ConfigureAwait(false);
+ });
}
}
else
@@ -606,7 +623,7 @@ await SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.NotEnoughSpace
- }).ConfigureAwait(false);
+ });
}
}
@@ -623,10 +640,10 @@ await SendPacketAsync(new MsgiPacket
Shop!.ShopItems.TryRemove(slot, out _);
}
- await SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)type, slotChar)).ConfigureAwait(false);
+ await SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)type, slotChar));
var sellAmount = (item?.Price ?? 0) * amount;
Gold += sellAmount;
- await SendPacketAsync(this.GenerateGold()).ConfigureAwait(false);
+ await SendPacketAsync(this.GenerateGold());
Shop!.Sell += sellAmount;
await SendPacketAsync(new SellListPacket
@@ -641,23 +658,23 @@ await SendPacketAsync(new SellListPacket
SellAmount = item?.Amount ?? 0
}
}
- }).ConfigureAwait(false);
+ });
if (!Shop.ShopItems.IsEmpty)
{
return this.GenerateNInv(1, 0);
}
- await CloseShopAsync().ConfigureAwait(false);
+ await CloseShopAsync();
return null;
}
private async Task GenerateLevelupPacketsAsync()
{
- await SendPacketAsync(GenerateStat()).ConfigureAwait(false);
- await SendPacketAsync(this.GenerateStatInfo()).ConfigureAwait(false);
- await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService)).ConfigureAwait(false);
+ await SendPacketAsync(GenerateStat());
+ await SendPacketAsync(this.GenerateStatInfo());
+ await SendPacketAsync(this.GenerateLev(experienceService, jobExperienceService, heroExperienceService));
var mapSessions = sessionRegistry.GetCharacters(s => s.MapInstance == MapInstance);
await Task.WhenAll(mapSessions.Select(async s =>
@@ -665,13 +682,13 @@ await Task.WhenAll(mapSessions.Select(async s =>
if (s.VisualId != VisualId)
{
await s.SendPacketAsync(this.GenerateIn(Authority == AuthorityType.Moderator
- ? GetMessageFromKey(LanguageKey.SUPPORT) : string.Empty)).ConfigureAwait(false);
+ ? GetMessageFromKey(LanguageKey.SUPPORT) : string.Empty));
//TODO: Generate GIDX
}
- await s.SendPacketAsync(this.GenerateEff(6)).ConfigureAwait(false);
- await s.SendPacketAsync(this.GenerateEff(198)).ConfigureAwait(false);
- })).ConfigureAwait(false);
+ await s.SendPacketAsync(this.GenerateEff(6));
+ await s.SendPacketAsync(this.GenerateEff(198));
+ }));
foreach (var member in Group!.Keys)
{
@@ -681,18 +698,18 @@ await s.SendPacketAsync(this.GenerateIn(Authority == AuthorityType.Moderator
groupMember?.SendPacketAsync(groupMember.Group!.GeneratePinit());
}
- await SendPacketAsync(Group.GeneratePinit()).ConfigureAwait(false);
+ await SendPacketAsync(Group.GeneratePinit());
}
public async Task SetLevelAsync(byte level)
{
this.SetLevel(level);
- await GenerateLevelupPacketsAsync().ConfigureAwait(false);
+ await GenerateLevelupPacketsAsync();
await SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.LevelIncreased
- }).ConfigureAwait(false);
+ });
}
diff --git a/src/NosCore.GameObject/Services/MapInstanceGenerationService/MapDesignObject.cs b/src/NosCore.GameObject/ComponentEntities/Entities/MapDesignObject.cs
similarity index 97%
rename from src/NosCore.GameObject/Services/MapInstanceGenerationService/MapDesignObject.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/MapDesignObject.cs
index 1b589c2ce..22055a6b6 100644
--- a/src/NosCore.GameObject/Services/MapInstanceGenerationService/MapDesignObject.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/MapDesignObject.cs
@@ -22,7 +22,7 @@
using NosCore.Packets.ServerPackets.Map;
using NosCore.Packets.ServerPackets.Miniland;
-namespace NosCore.GameObject.Services.MapInstanceGenerationService
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class MapDesignObject : MinilandObjectDto
{
diff --git a/src/NosCore.GameObject/Services/MapItemGenerationService/MapItem.cs b/src/NosCore.GameObject/ComponentEntities/Entities/MapItem.cs
similarity index 95%
rename from src/NosCore.GameObject/Services/MapItemGenerationService/MapItem.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/MapItem.cs
index b041d0ff4..d7756d3e4 100644
--- a/src/NosCore.GameObject/Services/MapItemGenerationService/MapItem.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/MapItem.cs
@@ -29,8 +29,9 @@
using System.Reactive.Subjects;
using System.Threading.Tasks;
using NodaTime;
+using NosCore.GameObject.Services.MapItemGenerationService;
-namespace NosCore.GameObject.Services.MapItemGenerationService
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class MapItem(long visualId) : ICountableEntity, IRequestableEntity>
{
diff --git a/src/NosCore.GameObject/MapMonster.cs b/src/NosCore.GameObject/ComponentEntities/Entities/MapMonster.cs
similarity index 94%
rename from src/NosCore.GameObject/MapMonster.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/MapMonster.cs
index 676eb1fe6..81dc4eb5d 100644
--- a/src/NosCore.GameObject/MapMonster.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/MapMonster.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -22,6 +22,7 @@
using NosCore.GameObject.ComponentEntities.Extensions;
using NosCore.GameObject.ComponentEntities.Interfaces;
using NosCore.GameObject.Services.MapInstanceGenerationService;
+using NosCore.GameObject.Services.ShopService;
using NosCore.PathFinder.Interfaces;
using NosCore.Shared.Enumerations;
using Serilog;
@@ -33,7 +34,7 @@
using System.Threading;
using System.Collections.Concurrent;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class MapMonster(ILogger logger, IHeuristic distanceCalculator, IClock clock,
ISpeedCalculationService speedCalculationService)
@@ -99,20 +100,21 @@ internal void StopLife()
public Task StartLifeAsync()
{
+ Life?.Dispose();
+
async Task LifeAsync()
{
try
{
if (!MapInstance.IsSleeping)
{
- await MonsterLifeAsync().ConfigureAwait(false);
+ await MonsterLifeAsync();
}
}
catch (Exception e)
{
logger.Error(e.Message, e);
}
-
}
Life = Observable.Interval(TimeSpan.FromMilliseconds(400)).Select(_ => LifeAsync()).Subscribe();
return Task.CompletedTask;
diff --git a/src/NosCore.GameObject/MapNpc.cs b/src/NosCore.GameObject/ComponentEntities/Entities/MapNpc.cs
similarity index 96%
rename from src/NosCore.GameObject/MapNpc.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/MapNpc.cs
index 80760999d..fe294fc6f 100644
--- a/src/NosCore.GameObject/MapNpc.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/MapNpc.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -26,6 +26,7 @@
using NosCore.GameObject.Services.ItemGenerationService;
using NosCore.GameObject.Services.MapInstanceGenerationService;
using NosCore.GameObject.Services.NRunService;
+using NosCore.GameObject.Services.ShopService;
using NosCore.PathFinder.Interfaces;
using NosCore.Shared.Enumerations;
using Serilog;
@@ -38,7 +39,7 @@
using NodaTime;
using System.Threading;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class MapNpc(IItemGenerationService? itemProvider, ILogger logger, IHeuristic distanceCalculator,
IClock clock)
@@ -133,13 +134,15 @@ internal void StopLife()
public Task StartLifeAsync()
{
+ Life?.Dispose();
+
async Task LifeAsync()
{
try
{
if (!MapInstance.IsSleeping)
{
- await MonsterLifeAsync().ConfigureAwait(false);
+ await MonsterLifeAsync();
}
}
catch (Exception e)
diff --git a/src/NosCore.GameObject/Pet.cs b/src/NosCore.GameObject/ComponentEntities/Entities/Pet.cs
similarity index 95%
rename from src/NosCore.GameObject/Pet.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/Pet.cs
index 8f952b481..a683671fe 100644
--- a/src/NosCore.GameObject/Pet.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/Pet.cs
@@ -20,14 +20,16 @@
using NosCore.Data.Dto;
using NosCore.Data.StaticEntities;
using NosCore.GameObject.ComponentEntities.Interfaces;
+using NosCore.GameObject.Services.GroupService;
using NosCore.GameObject.Services.MapInstanceGenerationService;
+using NosCore.GameObject.Services.ShopService;
using NosCore.Shared.Enumerations;
using System;
using System.Collections.Concurrent;
using NodaTime;
using System.Threading;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class Pet : MapMonsterDto, INamedEntity //TODO replace MapMonsterDTO by the correct PetDTO
{
diff --git a/src/NosCore.GameObject/Portal.cs b/src/NosCore.GameObject/ComponentEntities/Entities/Portal.cs
similarity index 96%
rename from src/NosCore.GameObject/Portal.cs
rename to src/NosCore.GameObject/ComponentEntities/Entities/Portal.cs
index da397dfdd..2961c253d 100644
--- a/src/NosCore.GameObject/Portal.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Entities/Portal.cs
@@ -21,7 +21,7 @@
using NosCore.Packets.ServerPackets.Portals;
using System;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.ComponentEntities.Entities
{
public class Portal : PortalDto
{
diff --git a/src/NosCore.GameObject/ComponentEntities/Extensions/AliveEntityExtension.cs b/src/NosCore.GameObject/ComponentEntities/Extensions/AliveEntityExtension.cs
index 4c1976bb4..acf1f8927 100644
--- a/src/NosCore.GameObject/ComponentEntities/Extensions/AliveEntityExtension.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Extensions/AliveEntityExtension.cs
@@ -41,15 +41,6 @@
using System.Threading.Tasks;
using NodaTime;
using NosCore.Networking;
-using NosCore.GameObject.Networking.ClientSession;
-using NosCore.Packets.ClientPackets.Battle;
-using NosCore.Packets.ServerPackets.Battle;
-using Microsoft.AspNetCore.Http;
-using NosCore.Data.Enumerations.Battle;
-using NosCore.Data.Enumerations.Map;
-using static NosCore.Data.Enumerations.Buff.AdditionalTypes;
-using System.Collections.Concurrent;
-using System.Threading;
namespace NosCore.GameObject.ComponentEntities.Extensions
diff --git a/src/NosCore.GameObject/ComponentEntities/Extensions/CharacterEntityExtension.cs b/src/NosCore.GameObject/ComponentEntities/Extensions/CharacterEntityExtension.cs
index 211d25703..8528aa072 100644
--- a/src/NosCore.GameObject/ComponentEntities/Extensions/CharacterEntityExtension.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Extensions/CharacterEntityExtension.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -363,7 +363,7 @@ public static async Task GenerateBlinitAsync(this ICharacterEntity
IBlacklistHub blacklistHttpClient)
{
var subpackets = new List();
- var blackList = await blacklistHttpClient.GetBlacklistedAsync(visualEntity.VisualId).ConfigureAwait(false);
+ var blackList = await blacklistHttpClient.GetBlacklistedAsync(visualEntity.VisualId);
foreach (var relation in blackList)
{
if (relation.CharacterId == visualEntity.VisualId)
@@ -385,12 +385,12 @@ public static async Task GenerateFinitAsync(this ICharacterEntity v
IChannelHub channelHttpClient, IPubSubHub pubSubHub)
{
//same canal
- var servers = (await channelHttpClient.GetCommunicationChannels().ConfigureAwait(false))
+ var servers = (await channelHttpClient.GetCommunicationChannels())
?.Where(c => c.Type == ServerType.WorldServer).ToList();
var accounts = await pubSubHub.GetSubscribersAsync();
var subpackets = new List();
- var friendlist = await friendHttpClient.GetFriendsAsync(visualEntity.VisualId).ConfigureAwait(false);
+ var friendlist = await friendHttpClient.GetFriendsAsync(visualEntity.VisualId);
//TODO add spouselist
//var spouseList = _webApiAccess.Get>(WebApiRoute.Spouse, friendServer.WebApi, visualEntity.VisualId) ?? new List();
foreach (var relation in friendlist)
@@ -412,7 +412,7 @@ public static async Task GenerateFinitAsync(this ICharacterEntity v
public static async Task SendFinfoAsync(this ICharacterEntity visualEntity, IFriendHub friendHttpClient,
IPubSubHub pubSubHub, ISerializer packetSerializer, bool isConnected)
{
- var friendlist = await friendHttpClient.GetFriendsAsync(visualEntity.VisualId).ConfigureAwait(false);
+ var friendlist = await friendHttpClient.GetFriendsAsync(visualEntity.VisualId);
await Task.WhenAll(friendlist.Select(friend =>
pubSubHub.SendMessageAsync(new PostedPacket
{
@@ -437,7 +437,7 @@ await Task.WhenAll(friendlist.Select(friend =>
Id = friend.CharacterId,
Name = friend.CharacterName!
}
- }))).ConfigureAwait(false);
+ })));
}
public static ServerGetPacket GenerateGet(this ICharacterEntity visualEntity, long itemId)
diff --git a/src/NosCore.GameObject/ComponentEntities/Extensions/GroupExtension.cs b/src/NosCore.GameObject/ComponentEntities/Extensions/GroupExtension.cs
index 11421ab9b..1ede33863 100644
--- a/src/NosCore.GameObject/ComponentEntities/Extensions/GroupExtension.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Extensions/GroupExtension.cs
@@ -18,6 +18,7 @@
// along with this program. If not, see .
using NosCore.GameObject.ComponentEntities.Interfaces;
+using NosCore.GameObject.Services.GroupService;
using NosCore.Packets.ServerPackets.Shop;
using System.Collections.Generic;
using System.Linq;
diff --git a/src/NosCore.GameObject/ComponentEntities/Extensions/VisualEntityExtension.cs b/src/NosCore.GameObject/ComponentEntities/Extensions/VisualEntityExtension.cs
index 7b15323a1..53af3ef53 100644
--- a/src/NosCore.GameObject/ComponentEntities/Extensions/VisualEntityExtension.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Extensions/VisualEntityExtension.cs
@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.ComponentEntities.Entities;
using NosCore.GameObject.ComponentEntities.Interfaces;
using NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Chats;
diff --git a/src/NosCore.GameObject/ComponentEntities/Interfaces/IAliveEntity.cs b/src/NosCore.GameObject/ComponentEntities/Interfaces/IAliveEntity.cs
index 2a8772493..14bc84374 100644
--- a/src/NosCore.GameObject/ComponentEntities/Interfaces/IAliveEntity.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Interfaces/IAliveEntity.cs
@@ -19,8 +19,7 @@
using System.Collections.Concurrent;
using System.Threading;
-using System.Threading.Tasks;
-using NosCore.GameObject.Services.BattleService;
+using NosCore.GameObject.Services.ShopService;
namespace NosCore.GameObject.ComponentEntities.Interfaces
{
diff --git a/src/NosCore.GameObject/ComponentEntities/Interfaces/ICharacterEntity.cs b/src/NosCore.GameObject/ComponentEntities/Interfaces/ICharacterEntity.cs
index 5f42d7f22..deaaec475 100644
--- a/src/NosCore.GameObject/ComponentEntities/Interfaces/ICharacterEntity.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Interfaces/ICharacterEntity.cs
@@ -30,6 +30,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using NosCore.GameObject.Services.BattleService;
+using NosCore.GameObject.Services.GroupService;
using NosCore.GameObject.Services.MapChangeService;
using NosCore.Networking;
using MailData = NosCore.GameObject.InterChannelCommunication.Messages.MailData;
diff --git a/src/NosCore.GameObject/ComponentEntities/Interfaces/INamedEntity.cs b/src/NosCore.GameObject/ComponentEntities/Interfaces/INamedEntity.cs
index a49b7dfea..251b4f24e 100644
--- a/src/NosCore.GameObject/ComponentEntities/Interfaces/INamedEntity.cs
+++ b/src/NosCore.GameObject/ComponentEntities/Interfaces/INamedEntity.cs
@@ -17,6 +17,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.Services.GroupService;
+
namespace NosCore.GameObject.ComponentEntities.Interfaces
{
public interface INamedEntity : IAliveEntity
diff --git a/src/NosCore.GameObject/IEventHandler.cs b/src/NosCore.GameObject/Infastructure/IEventHandler.cs
similarity index 96%
rename from src/NosCore.GameObject/IEventHandler.cs
rename to src/NosCore.GameObject/Infastructure/IEventHandler.cs
index 91c11518b..5f5245ad0 100644
--- a/src/NosCore.GameObject/IEventHandler.cs
+++ b/src/NosCore.GameObject/Infastructure/IEventHandler.cs
@@ -20,7 +20,7 @@
using NosCore.GameObject.Networking.ClientSession;
using System.Threading.Tasks;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Infastructure
{
public interface IEventHandler : IEventHandler
{
diff --git a/src/NosCore.GameObject/IPacketHandler.cs b/src/NosCore.GameObject/Infastructure/IPacketHandler.cs
similarity index 97%
rename from src/NosCore.GameObject/IPacketHandler.cs
rename to src/NosCore.GameObject/Infastructure/IPacketHandler.cs
index 78ac98474..c356eb908 100644
--- a/src/NosCore.GameObject/IPacketHandler.cs
+++ b/src/NosCore.GameObject/Infastructure/IPacketHandler.cs
@@ -21,7 +21,7 @@
using NosCore.Packets.Interfaces;
using System.Threading.Tasks;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Infastructure
{
public interface IPacketHandler
{
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BaseHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BaseHubClient.cs
new file mode 100644
index 000000000..bfdd2a70e
--- /dev/null
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BaseHubClient.cs
@@ -0,0 +1,132 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.SignalR.Client;
+using Polly;
+using Polly.Retry;
+using Serilog;
+
+namespace NosCore.GameObject.InterChannelCommunication.Hubs;
+
+public abstract class BaseHubClient : IAsyncDisposable
+{
+ private readonly HubConnection _hubConnection;
+ private readonly SemaphoreSlim _connectionLock = new(1, 1);
+ private readonly ILogger _logger;
+ private bool _isStarted;
+
+ private static readonly AsyncRetryPolicy RetryPolicy = Policy
+ .Handle()
+ .WaitAndRetryAsync(
+ 3,
+ attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
+ (exception, timeSpan, retryCount, _) =>
+ {
+ Log.Warning(exception, "Hub call failed. Retry {RetryCount} in {TimeSpan}", retryCount, timeSpan);
+ });
+
+ protected BaseHubClient(HubConnectionFactory hubConnectionFactory, string hubName, ILogger logger)
+ {
+ _logger = logger;
+ _hubConnection = hubConnectionFactory.Create(hubName);
+
+ _hubConnection.Reconnecting += error =>
+ {
+ _logger.Warning("Hub {HubName} reconnecting...", hubName);
+ return Task.CompletedTask;
+ };
+
+ _hubConnection.Reconnected += connectionId =>
+ {
+ _logger.Information("Hub {HubName} reconnected", hubName);
+ return Task.CompletedTask;
+ };
+
+ _hubConnection.Closed += error =>
+ {
+ _isStarted = false;
+ _logger.Warning("Hub {HubName} connection closed", hubName);
+ return Task.CompletedTask;
+ };
+ }
+
+ protected async Task EnsureConnectedAsync()
+ {
+ if (_hubConnection.State == HubConnectionState.Connected)
+ {
+ return;
+ }
+
+ await _connectionLock.WaitAsync();
+ try
+ {
+ if (!_isStarted || _hubConnection.State == HubConnectionState.Disconnected)
+ {
+ await _hubConnection.StartAsync();
+ _isStarted = true;
+ }
+ }
+ finally
+ {
+ _connectionLock.Release();
+ }
+ }
+
+ protected async Task InvokeAsync(string methodName, params object?[] args)
+ {
+ return await RetryPolicy.ExecuteAsync(async () =>
+ {
+ await EnsureConnectedAsync();
+ return await _hubConnection.InvokeCoreAsync(methodName, args);
+ });
+ }
+
+ protected async Task InvokeAsync(string methodName, params object?[] args)
+ {
+ await RetryPolicy.ExecuteAsync(async () =>
+ {
+ await EnsureConnectedAsync();
+ await _hubConnection.InvokeCoreAsync(methodName, args);
+ });
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ await _connectionLock.WaitAsync();
+ try
+ {
+ if (_hubConnection.State != HubConnectionState.Disconnected)
+ {
+ await _hubConnection.StopAsync();
+ _isStarted = false;
+ }
+ }
+ finally
+ {
+ _connectionLock.Release();
+ }
+
+ await _hubConnection.DisposeAsync();
+ _connectionLock.Dispose();
+ GC.SuppressFinalize(this);
+ }
+}
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHub.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHub.cs
index d2645de3a..433a432d6 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHub.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHub.cs
@@ -33,7 +33,7 @@ public Task> GetBazaar(long id, byte? index, byte? pageSize, Ba
byte? subTypeFilter, byte? levelFilter, byte? rareFilter, byte? upgradeFilter, long? sellerFilter) => Task.FromResult(bazaarService.GetBazaar(id, index, pageSize, typeFilter,
subTypeFilter, levelFilter, rareFilter, upgradeFilter, sellerFilter));
- public Task DeleteBazaarAsync(long id, short count, string requestCharacterName) => bazaarService.DeleteBazaarAsync(id, count, requestCharacterName);
+ public Task DeleteBazaarAsync(long id, short count, string requestCharacterName, long? requestCharacterId = null) => bazaarService.DeleteBazaarAsync(id, count, requestCharacterName, requestCharacterId);
public Task AddBazaarAsync( BazaarRequest bazaarRequest) => bazaarService.AddBazaarAsync(bazaarRequest.ItemInstanceId,
bazaarRequest.CharacterId, bazaarRequest.CharacterName, bazaarRequest.HasMedal, bazaarRequest.Price, bazaarRequest.IsPackage, bazaarRequest.Duration, bazaarRequest.Amount);
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHubClient.cs
index f9cd7d297..1f77693e7 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/BazaarHubClient.cs
@@ -1,67 +1,46 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System.Collections.Generic;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.SignalR.Client;
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.WebApi;
using NosCore.Packets.Enumerations;
+using Serilog;
namespace NosCore.GameObject.InterChannelCommunication.Hubs.BazaarHub
{
- public class BazaarHubClient(HubConnectionFactory hubConnectionFactory) : IBazaarHub
+ public class BazaarHubClient(HubConnectionFactory hubConnectionFactory, ILogger logger)
+ : BaseHubClient(hubConnectionFactory, nameof(BazaarHub), logger), IBazaarHub
{
- private readonly HubConnection _hubConnection = hubConnectionFactory.Create(nameof(BazaarHub));
-
- public async Task> GetBazaar(long id, byte? index, byte? pageSize, BazaarListType? typeFilter,
- byte? subTypeFilter, byte? levelFilter, byte? rareFilter, byte? upgradeFilter, long? sellerFilter)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync>(nameof(GetBazaar), id, index, pageSize, typeFilter,
+ public Task> GetBazaar(long id, byte? index, byte? pageSize, BazaarListType? typeFilter,
+ byte? subTypeFilter, byte? levelFilter, byte? rareFilter, byte? upgradeFilter, long? sellerFilter) =>
+ InvokeAsync>(nameof(GetBazaar), id, index, pageSize, typeFilter,
subTypeFilter, levelFilter, rareFilter, upgradeFilter, sellerFilter);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task DeleteBazaarAsync(long id, short count, string requestCharacterName)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(DeleteBazaarAsync), id, count, requestCharacterName);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task DeleteBazaarAsync(long id, short count, string requestCharacterName, long? requestCharacterId = null) =>
+ InvokeAsync(nameof(DeleteBazaarAsync), id, count, requestCharacterName, requestCharacterId);
- public async Task AddBazaarAsync(BazaarRequest bazaarRequest)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(AddBazaarAsync), bazaarRequest);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task AddBazaarAsync(BazaarRequest bazaarRequest) =>
+ InvokeAsync(nameof(AddBazaarAsync), bazaarRequest);
- public async Task ModifyBazaarAsync(long id, Json.Patch.JsonPatch bzMod)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(ModifyBazaarAsync), id, bzMod);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task ModifyBazaarAsync(long id, Json.Patch.JsonPatch bzMod) =>
+ InvokeAsync(nameof(ModifyBazaarAsync), id, bzMod);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/IBazaarHub.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/IBazaarHub.cs
index c3054f374..d7ba5987d 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/IBazaarHub.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BazaarHub/IBazaarHub.cs
@@ -29,7 +29,7 @@ public interface IBazaarHub
{
Task> GetBazaar(long id, byte? index, byte? pageSize, BazaarListType? typeFilter,
byte? subTypeFilter, byte? levelFilter, byte? rareFilter, byte? upgradeFilter, long? sellerFilter);
- Task DeleteBazaarAsync(long id, short count, string requestCharacterName);
+ Task DeleteBazaarAsync(long id, short count, string requestCharacterName, long? requestCharacterId = null);
Task AddBazaarAsync(BazaarRequest bazaarRequest);
Task ModifyBazaarAsync(long id, Json.Patch.JsonPatch bzMod);
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BlacklistHub/BlacklistHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BlacklistHub/BlacklistHubClient.cs
index e06751e7a..d30c78134 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/BlacklistHub/BlacklistHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/BlacklistHub/BlacklistHubClient.cs
@@ -1,55 +1,41 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.SignalR.Client;
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.WebApi;
+using Serilog;
namespace NosCore.GameObject.InterChannelCommunication.Hubs.BlacklistHub
{
- public class BlacklistHubClient(HubConnectionFactory hubConnectionFactory) : IBlacklistHub
+ public class BlacklistHubClient(HubConnectionFactory hubConnectionFactory, ILogger logger)
+ : BaseHubClient(hubConnectionFactory, nameof(BlacklistHub), logger), IBlacklistHub
{
- private readonly HubConnection _hubConnection = hubConnectionFactory.Create(nameof(BlacklistHub));
+ public Task AddBlacklistAsync(BlacklistRequest blacklistRequest) =>
+ InvokeAsync(nameof(AddBlacklistAsync), blacklistRequest);
- public async Task AddBlacklistAsync(BlacklistRequest blacklistRequest)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(AddBlacklistAsync), blacklistRequest);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task> GetBlacklistedAsync(long id)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync>(nameof(GetBlacklistedAsync), id);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task DeleteAsync(Guid id)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(DeleteAsync), id);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task> GetBlacklistedAsync(long id) =>
+ InvokeAsync>(nameof(GetBlacklistedAsync), id);
+
+ public Task DeleteAsync(Guid id) =>
+ InvokeAsync(nameof(DeleteAsync), id);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/ChannelHub/ChannelHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/ChannelHub/ChannelHubClient.cs
index c63a50da8..077bdfbd6 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/ChannelHub/ChannelHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/ChannelHub/ChannelHubClient.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
@@ -26,7 +26,7 @@ await Policy
(_, __, timeSpan) =>
logger.Verbose(
logLanguage[LogLanguageKey.MASTER_SERVER_PING])
- ).ExecuteAsync(Ping).ConfigureAwait(false);
+ ).ExecuteAsync(Ping);
logger.Error(
logLanguage[LogLanguageKey.MASTER_SERVER_PING_FAILED]);
Environment.Exit(0);
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/FriendHub/FriendHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/FriendHub/FriendHubClient.cs
index 8b8533a4e..bb45e2f15 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/FriendHub/FriendHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/FriendHub/FriendHubClient.cs
@@ -1,55 +1,41 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.SignalR.Client;
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.WebApi;
+using Serilog;
namespace NosCore.GameObject.InterChannelCommunication.Hubs.FriendHub
{
- public class FriendHubClient(HubConnectionFactory hubConnectionFactory) : IFriendHub
+ public class FriendHubClient(HubConnectionFactory hubConnectionFactory, ILogger logger)
+ : BaseHubClient(hubConnectionFactory, nameof(FriendHub), logger), IFriendHub
{
- private readonly HubConnection _hubConnection = hubConnectionFactory.Create(nameof(FriendHub));
+ public Task AddFriendAsync(FriendShipRequest friendPacket) =>
+ InvokeAsync(nameof(AddFriendAsync), friendPacket);
- public async Task AddFriendAsync(FriendShipRequest friendPacket)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(AddFriendAsync), friendPacket);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task> GetFriendsAsync(long id)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync>(nameof(GetFriendsAsync), id);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task DeleteAsync(Guid id)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(DeleteAsync), id);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task> GetFriendsAsync(long id) =>
+ InvokeAsync>(nameof(GetFriendsAsync), id);
+
+ public Task DeleteAsync(Guid id) =>
+ InvokeAsync(nameof(DeleteAsync), id);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/MailHub/MailHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/MailHub/MailHubClient.cs
index 973e138ff..7adec906d 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/MailHub/MailHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/MailHub/MailHubClient.cs
@@ -1,62 +1,44 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System.Collections.Generic;
using System.Threading.Tasks;
using Json.Patch;
-using Microsoft.AspNetCore.SignalR.Client;
using NosCore.Data.WebApi;
using NosCore.GameObject.InterChannelCommunication.Messages;
+using Serilog;
namespace NosCore.GameObject.InterChannelCommunication.Hubs.MailHub
{
- public class MailHubClient(HubConnectionFactory hubConnectionFactory) : IMailHub
+ public class MailHubClient(HubConnectionFactory hubConnectionFactory, ILogger logger)
+ : BaseHubClient(hubConnectionFactory, nameof(MailHub), logger), IMailHub
{
- private readonly HubConnection _hubConnection = hubConnectionFactory.Create(nameof(MailHub));
+ public Task> GetMails(long id, long characterId, bool senderCopy) =>
+ InvokeAsync>(nameof(GetMails), id, characterId, senderCopy);
- public async Task> GetMails(long id, long characterId, bool senderCopy)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync>(nameof(GetMails), id, characterId, senderCopy);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task DeleteMailAsync(long id, long characterId, bool senderCopy)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(DeleteMailAsync), id, characterId, senderCopy);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task ViewMailAsync(long id, JsonPatch mailData)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(ViewMailAsync), id, mailData);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task SendMailAsync(MailRequest mail)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(SendMailAsync), mail);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task DeleteMailAsync(long id, long characterId, bool senderCopy) =>
+ InvokeAsync(nameof(DeleteMailAsync), id, characterId, senderCopy);
+
+ public Task ViewMailAsync(long id, JsonPatch mailData) =>
+ InvokeAsync(nameof(ViewMailAsync), id, mailData);
+
+ public Task SendMailAsync(MailRequest mail) =>
+ InvokeAsync(nameof(SendMailAsync), mail);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/InterChannelCommunication/Hubs/WarehouseHub/WarehouseHubClient.cs b/src/NosCore.GameObject/InterChannelCommunication/Hubs/WarehouseHub/WarehouseHubClient.cs
index fe9c22fc8..d17494cca 100644
--- a/src/NosCore.GameObject/InterChannelCommunication/Hubs/WarehouseHub/WarehouseHubClient.cs
+++ b/src/NosCore.GameObject/InterChannelCommunication/Hubs/WarehouseHub/WarehouseHubClient.cs
@@ -1,57 +1,41 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.SignalR.Client;
using NosCore.Data.Enumerations.Miniland;
using NosCore.Data.WebApi;
+using Serilog;
namespace NosCore.GameObject.InterChannelCommunication.Hubs.WarehouseHub
{
- public class WarehouseHubClient(HubConnectionFactory hubConnectionFactory) : IWarehouseHub
+ public class WarehouseHubClient(HubConnectionFactory hubConnectionFactory, ILogger logger)
+ : BaseHubClient(hubConnectionFactory, nameof(WarehouseHub), logger), IWarehouseHub
{
- private readonly HubConnection _hubConnection = hubConnectionFactory.Create(nameof(WarehouseHub));
+ public Task> GetWarehouseItems(Guid? id, long? ownerId, WarehouseType warehouseType, byte? slot) =>
+ InvokeAsync>(nameof(GetWarehouseItems), id, ownerId, warehouseType, slot);
+ public Task DeleteWarehouseItemAsync(Guid id) =>
+ InvokeAsync(nameof(DeleteWarehouseItemAsync), id);
- public async Task> GetWarehouseItems(Guid? id, long? ownerId, WarehouseType warehouseType, byte? slot)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync>(nameof(GetWarehouseItems), id, ownerId, warehouseType, slot);
- await _hubConnection.StopAsync();
- return result;
- }
- public async Task DeleteWarehouseItemAsync(Guid id)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(DeleteWarehouseItemAsync), id);
- await _hubConnection.StopAsync();
- return result;
- }
-
- public async Task AddWarehouseItemAsync(WareHouseDepositRequest depositRequest)
- {
- await _hubConnection.StartAsync();
- var result = await _hubConnection.InvokeAsync(nameof(AddWarehouseItemAsync), depositRequest);
- await _hubConnection.StopAsync();
- return result;
- }
+ public Task AddWarehouseItemAsync(WareHouseDepositRequest depositRequest) =>
+ InvokeAsync(nameof(AddWarehouseItemAsync), depositRequest);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/ClientSession.cs b/src/NosCore.GameObject/Networking/ClientSession/ClientSession.cs
index b10acde36..569863a7e 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/ClientSession.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/ClientSession.cs
@@ -35,6 +35,8 @@
using NosCore.Networking;
using NosCore.Networking.Encoding;
using NosCore.Shared.I18N;
+using NosCore.GameObject.Infastructure;
+using NosCore.GameObject.ComponentEntities.Entities;
namespace NosCore.GameObject.Networking.ClientSession
{
@@ -152,7 +154,7 @@ public async Task HandlePacketAsync(NosPackageInfo package)
{
try
{
- await HandlePacketsAsync(package.Packets, true).ConfigureAwait(false);
+ await HandlePacketsAsync(package.Packets, true);
}
catch (Exception ex)
{
@@ -181,7 +183,7 @@ public async Task OnDisconnectedAsync()
foreach (var handler in disconnectHandlers)
{
- await handler.HandleDisconnectAsync(this).ConfigureAwait(false);
+ await handler.HandleDisconnectAsync(this);
}
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/ExchangeDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/ExchangeDisconnectHandler.cs
index f86acda93..720414a20 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/ExchangeDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/ExchangeDisconnectHandler.cs
@@ -18,6 +18,7 @@
// along with this program. If not, see .
using System.Threading.Tasks;
+using NosCore.GameObject.ComponentEntities.Entities;
using NosCore.GameObject.Services.BroadcastService;
using NosCore.GameObject.Services.ExchangeService;
using NosCore.Packets.Enumerations;
@@ -42,7 +43,7 @@ public async Task HandleDisconnectAsync(ClientSession session)
var closeExchange = exchangeService.CloseExchange(session.Character.VisualId, ExchangeResultType.Failure);
if (sessionRegistry.GetCharacter(s => s.VisualId == targetId) is Character target)
{
- await target.SendPacketAsync(closeExchange).ConfigureAwait(false);
+ await target.SendPacketAsync(closeExchange);
}
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/FriendNotificationDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/FriendNotificationDisconnectHandler.cs
index a87b302ee..a31281806 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/FriendNotificationDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/FriendNotificationDisconnectHandler.cs
@@ -34,6 +34,6 @@ public async Task HandleDisconnectAsync(ClientSession session)
return;
}
- await session.Character.SendFinfoAsync(friendHub, pubSubHub, serializer, false).ConfigureAwait(false);
+ await session.Character.SendFinfoAsync(friendHub, pubSubHub, serializer, false);
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/GroupDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/GroupDisconnectHandler.cs
index b3d6b3f1b..0c34ea22b 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/GroupDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/GroupDisconnectHandler.cs
@@ -30,6 +30,6 @@ public async Task HandleDisconnectAsync(ClientSession session)
return;
}
- await session.Character.LeaveGroupAsync().ConfigureAwait(false);
+ await session.Character.LeaveGroupAsync();
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MapDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MapDisconnectHandler.cs
index b2bd39b07..ec5f33819 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MapDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MapDisconnectHandler.cs
@@ -37,6 +37,6 @@ public async Task HandleDisconnectAsync(ClientSession session)
session.Character.MapInstance.Sessions.Remove(session.Channel);
}
- await session.Character.MapInstance.SendPacketAsync(session.Character.GenerateOut()).ConfigureAwait(false);
+ await session.Character.MapInstance.SendPacketAsync(session.Character.GenerateOut());
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MinilandDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MinilandDisconnectHandler.cs
index b4077e498..9ae60a205 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MinilandDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/MinilandDisconnectHandler.cs
@@ -33,7 +33,7 @@ public async Task HandleDisconnectAsync(ClientSession session)
return;
}
- var minilandId = await minilandService.DeleteMinilandAsync(session.Character.CharacterId).ConfigureAwait(false);
+ var minilandId = await minilandService.DeleteMinilandAsync(session.Character.CharacterId);
if (minilandId != null)
{
mapInstanceGeneratorService.RemoveMap((Guid)minilandId);
diff --git a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/SaveDisconnectHandler.cs b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/SaveDisconnectHandler.cs
index 765c2a21a..eda5522f6 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/SaveDisconnectHandler.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/DisconnectHandlers/SaveDisconnectHandler.cs
@@ -31,6 +31,6 @@ public async Task HandleDisconnectAsync(ClientSession session)
return;
}
- await saveService.SaveAsync(session.Character).ConfigureAwait(false);
+ await saveService.SaveAsync(session.Character);
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/LoginPacketHandlingStrategy.cs b/src/NosCore.GameObject/Networking/ClientSession/LoginPacketHandlingStrategy.cs
index ddc37c1ca..aa1fc7660 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/LoginPacketHandlingStrategy.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/LoginPacketHandlingStrategy.cs
@@ -19,7 +19,6 @@
using System.Threading.Tasks;
using NosCore.Data.Enumerations.I18N;
-using NosCore.Packets.Attributes;
using NosCore.Packets.Enumerations;
using NosCore.Packets.Interfaces;
using NosCore.Shared.I18N;
@@ -35,7 +34,7 @@ public async Task HandlePacketAsync(IPacket packet, ClientSession session, bool
var packetHeader = packet.Header;
if (string.IsNullOrWhiteSpace(packetHeader))
{
- await session.DisconnectAsync().ConfigureAwait(false);
+ await session.DisconnectAsync();
return;
}
@@ -53,6 +52,6 @@ public async Task HandlePacketAsync(IPacket packet, ClientSession session, bool
return;
}
- await handler.ExecuteAsync(packet, session).ConfigureAwait(false);
+ await handler.ExecuteAsync(packet, session);
}
}
diff --git a/src/NosCore.GameObject/Networking/ClientSession/WorldPacketHandlingStrategy.cs b/src/NosCore.GameObject/Networking/ClientSession/WorldPacketHandlingStrategy.cs
index 9d5766580..95c3cc822 100644
--- a/src/NosCore.GameObject/Networking/ClientSession/WorldPacketHandlingStrategy.cs
+++ b/src/NosCore.GameObject/Networking/ClientSession/WorldPacketHandlingStrategy.cs
@@ -20,11 +20,10 @@
using System.Threading.Tasks;
using NosCore.Data.CommandPackets;
using NosCore.Data.Enumerations.I18N;
+using NosCore.GameObject.Infastructure;
using NosCore.Networking.SessionRef;
using NosCore.Packets.Attributes;
-using NosCore.Packets.ClientPackets.CharacterSelectionScreen;
using NosCore.Packets.ClientPackets.Infrastructure;
-using NosCore.Packets.ClientPackets.Login;
using NosCore.Packets.ClientPackets.UI;
using NosCore.Packets.Enumerations;
using NosCore.Packets.Interfaces;
@@ -61,7 +60,7 @@ public async Task HandlePacketAsync(IPacket packet, ClientSession session, bool
if (string.IsNullOrWhiteSpace(packetHeader) && isFromNetwork)
{
logger.Warning(logLanguage[LogLanguageKey.CORRUPT_PACKET], processedPacket);
- await session.DisconnectAsync().ConfigureAwait(false);
+ await session.DisconnectAsync();
return;
}
@@ -96,7 +95,7 @@ private async Task ValidateKeepAliveAsync(IPacket packet, ClientSession se
if (session.LastKeepAliveIdentity != 0 && packet.KeepAliveId != session.LastKeepAliveIdentity + 1)
{
logger.Error(logLanguage[LogLanguageKey.CORRUPTED_KEEPALIVE], session.SessionId);
- await session.DisconnectAsync().ConfigureAwait(false);
+ await session.DisconnectAsync();
return false;
}
@@ -104,7 +103,7 @@ private async Task ValidateKeepAliveAsync(IPacket packet, ClientSession se
if (packet.KeepAliveId == null)
{
- await session.DisconnectAsync().ConfigureAwait(false);
+ await session.DisconnectAsync();
return false;
}
@@ -209,7 +208,7 @@ private async Task ExecuteHandlerAsync(IPacketHandler handler, IPacket packet, C
try
{
- await Task.WhenAll(handler.ExecuteAsync(packet, session), Task.Delay(200)).ConfigureAwait(false);
+ await Task.WhenAll(handler.ExecuteAsync(packet, session), Task.Delay(200));
}
finally
{
diff --git a/src/NosCore.GameObject/Services/BattleService/BattleService.cs b/src/NosCore.GameObject/Services/BattleService/BattleService.cs
index bf0dd051b..d9c1330c3 100644
--- a/src/NosCore.GameObject/Services/BattleService/BattleService.cs
+++ b/src/NosCore.GameObject/Services/BattleService/BattleService.cs
@@ -24,7 +24,6 @@
using NosCore.Packets.Enumerations;
using NosCore.Packets.ServerPackets.Battle;
using NosCore.Shared.Enumerations;
-using static NosCore.Data.Enumerations.Buff.AdditionalTypes;
namespace NosCore.GameObject.Services.BattleService;
diff --git a/src/NosCore.GameObject/Services/BattleService/CharacterSkill.cs b/src/NosCore.GameObject/Services/BattleService/CharacterSkill.cs
index 0fe5a46cc..d2671091e 100644
--- a/src/NosCore.GameObject/Services/BattleService/CharacterSkill.cs
+++ b/src/NosCore.GameObject/Services/BattleService/CharacterSkill.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using NosCore.Data.Dto;
using NosCore.Data.StaticEntities;
diff --git a/src/NosCore.GameObject/Holders/BazaarItemsHolder.cs b/src/NosCore.GameObject/Services/BazaarService/BazaarRegistry.cs
similarity index 55%
rename from src/NosCore.GameObject/Holders/BazaarItemsHolder.cs
rename to src/NosCore.GameObject/Services/BazaarService/BazaarRegistry.cs
index 1f3fc155f..312102aab 100644
--- a/src/NosCore.GameObject/Holders/BazaarItemsHolder.cs
+++ b/src/NosCore.GameObject/Services/BazaarService/BazaarRegistry.cs
@@ -1,19 +1,19 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
@@ -25,11 +25,13 @@
using System.Collections.Generic;
using System.Linq;
-namespace NosCore.GameObject.Holders
+namespace NosCore.GameObject.Services.BazaarService
{
- public class BazaarItemsHolder
+ public class BazaarRegistry : IBazaarRegistry
{
- public BazaarItemsHolder(IDao bazaarItemDao,
+ private readonly ConcurrentDictionary _bazaarItems;
+
+ public BazaarRegistry(IDao bazaarItemDao,
IDao itemInstanceDao, IDao characterDao)
{
var billist = bazaarItemDao.LoadAll().ToList();
@@ -38,14 +40,33 @@ public BazaarItemsHolder(IDao bazaarItemDao,
var itemInstancelist = itemInstanceDao.Where(s => bzItemInstanceIds.Contains(s!.Id))?.ToList() ?? new List();
var characterList = characterDao.Where(s => bzCharacterIds.Contains(s.CharacterId))?.ToList() ?? new List();
- BazaarItems = new ConcurrentDictionary(billist.ToDictionary(x => x.BazaarItemId,
+ _bazaarItems = new ConcurrentDictionary(billist.ToDictionary(x => x.BazaarItemId,
x => new BazaarLink
{
ItemInstance = (ItemInstanceDto?)itemInstancelist.First(s => s!.Id == x.ItemInstanceId),
- BazaarItem = x, SellerName = characterList.First(s => s.CharacterId == x.SellerId).Name!
+ BazaarItem = x,
+ SellerName = characterList.First(s => s.CharacterId == x.SellerId).Name!
}));
}
- public ConcurrentDictionary BazaarItems { get; set; }
+ public IEnumerable GetAll() => _bazaarItems.Values;
+
+ public BazaarLink? GetById(long bazaarItemId) =>
+ _bazaarItems.TryGetValue(bazaarItemId, out var link) ? link : null;
+
+ public IEnumerable GetBySellerId(long sellerId) =>
+ _bazaarItems.Values.Where(s => s.BazaarItem?.SellerId == sellerId);
+
+ public void Register(long bazaarItemId, BazaarLink bazaarLink) =>
+ _bazaarItems.TryAdd(bazaarItemId, bazaarLink);
+
+ public bool Unregister(long bazaarItemId) =>
+ _bazaarItems.TryRemove(bazaarItemId, out _);
+
+ public void Update(long bazaarItemId, BazaarLink bazaarLink) =>
+ _bazaarItems[bazaarItemId] = bazaarLink;
+
+ public int CountBySellerId(long sellerId) =>
+ _bazaarItems.Values.Count(o => o.BazaarItem?.SellerId == sellerId);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/BazaarService/BazaarService.cs b/src/NosCore.GameObject/Services/BazaarService/BazaarService.cs
index b2df935c9..9944f9c6d 100644
--- a/src/NosCore.GameObject/Services/BazaarService/BazaarService.cs
+++ b/src/NosCore.GameObject/Services/BazaarService/BazaarService.cs
@@ -26,7 +26,6 @@
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.Enumerations.Items;
using NosCore.Data.WebApi;
-using NosCore.GameObject.Holders;
using NosCore.Packets.Enumerations;
using System;
using System.Collections.Generic;
@@ -36,7 +35,7 @@
namespace NosCore.GameObject.Services.BazaarService
{
- public class BazaarService(BazaarItemsHolder holder, IDao bazaarItemDao,
+ public class BazaarService(IBazaarRegistry bazaarRegistry, IDao bazaarItemDao,
IDao itemInstanceDao, IClock clock)
: IBazaarService
{
@@ -57,12 +56,14 @@ public List GetBazaar(long id, byte? index, byte? pageSize, BazaarLi
IEnumerable bzlinks;
if (id != -1)
{
- bzlinks = holder.BazaarItems.Values.Where(s => s.BazaarItem?.BazaarItemId == id);
+ var item = bazaarRegistry.GetById(id);
+ bzlinks = item != null ? new[] { item } : Enumerable.Empty();
}
else
{
- bzlinks = holder.BazaarItems.Values.Where(s =>
- (s.BazaarItem?.SellerId == sellerFilter) || (sellerFilter == null));
+ bzlinks = sellerFilter != null
+ ? bazaarRegistry.GetBySellerId(sellerFilter.Value)
+ : bazaarRegistry.GetAll();
}
foreach (var bz in bzlinks)
@@ -164,30 +165,37 @@ public List GetBazaar(long id, byte? index, byte? pageSize, BazaarLi
return bzlist.Skip(index ?? 0 * pageSize ?? 0).Take((byte)(pageSize ?? bzlist.Count)).ToList();
}
- public async Task DeleteBazaarAsync(long id, short count, string requestCharacterName)
+ public async Task DeleteBazaarAsync(long id, short count, string requestCharacterName, long? requestCharacterId = null)
{
- var bzlink = holder.BazaarItems.Values.FirstOrDefault(s => s.BazaarItem?.BazaarItemId == id);
+ var bzlink = bazaarRegistry.GetById(id);
if (bzlink == null)
{
throw new ArgumentException();
}
- if ((bzlink.ItemInstance?.Amount - count < 0) || (count < 0))
+ if ((bzlink.ItemInstance?.Amount - count < 0) || (count <= 0))
{
return false;
}
- if ((bzlink.ItemInstance?.Amount == count) && (requestCharacterName == bzlink.SellerName))
+ if (bzlink.ItemInstance?.Amount == count)
{
- await bazaarItemDao.TryDeleteAsync(bzlink.BazaarItem!.BazaarItemId).ConfigureAwait(false);
- holder.BazaarItems.TryRemove(bzlink.BazaarItem.BazaarItemId, out _);
- await itemInstanceDao.TryDeleteAsync(bzlink.ItemInstance.Id).ConfigureAwait(false);
+ await bazaarItemDao.TryDeleteAsync(bzlink.BazaarItem!.BazaarItemId);
+ bazaarRegistry.Unregister(bzlink.BazaarItem.BazaarItemId);
+ await itemInstanceDao.TryDeleteAsync(bzlink.ItemInstance.Id);
}
else
{
var item = (IItemInstanceDto)bzlink.ItemInstance!;
item.Amount -= count;
- await itemInstanceDao.TryInsertOrUpdateAsync(item).ConfigureAwait(false);
+ await itemInstanceDao.TryInsertOrUpdateAsync(item);
+
+ if (item.Amount <= 0)
+ {
+ await bazaarItemDao.TryDeleteAsync(bzlink.BazaarItem!.BazaarItemId);
+ bazaarRegistry.Unregister(bzlink.BazaarItem.BazaarItemId);
+ await itemInstanceDao.TryDeleteAsync(item.Id);
+ }
}
return true;
@@ -195,8 +203,8 @@ public async Task DeleteBazaarAsync(long id, short count, string requestCh
public async Task AddBazaarAsync(Guid itemInstanceId, long characterId, string? characterName, bool hasMedal, long price, bool isPackage, short duration, short amount)
{
- var items = holder.BazaarItems.Values.Where(o => o.BazaarItem!.SellerId == characterId);
- if (items.Count() > 10 * (hasMedal ? 10 : 1) - 1)
+ var itemCount = bazaarRegistry.CountBySellerId(characterId);
+ if (itemCount > 10 * (hasMedal ? 10 : 1) - 1)
{
return LanguageKey.LIMIT_EXCEEDED;
}
@@ -235,10 +243,11 @@ public async Task AddBazaarAsync(Guid itemInstanceId, long characte
ItemInstanceId = item!.Id
};
bazaarItem = await bazaarItemDao.TryInsertOrUpdateAsync(bazaarItem).ConfigureAwait(true);
- holder.BazaarItems.TryAdd(bazaarItem.BazaarItemId,
+ bazaarRegistry.Register(bazaarItem.BazaarItemId,
new BazaarLink
{
- BazaarItem = bazaarItem, SellerName = characterName,
+ BazaarItem = bazaarItem,
+ SellerName = characterName,
ItemInstance = (ItemInstanceDto)item
});
@@ -247,8 +256,7 @@ public async Task AddBazaarAsync(Guid itemInstanceId, long characte
public async Task ModifyBazaarAsync(long id, Json.Patch.JsonPatch bzMod)
{
- var item = holder.BazaarItems.Values
- .FirstOrDefault(o => o.BazaarItem?.BazaarItemId == id);
+ var item = bazaarRegistry.GetById(id);
if ((item?.BazaarItem == null) || (item.BazaarItem?.Amount != item.ItemInstance?.Amount))
{
return null;
@@ -258,7 +266,7 @@ public async Task AddBazaarAsync(Guid itemInstanceId, long characte
item = JsonSerializer.Deserialize(result.Result, new JsonSerializerOptions().ConfigureForNodaTime(DateTimeZoneProviders.Tzdb));
var bz = item!.BazaarItem!;
await bazaarItemDao.TryInsertOrUpdateAsync(bz).ConfigureAwait(true);
- holder.BazaarItems[item.BazaarItem!.BazaarItemId] = item;
+ bazaarRegistry.Update(item.BazaarItem!.BazaarItemId, item);
return item;
}
}
diff --git a/src/NosCore.GameObject/Services/BazaarService/IBazaarRegistry.cs b/src/NosCore.GameObject/Services/BazaarService/IBazaarRegistry.cs
new file mode 100644
index 000000000..ef1c74d7d
--- /dev/null
+++ b/src/NosCore.GameObject/Services/BazaarService/IBazaarRegistry.cs
@@ -0,0 +1,35 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using NosCore.Data.WebApi;
+using System.Collections.Generic;
+
+namespace NosCore.GameObject.Services.BazaarService
+{
+ public interface IBazaarRegistry
+ {
+ IEnumerable GetAll();
+ BazaarLink? GetById(long bazaarItemId);
+ IEnumerable GetBySellerId(long sellerId);
+ void Register(long bazaarItemId, BazaarLink bazaarLink);
+ bool Unregister(long bazaarItemId);
+ void Update(long bazaarItemId, BazaarLink bazaarLink);
+ int CountBySellerId(long sellerId);
+ }
+}
diff --git a/src/NosCore.GameObject/Services/BazaarService/IBazaarService.cs b/src/NosCore.GameObject/Services/BazaarService/IBazaarService.cs
index 0cf6eac46..5471a668e 100644
--- a/src/NosCore.GameObject/Services/BazaarService/IBazaarService.cs
+++ b/src/NosCore.GameObject/Services/BazaarService/IBazaarService.cs
@@ -31,7 +31,7 @@ public interface IBazaarService
List GetBazaar(long id, byte? index, byte? pageSize, BazaarListType? typeFilter,
byte? subTypeFilter, byte? levelFilter, byte? rareFilter, byte? upgradeFilter, long? sellerFilter);
- Task DeleteBazaarAsync(long id, short count, string requestCharacterName);
+ Task DeleteBazaarAsync(long id, short count, string requestCharacterName, long? requestCharacterId = null);
Task AddBazaarAsync(Guid itemInstanceId, long characterId, string? characterName, bool hasMedal, long price, bool isPackage, short duration, short amount);
diff --git a/src/NosCore.GameObject/Services/BlackListService/BlacklistService.cs b/src/NosCore.GameObject/Services/BlackListService/BlacklistService.cs
index 5e223ff98..ca02eefa3 100644
--- a/src/NosCore.GameObject/Services/BlackListService/BlacklistService.cs
+++ b/src/NosCore.GameObject/Services/BlackListService/BlacklistService.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -73,7 +73,7 @@ public async Task BlacklistPlayerAsync(long characterId, long secon
RelationType = CharacterRelationType.Blocked
};
- await characterRelationDao.TryInsertOrUpdateAsync(data).ConfigureAwait(false);
+ await characterRelationDao.TryInsertOrUpdateAsync(data);
return LanguageKey.BLACKLIST_ADDED;
}
@@ -97,7 +97,7 @@ public async Task> GetBlacklistedListAsync(long id
charList.Add(new CharacterRelationStatus
{
- CharacterName = (await characterDao.FirstOrDefaultAsync(s => s.CharacterId == rel.RelatedCharacterId).ConfigureAwait(false))?.Name ?? "",
+ CharacterName = (await characterDao.FirstOrDefaultAsync(s => s.CharacterId == rel.RelatedCharacterId))?.Name ?? "",
CharacterId = rel.RelatedCharacterId,
IsConnected = character != null,
RelationType = rel.RelationType,
@@ -111,12 +111,12 @@ public async Task> GetBlacklistedListAsync(long id
public async Task UnblacklistAsync(Guid id)
{
var rel = await characterRelationDao.FirstOrDefaultAsync(s =>
- (s.CharacterRelationId == id) && (s.RelationType == CharacterRelationType.Blocked)).ConfigureAwait(false);
+ (s.CharacterRelationId == id) && (s.RelationType == CharacterRelationType.Blocked));
if (rel == null)
{
return false;
}
- await characterRelationDao.TryDeleteAsync(rel.CharacterRelationId).ConfigureAwait(false);
+ await characterRelationDao.TryDeleteAsync(rel.CharacterRelationId);
return true;
}
}
diff --git a/src/NosCore.GameObject/Services/BroadcastService/PacketBroadcaster.cs b/src/NosCore.GameObject/Services/BroadcastService/PacketBroadcaster.cs
index 3f1d11744..748adbabe 100644
--- a/src/NosCore.GameObject/Services/BroadcastService/PacketBroadcaster.cs
+++ b/src/NosCore.GameObject/Services/BroadcastService/PacketBroadcaster.cs
@@ -28,7 +28,7 @@ public class PacketBroadcaster(ISessionRegistry sessionRegistry) : IPacketBroadc
{
public async Task SendToAsync(IPacketTarget target, IPacket packet)
{
- await SendToAsync(target, new[] { packet }).ConfigureAwait(false);
+ await SendToAsync(target, new[] { packet });
}
public async Task SendToAsync(IPacketTarget target, IEnumerable packets)
@@ -37,7 +37,7 @@ public async Task SendToAsync(IPacketTarget target, IEnumerable packets
var sessions = GetTargetSessions(target);
var tasks = sessions.Select(s => s.Sender.SendPacketsAsync(packetList));
- await Task.WhenAll(tasks).ConfigureAwait(false);
+ await Task.WhenAll(tasks);
}
private IEnumerable GetTargetSessions(IPacketTarget target)
diff --git a/src/NosCore.GameObject/Services/BroadcastService/SessionRegistry.cs b/src/NosCore.GameObject/Services/BroadcastService/SessionRegistry.cs
index dfc4fd138..c40debc7c 100644
--- a/src/NosCore.GameObject/Services/BroadcastService/SessionRegistry.cs
+++ b/src/NosCore.GameObject/Services/BroadcastService/SessionRegistry.cs
@@ -25,10 +25,11 @@
using NosCore.Data.WebApi;
using NosCore.GameObject.ComponentEntities.Interfaces;
using NosCore.Packets.Interfaces;
+using Serilog;
namespace NosCore.GameObject.Services.BroadcastService
{
- public class SessionRegistry : ISessionRegistry
+ public class SessionRegistry(ILogger logger) : ISessionRegistry
{
private readonly ConcurrentDictionary _sessionsByChannelId = new();
private readonly ConcurrentDictionary _channelIdByCharacterId = new();
@@ -110,14 +111,36 @@ public IEnumerable GetCharacters(Func?
public async Task BroadcastPacketAsync(IPacket packet)
{
- await Task.WhenAll(_sessionsByChannelId.Values.Select(s => s.Sender.SendPacketAsync(packet)));
+ var tasks = _sessionsByChannelId.Values.Select(async s =>
+ {
+ try
+ {
+ await s.Sender.SendPacketAsync(packet);
+ }
+ catch (Exception ex)
+ {
+ logger.Warning(ex, "Broadcast to {ChannelId} failed", s.ChannelId);
+ }
+ });
+ await Task.WhenAll(tasks);
}
public async Task BroadcastPacketAsync(IPacket packet, string excludeChannelId)
{
- await Task.WhenAll(_sessionsByChannelId.Values
+ var tasks = _sessionsByChannelId.Values
.Where(s => s.ChannelId != excludeChannelId)
- .Select(s => s.Sender.SendPacketAsync(packet)));
+ .Select(async s =>
+ {
+ try
+ {
+ await s.Sender.SendPacketAsync(packet);
+ }
+ catch (Exception ex)
+ {
+ logger.Warning(ex, "Broadcast to {ChannelId} failed", s.ChannelId);
+ }
+ });
+ await Task.WhenAll(tasks);
}
public async Task DisconnectByCharacterIdAsync(long characterId)
diff --git a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DeleteMailDataMessageChannelCommunicationMessageHandler.cs b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DeleteMailDataMessageChannelCommunicationMessageHandler.cs
index da6a5a462..2fcb859c5 100644
--- a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DeleteMailDataMessageChannelCommunicationMessageHandler.cs
+++ b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DeleteMailDataMessageChannelCommunicationMessageHandler.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using NosCore.Packets.ServerPackets.Parcel;
using NosCore.GameObject.Services.BroadcastService;
using DeleteMailData = NosCore.GameObject.InterChannelCommunication.Messages.DeleteMailData;
@@ -21,7 +21,7 @@ await session.SendPacketAsync(new PostPacket
Type = 2,
PostType = data.PostType,
Id = data.MailId
- }).ConfigureAwait(false);
+ });
}
}
}
diff --git a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DisconnectDataMessageChannelCommunicationMessageHandler.cs b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DisconnectDataMessageChannelCommunicationMessageHandler.cs
index 98f955468..841d0d23e 100644
--- a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DisconnectDataMessageChannelCommunicationMessageHandler.cs
+++ b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/DisconnectDataMessageChannelCommunicationMessageHandler.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using NosCore.GameObject.Services.BroadcastService;
using DisconnectData = NosCore.GameObject.InterChannelCommunication.Messages.DisconnectData;
@@ -14,7 +14,7 @@ public override async Task Handle(DisconnectData data)
return;
}
- await sessionRegistry.DisconnectByCharacterIdAsync(data.CharacterId).ConfigureAwait(false);
+ await sessionRegistry.DisconnectByCharacterIdAsync(data.CharacterId);
}
}
}
diff --git a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/MailDataMessageChannelCommunicationMessageHandler.cs b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/MailDataMessageChannelCommunicationMessageHandler.cs
index a5cc4705e..33ccdfd6b 100644
--- a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/MailDataMessageChannelCommunicationMessageHandler.cs
+++ b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/MailDataMessageChannelCommunicationMessageHandler.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using NosCore.Core.I18N;
using NosCore.Data.Enumerations.I18N;
using NosCore.GameObject.ComponentEntities.Extensions;
@@ -24,10 +24,10 @@ public override async Task Handle(MailData data)
{
await session.SendPacketAsync(session.GenerateSay(
string.Format(gameLanguageLocalizer[LanguageKey.ITEM_GIFTED, session.AccountLanguage],
- data.ItemInstance.Amount), SayColorType.Green)).ConfigureAwait(false);
+ data.ItemInstance.Amount), SayColorType.Green));
}
- await session.GenerateMailAsync(new[] { data }).ConfigureAwait(false);
+ await session.GenerateMailAsync(new[] { data });
}
}
}
diff --git a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/PostedPacketMessageChannelCommunicationMessageHandler.cs b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/PostedPacketMessageChannelCommunicationMessageHandler.cs
index d1ce96dad..4c9df0d9d 100644
--- a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/PostedPacketMessageChannelCommunicationMessageHandler.cs
+++ b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/PostedPacketMessageChannelCommunicationMessageHandler.cs
@@ -1,8 +1,7 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.Enumerations.Interaction;
using NosCore.GameObject.ComponentEntities.Interfaces;
-using NosCore.Networking;
using NosCore.Packets.Interfaces;
using NosCore.Shared.I18N;
using Serilog;
@@ -21,7 +20,7 @@ public override async Task Handle(PostedPacket postedPacket)
switch (postedPacket.ReceiverType)
{
case ReceiverType.All:
- await sessionRegistry.BroadcastPacketAsync(message).ConfigureAwait(false);
+ await sessionRegistry.BroadcastPacketAsync(message);
break;
case ReceiverType.OnlySomeone:
ICharacterEntity? receiverSession;
@@ -42,7 +41,7 @@ public override async Task Handle(PostedPacket postedPacket)
return;
}
- await receiverSession.SendPacketAsync(message).ConfigureAwait(false);
+ await receiverSession.SendPacketAsync(message);
break;
default:
logger.Error(logLanguage[LogLanguageKey.UNKWNOWN_RECEIVERTYPE]);
diff --git a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/StatDataMessageChannelCommunicationMessageHandler.cs b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/StatDataMessageChannelCommunicationMessageHandler.cs
index 7df59b1ac..0e8be7585 100644
--- a/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/StatDataMessageChannelCommunicationMessageHandler.cs
+++ b/src/NosCore.GameObject/Services/ChannelCommunicationService/Handlers/StatDataMessageChannelCommunicationMessageHandler.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using NosCore.Core.Configuration;
using NosCore.Data.Enumerations;
@@ -31,13 +31,13 @@ public override async Task Handle(StatData data)
session.SetLevel((byte)data.Data);
break;
case UpdateStatActionType.UpdateJobLevel:
- await session.SetJobLevelAsync((byte)data.Data).ConfigureAwait(false);
+ await session.SetJobLevelAsync((byte)data.Data);
break;
case UpdateStatActionType.UpdateHeroLevel:
- await session.SetHeroLevelAsync((byte)data.Data).ConfigureAwait(false);
+ await session.SetHeroLevelAsync((byte)data.Data);
break;
case UpdateStatActionType.UpdateReputation:
- await session.SetReputationAsync(data.Data).ConfigureAwait(false);
+ await session.SetReputationAsync(data.Data);
break;
case UpdateStatActionType.UpdateGold:
if (session.Gold + data.Data > worldConfiguration.Value.MaxGoldAmount)
@@ -45,10 +45,10 @@ public override async Task Handle(StatData data)
return;
}
- await session.SetGoldAsync(data.Data).ConfigureAwait(false);
+ await session.SetGoldAsync(data.Data);
break;
case UpdateStatActionType.UpdateClass:
- await session.ChangeClassAsync((CharacterClassType)data.Data).ConfigureAwait(false);
+ await session.ChangeClassAsync((CharacterClassType)data.Data);
break;
default:
logger.Error(logLanguage[LogLanguageKey.UNKWNOWN_RECEIVERTYPE]);
diff --git a/src/NosCore.GameObject/Services/ChannelService/ChannelService.cs b/src/NosCore.GameObject/Services/ChannelService/ChannelService.cs
index 0df9a15a2..dd2ed86ee 100644
--- a/src/NosCore.GameObject/Services/ChannelService/ChannelService.cs
+++ b/src/NosCore.GameObject/Services/ChannelService/ChannelService.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -33,7 +33,7 @@ public class ChannelService(IAuthHub authHttpClient,
{
public async Task MoveChannelAsync(Networking.ClientSession.ClientSession clientSession, int channelId)
{
- var servers = await channelHttpClient.GetCommunicationChannels().ConfigureAwait(false);
+ var servers = await channelHttpClient.GetCommunicationChannels();
var server = servers.FirstOrDefault(x => x.Id == channelId);
if (server == null || server.Type != ServerType.WorldServer)
{
diff --git a/src/NosCore.GameObject/Services/CharacterService/CharacterInitializationService.cs b/src/NosCore.GameObject/Services/CharacterService/CharacterInitializationService.cs
index b3b8f6a1e..a9effb414 100644
--- a/src/NosCore.GameObject/Services/CharacterService/CharacterInitializationService.cs
+++ b/src/NosCore.GameObject/Services/CharacterService/CharacterInitializationService.cs
@@ -18,6 +18,7 @@
// along with this program. If not, see .
using System.Threading.Tasks;
+using NosCore.GameObject.ComponentEntities.Entities;
using NosCore.GameObject.Services.MapInstanceGenerationService;
using NosCore.GameObject.Services.MinilandService;
diff --git a/src/NosCore.GameObject/Services/CharacterService/ICharacterInitializationService.cs b/src/NosCore.GameObject/Services/CharacterService/ICharacterInitializationService.cs
index 080e6020a..e2583f6d5 100644
--- a/src/NosCore.GameObject/Services/CharacterService/ICharacterInitializationService.cs
+++ b/src/NosCore.GameObject/Services/CharacterService/ICharacterInitializationService.cs
@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.ComponentEntities.Entities;
using System.Threading.Tasks;
namespace NosCore.GameObject.Services.CharacterService
diff --git a/src/NosCore.GameObject/Services/EventLoaderService/EventLoaderService.cs b/src/NosCore.GameObject/Services/EventLoaderService/EventLoaderService.cs
index 04ddc4d5f..8247ce8a6 100644
--- a/src/NosCore.GameObject/Services/EventLoaderService/EventLoaderService.cs
+++ b/src/NosCore.GameObject/Services/EventLoaderService/EventLoaderService.cs
@@ -18,6 +18,7 @@
// along with this program. If not, see .
using NosCore.GameObject.ComponentEntities.Interfaces;
+using NosCore.GameObject.Infastructure;
using NosCore.GameObject.Networking.ClientSession;
using System;
using System.Collections.Generic;
diff --git a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/ChannelCommunicationRunner.cs b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/ChannelCommunicationRunner.cs
index 25e2ea176..c2ab97c5c 100644
--- a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/ChannelCommunicationRunner.cs
+++ b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/ChannelCommunicationRunner.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -65,7 +65,7 @@ private void OnMessageReceived(IMessage message)
{
if (_handlers.TryGetValue(message.GetType(), out var handler))
{
- await handler.Handle(message).ConfigureAwait(false);
+ await handler.Handle(message);
}
else
{
@@ -81,13 +81,13 @@ private void OnMessageReceived(IMessage message)
public async Task StartAsync(CancellationToken cancellationToken)
{
- await _pubSubHubClient.StartAsync().ConfigureAwait(false);
+ await _pubSubHubClient.StartAsync();
}
public async Task StopAsync(CancellationToken cancellationToken)
{
_pubSubHubClient.OnMessageReceived -= OnMessageReceived;
- await _pubSubHubClient.StopAsync().ConfigureAwait(false);
+ await _pubSubHubClient.StopAsync();
}
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/RemoveTimeoutStaticBonuses.cs b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/RemoveTimeoutStaticBonuses.cs
index 8f5b7316b..a4505eb8b 100644
--- a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/RemoveTimeoutStaticBonuses.cs
+++ b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/RemoveTimeoutStaticBonuses.cs
@@ -18,7 +18,6 @@
// along with this program. If not, see .
using JetBrains.Annotations;
-using NosCore.GameObject.Networking;
using NosCore.GameObject.Networking.ClientSession;
using NosCore.Packets.Enumerations;
using System;
diff --git a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/SaveAll.cs b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/SaveAll.cs
index 4f70ad970..900a89b07 100644
--- a/src/NosCore.GameObject/Services/EventLoaderService/Handlers/SaveAll.cs
+++ b/src/NosCore.GameObject/Services/EventLoaderService/Handlers/SaveAll.cs
@@ -19,7 +19,6 @@
using JetBrains.Annotations;
using NosCore.Data.Enumerations.I18N;
-using NosCore.GameObject.Networking;
using NosCore.GameObject.Networking.ClientSession;
using System;
using System.Linq;
diff --git a/src/NosCore.GameObject/Services/EventLoaderService/ITimedEventHandler.cs b/src/NosCore.GameObject/Services/EventLoaderService/ITimedEventHandler.cs
index 1c968ca55..b46fec88e 100644
--- a/src/NosCore.GameObject/Services/EventLoaderService/ITimedEventHandler.cs
+++ b/src/NosCore.GameObject/Services/EventLoaderService/ITimedEventHandler.cs
@@ -18,6 +18,7 @@
// along with this program. If not, see .
using NodaTime;
+using NosCore.GameObject.Infastructure;
namespace NosCore.GameObject.Services.EventLoaderService
{
diff --git a/src/NosCore.GameObject/ExchangeData.cs b/src/NosCore.GameObject/Services/ExchangeService/ExchangeData.cs
similarity index 91%
rename from src/NosCore.GameObject/ExchangeData.cs
rename to src/NosCore.GameObject/Services/ExchangeService/ExchangeData.cs
index 4b123c925..4063bc3db 100644
--- a/src/NosCore.GameObject/ExchangeData.cs
+++ b/src/NosCore.GameObject/Services/ExchangeService/ExchangeData.cs
@@ -1,26 +1,26 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using NosCore.GameObject.Services.InventoryService;
using System.Collections.Concurrent;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Services.ExchangeService
{
public class ExchangeData
{
@@ -32,4 +32,4 @@ public class ExchangeData
public bool ExchangeConfirmed { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/ExchangeService/ExchangeRequestRegistry.cs b/src/NosCore.GameObject/Services/ExchangeService/ExchangeRequestRegistry.cs
new file mode 100644
index 000000000..db7099b60
--- /dev/null
+++ b/src/NosCore.GameObject/Services/ExchangeService/ExchangeRequestRegistry.cs
@@ -0,0 +1,84 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+
+namespace NosCore.GameObject.Services.ExchangeService
+{
+ public class ExchangeRequestRegistry : IExchangeRequestRegistry
+ {
+ private readonly ConcurrentDictionary _exchangeDatas = new();
+ private readonly ConcurrentDictionary _initiatorToTarget = new();
+ private readonly ConcurrentDictionary _targetToInitiator = new();
+
+ public ExchangeData? GetExchangeData(long characterId) =>
+ _exchangeDatas.TryGetValue(characterId, out var data) ? data : null;
+
+ public void SetExchangeData(long characterId, ExchangeData data) =>
+ _exchangeDatas[characterId] = data;
+
+ public bool RemoveExchangeData(long characterId) =>
+ _exchangeDatas.TryRemove(characterId, out _);
+
+ public long? GetExchangeRequest(long characterId) =>
+ _initiatorToTarget.TryGetValue(characterId, out var targetId) ? targetId : null;
+
+ public KeyValuePair? GetExchangeRequestPair(long characterId)
+ {
+ if (_initiatorToTarget.TryGetValue(characterId, out var target))
+ {
+ return new KeyValuePair(characterId, target);
+ }
+
+ if (_targetToInitiator.TryGetValue(characterId, out var initiator))
+ {
+ return new KeyValuePair(initiator, characterId);
+ }
+
+ return null;
+ }
+
+ public void SetExchangeRequest(long characterId, long targetCharacterId)
+ {
+ _initiatorToTarget[characterId] = targetCharacterId;
+ _targetToInitiator[targetCharacterId] = characterId;
+ }
+
+ public bool RemoveExchangeRequest(long characterId)
+ {
+ if (_initiatorToTarget.TryRemove(characterId, out var target))
+ {
+ _targetToInitiator.TryRemove(target, out _);
+ return true;
+ }
+
+ if (_targetToInitiator.TryRemove(characterId, out var initiator))
+ {
+ _initiatorToTarget.TryRemove(initiator, out _);
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool HasExchange(long characterId) =>
+ _initiatorToTarget.ContainsKey(characterId) || _targetToInitiator.ContainsKey(characterId);
+ }
+}
diff --git a/src/NosCore.GameObject/Services/ExchangeService/ExchangeService.cs b/src/NosCore.GameObject/Services/ExchangeService/ExchangeService.cs
index bfcad36f6..01040dcfb 100644
--- a/src/NosCore.GameObject/Services/ExchangeService/ExchangeService.cs
+++ b/src/NosCore.GameObject/Services/ExchangeService/ExchangeService.cs
@@ -1,19 +1,19 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
@@ -23,7 +23,6 @@
using NosCore.Data.Enumerations.I18N;
using NosCore.GameObject.ComponentEntities.Extensions;
using NosCore.GameObject.ComponentEntities.Interfaces;
-using NosCore.GameObject.Holders;
using NosCore.GameObject.Networking.ClientSession;
using NosCore.GameObject.Services.InventoryService;
using NosCore.GameObject.Services.ItemGenerationService;
@@ -41,17 +40,20 @@
namespace NosCore.GameObject.Services.ExchangeService
{
public class ExchangeService(IItemGenerationService itemBuilderService,
- IOptions worldConfiguration, ILogger logger, ExchangeRequestHolder requestHolder,
+ IOptions worldConfiguration, ILogger logger, IExchangeRequestRegistry exchangeRegistry,
ILogLanguageLocalizer logLanguage, IGameLanguageLocalizer gameLanguageLocalizer)
: IExchangeService
{
public void SetGold(long visualId, long gold, long bankGold)
{
- requestHolder.ExchangeDatas[visualId].Gold = gold;
- requestHolder.ExchangeDatas[visualId].BankGold = bankGold;
+ var data = exchangeRegistry.GetExchangeData(visualId);
+ if (data != null)
+ {
+ data.Gold = gold;
+ data.BankGold = bankGold;
+ }
}
- //TODO: Remove these clientsessions as parameter
public Tuple?> ValidateExchange(ClientSession session,
ICharacterEntity targetSession)
{
@@ -107,11 +109,21 @@ public void SetGold(long visualId, long gold, long bankGold)
dictionary);
}
- if (session.Character.InventoryService.EnoughPlace(
+ var targetFirstItem = targetInfo.ExchangeItems.Keys.FirstOrDefault();
+ var exchangeFirstItem = exchangeInfo.ExchangeItems.Keys.FirstOrDefault();
+
+ var targetHasItems = targetFirstItem != null;
+ var exchangeHasItems = exchangeFirstItem != null;
+
+ var targetEnoughPlace = !targetHasItems || session.Character.InventoryService.EnoughPlace(
targetInfo.ExchangeItems.Keys.Select(s => s.ItemInstance).ToList(),
- targetInfo.ExchangeItems.Keys.First().Type) && targetSession.InventoryService.EnoughPlace(
+ targetFirstItem!.Type);
+
+ var exchangeEnoughPlace = !exchangeHasItems || targetSession.InventoryService.EnoughPlace(
exchangeInfo.ExchangeItems.Keys.Select(s => s.ItemInstance).ToList(),
- targetInfo.ExchangeItems.Keys.First().Type))
+ exchangeFirstItem!.Type);
+
+ if (targetEnoughPlace && exchangeEnoughPlace)
{
return new Tuple?>(ExchangeResultType.Success, null);
}
@@ -131,68 +143,76 @@ public void SetGold(long visualId, long gold, long bankGold)
public void ConfirmExchange(long visualId)
{
- requestHolder.ExchangeDatas[visualId].ExchangeConfirmed = true;
+ var data = exchangeRegistry.GetExchangeData(visualId);
+ if (data != null)
+ {
+ data.ExchangeConfirmed = true;
+ }
}
public bool IsExchangeConfirmed(long visualId)
{
- return requestHolder.ExchangeDatas[visualId].ExchangeConfirmed;
+ return exchangeRegistry.GetExchangeData(visualId)?.ExchangeConfirmed ?? false;
}
public ExchangeData GetData(long visualId)
{
- return requestHolder.ExchangeDatas[visualId];
+ return exchangeRegistry.GetExchangeData(visualId) ?? new ExchangeData();
}
public void AddItems(long visualId, InventoryItemInstance item, short amount)
{
- var data = requestHolder.ExchangeRequests.FirstOrDefault(k => k.Key == visualId);
- if (data.Equals(default))
+ var request = exchangeRegistry.GetExchangeRequest(visualId);
+ if (request == null)
{
logger.Error(logLanguage[LogLanguageKey.INVALID_EXCHANGE]);
return;
}
- requestHolder.ExchangeDatas[data.Key].ExchangeItems.TryAdd(item, amount);
+ var data = exchangeRegistry.GetExchangeData(visualId);
+ data?.ExchangeItems.TryAdd(item, amount);
}
public bool CheckExchange(long visualId)
{
- return requestHolder.ExchangeRequests.Any(k => (k.Key == visualId) || (k.Value == visualId));
+ return exchangeRegistry.HasExchange(visualId);
}
public long? GetTargetId(long visualId)
{
- var id = requestHolder.ExchangeRequests.FirstOrDefault(k => (k.Key == visualId) || (k.Value == visualId));
- if (id.Equals(default(KeyValuePair)))
+ var pair = exchangeRegistry.GetExchangeRequestPair(visualId);
+ if (pair == null)
{
return null;
}
- return id.Value == visualId ? id.Key : id.Value;
+ return pair.Value.Value == visualId ? pair.Value.Key : pair.Value.Value;
}
public bool CheckExchange(long visualId, long targetId)
{
- return requestHolder.ExchangeRequests.Any(k => (k.Key == visualId) && (k.Value == visualId)) ||
- requestHolder.ExchangeRequests.Any(k => (k.Key == targetId) && (k.Value == targetId));
+ var pair1 = exchangeRegistry.GetExchangeRequestPair(visualId);
+ var pair2 = exchangeRegistry.GetExchangeRequestPair(targetId);
+ return (pair1 != null && pair1.Value.Key == visualId && pair1.Value.Value == visualId) ||
+ (pair2 != null && pair2.Value.Key == targetId && pair2.Value.Value == targetId);
}
public ExcClosePacket? CloseExchange(long visualId, ExchangeResultType resultType)
{
- var data = requestHolder.ExchangeRequests.FirstOrDefault(k => (k.Key == visualId) || (k.Value == visualId));
- if ((data.Key == 0) && (data.Value == 0))
+ var pair = exchangeRegistry.GetExchangeRequestPair(visualId);
+ if (pair == null)
{
logger.Error(logLanguage[LogLanguageKey.INVALID_EXCHANGE]);
return null;
}
- if (!requestHolder.ExchangeDatas.TryRemove(data.Key, out _) || !requestHolder.ExchangeRequests.TryRemove(data.Key, out _))
+ var data = pair.Value;
+ if (!exchangeRegistry.RemoveExchangeData(data.Key) || !exchangeRegistry.RemoveExchangeRequest(data.Key))
{
logger.Error(logLanguage[LogLanguageKey.TRY_REMOVE_FAILED], data.Key);
}
- if (!requestHolder.ExchangeDatas.TryRemove(data.Value, out _) || !requestHolder.ExchangeRequests.TryRemove(data.Value, out _))
+ if (!exchangeRegistry.RemoveExchangeData(data.Value) || !exchangeRegistry.RemoveExchangeRequest(data.Value))
{
logger.Error(logLanguage[LogLanguageKey.TRY_REMOVE_FAILED], data.Value);
}
@@ -211,10 +231,10 @@ public bool OpenExchange(long visualId, long targetVisualId)
return false;
}
- requestHolder.ExchangeRequests[visualId] = targetVisualId;
- requestHolder.ExchangeRequests[targetVisualId] = visualId;
- requestHolder.ExchangeDatas[visualId] = new ExchangeData();
- requestHolder.ExchangeDatas[targetVisualId] = new ExchangeData();
+ exchangeRegistry.SetExchangeRequest(visualId, targetVisualId);
+ exchangeRegistry.SetExchangeRequest(targetVisualId, visualId);
+ exchangeRegistry.SetExchangeData(visualId, new ExchangeData());
+ exchangeRegistry.SetExchangeData(targetVisualId, new ExchangeData());
return true;
}
@@ -222,44 +242,82 @@ public List> ProcessExchange(long firstUser, long
IInventoryService sessionInventory, IInventoryService targetInventory)
{
var usersArray = new[] { firstUser, secondUser };
- var items = new List>(); //SessionId, PocketChange
+ var items = new List>();
+ var pendingTransfers = new List<(
+ IInventoryService OriginInventory,
+ IInventoryService DestInventory,
+ InventoryItemInstance OriginalItem,
+ short Amount,
+ long TargetId,
+ long SessionId,
+ bool IsFullTransfer
+ )>();
foreach (var user in usersArray)
{
- foreach (var item in requestHolder.ExchangeDatas[user].ExchangeItems)
+ var userData = exchangeRegistry.GetExchangeData(user);
+ if (userData == null) continue;
+
+ foreach (var item in userData.ExchangeItems)
{
var destInventory = user == firstUser ? targetInventory : sessionInventory;
var originInventory = user == firstUser ? sessionInventory : targetInventory;
var targetId = user == firstUser ? secondUser : firstUser;
var sessionId = user == firstUser ? firstUser : secondUser;
- InventoryItemInstance? newItem = null;
+ var isFullTransfer = item.Value == item.Key.ItemInstance.Amount;
- if (item.Value == item.Key.ItemInstance.Amount)
- {
- originInventory.Remove(item.Key.ItemInstanceId);
- }
- else
- {
- newItem = originInventory.RemoveItemAmountFromInventory(item.Value, item.Key.ItemInstanceId);
- }
+ pendingTransfers.Add((originInventory, destInventory, item.Key, item.Value, targetId, sessionId, isFullTransfer));
+ }
+ }
- var inv = destInventory.AddItemToPocket(InventoryItemInstance.Create(itemBuilderService.Create(
- item.Key.ItemInstance.ItemVNum,
- item.Key.ItemInstance.Amount, (sbyte)item.Key.ItemInstance.Rare, item.Key.ItemInstance.Upgrade,
- (byte)item.Key.ItemInstance.Design), targetId))?.FirstOrDefault();
- if (inv == null)
+ var addedItems = new List<(IInventoryService Inventory, InventoryItemInstance Item)>();
+
+ foreach (var transfer in pendingTransfers)
+ {
+ var newItem = itemBuilderService.Create(
+ transfer.OriginalItem.ItemInstance.ItemVNum,
+ transfer.Amount,
+ (sbyte)transfer.OriginalItem.ItemInstance.Rare,
+ transfer.OriginalItem.ItemInstance.Upgrade,
+ (byte)transfer.OriginalItem.ItemInstance.Design);
+
+ var inv = transfer.DestInventory.AddItemToPocket(
+ InventoryItemInstance.Create(newItem, transfer.TargetId))?.FirstOrDefault();
+
+ if (inv == null)
+ {
+ foreach (var added in addedItems)
{
- return items;
+ added.Inventory.DeleteFromTypeAndSlot(added.Item.Type, added.Item.Slot);
}
+ return new List>();
+ }
+
+ addedItems.Add((transfer.DestInventory, inv));
+ }
+
+ for (var i = 0; i < pendingTransfers.Count; i++)
+ {
+ var transfer = pendingTransfers[i];
+ var addedItem = addedItems[i];
- items.Add(new KeyValuePair(sessionId,
- newItem.GeneratePocketChange((PocketType)item.Key.Type, item.Key.Slot)));
- items.Add(new KeyValuePair(targetId,
- item.Key.GeneratePocketChange((PocketType)inv.Type, inv.Slot)));
+ InventoryItemInstance? sourceItem = null;
+ if (transfer.IsFullTransfer)
+ {
+ transfer.OriginInventory.Remove(transfer.OriginalItem.ItemInstanceId);
}
+ else
+ {
+ sourceItem = transfer.OriginInventory.RemoveItemAmountFromInventory(transfer.Amount, transfer.OriginalItem.ItemInstanceId);
+ }
+
+ items.Add(new KeyValuePair(transfer.SessionId,
+ (sourceItem ?? transfer.OriginalItem).GeneratePocketChange((PocketType)transfer.OriginalItem.Type, transfer.OriginalItem.Slot)));
+ items.Add(new KeyValuePair(transfer.TargetId,
+ transfer.OriginalItem.GeneratePocketChange((PocketType)addedItem.Item.Type, addedItem.Item.Slot)));
}
return items;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/ExchangeService/IExchangeRequestRegistry.cs b/src/NosCore.GameObject/Services/ExchangeService/IExchangeRequestRegistry.cs
new file mode 100644
index 000000000..5ef24ec37
--- /dev/null
+++ b/src/NosCore.GameObject/Services/ExchangeService/IExchangeRequestRegistry.cs
@@ -0,0 +1,36 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Generic;
+
+namespace NosCore.GameObject.Services.ExchangeService
+{
+ public interface IExchangeRequestRegistry
+ {
+ ExchangeData? GetExchangeData(long characterId);
+ void SetExchangeData(long characterId, ExchangeData data);
+ bool RemoveExchangeData(long characterId);
+
+ long? GetExchangeRequest(long characterId);
+ KeyValuePair? GetExchangeRequestPair(long characterId);
+ void SetExchangeRequest(long characterId, long targetCharacterId);
+ bool RemoveExchangeRequest(long characterId);
+ bool HasExchange(long characterId);
+ }
+}
diff --git a/src/NosCore.GameObject/CharacterRelation.cs b/src/NosCore.GameObject/Services/FriendService/CharacterRelation.cs
similarity index 89%
rename from src/NosCore.GameObject/CharacterRelation.cs
rename to src/NosCore.GameObject/Services/FriendService/CharacterRelation.cs
index a43cbd61f..804614951 100644
--- a/src/NosCore.GameObject/CharacterRelation.cs
+++ b/src/NosCore.GameObject/Services/FriendService/CharacterRelation.cs
@@ -1,28 +1,28 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using NosCore.Data.Dto;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Services.FriendService
{
public class CharacterRelation : CharacterRelationDto
{
public string? CharacterName { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/FriendService/FriendRequestRegistry.cs b/src/NosCore.GameObject/Services/FriendService/FriendRequestRegistry.cs
new file mode 100644
index 000000000..1acf513e5
--- /dev/null
+++ b/src/NosCore.GameObject/Services/FriendService/FriendRequestRegistry.cs
@@ -0,0 +1,40 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace NosCore.GameObject.Services.FriendService
+{
+ public class FriendRequestRegistry : IFriendRequestRegistry
+ {
+ private readonly ConcurrentDictionary _friendRequests = new();
+
+ public IEnumerable> GetRequestsForCharacter(long characterId) =>
+ _friendRequests.Where(s => s.Value.ReceiverId == characterId || s.Value.SenderId == characterId);
+
+ public void RegisterRequest(Guid requestId, long senderId, long receiverId) =>
+ _friendRequests[requestId] = (senderId, receiverId);
+
+ public bool UnregisterRequest(Guid requestId) =>
+ _friendRequests.TryRemove(requestId, out _);
+ }
+}
diff --git a/src/NosCore.GameObject/Services/FriendService/FriendService.cs b/src/NosCore.GameObject/Services/FriendService/FriendService.cs
index 5a32ea83f..fdf9c2b95 100644
--- a/src/NosCore.GameObject/Services/FriendService/FriendService.cs
+++ b/src/NosCore.GameObject/Services/FriendService/FriendService.cs
@@ -1,19 +1,19 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
@@ -21,7 +21,6 @@
using NosCore.Data.Dto;
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.WebApi;
-using NosCore.GameObject.Holders;
using NosCore.Packets.Enumerations;
using NosCore.Shared.I18N;
using Serilog;
@@ -37,7 +36,7 @@
namespace NosCore.GameObject.Services.FriendService
{
public class FriendService(ILogger logger, IDao characterRelationDao,
- IDao characterDao, FriendRequestHolder friendRequestHolder,
+ IDao characterDao, IFriendRequestRegistry friendRequestRegistry,
IPubSubHub pubSubHub, IChannelHub channelHub, ILogLanguageLocalizer logLanguage)
: IFriendService
{
@@ -48,9 +47,9 @@ public async Task AddFriendAsync(long characterId, long secondChara
var character = accounts.FirstOrDefault(s => s.ConnectedCharacter?.Id == characterId && servers.Where(c => c.Type == ServerType.WorldServer).Any(x => x.Id == s.ChannelId));
var targetCharacter = accounts.FirstOrDefault(s => s.ConnectedCharacter?.Id == secondCharacterId && servers.Where(c => c.Type == ServerType.WorldServer).Any(x => x.Id == s.ChannelId));
- var friendRequest = friendRequestHolder.FriendRequestCharacters.Where(s =>
- (s.Value.Item2 == character?.ConnectedCharacter?.Id) &&
- (s.Value.Item1 == targetCharacter?.ConnectedCharacter?.Id)).ToList();
+ var friendRequest = friendRequestRegistry.GetRequestsForCharacter(character?.ConnectedCharacter?.Id ?? 0)
+ .Where(s => s.Value.ReceiverId == character?.ConnectedCharacter?.Id &&
+ s.Value.SenderId == targetCharacter?.ConnectedCharacter?.Id).ToList();
if ((character != null) && (targetCharacter != null))
{
if (character.ChannelId != targetCharacter.ChannelId)
@@ -86,9 +85,9 @@ public async Task AddFriendAsync(long characterId, long secondChara
if (!friendRequest.Any())
{
- friendRequestHolder.FriendRequestCharacters[Guid.NewGuid()] =
- new Tuple(character.ConnectedCharacter.Id,
- targetCharacter.ConnectedCharacter.Id);
+ friendRequestRegistry.RegisterRequest(Guid.NewGuid(),
+ character.ConnectedCharacter.Id,
+ targetCharacter.ConnectedCharacter.Id);
return LanguageKey.FRIEND_REQUEST_SENT;
}
@@ -102,7 +101,7 @@ public async Task AddFriendAsync(long characterId, long secondChara
RelationType = CharacterRelationType.Friend
};
- await characterRelationDao.TryInsertOrUpdateAsync(data).ConfigureAwait(false);
+ await characterRelationDao.TryInsertOrUpdateAsync(data);
var data2 = new CharacterRelationDto
{
CharacterId = targetCharacter.ConnectedCharacter.Id,
@@ -110,20 +109,20 @@ public async Task AddFriendAsync(long characterId, long secondChara
RelationType = CharacterRelationType.Friend
};
- await characterRelationDao.TryInsertOrUpdateAsync(data2).ConfigureAwait(false);
- friendRequestHolder.FriendRequestCharacters.TryRemove(friendRequest.First().Key, out _);
+ await characterRelationDao.TryInsertOrUpdateAsync(data2);
+ friendRequestRegistry.UnregisterRequest(friendRequest.First().Key);
return LanguageKey.FRIEND_ADDED;
case FinsPacketType.Rejected:
- friendRequestHolder.FriendRequestCharacters.TryRemove(friendRequest.First().Key, out _);
+ friendRequestRegistry.UnregisterRequest(friendRequest.First().Key);
return LanguageKey.FRIEND_REJECTED;
default:
logger.Error(logLanguage[LogLanguageKey.INVITETYPE_UNKNOWN]);
- friendRequestHolder.FriendRequestCharacters.TryRemove(friendRequest.First().Key, out _);
+ friendRequestRegistry.UnregisterRequest(friendRequest.First().Key);
throw new ArgumentException();
}
}
- friendRequestHolder.FriendRequestCharacters.TryRemove(friendRequest.First().Key, out _);
+ friendRequestRegistry.UnregisterRequest(friendRequest.First().Key);
throw new ArgumentException();
}
@@ -141,10 +140,10 @@ public async Task> GetFriendsAsync(long id)
var servers = await channelHub.GetCommunicationChannels();
var accounts = await pubSubHub.GetSubscribersAsync();
var character = accounts.FirstOrDefault(s => s.ConnectedCharacter?.Id == rel.RelatedCharacterId && servers.Where(c => c.Type == ServerType.WorldServer).Any(x => x.Id == s.ChannelId));
-
+
charList.Add(new CharacterRelationStatus
{
- CharacterName = (await characterDao.FirstOrDefaultAsync(s => s.CharacterId == rel.RelatedCharacterId).ConfigureAwait(false))?.Name,
+ CharacterName = (await characterDao.FirstOrDefaultAsync(s => s.CharacterId == rel.RelatedCharacterId))?.Name,
CharacterId = rel.RelatedCharacterId,
IsConnected = character != null,
RelationType = rel.RelationType,
@@ -158,21 +157,21 @@ public async Task> GetFriendsAsync(long id)
public async Task DeleteAsync(Guid id)
{
var rel = await characterRelationDao.FirstOrDefaultAsync(s =>
- (s.CharacterRelationId == id) && (s.RelationType == CharacterRelationType.Friend)).ConfigureAwait(false);
+ (s.CharacterRelationId == id) && (s.RelationType == CharacterRelationType.Friend));
if (rel == null)
{
return false;
}
var rel2 = await characterRelationDao.FirstOrDefaultAsync(s =>
(s.CharacterId == rel.RelatedCharacterId) && (s.RelatedCharacterId == rel.CharacterId) &&
- (s.RelationType == CharacterRelationType.Friend)).ConfigureAwait(false);
+ (s.RelationType == CharacterRelationType.Friend));
if (rel2 == null)
{
return false;
}
- await characterRelationDao.TryDeleteAsync(rel.CharacterRelationId).ConfigureAwait(false);
- await characterRelationDao.TryDeleteAsync(rel2.CharacterRelationId).ConfigureAwait(false);
+ await characterRelationDao.TryDeleteAsync(rel.CharacterRelationId);
+ await characterRelationDao.TryDeleteAsync(rel2.CharacterRelationId);
return true;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Holders/FriendRequestHolder.cs b/src/NosCore.GameObject/Services/FriendService/IFriendRequestRegistry.cs
similarity index 65%
rename from src/NosCore.GameObject/Holders/FriendRequestHolder.cs
rename to src/NosCore.GameObject/Services/FriendService/IFriendRequestRegistry.cs
index bf1cb98d8..003d5b3e9 100644
--- a/src/NosCore.GameObject/Holders/FriendRequestHolder.cs
+++ b/src/NosCore.GameObject/Services/FriendService/IFriendRequestRegistry.cs
@@ -1,29 +1,31 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
using System;
-using System.Collections.Concurrent;
+using System.Collections.Generic;
-namespace NosCore.GameObject.Holders
+namespace NosCore.GameObject.Services.FriendService
{
- public class FriendRequestHolder
+ public interface IFriendRequestRegistry
{
- public ConcurrentDictionary> FriendRequestCharacters { get; set; } = new();
+ IEnumerable> GetRequestsForCharacter(long characterId);
+ void RegisterRequest(Guid requestId, long senderId, long receiverId);
+ bool UnregisterRequest(Guid requestId);
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Group.cs b/src/NosCore.GameObject/Services/GroupService/Group.cs
similarity index 97%
rename from src/NosCore.GameObject/Group.cs
rename to src/NosCore.GameObject/Services/GroupService/Group.cs
index 26a3b4e2a..4916f1a80 100644
--- a/src/NosCore.GameObject/Group.cs
+++ b/src/NosCore.GameObject/Services/GroupService/Group.cs
@@ -1,19 +1,19 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
@@ -32,7 +32,7 @@
using NosCore.Networking.SessionGroup;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Services.GroupService
{
public class Group(GroupType type, ISessionGroupFactory sessionGroupFactory) : ConcurrentDictionary, Tuple>,
IBroadcastable
@@ -113,4 +113,4 @@ public void LeaveGroup(INamedEntity namedEntity)
TryRemove(new Tuple(namedEntity.VisualType, namedEntity.VisualId), out _);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/GroupService/GroupRegistry.cs b/src/NosCore.GameObject/Services/GroupService/GroupRegistry.cs
new file mode 100644
index 000000000..40b84fcf1
--- /dev/null
+++ b/src/NosCore.GameObject/Services/GroupService/GroupRegistry.cs
@@ -0,0 +1,62 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace NosCore.GameObject.Services.GroupService
+{
+ public class GroupRegistry : IGroupRegistry
+ {
+ private readonly ConcurrentDictionary _groupsById = new();
+ private readonly ConcurrentDictionary _characterToGroupId = new();
+ private long _nextId;
+
+ public Group? GetById(long groupId)
+ {
+ _groupsById.TryGetValue(groupId, out var group);
+ return group;
+ }
+
+ public void Register(Group group)
+ {
+ _groupsById[group.GroupId] = group;
+ }
+
+ public void Unregister(long groupId)
+ {
+ _groupsById.TryRemove(groupId, out _);
+ }
+
+ public void RegisterMember(long characterId, long groupId)
+ {
+ _characterToGroupId[characterId] = groupId;
+ }
+
+ public void UnregisterMember(long characterId)
+ {
+ _characterToGroupId.TryRemove(characterId, out _);
+ }
+
+ public long GetNextGroupId()
+ {
+ return Interlocked.Increment(ref _nextId);
+ }
+ }
+}
diff --git a/src/NosCore.GameObject/Holders/ExchangeRequestHolder.cs b/src/NosCore.GameObject/Services/GroupService/IGroupRegistry.cs
similarity index 66%
rename from src/NosCore.GameObject/Holders/ExchangeRequestHolder.cs
rename to src/NosCore.GameObject/Services/GroupService/IGroupRegistry.cs
index 4cc4071a7..d2eddf9b3 100644
--- a/src/NosCore.GameObject/Holders/ExchangeRequestHolder.cs
+++ b/src/NosCore.GameObject/Services/GroupService/IGroupRegistry.cs
@@ -1,30 +1,31 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-using System.Collections.Concurrent;
-
-namespace NosCore.GameObject.Holders
+namespace NosCore.GameObject.Services.GroupService
{
- public class ExchangeRequestHolder
+ public interface IGroupRegistry
{
- public readonly ConcurrentDictionary ExchangeDatas = new();
-
- public readonly ConcurrentDictionary ExchangeRequests = new();
+ Group? GetById(long groupId);
+ void Register(Group group);
+ void Unregister(long groupId);
+ void RegisterMember(long characterId, long groupId);
+ void UnregisterMember(long characterId);
+ long GetNextGroupId();
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/GuriRunnerService/GuriRunnerService.cs b/src/NosCore.GameObject/Services/GuriRunnerService/GuriRunnerService.cs
index 54053e7c2..3944a8f65 100644
--- a/src/NosCore.GameObject/Services/GuriRunnerService/GuriRunnerService.cs
+++ b/src/NosCore.GameObject/Services/GuriRunnerService/GuriRunnerService.cs
@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.Infastructure;
using NosCore.GameObject.Networking.ClientSession;
using NosCore.Packets.ClientPackets.UI;
using System;
diff --git a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/MfaGuriHandler.cs b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/MfaGuriHandler.cs
index 7441bae0a..d1f95630a 100644
--- a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/MfaGuriHandler.cs
+++ b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/MfaGuriHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -57,9 +57,9 @@ await requestData.ClientSession.SendPacketAsync(new NosCore.Packets.ServerPacket
Type = GuriPacketType.TextInput,
Argument = 3,
EntityId = 0
- }).ConfigureAwait(false);
+ });
- await requestData.ClientSession.SendPacketAsync(new InfoiPacket { Message = Game18NConstString.IncorrectPassword }).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(new InfoiPacket { Message = Game18NConstString.IncorrectPassword });
}
}
}
diff --git a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/SpeakerGuriHandler.cs b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/SpeakerGuriHandler.cs
index c384685b1..ee2f8d904 100644
--- a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/SpeakerGuriHandler.cs
+++ b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/SpeakerGuriHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -22,7 +22,6 @@
using NosCore.Data.Enumerations.I18N;
using NosCore.Data.Enumerations.Items;
using NosCore.GameObject.ComponentEntities.Extensions;
-using NosCore.GameObject.Networking;
using NosCore.GameObject.Networking.ClientSession;
using NosCore.GameObject.Services.InventoryService;
using NosCore.Packets.ClientPackets.UI;
@@ -83,16 +82,16 @@ public async Task ExecuteAsync(RequestData requestData)
return;
}
message = CraftMessage(message, valuesplit.Skip(2).ToArray()).Replace(' ', '|');
- await sessionRegistry.BroadcastPacketAsync(requestData.ClientSession.Character.GenerateSayItem(message, deeplink), requestData.ClientSession.Channel!.Id).ConfigureAwait(false);
+ await sessionRegistry.BroadcastPacketAsync(requestData.ClientSession.Character.GenerateSayItem(message, deeplink), requestData.ClientSession.Channel!.Id);
}
else
{
message = CraftMessage(message, valuesplit);
- await sessionRegistry.BroadcastPacketAsync(requestData.ClientSession.Character.GenerateSay(message, (SayColorType)13), requestData.ClientSession.Channel!.Id).ConfigureAwait(false);
+ await sessionRegistry.BroadcastPacketAsync(requestData.ClientSession.Character.GenerateSay(message, (SayColorType)13), requestData.ClientSession.Channel!.Id);
}
requestData.ClientSession.Character.InventoryService.RemoveItemAmountFromInventory(1, inv.ItemInstanceId);
- await requestData.ClientSession.Character.SendPacketAsync(inv.GeneratePocketChange(PocketType.Etc, (short)(requestData.Data.VisualId ?? 0))).ConfigureAwait(false);
+ await requestData.ClientSession.Character.SendPacketAsync(inv.GeneratePocketChange(PocketType.Etc, (short)(requestData.Data.VisualId ?? 0)));
}
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/TitleGuriHandler.cs b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/TitleGuriHandler.cs
index e90598304..dd6ffa214 100644
--- a/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/TitleGuriHandler.cs
+++ b/src/NosCore.GameObject/Services/GuriRunnerService/Handlers/TitleGuriHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -57,10 +57,10 @@ public async Task ExecuteAsync(RequestData requestData)
Active = false,
CharacterId = requestData.ClientSession.Character.VisualId
});
- await requestData.ClientSession.Character.MapInstance.SendPacketAsync(requestData.ClientSession.Character.GenerateTitle()).ConfigureAwait(false);
- await requestData.ClientSession.SendPacketAsync(new InfoiPacket { Message = Game18NConstString.TitleChangedOrHidden }).ConfigureAwait(false);
+ await requestData.ClientSession.Character.MapInstance.SendPacketAsync(requestData.ClientSession.Character.GenerateTitle());
+ await requestData.ClientSession.SendPacketAsync(new InfoiPacket { Message = Game18NConstString.TitleChangedOrHidden });
requestData.ClientSession.Character.InventoryService.RemoveItemAmountFromInventory(1, inv.ItemInstanceId);
- await requestData.ClientSession.SendPacketAsync(inv.GeneratePocketChange((PocketType)inv.Type, inv.Slot)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(inv.GeneratePocketChange((PocketType)inv.Type, inv.Slot));
}
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/GuriRunnerService/IGuriEventHandler.cs b/src/NosCore.GameObject/Services/GuriRunnerService/IGuriEventHandler.cs
index 485a66332..f0b0b9106 100644
--- a/src/NosCore.GameObject/Services/GuriRunnerService/IGuriEventHandler.cs
+++ b/src/NosCore.GameObject/Services/GuriRunnerService/IGuriEventHandler.cs
@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.Infastructure;
using NosCore.Packets.ClientPackets.UI;
namespace NosCore.GameObject.Services.GuriRunnerService
diff --git a/src/NosCore.GameObject/Services/InventoryService/IInventoryService.cs b/src/NosCore.GameObject/Services/InventoryService/IInventoryService.cs
index 63ecdd33c..18e597e4e 100644
--- a/src/NosCore.GameObject/Services/InventoryService/IInventoryService.cs
+++ b/src/NosCore.GameObject/Services/InventoryService/IInventoryService.cs
@@ -19,12 +19,14 @@
using NosCore.Data.Enumerations;
using NosCore.GameObject.Services.ItemGenerationService.Item;
+using NosCore.GameObject.Services.ItemStorage;
using System;
using System.Collections.Generic;
namespace NosCore.GameObject.Services.InventoryService
{
- public interface IInventoryService : IDictionary
+ public interface IInventoryService : IDictionary,
+ IMutableSlotBasedStorage
{
Dictionary Expensions { get; set; }
@@ -35,7 +37,6 @@ public interface IInventoryService : IDictionary
AddItemToPocket(InventoryItemInstance newItem, NoscorePocketType? type, short? slot);
bool CanAddItem(short itemVnum);
- int CountItem(int itemVNum);
int CountItemInAnPocket(NoscorePocketType inv);
InventoryItemInstance? DeleteById(Guid id);
InventoryItemInstance? DeleteFromTypeAndSlot(NoscorePocketType type, short slot);
@@ -48,10 +49,6 @@ public interface IInventoryService : IDictionary
InventoryItemInstance? MoveInPocket(short sourceSlot, NoscorePocketType sourceType, NoscorePocketType targetType,
short? targetSlot, bool swap);
- bool TryMoveItem(NoscorePocketType sourcetype, short sourceSlot, short amount, short destinationSlot,
- out InventoryItemInstance? sourcePocket, out InventoryItemInstance? destinationPocket);
-
- bool EnoughPlace(List itemInstances, NoscorePocketType type);
InventoryItemInstance? RemoveItemAmountFromInventory(short amount, Guid id);
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/InventoryService/InventoryItemInstance.cs b/src/NosCore.GameObject/Services/InventoryService/InventoryItemInstance.cs
index 79fcb3994..64bfc129f 100644
--- a/src/NosCore.GameObject/Services/InventoryService/InventoryItemInstance.cs
+++ b/src/NosCore.GameObject/Services/InventoryService/InventoryItemInstance.cs
@@ -18,20 +18,31 @@
// along with this program. If not, see .
using NosCore.Data.Dto;
+using NosCore.Data.Enumerations;
using NosCore.GameObject.Services.ItemGenerationService.Item;
+using NosCore.GameObject.Services.ItemStorage;
using System;
namespace NosCore.GameObject.Services.InventoryService
{
- public class InventoryItemInstance : InventoryItemInstanceDto
+ public class InventoryItemInstance : InventoryItemInstanceDto, ISlotItem
{
public InventoryItemInstance(IItemInstance itemInstance)
{
ItemInstance = itemInstance;
ItemInstanceId = itemInstance.Id;
}
+
public IItemInstance ItemInstance { get; set; }
+ IItemInstance? ISlotItem.ItemInstance => ItemInstance;
+
+ NoscorePocketType ISlotItem.SlotType
+ {
+ get => Type;
+ set => Type = value;
+ }
+
public static InventoryItemInstance Create(IItemInstance it, long characterId)
{
return Create(it, characterId, null);
diff --git a/src/NosCore.GameObject/Services/InventoryService/InventoryService.cs b/src/NosCore.GameObject/Services/InventoryService/InventoryService.cs
index fd30b33de..15826ec69 100644
--- a/src/NosCore.GameObject/Services/InventoryService/InventoryService.cs
+++ b/src/NosCore.GameObject/Services/InventoryService/InventoryService.cs
@@ -23,6 +23,7 @@
using NosCore.Data.Enumerations;
using NosCore.Data.StaticEntities;
using NosCore.GameObject.Services.ItemGenerationService.Item;
+using NosCore.GameObject.Services.ItemStorage;
using Serilog;
using System;
using System.Collections.Concurrent;
@@ -34,7 +35,7 @@ namespace NosCore.GameObject.Services.InventoryService
public class InventoryService(List items, IOptions configuration, ILogger logger)
: ConcurrentDictionary, IInventoryService
{
- private byte GetMaxSlot(NoscorePocketType pocket)
+ public int GetMaxSlots(NoscorePocketType pocket)
{
//TODO make this configurable
return (byte)(pocket switch
@@ -104,6 +105,11 @@ public int CountItemInAnPocket(NoscorePocketType inv)
public List? AddItemToPocket(InventoryItemInstance newItem, NoscorePocketType? type,
short? slot)
{
+ if (newItem?.ItemInstance == null || newItem.ItemInstance.Amount <= 0)
+ {
+ return null;
+ }
+
var invlist = new List();
// override type if necessary
if (type.HasValue)
@@ -118,7 +124,7 @@ public int CountItemInAnPocket(NoscorePocketType inv)
var slotNotFull = this.ToList().Select(s => s.Value).Where(i =>
i.ItemInstance.ItemVNum.Equals(newItem.ItemInstance.ItemVNum) &&
(i.ItemInstance.Amount < configuration.Value.MaxItemAmount));
- var freeslot = GetMaxSlot(newItem.Type) - this.Count(s => s.Value.Type == newItem.Type);
+ var freeslot = GetMaxSlots(newItem.Type) - this.Count(s => s.Value.Type == newItem.Type);
IEnumerable itemInstances =
slotNotFull as IList ?? slotNotFull.ToList();
if (newItem.ItemInstance.Amount <= freeslot * configuration.Value.MaxItemAmount
@@ -161,8 +167,8 @@ public int CountItemInAnPocket(NoscorePocketType inv)
return null;
}
- if (this.Any(s => (s.Value.Slot == newItem.Slot) && (s.Value.Type == newItem.Type))
- || (newItem.Slot >= GetMaxSlot(newItem.Type)))
+ if (newItem.Slot < 0 || newItem.Slot >= GetMaxSlots(newItem.Type)
+ || this.Any(s => (s.Value.Slot == newItem.Slot) && (s.Value.Type == newItem.Type)))
{
return null;
}
@@ -336,8 +342,8 @@ public bool TryMoveItem(NoscorePocketType sourcetype, short sourceSlot, short am
sourcePocket = LoadBySlotAndType(sourceSlot, sourcetype);
destinationPocket = LoadBySlotAndType(destinationSlot, sourcetype);
- if ((sourceSlot == destinationSlot) || (amount == 0)
- || (destinationSlot > GetMaxSlot(sourcetype)))
+ if ((sourceSlot == destinationSlot) || (amount <= 0)
+ || (destinationSlot < 0) || (destinationSlot >= GetMaxSlots(sourcetype)))
{
return false;
}
@@ -436,7 +442,7 @@ public bool EnoughPlace(List itemInstances, NoscorePocketType typ
var itemList = this.Select(s => s.Value).Where(i => i.Type == type).ToList();
if (!place.ContainsKey(type))
{
- place.Add(type, GetMaxSlot(type) - itemList.Count);
+ place.Add(type, GetMaxSlots(type) - itemList.Count);
}
var amount = itemGroup.Sum(s => s.Amount);
@@ -457,6 +463,11 @@ public bool EnoughPlace(List itemInstances, NoscorePocketType typ
public InventoryItemInstance? RemoveItemAmountFromInventory(short amount, Guid id)
{
+ if (amount <= 0)
+ {
+ return null;
+ }
+
var inv = this[id];
if (inv?.ItemInstance != null)
{
@@ -474,20 +485,58 @@ public bool EnoughPlace(List itemInstances, NoscorePocketType typ
return null;
}
- private short? GetFreeSlot(NoscorePocketType type)
+ public short? GetFreeSlot(NoscorePocketType type)
{
- var itemInstanceSlotsByType = this.Select(s => s.Value).Where(i => i.Type == type).OrderBy(i => i.Slot)
- .Select(i => (int)i.Slot);
- IEnumerable instanceSlotsByType =
- itemInstanceSlotsByType as int[] ?? itemInstanceSlotsByType.ToArray();
- var nextFreeSlot = instanceSlotsByType.Any()
- ? Enumerable
- .Range(0, GetMaxSlot(type) + 1)
- .Except(instanceSlotsByType).FirstOrDefault()
- : 0;
- return (short?)nextFreeSlot < GetMaxSlot(type) ? (short?)nextFreeSlot : null;
+ var maxSlots = GetMaxSlots(type);
+ var occupiedSlots = new HashSet(
+ this.Select(s => s.Value).Where(i => i.Type == type).Select(i => i.Slot));
+
+ for (short slot = 0; slot < maxSlots; slot++)
+ {
+ if (!occupiedSlots.Contains(slot))
+ {
+ return slot;
+ }
+ }
+
+ return null;
}
+ public bool HasFreeSlot(NoscorePocketType slotType) => GetFreeSlot(slotType).HasValue;
+
+ public IEnumerable GetAllBySlotType(NoscorePocketType slotType) =>
+ this.Select(s => s.Value).Where(i => i.Type == slotType);
+
+ public IEnumerable GetAll() => this.Select(s => s.Value);
+
+ InventoryItemInstance? ISlotBasedStorage.GetBySlot(short slot, NoscorePocketType slotType) =>
+ LoadBySlotAndType(slot, slotType);
+
+ InventoryItemInstance? ISlotBasedStorage.GetById(Guid id) =>
+ LoadByItemInstanceId(id);
+
+ int ISlotBasedStorage.CountBySlotType(NoscorePocketType slotType) =>
+ CountItemInAnPocket(slotType);
+
+ List? IMutableSlotBasedStorage.AddItem(
+ InventoryItemInstance item, NoscorePocketType? slotType, short? slot) =>
+ AddItemToPocket(item, slotType, slot);
+
+ InventoryItemInstance? IMutableSlotBasedStorage.RemoveBySlot(
+ short slot, NoscorePocketType slotType) =>
+ DeleteFromTypeAndSlot(slotType, slot);
+
+ InventoryItemInstance? IMutableSlotBasedStorage.RemoveById(Guid id) =>
+ DeleteById(id);
+
+ InventoryItemInstance? IMutableSlotBasedStorage.RemoveItemAmount(
+ short amount, Guid id) =>
+ RemoveItemAmountFromInventory(amount, id);
+
+ InventoryItemInstance? IMutableSlotBasedStorage.MoveItem(
+ short sourceSlot, NoscorePocketType sourceType, NoscorePocketType targetType, short? targetSlot, bool swap) =>
+ MoveInPocket(sourceSlot, sourceType, targetType, targetSlot, swap);
+
private InventoryItemInstance? TakeItem(short slot, NoscorePocketType type)
{
var itemInstance = this.Select(s => s.Value).SingleOrDefault(i => (i.Slot == slot) && (i.Type == type));
diff --git a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BackPackHandler.cs b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BackPackHandler.cs
index faf754570..bf1fe4eb6 100644
--- a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BackPackHandler.cs
+++ b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BackPackHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -56,7 +56,7 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Green,
Message = Game18NConstString.NotInPair
- }).ConfigureAwait(false);
+ });
return;
}
@@ -69,7 +69,7 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Green,
Message = Game18NConstString.NotInPair
- }).ConfigureAwait(false);
+ });
return;
}
@@ -88,14 +88,14 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
Message = Game18NConstString.EffectActivated,
ArgumentType = 2,
Game18NArguments = { itemInstance.ItemInstance.Item.VNum.ToString() }
- }).ConfigureAwait(false);
+ });
await requestData.ClientSession.SendPacketAsync(
- itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot)).ConfigureAwait(false);
+ itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot));
requestData.ClientSession.Character.InventoryService.RemoveItemAmountFromInventory(1,
itemInstance.ItemInstanceId);
requestData.ClientSession.Character.LoadExpensions();
- await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateExts(conf)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateExts(conf));
}
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BazaarMedalsHandler.cs b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BazaarMedalsHandler.cs
index d61799914..e6510131e 100644
--- a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BazaarMedalsHandler.cs
+++ b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/BazaarMedalsHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -67,9 +67,9 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
Message = Game18NConstString.EffectActivated,
ArgumentType = 2,
Game18NArguments = { itemInstance.ItemInstance.Item.VNum.ToString() }
- }).ConfigureAwait(false);
+ });
- await requestData.ClientSession.SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot));
requestData.ClientSession.Character.InventoryService.RemoveItemAmountFromInventory(1, itemInstance.ItemInstanceId);
}
}
diff --git a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/MinilandBellHandler.cs b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/MinilandBellHandler.cs
index 0e7683eb8..887dec4c4 100644
--- a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/MinilandBellHandler.cs
+++ b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/MinilandBellHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -52,7 +52,7 @@ await requestData.ClientSession.Character.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Yellow,
Message = Game18NConstString.CanNotBeUsedHere
- }).ConfigureAwait(false);
+ });
return;
}
@@ -64,7 +64,7 @@ await requestData.ClientSession.Character.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Yellow,
Message = Game18NConstString.OnlyPotionInVehicle
- }).ConfigureAwait(false);
+ });
return;
}
@@ -75,14 +75,14 @@ await requestData.ClientSession.SendPacketAsync(new DelayPacket
Delay = 5000,
Type = DelayPacketType.ItemInUse,
Packet = requestData.ClientSession.Character.GenerateUseItem((PocketType)itemInstance.Type, itemInstance.Slot, 2, 0)
- }).ConfigureAwait(false);
+ });
return;
}
requestData.ClientSession.Character.InventoryService.RemoveItemAmountFromInventory(1, itemInstance.ItemInstanceId);
- await requestData.ClientSession.SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(itemInstance.GeneratePocketChange((PocketType)itemInstance.Type, itemInstance.Slot));
var miniland = minilandProvider.GetMiniland(requestData.ClientSession.Character.CharacterId);
- await mapChangeService.ChangeMapInstanceAsync(requestData.ClientSession, miniland.MapInstanceId, 5, 8).ConfigureAwait(false);
+ await mapChangeService.ChangeMapInstanceAsync(requestData.ClientSession, miniland.MapInstanceId, 5, 8);
}
}
}
\ No newline at end of file
diff --git a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/SpRechargerHandler.cs b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/SpRechargerHandler.cs
index e258bdae2..1b81df2dd 100644
--- a/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/SpRechargerHandler.cs
+++ b/src/NosCore.GameObject/Services/ItemGenerationService/Handlers/SpRechargerHandler.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -48,8 +48,8 @@ public async Task ExecuteAsync(RequestData> requestData)
{
- await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEff(123)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEff(123));
var itemInstance = requestData.Data.Item1;
var packet = requestData.Data.Item2;
@@ -71,7 +71,7 @@ await requestData.ClientSession.SendPacketAsync(
(PocketType)itemInstance.Type,
itemInstance.Slot, 1, (byte)(packet.Parameter ?? 0)),
Question = requestData.ClientSession.GetMessageFromKey(LanguageKey.ASK_BIND)
- }).ConfigureAwait(false);
+ });
return;
}
@@ -90,7 +90,7 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Yellow,
Message = Game18NConstString.CanNotWearThat
- }).ConfigureAwait(false);
+ });
return;
}
@@ -108,7 +108,7 @@ await requestData.ClientSession.SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.SpecialistAndFairyDifferentElement
- }).ConfigureAwait(false);
+ });
return;
}
}
@@ -127,7 +127,7 @@ await requestData.ClientSession.SendPacketAsync(new MsgiPacket
Message = Game18NConstString.CantTrasformWithSideEffect,
ArgumentType = 4,
Game18NArguments = { requestData.ClientSession.Character.SpCooldown - (int)Math.Round(timeSpanSinceLastSpUsage) }
- }).ConfigureAwait(false);
+ });
return;
}
@@ -139,7 +139,7 @@ await requestData.ClientSession.SendPacketAsync(new SayiPacket
VisualId = requestData.ClientSession.Character.CharacterId,
Type = SayColorType.Yellow,
Message = Game18NConstString.SpecialistCardsCannotBeTradedWhileTransformed
- }).ConfigureAwait(false);
+ });
return;
}
@@ -149,7 +149,7 @@ await requestData.ClientSession.SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.CantUseBecauseSoulDestroyed
- }).ConfigureAwait(false);
+ });
return;
}
}
@@ -160,7 +160,7 @@ await requestData.ClientSession.SendPacketAsync(new MsgiPacket
{
Type = MessageType.Default,
Message = Game18NConstString.CanNotBeWornDifferentClass
- }).ConfigureAwait(false);
+ });
return;
}
@@ -171,26 +171,26 @@ await requestData.ClientSession.SendPacketAsync(new MsgiPacket
requestData.ClientSession.Character.InventoryService
.LoadBySlotAndType(packet.Slot, (NoscorePocketType)packet.Type);
- await requestData.ClientSession.SendPacketAsync(newItem.GeneratePocketChange(packet.Type, packet.Slot)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(newItem.GeneratePocketChange(packet.Type, packet.Slot));
await requestData.ClientSession.Character.MapInstance.SendPacketAsync(requestData.ClientSession.Character
- .GenerateEq()).ConfigureAwait(false);
- await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEquipment()).ConfigureAwait(false);
+ .GenerateEq());
+ await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEquipment());
if (itemInstance.ItemInstance.Item.EquipmentSlot == EquipmentType.Sp)
{
- await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateSpPoint()).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateSpPoint());
}
if (itemInstance.ItemInstance.Item.EquipmentSlot == EquipmentType.Fairy)
{
await requestData.ClientSession.Character.MapInstance.SendPacketAsync(
- requestData.ClientSession.Character.GeneratePairy(itemInstance.ItemInstance as WearableInstance)).ConfigureAwait(false);
+ requestData.ClientSession.Character.GeneratePairy(itemInstance.ItemInstance as WearableInstance));
}
if (itemInstance.ItemInstance.Item.EquipmentSlot == EquipmentType.Amulet)
{
- await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEff(39)).ConfigureAwait(false);
+ await requestData.ClientSession.SendPacketAsync(requestData.ClientSession.Character.GenerateEff(39));
}
itemInstance.ItemInstance.BoundCharacterId = requestData.ClientSession.Character.CharacterId;
diff --git a/src/NosCore.GameObject/Services/ItemGenerationService/IUseItemEventHandler.cs b/src/NosCore.GameObject/Services/ItemGenerationService/IUseItemEventHandler.cs
index 25d716b7f..8a05c4601 100644
--- a/src/NosCore.GameObject/Services/ItemGenerationService/IUseItemEventHandler.cs
+++ b/src/NosCore.GameObject/Services/ItemGenerationService/IUseItemEventHandler.cs
@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using NosCore.GameObject.Infastructure;
using NosCore.GameObject.Services.InventoryService;
using NosCore.Packets.ClientPackets.Inventory;
using System;
diff --git a/src/NosCore.GameObject/Services/ItemStorage/ISlotBasedStorage.cs b/src/NosCore.GameObject/Services/ItemStorage/ISlotBasedStorage.cs
new file mode 100644
index 000000000..312223c90
--- /dev/null
+++ b/src/NosCore.GameObject/Services/ItemStorage/ISlotBasedStorage.cs
@@ -0,0 +1,68 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using NosCore.GameObject.Services.ItemGenerationService.Item;
+using System;
+using System.Collections.Generic;
+
+namespace NosCore.GameObject.Services.ItemStorage
+{
+ public interface ISlotBasedStorage
+ where TItem : class, ISlotItem
+ where TSlotType : struct, Enum
+ {
+ int GetMaxSlots(TSlotType slotType);
+
+ TItem? GetBySlot(short slot, TSlotType slotType);
+
+ TItem? GetById(Guid id);
+
+ IEnumerable GetAllBySlotType(TSlotType slotType);
+
+ IEnumerable GetAll();
+
+ short? GetFreeSlot(TSlotType slotType);
+
+ bool HasFreeSlot(TSlotType slotType);
+
+ int CountBySlotType(TSlotType slotType);
+
+ int CountItem(int itemVNum);
+ }
+
+ public interface IMutableSlotBasedStorage : ISlotBasedStorage
+ where TItem : class, ISlotItem
+ where TSlotType : struct, Enum
+ {
+ List? AddItem(TItem item, TSlotType? slotType = null, short? slot = null);
+
+ TItem? RemoveBySlot(short slot, TSlotType slotType);
+
+ TItem? RemoveById(Guid id);
+
+ TItem? RemoveItemAmount(short amount, Guid id);
+
+ TItem? MoveItem(short sourceSlot, TSlotType sourceType, TSlotType targetType, short? targetSlot = null, bool swap = false);
+
+ bool TryMoveItem(TSlotType slotType, short sourceSlot, short amount, short destinationSlot,
+ out TItem? sourcePocket, out TItem? destinationPocket);
+
+ bool EnoughPlace(List items, TSlotType slotType);
+ }
+}
diff --git a/src/NosCore.GameObject/WarehouseItem.cs b/src/NosCore.GameObject/Services/ItemStorage/ISlotItem.cs
similarity index 67%
rename from src/NosCore.GameObject/WarehouseItem.cs
rename to src/NosCore.GameObject/Services/ItemStorage/ISlotItem.cs
index 43a728552..ce764f72d 100644
--- a/src/NosCore.GameObject/WarehouseItem.cs
+++ b/src/NosCore.GameObject/Services/ItemStorage/ISlotItem.cs
@@ -1,29 +1,37 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-using NosCore.Data.Dto;
using NosCore.GameObject.Services.ItemGenerationService.Item;
+using System;
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Services.ItemStorage
{
- public class WarehouseItem : WarehouseItemDto
+ public interface ISlotItem
{
- public IItemInstance? ItemInstance { get; set; }
+ Guid Id { get; }
+ short Slot { get; set; }
+ IItemInstance? ItemInstance { get; }
}
-}
\ No newline at end of file
+
+ public interface ISlotItem : ISlotItem
+ where TSlotType : struct, Enum
+ {
+ TSlotType SlotType { get; set; }
+ }
+}
diff --git a/src/NosCore.GameObject/Services/ItemStorage/SlotStorageHelper.cs b/src/NosCore.GameObject/Services/ItemStorage/SlotStorageHelper.cs
new file mode 100644
index 000000000..328f662e5
--- /dev/null
+++ b/src/NosCore.GameObject/Services/ItemStorage/SlotStorageHelper.cs
@@ -0,0 +1,245 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using NosCore.GameObject.Services.ItemGenerationService.Item;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace NosCore.GameObject.Services.ItemStorage
+{
+ public static class SlotStorageHelper
+ {
+ public static short? FindFreeSlot(
+ IEnumerable items,
+ Func slotSelector,
+ int maxSlots)
+ where TItem : class
+ {
+ if (maxSlots <= 0 || maxSlots > short.MaxValue)
+ {
+ return null;
+ }
+
+ var occupiedSlots = new HashSet(items.Select(slotSelector));
+
+ for (short slot = 0; slot < maxSlots; slot++)
+ {
+ if (!occupiedSlots.Contains(slot))
+ {
+ return slot;
+ }
+ }
+
+ return null;
+ }
+
+ public static List StackItems(
+ IEnumerable existingItems,
+ TItem newItem,
+ Func itemInstanceSelector,
+ Action setAmount,
+ short maxItemAmount,
+ int maxSlots,
+ int currentCount)
+ where TItem : class
+ {
+ var result = new List();
+ var newItemInstance = itemInstanceSelector(newItem);
+
+ if (newItemInstance == null)
+ {
+ return result;
+ }
+
+ var slotNotFull = existingItems
+ .Where(i =>
+ {
+ var inst = itemInstanceSelector(i);
+ return inst != null &&
+ inst.ItemVNum == newItemInstance.ItemVNum &&
+ inst.Amount < maxItemAmount;
+ })
+ .ToList();
+
+ var freeSlotCount = maxSlots - currentCount;
+ var totalCapacity = freeSlotCount * maxItemAmount +
+ slotNotFull.Sum(s => maxItemAmount - (itemInstanceSelector(s)?.Amount ?? 0));
+
+ if (newItemInstance.Amount > totalCapacity)
+ {
+ return result;
+ }
+
+ foreach (var existingSlot in slotNotFull)
+ {
+ var existingInstance = itemInstanceSelector(existingSlot);
+ if (existingInstance == null || newItemInstance.Amount <= 0)
+ {
+ continue;
+ }
+
+ var combinedAmount = existingInstance.Amount + newItemInstance.Amount;
+ var maxAmount = combinedAmount > maxItemAmount ? maxItemAmount : combinedAmount;
+ var remaining = (short)(existingInstance.Amount + newItemInstance.Amount - maxAmount);
+
+ existingInstance.Amount = (short)maxAmount;
+ newItemInstance.Amount = remaining;
+
+ result.Add(existingSlot);
+ }
+
+ return result;
+ }
+
+ public static bool CanStack(IItemInstance? itemInstance)
+ {
+ if (itemInstance == null)
+ {
+ return false;
+ }
+
+ var itemType = itemInstance.Item?.Type;
+ return itemType == Data.Enumerations.NoscorePocketType.Etc ||
+ itemType == Data.Enumerations.NoscorePocketType.Main;
+ }
+
+ public static bool ValidateEnoughPlace(
+ IEnumerable existingItems,
+ List itemsToAdd,
+ Func itemInstanceSelector,
+ short maxItemAmount,
+ int maxSlots,
+ bool isStackable)
+ where TItem : class
+ {
+ var existingList = existingItems.ToList();
+ var currentCount = existingList.Count;
+ var availableSlots = maxSlots - currentCount;
+
+ foreach (var itemGroup in itemsToAdd.GroupBy(s => s.ItemVNum))
+ {
+ var amount = itemGroup.Sum(s => s.Amount);
+
+ if (isStackable)
+ {
+ var existingCapacity = existingList
+ .Where(s => itemInstanceSelector(s)?.ItemVNum == itemGroup.Key)
+ .Sum(s => maxItemAmount - (itemInstanceSelector(s)?.Amount ?? 0));
+
+ var needsNewSlots = amount - existingCapacity;
+ if (needsNewSlots > 0)
+ {
+ var slotsNeeded = (int)Math.Ceiling((double)needsNewSlots / maxItemAmount);
+ availableSlots -= slotsNeeded;
+ }
+ }
+ else
+ {
+ availableSlots -= itemGroup.Count();
+ }
+
+ if (availableSlots < 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static (TItem? Source, TItem? Destination) SwapItems(
+ TItem source,
+ TItem destination,
+ Action setSlot)
+ where TItem : class, ISlotItem
+ {
+ var sourceSlot = source.Slot;
+ var destSlot = destination.Slot;
+
+ setSlot(source, destSlot);
+ setSlot(destination, sourceSlot);
+
+ return (source, destination);
+ }
+
+ public static TItem? SplitItem(
+ TItem source,
+ short amount,
+ short destinationSlot,
+ Func createNewItem)
+ where TItem : class, ISlotItem
+ {
+ var sourceInstance = source.ItemInstance;
+ if (sourceInstance == null || sourceInstance.Amount < amount)
+ {
+ return null;
+ }
+
+ var clonedInstance = (IItemInstance)sourceInstance.Clone();
+ sourceInstance.Amount -= amount;
+ clonedInstance.Amount = amount;
+ clonedInstance.Id = Guid.NewGuid();
+
+ return createNewItem(clonedInstance, Guid.NewGuid(), destinationSlot);
+ }
+
+ public static bool TryStackOntoExisting(
+ TItem source,
+ TItem destination,
+ short amount,
+ short maxItemAmount,
+ Action? removeSource = null)
+ where TItem : class, ISlotItem
+ {
+ var sourceInstance = source.ItemInstance;
+ var destInstance = destination.ItemInstance;
+
+ if (sourceInstance == null || destInstance == null)
+ {
+ return false;
+ }
+
+ if (sourceInstance.ItemVNum != destInstance.ItemVNum)
+ {
+ return false;
+ }
+
+ var totalAmount = destInstance.Amount + amount;
+ if (totalAmount > maxItemAmount)
+ {
+ var overflow = totalAmount - maxItemAmount;
+ destInstance.Amount = maxItemAmount;
+ sourceInstance.Amount = (short)overflow;
+ }
+ else
+ {
+ destInstance.Amount = (short)totalAmount;
+ sourceInstance.Amount -= amount;
+
+ if (sourceInstance.Amount == 0)
+ {
+ removeSource?.Invoke(source);
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/NosCore.GameObject/Services/LoginService/LoginService.cs b/src/NosCore.GameObject/Services/LoginService/LoginService.cs
index 74469a10f..fda5d4c00 100644
--- a/src/NosCore.GameObject/Services/LoginService/LoginService.cs
+++ b/src/NosCore.GameObject/Services/LoginService/LoginService.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -60,36 +60,36 @@ public async Task LoginAsync(string? username, string md5String, ClientVersionSu
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.OldClient
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
return;
}
if (useApiAuth)
{
- username = await authHttpClient.GetAwaitingConnectionAsync(null, passwordToken, clientSession.SessionId).ConfigureAwait(false);
+ username = await authHttpClient.GetAwaitingConnectionAsync(null, passwordToken, clientSession.SessionId);
}
- var acc = await accountDao.FirstOrDefaultAsync(s => s.Name.ToLower() == (username ?? "").ToLower()).ConfigureAwait(false);
+ var acc = await accountDao.FirstOrDefaultAsync(s => s.Name.ToLower() == (username ?? "").ToLower());
if ((acc != null) && (acc.Name != username))
{
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.WrongCaps
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
return;
}
if ((acc == null)
- || (!useApiAuth && !string.Equals(acc.Password, passwordToken, StringComparison.OrdinalIgnoreCase)))
+ || (!useApiAuth && !string.Equals(acc.Password, passwordToken, StringComparison.Ordinal)))
{
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.AccountOrPasswordWrong
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
return;
}
@@ -99,14 +99,14 @@ await clientSession.SendPacketAsync(new FailcPacket
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.Banned
- }).ConfigureAwait(false);
+ });
break;
case AuthorityType.Closed:
case AuthorityType.Unconfirmed:
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.CantConnect
- }).ConfigureAwait(false);
+ });
break;
default:
var connectedAccount = await pubSubHub.GetSubscribersAsync();
@@ -117,21 +117,21 @@ await clientSession.SendPacketAsync(new FailcPacket
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.AlreadyConnected
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
return;
}
acc.Language = language;
- acc = await accountDao.TryInsertOrUpdateAsync(acc).ConfigureAwait(false);
+ acc = await accountDao.TryInsertOrUpdateAsync(acc);
if (servers.Count <= 0)
{
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.CantConnect
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
return;
}
@@ -195,19 +195,19 @@ await clientSession.SendPacketAsync(new FailcPacket
Name = useApiAuth ? "4" : "1"
}); //useless server to end the client reception
- await clientSession.SendPacketAsync(nstest).ConfigureAwait(false);
+ await clientSession.SendPacketAsync(nstest);
return;
}
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ await clientSession.DisconnectAsync();
}
catch
{
await clientSession.SendPacketAsync(new FailcPacket
{
Type = LoginFailType.UnhandledError
- }).ConfigureAwait(false);
- await clientSession.DisconnectAsync().ConfigureAwait(false);
+ });
+ await clientSession.DisconnectAsync();
}
}
}
diff --git a/src/NosCore.GameObject/Gift.cs b/src/NosCore.GameObject/Services/MailService/Gift.cs
similarity index 92%
rename from src/NosCore.GameObject/Gift.cs
rename to src/NosCore.GameObject/Services/MailService/Gift.cs
index 518b39a64..d7770e3f0 100644
--- a/src/NosCore.GameObject/Gift.cs
+++ b/src/NosCore.GameObject/Services/MailService/Gift.cs
@@ -1,23 +1,23 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-namespace NosCore.GameObject
+namespace NosCore.GameObject.Services.MailService
{
public class Gift
{
@@ -39,8 +39,8 @@ public Gift(short vnum, byte amount, short design = 0, bool isRareRandom = false
public short VNum { get; set; }
- public bool IsRandomRare { get; set; }
-
public bool IsRareRandom { get; set; }
+
+ public bool IsRandomRare { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Helper/GiftHelper.cs b/src/NosCore.GameObject/Services/MailService/GiftHelper.cs
similarity index 96%
rename from src/NosCore.GameObject/Helper/GiftHelper.cs
rename to src/NosCore.GameObject/Services/MailService/GiftHelper.cs
index 3a0952170..9c1f8f01d 100644
--- a/src/NosCore.GameObject/Helper/GiftHelper.cs
+++ b/src/NosCore.GameObject/Services/MailService/GiftHelper.cs
@@ -1,19 +1,19 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
-//
+//
// Copyright (C) 2019 - NosCore
-//
+//
// NosCore is a free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
@@ -23,7 +23,7 @@
using NosCore.GameObject.ComponentEntities.Extensions;
using NosCore.GameObject.ComponentEntities.Interfaces;
-namespace NosCore.GameObject.Helper;
+namespace NosCore.GameObject.Services.MailService;
public static class GiftHelper
{
@@ -62,4 +62,4 @@ public static MailRequest GenerateMailRequest(IClock clock, ICharacterEntity cha
};
return new MailRequest { Mail = mail, VNum = vnum, Amount = amount, Rare = rare, Upgrade = upgrade };
}
-}
\ No newline at end of file
+}
diff --git a/src/NosCore.GameObject/Services/MailService/IParcelRegistry.cs b/src/NosCore.GameObject/Services/MailService/IParcelRegistry.cs
new file mode 100644
index 000000000..807a11ce3
--- /dev/null
+++ b/src/NosCore.GameObject/Services/MailService/IParcelRegistry.cs
@@ -0,0 +1,34 @@
+// __ _ __ __ ___ __ ___ ___
+// | \| |/__\ /' _/ / _//__\| _ \ __|
+// | | ' | \/ |`._`.| \_| \/ | v / _|
+// |_|\__|\__/ |___/ \__/\__/|_|_\___|
+//
+// Copyright (C) 2019 - NosCore
+//
+// NosCore is a free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Concurrent;
+using NosCore.GameObject.InterChannelCommunication.Messages;
+
+namespace NosCore.GameObject.Services.MailService
+{
+ public interface IParcelRegistry
+ {
+ ConcurrentDictionary GetMails(long characterId, bool isSenderCopy);
+ MailData? GetMail(long characterId, bool isSenderCopy, long mailId);
+ void AddMail(long characterId, bool isSenderCopy, long mailId, MailData mailData);
+ bool RemoveMail(long characterId, bool isSenderCopy, long mailId, out MailData? mailData);
+ void UpdateMail(long characterId, bool isSenderCopy, long mailId, MailData mailData);
+ long GetNextMailId(long characterId, bool isSenderCopy);
+ }
+}
diff --git a/src/NosCore.GameObject/Services/MailService/MailService.cs b/src/NosCore.GameObject/Services/MailService/MailService.cs
index 32b22caa7..60f1274c9 100644
--- a/src/NosCore.GameObject/Services/MailService/MailService.cs
+++ b/src/NosCore.GameObject/Services/MailService/MailService.cs
@@ -1,4 +1,4 @@
-// __ _ __ __ ___ __ ___ ___
+// __ _ __ __ ___ __ ___ ___
// | \| |/__\ /' _/ / _//__\| _ \ __|
// | | ' | \/ |`._`.| \_| \/ | v / _|
// |_|\__|\__/ |___/ \__/\__/|_|_\___|
@@ -26,7 +26,6 @@
using NosCore.Data.Enumerations.Items;
using NosCore.Data.StaticEntities;
using NosCore.Data.WebApi;
-using NosCore.GameObject.Holders;
using NosCore.GameObject.Services.ItemGenerationService;
using System;
using System.Collections.Generic;
@@ -45,21 +44,22 @@ namespace NosCore.GameObject.Services.MailService
public class MailService(IDao mailDao, IDao itemInstanceDao,
IPubSubHub pubSubHub, IChannelHub channelHub,
List items, IItemGenerationService itemProvider,
- ParcelHolder parcelHolder,
+ IParcelRegistry parcelRegistry,
IDao characterDto)
: IMailService
{
public List GetMails(long id, long characterId, bool senderCopy)
{
- var mails = parcelHolder[characterId][false].Values.Concat(parcelHolder[characterId][true].Values);
+ var mails = parcelRegistry.GetMails(characterId, false).Values.Concat(parcelRegistry.GetMails(characterId, true).Values);
if (id == -1)
{
return mails.ToList();
}
- if (parcelHolder[characterId][senderCopy].ContainsKey(id))
+ var mail = parcelRegistry.GetMail(characterId, senderCopy, id);
+ if (mail != null)
{
- mails = new[] { parcelHolder[characterId][senderCopy][id] };
+ mails = new[] { mail };
}
else
{
@@ -71,15 +71,19 @@ public List GetMails(long id, long characterId, bool senderCopy)
public async Task