M Core/NosSmooth.Game/Data/Characters/Character.cs => Core/NosSmooth.Game/Data/Characters/Character.cs +0 -20
@@ 17,26 17,6 @@ namespace NosSmooth.Game.Data.Characters;
public class Character : Player
{
/// <summary>
- /// Gets or sets the inventory of the character.
- /// </summary>
- public Inventory.Inventory? Inventory { get; set; }
-
- /// <summary>
- /// Get or sets the friends of the character.
- /// </summary>
- public IReadOnlyList<Friend>? Friends { get; set; }
-
- /// <summary>
- /// Gets or sets the skills of the player.
- /// </summary>
- public Skills? Skills { get; set; }
-
- /// <summary>
- /// Gets or sets the group the player is in.
- /// </summary>
- public Group? Group { get; set; }
-
- /// <summary>
/// Gets or sets the c skill points.
/// </summary>
public int? SkillCp { get; set; }
M Core/NosSmooth.Game/Game.cs => Core/NosSmooth.Game/Game.cs +157 -4
@@ 7,8 7,11 @@
using Microsoft.Extensions.Options;
using NosSmooth.Core.Stateful;
using NosSmooth.Game.Data.Characters;
+using NosSmooth.Game.Data.Chat;
+using NosSmooth.Game.Data.Inventory;
using NosSmooth.Game.Data.Maps;
using NosSmooth.Game.Data.Raids;
+using NosSmooth.Game.Data.Social;
namespace NosSmooth.Game;
@@ 41,6 44,31 @@ public class Game : IStatefulEntity
public Character? Character { get; internal set; }
/// <summary>
+ /// Gets or sets the inventory of the character.
+ /// </summary>
+ public Inventory? Inventory { get; internal set; }
+
+ /// <summary>
+ /// Get or sets the friends of the character.
+ /// </summary>
+ public IReadOnlyList<Friend>? Friends { get; internal set; }
+
+ /// <summary>
+ /// Gets or sets the skills of the player.
+ /// </summary>
+ public Skills? Skills { get; internal set; }
+
+ /// <summary>
+ /// Gets or sets the family.
+ /// </summary>
+ public Family? Family { get; internal set; }
+
+ /// <summary>
+ /// Gets or sets the group the player is in.
+ /// </summary>
+ public Group? Group { get; internal set; }
+
+ /// <summary>
/// Gets the current map of the client.
/// </summary>
/// <remarks>
@@ 49,10 77,7 @@ public class Game : IStatefulEntity
public Map? CurrentMap
{
get => _currentMap;
- internal set
- {
- _currentMap = value;
- }
+ internal set { _currentMap = value; }
}
/// <summary>
@@ 64,6 89,134 @@ public class Game : IStatefulEntity
public Raid? CurrentRaid { get; internal set; }
/// <summary>
+ /// Creates the skills if they are null, or updates the current skills.
+ /// </summary>
+ /// <param name="create">The function for creating the skills.</param>
+ /// <param name="update">The function for updating the skills.</param>
+ /// <param name="releaseSemaphore">Whether to release the semaphore used for changing the skills.</param>
+ /// <param name="ct">The cancellation token for cancelling the operation.</param>
+ /// <returns>The updated skills.</returns>
+ internal async Task<Skills> CreateOrUpdateSkillsAsync
+ (
+ Func<Skills> create,
+ Func<Skills, Skills> update,
+ bool releaseSemaphore = true,
+ CancellationToken ct = default
+ )
+ {
+ return await CreateOrUpdateAsync
+ (
+ GameSemaphoreType.Skills,
+ () => Skills,
+ s => Skills = s,
+ create,
+ update,
+ releaseSemaphore,
+ ct
+ );
+ }
+
+ /// <summary>
+ /// Creates the inventory if it is null, or updates the current inventory.
+ /// </summary>
+ /// <param name="create">The function for creating the inventory.</param>
+ /// <param name="update">The function for updating the inventory.</param>
+ /// <param name="releaseSemaphore">Whether to release the semaphore used for changing the inventory.</param>
+ /// <param name="ct">The cancellation token for cancelling the operation.</param>
+ /// <returns>The updated inventory.</returns>
+ internal async Task<Inventory> CreateOrUpdateInventoryAsync
+ (
+ Func<Inventory> create,
+ Func<Inventory, Inventory> update,
+ bool releaseSemaphore = true,
+ CancellationToken ct = default
+ )
+ {
+ return await CreateOrUpdateAsync
+ (
+ GameSemaphoreType.Inventory,
+ () => Inventory,
+ i => Inventory = i,
+ create,
+ update,
+ releaseSemaphore,
+ ct
+ );
+ }
+
+ /// <summary>
+ /// Creates the family if it is null, or updates the current family.
+ /// </summary>
+ /// <param name="create">The function for creating the family.</param>
+ /// <param name="update">The function for updating the family.</param>
+ /// <param name="releaseSemaphore">Whether to release the semaphore used for changing the family.</param>
+ /// <param name="ct">The cancellation token for cancelling the operation.</param>
+ /// <returns>The updated family.</returns>
+ internal async Task<Family> CreateOrUpdateFamilyAsync
+ (
+ Func<Family> create,
+ Func<Family, Family> update,
+ bool releaseSemaphore = true,
+ CancellationToken ct = default
+ )
+ {
+ var family = await CreateOrUpdateAsync
+ (
+ GameSemaphoreType.Family,
+ () => Family,
+ c => Family = c,
+ create,
+ update,
+ releaseSemaphore,
+ ct
+ );
+
+ await CreateOrUpdateCharacterAsync
+ (
+ () => new Character
+ {
+ Family = family
+ },
+ c =>
+ {
+ c.Family = family;
+ return c;
+ },
+ ct: ct
+ );
+
+ return family;
+ }
+
+ /// <summary>
+ /// Creates the group if it is null, or updates the current group.
+ /// </summary>
+ /// <param name="create">The function for creating the group.</param>
+ /// <param name="update">The function for updating the group.</param>
+ /// <param name="releaseSemaphore">Whether to release the semaphore used for changing the group.</param>
+ /// <param name="ct">The cancellation token for cancelling the operation.</param>
+ /// <returns>The updated group.</returns>
+ internal async Task<Group> CreateOrUpdateGroupAsync
+ (
+ Func<Group> create,
+ Func<Group, Group> update,
+ bool releaseSemaphore = true,
+ CancellationToken ct = default
+ )
+ {
+ return await CreateOrUpdateAsync
+ (
+ GameSemaphoreType.Group,
+ () => Group,
+ c => Group = c,
+ create,
+ update,
+ releaseSemaphore,
+ ct
+ );
+ }
+
+ /// <summary>
/// Creates the character if it is null, or updates the current character.
/// </summary>
/// <param name="create">The function for creating the character.</param>
M Core/NosSmooth.Game/GameSemaphoreType.cs => Core/NosSmooth.Game/GameSemaphoreType.cs +28 -3
@@ 12,17 12,42 @@ namespace NosSmooth.Game;
public enum GameSemaphoreType
{
/// <summary>
- /// The semaphore for the character.
+ /// The semaphore for character.
/// </summary>
Character,
/// <summary>
- /// The semaphore for the map.
+ /// The semaphore for inventory.
+ /// </summary>
+ Inventory,
+
+ /// <summary>
+ /// The semaphore for friends.
+ /// </summary>
+ Friends,
+
+ /// <summary>
+ /// The semaphore for family.
+ /// </summary>
+ Family,
+
+ /// <summary>
+ /// The semaphore for group.
+ /// </summary>
+ Group,
+
+ /// <summary>
+ /// The semaphore for skills.
+ /// </summary>
+ Skills,
+
+ /// <summary>
+ /// The semaphore for map.
/// </summary>
Map,
/// <summary>
- /// The semaphore for the raid.
+ /// The semaphore for raid.
/// </summary>
Raid
}=
\ No newline at end of file
M Core/NosSmooth.Game/NosSmooth.Game.csproj => Core/NosSmooth.Game/NosSmooth.Game.csproj +0 -1
@@ 18,7 18,6 @@ Create Character in At responder if needed.</PackageReleaseNotes>
<ItemGroup>
<Folder Include="Apis" />
- <Folder Include="Events\Players" />
</ItemGroup>
<ItemGroup>
M Core/NosSmooth.Game/PacketHandlers/Characters/CharacterInitResponder.cs => Core/NosSmooth.Game/PacketHandlers/Characters/CharacterInitResponder.cs +29 -7
@@ 44,8 44,6 @@ public class CharacterInitResponder : IPacketResponder<CInfoPacket>, IPacketResp
(
() => new Character
{
- Family = new Family(packet.FamilyId, null, packet.FamilyName, packet.FamilyLevel, null),
- Group = new Group(packet.GroupId, default, default),
Id = packet.CharacterId,
Name = packet.Name,
Authority = packet.Authority,
@@ 69,22 67,46 @@ public class CharacterInitResponder : IPacketResponder<CInfoPacket>, IPacketResp
character.Class = packet.Class;
character.Icon = packet.Icon;
character.Compliment = packet.Compliment;
- character.Group = (character.Group ?? new Group(packet.GroupId, null, null)) with
- {
- Id = packet.GroupId
- };
character.Morph = (character.Morph ?? new Morph(packet.MorphVNum, packet.MorphUpgrade)) with
{
VNum = packet.MorphVNum, Upgrade = packet.MorphUpgrade
};
character.ArenaWinner = packet.ArenaWinner;
character.IsInvisible = packet.IsInvisible;
- character.Family = new Family(packet.FamilyId, null, packet.FamilyName, packet.FamilyLevel, null);
return character;
},
ct: ct
);
+ await _game.CreateOrUpdateGroupAsync
+ (
+ () => new Group(packet.GroupId, null, null),
+ g => g with
+ {
+ Id = packet.GroupId
+ },
+ ct: ct
+ );
+
+ await _game.CreateOrUpdateFamilyAsync
+ (
+ () => new Family
+ (
+ packet.FamilyId,
+ null,
+ packet.FamilyName,
+ packet.FamilyLevel,
+ null
+ ),
+ f => f with
+ {
+ Id = packet.FamilyId,
+ Name = packet.FamilyName,
+ Level = packet.FamilyLevel
+ },
+ ct: ct
+ );
+
if (character != oldCharacter)
{
return await _eventDispatcher.DispatchEvent(new ReceivedCharacterDataEvent(character), ct);
M Core/NosSmooth.Game/PacketHandlers/Characters/SkillResponder.cs => Core/NosSmooth.Game/PacketHandlers/Characters/SkillResponder.cs +13 -17
@@ 55,24 55,24 @@ public class SkillResponder : IPacketResponder<SkiPacket>
Skill primarySkill, secondarySkill;
- var character = _game.Character;
+ var skills = _game.Skills;
- if (character is not null && packet.PrimarySkillVNum == character.Skills?.PrimarySkill.SkillVNum)
+ if (packet.PrimarySkillVNum == skills?.PrimarySkill.SkillVNum)
{
- primarySkill = character.Skills.PrimarySkill;
+ primarySkill = skills.PrimarySkill;
}
else
{
primarySkill = await CreateSkill(packet.PrimarySkillVNum, default);
}
- if (character is not null && packet.PrimarySkillVNum == packet.SecondarySkillVNum)
+ if (packet.PrimarySkillVNum == packet.SecondarySkillVNum)
{
secondarySkill = primarySkill;
}
- else if (character is not null && packet.SecondarySkillVNum == character.Skills?.SecondarySkill.SkillVNum)
+ else if (packet.SecondarySkillVNum == skills?.SecondarySkill.SkillVNum)
{
- secondarySkill = character.Skills.SecondarySkill;
+ secondarySkill = skills.SecondarySkill;
}
else
{
@@ 80,13 80,13 @@ public class SkillResponder : IPacketResponder<SkiPacket>
}
var skillsFromPacket = packet.SkillSubPackets?.Select(x => x.SkillVNum).ToList() ?? new List<int>();
- var skillsFromCharacter = character?.Skills is null
+ var skillsFromCharacter = skills is null
? new List<int>()
- : character.Skills.OtherSkills.Select(x => x.SkillVNum).ToList();
+ : skills.OtherSkills.Select(x => x.SkillVNum).ToList();
var newSkills = skillsFromPacket.Except(skillsFromCharacter);
var oldSkills = skillsFromCharacter.Except(skillsFromPacket);
- var otherSkillsFromCharacter = new List<Skill>(character?.Skills?.OtherSkills ?? new Skill[] { });
+ var otherSkillsFromCharacter = new List<Skill>(skills?.OtherSkills ?? new Skill[] { });
otherSkillsFromCharacter.RemoveAll(x => oldSkills.Contains(x.SkillVNum));
foreach (var newSkill in newSkills)
@@ 94,16 94,12 @@ public class SkillResponder : IPacketResponder<SkiPacket>
otherSkillsFromCharacter.Add(await CreateSkill(newSkill, default));
}
- var skills = new Skills(primarySkill, secondarySkill, otherSkillsFromCharacter);
+ skills = new Skills(primarySkill, secondarySkill, otherSkillsFromCharacter);
- await _game.CreateOrUpdateCharacterAsync
+ await _game.CreateOrUpdateSkillsAsync
(
- () => new Character { Skills = skills },
- c =>
- {
- c.Skills = skills;
- return c;
- },
+ () => skills,
+ _ => skills,
ct: ct
);
M Core/NosSmooth.Game/PacketHandlers/Entities/AoeSkillUsedResponder.cs => Core/NosSmooth.Game/PacketHandlers/Entities/AoeSkillUsedResponder.cs +1 -1
@@ 63,7 63,7 @@ public class AoeSkillUsedResponder : IPacketResponder<BsPacket>
if (caster is Character character)
{
- var skillResult = character.Skills?.TryGetSkillByVNum(packet.SkillVNum);
+ var skillResult = _game.Skills?.TryGetSkillByVNum(packet.SkillVNum);
if (skillResult?.IsSuccess ?? false)
{
skillEntity = skillResult.Value.Entity;
M Core/NosSmooth.Game/PacketHandlers/Entities/SkillUsedResponder.cs => Core/NosSmooth.Game/PacketHandlers/Entities/SkillUsedResponder.cs +9 -6
@@ 82,9 82,10 @@ public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<S
}
Skill? skillEntity;
- if (packet.SkillVNum is not null && caster is Character character && character.Skills is not null)
+ var skills = _game.Skills;
+ if (packet.SkillVNum is not null && caster is Character character && skills is not null)
{
- var skillResult = character.Skills.TryGetSkillByVNum(packet.SkillVNum.Value);
+ var skillResult = skills.TryGetSkillByVNum(packet.SkillVNum.Value);
if (skillResult.IsDefined(out skillEntity))
{
@@ 159,17 160,19 @@ public class SkillUsedResponder : IPacketResponder<SuPacket>, IPacketResponder<S
public async Task<Result> Respond(PacketEventArgs<SrPacket> packetArgs, CancellationToken ct = default)
{
var packet = packetArgs.Packet;
- var character = _game.Character;
- if (character is not null && character.Skills is not null)
+ var skills = _game.Skills;
+ if (skills is not null)
{
- var skillResult = character.Skills.TryGetSkillByCastId(packet.SkillId);
+ var skillResult = skills.TryGetSkillByCastId(packet.SkillId);
if (skillResult.IsDefined(out var skillEntity))
{
skillEntity.IsOnCooldown = false;
- await _eventDispatcher.DispatchEvent(new SkillReadyEvent(skillEntity, skillEntity.SkillVNum), ct);
}
+
+ await _eventDispatcher.DispatchEvent
+ (new SkillReadyEvent(skillEntity, skillEntity?.SkillVNum ?? packet.SkillId), ct);
}
else
{
M Extensions/NosSmooth.Extensions.Combat/Operations/UsePrimarySkillOperation.cs => Extensions/NosSmooth.Extensions.Combat/Operations/UsePrimarySkillOperation.cs +1 -6
@@ 65,13 65,8 @@ public record UsePrimarySkillOperation(ILivingEntity Target) : ICombatOperation
private Result<Skill> GetPrimarySkill(ICombatState combatState)
{
- var character = combatState.Game.Character;
- if (character is null)
- {
- return new CharacterNotInitializedError();
- }
+ var skills = combatState.Game.Skills;
- var skills = character.Skills;
if (skills is null)
{
return new CharacterNotInitializedError("Skills");
M Extensions/NosSmooth.Extensions.Combat/Techniques/SimpleAttackTechnique.cs => Extensions/NosSmooth.Extensions.Combat/Techniques/SimpleAttackTechnique.cs +1 -1
@@ 87,7 87,7 @@ public class SimpleAttackTechnique : ICombatTechnique
if (_currentSkill is null)
{
- var skills = character.Skills;
+ var skills = state.Game.Skills;
if (skills is null)
{
return new CharacterNotInitializedError("Skills");