diff --git a/Lib9c.Models/States/WorldBossKillRewardRecord.cs b/Lib9c.Models/States/WorldBossKillRewardRecord.cs index d58860f..c15ca97 100644 --- a/Lib9c.Models/States/WorldBossKillRewardRecord.cs +++ b/Lib9c.Models/States/WorldBossKillRewardRecord.cs @@ -6,7 +6,7 @@ namespace Lib9c.Models.States; -public class WorldBossKillRewardRecord : IBencodable +public record WorldBossKillRewardRecord : IBencodable { public Dictionary RewardRecordDictionary { get; init; } diff --git a/Lib9c.Models/States/WorldBossState.cs b/Lib9c.Models/States/WorldBossState.cs index 4c7a066..ee94413 100644 --- a/Lib9c.Models/States/WorldBossState.cs +++ b/Lib9c.Models/States/WorldBossState.cs @@ -7,7 +7,7 @@ namespace Lib9c.Models.States; -public class WorldBossState : IBencodable +public record WorldBossState : IBencodable { public int Id { get; init; } public int Level { get; init; } diff --git a/Lib9c.Models/States/WorldInformationState.cs b/Lib9c.Models/States/WorldInformationState.cs new file mode 100644 index 0000000..5203d80 --- /dev/null +++ b/Lib9c.Models/States/WorldInformationState.cs @@ -0,0 +1,33 @@ +using Bencodex; +using Bencodex.Types; +using Lib9c.Models.Exceptions; +using Lib9c.Models.Extensions; +using Lib9c.Models.WorldInformation; +using ValueKind = Bencodex.Types.ValueKind; + +namespace Lib9c.Models.States; + +public record WorldInformationState : IBencodable +{ + public Dictionary WorldDictionary { get; init; } + + public WorldInformationState(IValue bencoded) + { + if (bencoded is not Dictionary d) + { + throw new UnsupportedArgumentValueException( + nameof(bencoded), + new[] { ValueKind.Dictionary }, + bencoded.Kind + ); + } + + WorldDictionary = d.ToDictionary(kv => kv.Key.ToInteger(), kv => new World(kv.Value)); + } + + public IValue Bencoded => + WorldDictionary.Aggregate( + List.Empty, + (current, kv) => current.Add(List.Empty.Add(kv.Key.Serialize()).Add(kv.Value.Bencoded)) + ); +} diff --git a/Lib9c.Models/WorldInformation/World.cs b/Lib9c.Models/WorldInformation/World.cs new file mode 100644 index 0000000..ed1f89c --- /dev/null +++ b/Lib9c.Models/WorldInformation/World.cs @@ -0,0 +1,55 @@ +using Bencodex; +using Bencodex.Types; +using Lib9c.Models.Exceptions; +using Lib9c.Models.Extensions; +using ValueKind = Bencodex.Types.ValueKind; + +namespace Lib9c.Models.WorldInformation; + +public record World : IBencodable +{ + public int Id { get; init; } + public string Name { get; init; } + public int StageBegin { get; init; } + public int StageEnd { get; init; } + public long UnlockedBlockIndex { get; init; } + public long StageClearedBlockIndex { get; init; } + public int StageClearedId { get; init; } + + public bool IsUnlocked => UnlockedBlockIndex != -1; + public bool IsStageCleared => StageClearedBlockIndex != -1; + + public World(IValue bencoded) + { + if (bencoded is not Dictionary d) + { + throw new UnsupportedArgumentValueException( + nameof(bencoded), + new[] { ValueKind.Dictionary }, + bencoded.Kind + ); + } + + Id = d.GetInteger("Id"); + Name = d.GetString("Name"); + StageBegin = d.GetInteger("StageBegin"); + StageEnd = d.GetInteger("StageEnd"); + UnlockedBlockIndex = d.GetLong("UnlockedBlockIndex"); + StageClearedBlockIndex = d.GetLong("StageClearedBlockIndex"); + StageClearedId = d.GetInteger("StageClearedId"); + } + + public IValue Bencoded => + new Dictionary( + new Dictionary + { + [(Text)"Id"] = Id.Serialize(), + [(Text)"Name"] = Name.Serialize(), + [(Text)"StageBegin"] = StageBegin.Serialize(), + [(Text)"StageEnd"] = StageEnd.Serialize(), + [(Text)"UnlockedBlockIndex"] = UnlockedBlockIndex.Serialize(), + [(Text)"StageClearedBlockIndex"] = StageClearedBlockIndex.Serialize(), + [(Text)"StageClearedId"] = StageClearedId.Serialize(), + } + ); +} diff --git a/Mimir.MongoDB/Bson/WorldInformationDocument.cs b/Mimir.MongoDB/Bson/WorldInformationDocument.cs index 265b85b..0765c87 100644 --- a/Mimir.MongoDB/Bson/WorldInformationDocument.cs +++ b/Mimir.MongoDB/Bson/WorldInformationDocument.cs @@ -1,22 +1,9 @@ -using Bencodex.Types; +using Lib9c.Models.States; using Libplanet.Crypto; -using Lib9c.Models.Extensions; using MongoDB.Bson.Serialization.Attributes; -using Nekoyume.Model; namespace Mimir.MongoDB.Bson; [BsonIgnoreExtraElements] -public record WorldInformationDocument : MimirBsonDocument -{ - public IDictionary Object { get; init; } - - public WorldInformationDocument(Address Address, WorldInformation worldInformation) - : base(Address) - { - Object = ((Dictionary)worldInformation.Serialize()).ToDictionary( - kv => kv.Key.ToInteger(), - kv => new WorldInformation.World((Dictionary)kv.Value) - ); - } -} +public record WorldInformationDocument(Address Address, WorldInformationState Object) + : MimirBsonDocument(Address); diff --git a/Mimir.MongoDB/CollectionNames.cs b/Mimir.MongoDB/CollectionNames.cs index f8168ae..ac2adb2 100644 --- a/Mimir.MongoDB/CollectionNames.cs +++ b/Mimir.MongoDB/CollectionNames.cs @@ -27,7 +27,7 @@ static CollectionNames() CollectionAndAddressMappings.Add(Nekoyume.Addresses.ActionPoint, "action_point"); CollectionAndAddressMappings.Add(Nekoyume.Addresses.DailyReward, "daily_reward"); CollectionAndAddressMappings.Add(Nekoyume.Addresses.Inventory, "inventory"); - // CollectionAndAddressMappings.Add(Nekoyume.Addresses.WorldInformation, "world_information"); + CollectionAndAddressMappings.Add(Nekoyume.Addresses.WorldInformation, "world_information"); // CollectionAndAddressMappings.Add(Nekoyume.Addresses.QuestList, "quest_list"); CollectionAndAddressMappings.Add(Nekoyume.Addresses.RuneState, "all_rune"); CollectionAndAddressMappings.Add(Nekoyume.Addresses.Collection, "collection"); @@ -81,7 +81,7 @@ static CollectionNames() CollectionAndStateTypeMappings.Add(typeof(ProductsStateDocument), "products"); CollectionAndStateTypeMappings.Add(typeof(ProductDocument), "product"); // CollectionAndStateTypeMappings.Add(typeof(QuestListDocument), "quest_list"); - // CollectionAndStateTypeMappings.Add(typeof(WorldInformationDocument), "world_information"); + CollectionAndStateTypeMappings.Add(typeof(WorldInformationDocument), "world_information"); CollectionAndStateTypeMappings.Add(typeof(ItemSlotDocument), "item_slot"); CollectionAndStateTypeMappings.Add(typeof(RuneSlotDocument), "rune_slot"); CollectionAndStateTypeMappings.Add(typeof(WorldBossStateDocument), "world_boss"); diff --git a/Mimir.Worker/Handler/AddressHandlerMappings.cs b/Mimir.Worker/Handler/AddressHandlerMappings.cs index 185dc3f..f50e792 100644 --- a/Mimir.Worker/Handler/AddressHandlerMappings.cs +++ b/Mimir.Worker/Handler/AddressHandlerMappings.cs @@ -28,7 +28,7 @@ static AddressHandlerMappings() HandlerMappings.Add(Addresses.ActionPoint, new ActionPointStateHandler()); HandlerMappings.Add(Addresses.DailyReward, new DailyRewardStateHandler()); HandlerMappings.Add(Addresses.Inventory, new InventoryStateHandler()); - // HandlerMappings.Add(Addresses.WorldInformation, new WorldInformationStateHandler()); + HandlerMappings.Add(Addresses.WorldInformation, new WorldInformationStateHandler()); // HandlerMappings.Add(Addresses.QuestList, new QuestListStateHandler()); HandlerMappings.Add(Addresses.RuneState, new AllRuneStateHandler()); HandlerMappings.Add(Addresses.Collection, new CollectionStateHandler()); diff --git a/Mimir.Worker/Handler/AllRuneStateHandler.cs b/Mimir.Worker/Handler/AllRuneStateHandler.cs index ca0832a..fb2f413 100644 --- a/Mimir.Worker/Handler/AllRuneStateHandler.cs +++ b/Mimir.Worker/Handler/AllRuneStateHandler.cs @@ -8,14 +8,7 @@ public class AllRuneStateHandler : IStateHandler { public MimirBsonDocument ConvertToDocument(StateDiffContext context) { - if (context.RawState is not List value) - { - throw new InvalidCastException( - $"{nameof(context.RawState)} Invalid state type. Expected {nameof(List)}, got {context.RawState.GetType().Name}." - ); - } - - var allRuneState = new AllRuneState(value); + var allRuneState = new AllRuneState(context.RawState); return new AllRuneDocument(context.Address, allRuneState); } } diff --git a/Mimir.Worker/Handler/WorldInformationStateHandler.cs b/Mimir.Worker/Handler/WorldInformationStateHandler.cs index 9fe6332..41e1204 100644 --- a/Mimir.Worker/Handler/WorldInformationStateHandler.cs +++ b/Mimir.Worker/Handler/WorldInformationStateHandler.cs @@ -1,6 +1,5 @@ -using Bencodex.Types; +using Lib9c.Models.States; using Mimir.MongoDB.Bson; -using Nekoyume.Model; namespace Mimir.Worker.Handler; @@ -8,13 +7,9 @@ public class WorldInformationStateHandler : IStateHandler { public MimirBsonDocument ConvertToDocument(StateDiffContext context) { - if (context.RawState is Dictionary dict) - { - return new WorldInformationDocument(context.Address, new WorldInformation(dict)); - } - - throw new InvalidCastException( - $"{nameof(context.RawState)} Invalid state type. Expected Dictionary." + return new WorldInformationDocument( + context.Address, + new WorldInformationState(context.RawState) ); } } diff --git a/Mimir.Worker/Poller/TxPoller.cs b/Mimir.Worker/Poller/TxPoller.cs index 8c25fec..def00c1 100644 --- a/Mimir.Worker/Poller/TxPoller.cs +++ b/Mimir.Worker/Poller/TxPoller.cs @@ -41,8 +41,8 @@ MongoDbService dbService [ new PatchTableHandler(stateService, dbService), // World - // new HackAndSlashHandler(stateService, dbService), - // new HackAndSlashSweepHandler(stateService, dbService), + new HackAndSlashHandler(stateService, dbService), + new HackAndSlashSweepHandler(stateService, dbService), // Arena new JoinArenaHandler(stateService, dbService), @@ -50,7 +50,7 @@ MongoDbService dbService // Raid new RaidHandler(stateService, dbService), // Event Dungeon - // new EventDungeonBattleHandler(stateService, dbService), + new EventDungeonBattleHandler(stateService, dbService), // Market new ProductsHandler(stateService, dbService),