diff --git a/Entity/System/Room.cs b/Entity/System/Room.cs index 194109d..32c0126 100644 --- a/Entity/System/Room.cs +++ b/Entity/System/Room.cs @@ -1,4 +1,5 @@ -using Milimoe.FunGame.Core.Interface.Entity; +using System.Collections.Concurrent; +using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Entity @@ -18,7 +19,7 @@ namespace Milimoe.FunGame.Core.Entity public bool HasPass => Password.Trim() != ""; public string Password { get; set; } = ""; public int MaxUsers { get; set; } = 0; - public Dictionary UserAndIsReady { get; } = []; + public ConcurrentDictionary UserAndIsReady { get; } = []; public GameStatistics Statistics { get; set; } internal Room() diff --git a/Library/Common/JsonConverter/NovelCharacterNodeConverter.cs b/Library/Common/JsonConverter/NovelCharacterNodeConverter.cs new file mode 100644 index 0000000..aaccd06 --- /dev/null +++ b/Library/Common/JsonConverter/NovelCharacterNodeConverter.cs @@ -0,0 +1,44 @@ +using System.Text.Json; +using Milimoe.FunGame.Core.Library.Common.Architecture; +using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; + +namespace Milimoe.FunGame.Core.Library.Common.JsonConverter +{ + public class NovelCharacterNodeConverter : BaseEntityConverter + { + public override NovelCharacterNode NewInstance() + { + return new NovelCharacterNode(); + } + + public override void ReadPropertyName(ref Utf8JsonReader reader, string propertyName, JsonSerializerOptions options, ref NovelCharacterNode result, Dictionary convertingContext) + { + switch (propertyName) + { + case nameof(NovelCharacterNode.Name): + result.Name = reader.GetString() ?? ""; + break; + case nameof(NovelCharacterNode.PortraitImagePath): + result.PortraitImagePath = reader.GetString() ?? ""; + break; + case nameof(NovelCharacterNode.StandOut): + result.StandOut = reader.GetBoolean(); + break; + case nameof(NovelCharacterNode.PositionType): + result.PositionType = (PositionType)reader.GetInt32(); + break; + } + } + + public override void Write(Utf8JsonWriter writer, NovelCharacterNode value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString(nameof(NovelCharacterNode.Name), value.Name); + if (value.PortraitImagePath != "") writer.WriteString(nameof(NovelCharacterNode.PortraitImagePath), value.PortraitImagePath); + if (value.StandOut) writer.WriteBoolean(nameof(NovelCharacterNode.StandOut), value.StandOut); + if (value.PositionType != PositionType.Center) writer.WriteNumber(nameof(NovelCharacterNode.PositionType), (int)value.PositionType); + writer.WriteEndObject(); + } + } +} diff --git a/Library/Common/JsonConverter/NovelNodeConverter.cs b/Library/Common/JsonConverter/NovelNodeConverter.cs index c52d402..9190d07 100644 --- a/Library/Common/JsonConverter/NovelNodeConverter.cs +++ b/Library/Common/JsonConverter/NovelNodeConverter.cs @@ -34,14 +34,17 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter case nameof(NovelNode.Name): result.Name = reader.GetString() ?? ""; break; - case nameof(NovelNode.Name2): - result.Name2 = reader.GetString() ?? ""; - break; case nameof(NovelNode.Content): result.Content = reader.GetString() ?? ""; break; - case nameof(NovelNode.PortraitImagePath): - result.PortraitImagePath = reader.GetString() ?? ""; + case nameof(NovelNode.Character): + result.Character = NetworkUtility.JsonDeserialize(ref reader, options) ?? new() + { + StandOut = true + }; + break; + case nameof(NovelNode.Opponents): + result.Opponents = NetworkUtility.JsonDeserialize>(ref reader, options) ?? []; break; case nameof(NovelNode.AndPredicates): result.Values[nameof(NovelNode.AndPredicates)] = NetworkUtility.JsonDeserialize>(ref reader, options) ?? []; @@ -66,9 +69,14 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter JsonSerializer.Serialize(writer, value.Options, options); } writer.WriteString(nameof(NovelNode.Name), value.Name); - if (value.Name2 != "") writer.WriteString(nameof(NovelNode.Name2), value.Name2); writer.WriteString(nameof(NovelNode.Content), value.Content); - if (value.PortraitImagePath != "") writer.WriteString(nameof(NovelNode.PortraitImagePath), value.PortraitImagePath); + writer.WritePropertyName(nameof(NovelNode.Character)); + JsonSerializer.Serialize(writer, value.Character, options); + if (value.Opponents.Count > 0) + { + writer.WritePropertyName(nameof(NovelNode.Opponents)); + JsonSerializer.Serialize(writer, value.Opponents, options); + } if (value.AndPredicates.Count > 0) { writer.WritePropertyName(nameof(NovelNode.AndPredicates)); diff --git a/Model/NovelNode.cs b/Model/NovelNode.cs index 27416bb..c671847 100644 --- a/Model/NovelNode.cs +++ b/Model/NovelNode.cs @@ -1,4 +1,6 @@ -namespace Milimoe.FunGame.Core.Model +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Model { public class NovelNode { @@ -6,13 +8,16 @@ public int Priority { get; set; } = 0; public NovelNode? Previous { get; set; } = null; public List NextNodes { get; set; } = []; - public NovelNode? Next => NextNodes.OrderByDescending(n => n.Priority).Where(n => n.ShowNode).FirstOrDefault(); + public NovelNode? Next => NextNodes.OrderByDescending(n => n.Priority).FirstOrDefault(n => n.ShowNode); public List Options { get; set; } = []; public List AvailableOptions => [.. Options.Where(o => o.ShowOption)]; public string Name { get; set; } = ""; - public string Name2 { get; set; } = ""; public string Content { get; set; } = ""; - public string PortraitImagePath { get; set; } = ""; + public NovelCharacterNode Character { get; set; } = new() + { + StandOut = true + }; + public List Opponents { get; set; } = []; public Dictionary> AndPredicates { get; set; } = []; public Dictionary> OrPredicates { get; set; } = []; public bool ShowNode @@ -45,4 +50,12 @@ } internal Dictionary Values { get; set; } = []; } + + public class NovelCharacterNode + { + public string Name { get; set; } = ""; + public string PortraitImagePath { get; set; } = ""; + public bool StandOut { get; set; } = false; + public PositionType PositionType { get; set; } = PositionType.Center; + } } diff --git a/Model/RoomList.cs b/Model/RoomList.cs index 4de640a..777a182 100644 --- a/Model/RoomList.cs +++ b/Model/RoomList.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Collections.Concurrent; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Constant; @@ -6,9 +7,9 @@ namespace Milimoe.FunGame.Core.Model { public class RoomList : IEnumerable { - private readonly Dictionary _list = []; - private readonly Dictionary> _userList = []; - private readonly Dictionary> _readyUserList = []; + private readonly ConcurrentDictionary _list = []; + private readonly ConcurrentDictionary> _userList = []; + private readonly ConcurrentDictionary> _readyUserList = []; public Room this[string roomid] => GetRoom(roomid); @@ -39,9 +40,9 @@ namespace Milimoe.FunGame.Core.Model public void AddRoom(Room room) { - _list.Add(room.Roomid, room); - _userList.Add(room.Roomid, []); - _readyUserList.Add(room.Roomid, []); + _list.TryAdd(room.Roomid, room); + _userList.TryAdd(room.Roomid, []); + _readyUserList.TryAdd(room.Roomid, []); } public void AddRooms(List rooms) @@ -54,9 +55,9 @@ namespace Milimoe.FunGame.Core.Model public void RemoveRoom(string roomid) { - _list.Remove(roomid); - _userList.Remove(roomid); - _readyUserList.Remove(roomid); + _list.TryRemove(roomid, out _); + _userList.TryRemove(roomid, out _); + _readyUserList.TryRemove(roomid, out _); } public void RemoveRoom(Room room) => RemoveRoom(room.Roomid); @@ -76,7 +77,7 @@ namespace Milimoe.FunGame.Core.Model { if (roomid != "-1" && user.Id != 0) { - this[roomid].UserAndIsReady.Remove(user); + this[roomid].UserAndIsReady.TryRemove(user, out _); } } diff --git a/Service/JsonManager.cs b/Service/JsonManager.cs index de3c7bd..20c356a 100644 --- a/Service/JsonManager.cs +++ b/Service/JsonManager.cs @@ -22,8 +22,8 @@ namespace Milimoe.FunGame.Core.Service Converters = { new DateTimeConverter(), new DataTableConverter(), new DataSetConverter(), new UserConverter(), new RoomConverter(), new CharacterConverter(), new MagicResistanceConverter(), new EquipSlotConverter(), new SkillConverter(), new EffectConverter(), new ItemConverter(), new InventoryConverter(), new NormalAttackConverter(), new ClubConverter(), new GoodsConverter(), new StoreConverter(), - new NovelOptionConverter(), new NovelNodeConverter(), new ShieldConverter(), new RoundRecordConverter(), new ActivityConverter(), new QuestConverter(), - new MarketConverter(), new MarketItemConverter() + new NovelOptionConverter(), new NovelNodeConverter(), new NovelCharacterNodeConverter(), new ShieldConverter(), new RoundRecordConverter(), new ActivityConverter(), + new QuestConverter(), new MarketConverter(), new MarketItemConverter() } };