From 114c1e96525a5f625ea65e777aec4ab604825079 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Fri, 20 Sep 2024 15:34:47 +0900 Subject: [PATCH 01/20] upgrade project packages --- Lib9c.GraphQL/Lib9c.GraphQL.csproj | 4 ++-- Lib9c.Models/Lib9c.Models.csproj | 4 ++-- Mimir.MongoDB/Mimir.MongoDB.csproj | 1 + Mimir.Worker/Mimir.Worker.csproj | 6 +++--- Mimir/Mimir.csproj | 15 +++++++-------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Lib9c.GraphQL/Lib9c.GraphQL.csproj b/Lib9c.GraphQL/Lib9c.GraphQL.csproj index 0f50a425..d7bf8dad 100644 --- a/Lib9c.GraphQL/Lib9c.GraphQL.csproj +++ b/Lib9c.GraphQL/Lib9c.GraphQL.csproj @@ -10,8 +10,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Lib9c.Models/Lib9c.Models.csproj b/Lib9c.Models/Lib9c.Models.csproj index 0dc4b652..8c158f32 100644 --- a/Lib9c.Models/Lib9c.Models.csproj +++ b/Lib9c.Models/Lib9c.Models.csproj @@ -8,10 +8,10 @@ - + - + diff --git a/Mimir.MongoDB/Mimir.MongoDB.csproj b/Mimir.MongoDB/Mimir.MongoDB.csproj index 1f4a2065..d53691eb 100644 --- a/Mimir.MongoDB/Mimir.MongoDB.csproj +++ b/Mimir.MongoDB/Mimir.MongoDB.csproj @@ -8,6 +8,7 @@ + diff --git a/Mimir.Worker/Mimir.Worker.csproj b/Mimir.Worker/Mimir.Worker.csproj index 501f6271..8dfbd926 100644 --- a/Mimir.Worker/Mimir.Worker.csproj +++ b/Mimir.Worker/Mimir.Worker.csproj @@ -9,14 +9,14 @@ - + - - + + diff --git a/Mimir/Mimir.csproj b/Mimir/Mimir.csproj index 45c0d566..acf71b6c 100644 --- a/Mimir/Mimir.csproj +++ b/Mimir/Mimir.csproj @@ -14,12 +14,11 @@ - - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -27,8 +26,8 @@ - - + + From dd695a2c2fd8863780f7d88de9ea2834c2da57eb Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Fri, 20 Sep 2024 17:55:14 +0900 Subject: [PATCH 02/20] clean up MongoDbService --- Mimir.Worker/ActionHandler/ProductsHandler.cs | 19 +- Mimir.Worker/Initializer/ArenaInitializer.cs | 14 +- .../Poller/DiffPoller/DiffConsumer.cs | 4 +- .../Poller/DiffPoller/DiffProducer.cs | 4 +- Mimir.Worker/Poller/TxPoller.cs | 8 +- Mimir.Worker/Services/MongoDbService.cs | 168 ++++++------------ 6 files changed, 85 insertions(+), 132 deletions(-) diff --git a/Mimir.Worker/ActionHandler/ProductsHandler.cs b/Mimir.Worker/ActionHandler/ProductsHandler.cs index 71df1849..d7ab5122 100644 --- a/Mimir.Worker/ActionHandler/ProductsHandler.cs +++ b/Mimir.Worker/ActionHandler/ProductsHandler.cs @@ -7,6 +7,7 @@ using Mimir.MongoDB.Bson; using Mimir.Worker.Exceptions; using Mimir.Worker.Services; +using MongoDB.Bson; using MongoDB.Driver; using Serilog; @@ -100,9 +101,7 @@ public async Task SyncWrappedProductsStateAsync( ) { var productIds = productsState.ProductIds.Select(id => Guid.Parse(id.ToString())).ToList(); - var existingProductIds = await GetExistingProductIds(productsStateAddress); - var productsToAdd = productIds.Except(existingProductIds).ToList(); var productsToRemove = existingProductIds.Except(productIds).ToList(); @@ -119,12 +118,12 @@ [new ProductsStateDocument(productsStateAddress, productsState, avatarAddress)], private async Task> GetExistingProductIds(Address productsStateAddress) { - var existingState = await Store.GetProductsStateByAddress(productsStateAddress); + var filter = Builders.Filter.Eq("Address", productsStateAddress.ToHex()); + var existingState = await Store.GetCollection().Find(filter).FirstOrDefaultAsync(); return existingState == null - ? new List() - : existingState["Object"] - ["ProductIds"] - .AsBsonArray.Select(p => Guid.Parse(p.AsString)) + ? [] + : existingState["Object"]["ProductIds"].AsBsonArray + .Select(p => Guid.Parse(p.AsString)) .ToList(); } @@ -306,9 +305,13 @@ private decimal CalculateUnitPrice(ItemProduct itemProduct) private async Task RemoveOldProductsAsync(List productsToRemove) { + var collection = Store.GetCollection(); foreach (var productId in productsToRemove) { - await Store.RemoveProduct(productId); + var productFilter = Builders.Filter.Eq( + "Object.TradableItem.TradableId", + productId.ToString()); + await collection.DeleteOneAsync(productFilter); } } } diff --git a/Mimir.Worker/Initializer/ArenaInitializer.cs b/Mimir.Worker/Initializer/ArenaInitializer.cs index 9e5cddd8..5aee5cb2 100644 --- a/Mimir.Worker/Initializer/ArenaInitializer.cs +++ b/Mimir.Worker/Initializer/ArenaInitializer.cs @@ -1,5 +1,8 @@ +using Mimir.MongoDB.Bson; using Mimir.Worker.CollectionUpdaters; using Mimir.Worker.Services; +using MongoDB.Bson; +using MongoDB.Driver; using Nekoyume.TableData; using Serilog; @@ -70,8 +73,15 @@ public override async Task IsInitialized() } var roundData = arenaSheet.GetRoundByBlockIndex(blockIndex); - var count = await _store.GetArenaDocumentCount(roundData.ChampionshipId, roundData.Round); - + var count = await GetArenaDocumentCount(roundData.ChampionshipId, roundData.Round); return count != 0; } + + private async Task GetArenaDocumentCount(int championshipId, int round) + { + var builder = Builders.Filter; + var filter = builder.Eq("ChampionshipId", championshipId); + filter &= builder.Eq("Round", round); + return await _store.GetCollection().Find(filter).CountDocumentsAsync(); + } } diff --git a/Mimir.Worker/Poller/DiffPoller/DiffConsumer.cs b/Mimir.Worker/Poller/DiffPoller/DiffConsumer.cs index 165e5e26..f5a97d8f 100644 --- a/Mimir.Worker/Poller/DiffPoller/DiffConsumer.cs +++ b/Mimir.Worker/Poller/DiffPoller/DiffConsumer.cs @@ -34,7 +34,7 @@ CancellationToken stoppingToken if (diffContext.DiffResponse.AccountDiffs.Count() == 0) { _logger.Information("{CollectionName}: No diffs", diffContext.CollectionName); - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(DiffPoller), @@ -59,7 +59,7 @@ await ProcessStateDiff( stoppingToken ); - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(DiffPoller), diff --git a/Mimir.Worker/Poller/DiffPoller/DiffProducer.cs b/Mimir.Worker/Poller/DiffPoller/DiffProducer.cs index 25758548..04f6857a 100644 --- a/Mimir.Worker/Poller/DiffPoller/DiffProducer.cs +++ b/Mimir.Worker/Poller/DiffPoller/DiffProducer.cs @@ -106,7 +106,7 @@ CancellationToken stoppingToken { try { - var syncedBlockIndex = await _dbService.GetLatestBlockIndex( + var syncedBlockIndex = await _dbService.GetLatestBlockIndexAsync( nameof(DiffPoller), collectionName, stoppingToken @@ -123,7 +123,7 @@ CancellationToken stoppingToken "Metadata collection is not found, set block index to {BlockIndex} - 1", currentBlockIndex ); - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(DiffPoller), diff --git a/Mimir.Worker/Poller/TxPoller.cs b/Mimir.Worker/Poller/TxPoller.cs index def00c14..9cc46b85 100644 --- a/Mimir.Worker/Poller/TxPoller.cs +++ b/Mimir.Worker/Poller/TxPoller.cs @@ -148,7 +148,7 @@ CancellationToken cancellationToken foreach (var collectionName in _collectionNames) { - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(TxPoller), @@ -212,7 +212,7 @@ await _dbService.UpdateLatestBlockIndex( foreach (var collectionName in _collectionNames) { - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(TxPoller), @@ -278,7 +278,7 @@ CancellationToken stoppingToken { try { - var syncedBlockIndex = await _dbService.GetLatestBlockIndex( + var syncedBlockIndex = await _dbService.GetLatestBlockIndexAsync( nameof(TxPoller), collectionName, stoppingToken @@ -292,7 +292,7 @@ CancellationToken stoppingToken "Metadata collection is not found, set block index to {BlockIndex} - 1", currentBlockIndex ); - await _dbService.UpdateLatestBlockIndex( + await _dbService.UpdateLatestBlockIndexAsync( new MetadataDocument { PollerType = nameof(TxPoller), diff --git a/Mimir.Worker/Services/MongoDbService.cs b/Mimir.Worker/Services/MongoDbService.cs index 616b0528..35d25f17 100644 --- a/Mimir.Worker/Services/MongoDbService.cs +++ b/Mimir.Worker/Services/MongoDbService.cs @@ -1,7 +1,6 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using Bencodex; -using Libplanet.Crypto; using Mimir.MongoDB; using Mimir.MongoDB.Bson; using Mimir.MongoDB.Bson.Serialization; @@ -18,29 +17,24 @@ namespace Mimir.Worker.Services; public class MongoDbService { + private readonly ILogger _logger; private readonly MongoClient _client; - private readonly IMongoDatabase _database; - private readonly GridFSBucket _gridFs; - - private readonly ILogger _logger; - private readonly Dictionary> _stateCollectionMappings; - - private IMongoCollection MetadataCollection => - _database.GetCollection("metadata"); + private readonly IMongoCollection _metadataCollection; public MongoDbService(string connectionString, PlanetType planetType, string? pathToCAFile) { + _logger = Log.ForContext(); SerializationRegistry.Register(); var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString)); if (pathToCAFile is not null) { - X509Store localTrustStore = new X509Store(StoreName.Root); - X509Certificate2Collection certificateCollection = new X509Certificate2Collection(); + var localTrustStore = new X509Store(StoreName.Root); + var certificateCollection = new X509Certificate2Collection(); certificateCollection.Import(pathToCAFile); try { @@ -49,7 +43,7 @@ public MongoDbService(string connectionString, PlanetType planetType, string? pa } catch (Exception ex) { - Console.WriteLine("Root certificate import failed: " + ex.Message); + _logger.Debug(ex, "Root certificate import failed"); throw; } finally @@ -61,39 +55,36 @@ public MongoDbService(string connectionString, PlanetType planetType, string? pa _client = new MongoClient(settings); _database = _client.GetDatabase(planetType.ToString()); _gridFs = new GridFSBucket(_database); - _logger = Log.ForContext(); _stateCollectionMappings = InitStateCollections(); - } - - public MongoClient GetMongoClient() - { - return _client; + _metadataCollection = _database.GetCollection("metadata"); } private Dictionary> InitStateCollections() { var mappings = new Dictionary>(); - foreach ( - var collectionName in CollectionNames.CollectionAndStateTypeMappings.Values.Concat( - CollectionNames.CollectionAndAddressMappings.Values - ) - ) + var collectionNames = CollectionNames.CollectionAndStateTypeMappings.Values + .Concat(CollectionNames.CollectionAndAddressMappings.Values); + foreach (var collectionName in collectionNames) { var collection = _database.GetCollection(collectionName); mappings[collectionName] = collection; - var count = collection.CountDocuments(new BsonDocument()); + if (collection.CountDocuments(Builders.Filter.Empty) > 0) + { + continue; + } - if (count == 0) + try { - try - { - _database.CreateCollection(collectionName); - } - catch (MongoCommandException) - { - // ignore already exists - } + _database.CreateCollection(collectionName); + } + catch (MongoCommandException e) + { + // ignore already exists + _logger.Debug( + e, + "Collection already exists. {CollectionName}", + collectionName); } } @@ -104,37 +95,22 @@ public IMongoCollection GetCollection(string collectionName) { if (!_stateCollectionMappings.TryGetValue(collectionName, out var collection)) { - throw new InvalidOperationException( - $"No collection mapping found for name: {collectionName}" - ); + throw new InvalidOperationException($"No collection mapping found for name: {collectionName}"); } return collection; } - public async Task GetArenaDocumentCount(int championshipId, int round) - { - var builder = Builders.Filter; - var filter = builder.Eq("ChampionshipId", championshipId); - filter &= builder.Eq("Round", round); - - var documents = GetCollection().Find(filter); - var count = await documents.CountDocumentsAsync(); - - return count; - } - public IMongoCollection GetCollection() { var collectionName = CollectionNames.GetCollectionName(); return GetCollection(collectionName); } - public async Task UpdateLatestBlockIndex( + public async Task UpdateLatestBlockIndexAsync( MetadataDocument document, IClientSessionHandle? session = null, - CancellationToken cancellationToken = default - ) + CancellationToken cancellationToken = default) { var builder = Builders.Filter; var filter = builder.Eq("PollerType", document.PollerType); @@ -142,19 +118,18 @@ public async Task UpdateLatestBlockIndex( var update = Builders.Update.Set( "LatestBlockIndex", - document.LatestBlockIndex - ); + document.LatestBlockIndex); var updateOptions = new UpdateOptions { IsUpsert = true }; var result = session is null - ? await MetadataCollection.UpdateOneAsync( + ? await _metadataCollection.UpdateOneAsync( filter, update, updateOptions, cancellationToken ) - : await MetadataCollection.UpdateOneAsync( + : await _metadataCollection.UpdateOneAsync( session, filter, update, @@ -165,17 +140,16 @@ public async Task UpdateLatestBlockIndex( return result; } - public async Task GetLatestBlockIndex( + public async Task GetLatestBlockIndexAsync( string pollerType, string collectionName, - CancellationToken cancellationToken = default - ) + CancellationToken cancellationToken = default) { var builder = Builders.Filter; var filter = builder.Eq("PollerType", pollerType); filter &= builder.Eq("CollectionName", collectionName); - var doc = await MetadataCollection.FindSync(filter).FirstAsync(cancellationToken); + var doc = await _metadataCollection.Find(filter).FirstAsync(cancellationToken); return doc.LatestBlockIndex; } @@ -202,8 +176,7 @@ public async Task UpsertStateDataManyAsync( string collectionName, List documents, IClientSessionHandle? session = null, - CancellationToken cancellationToken = default - ) + CancellationToken cancellationToken = default) { List> bulkOps = []; foreach (var document in documents) @@ -212,70 +185,54 @@ public async Task UpsertStateDataManyAsync( bulkOps.Add(stateUpdateModel); } - if (session is null) - { - return await GetCollection(collectionName) - .BulkWriteAsync(bulkOps, null, cancellationToken); - } - else - { - return await GetCollection(collectionName) + return session is null + ? await GetCollection(collectionName) + .BulkWriteAsync(bulkOps, null, cancellationToken) + : await GetCollection(collectionName) .BulkWriteAsync(session, bulkOps, null, cancellationToken); - } } public async Task UpsertSheetDocumentAsync( string collectionName, List documents, IClientSessionHandle? session = null, - CancellationToken cancellationToken = default - ) + CancellationToken cancellationToken = default) { - List> bulkOps = new List>(); + List> bulkOps = []; foreach (var document in documents) { - var stateUpdateModel = await GetSheetDocumentUpdateModel(document); + var stateUpdateModel = await GetSheetDocumentUpdateModelAsync(document, cancellationToken); bulkOps.Add(stateUpdateModel); } - if (session is null) - { - return await GetCollection(collectionName) - .BulkWriteAsync(bulkOps, null, cancellationToken); - } - else - { - return await GetCollection(collectionName) + return session is null + ? await GetCollection(collectionName) + .BulkWriteAsync(bulkOps, null, cancellationToken) + : await GetCollection(collectionName) .BulkWriteAsync(session, bulkOps, null, cancellationToken); - } } - public UpdateOneModel GetMimirDocumentUpdateModel( + private UpdateOneModel GetMimirDocumentUpdateModel( string collectionName, - MimirBsonDocument document - ) + MimirBsonDocument document) { - var filter = Builders.Filter.Eq("Address", document.Address.ToHex()); var stateJson = document.ToJson(); var bsonDocument = BsonDocument.Parse(stateJson); - var update = new BsonDocument("$set", bsonDocument); - // var update = Builders.Update - // .Set(doc => doc, document); + var filter = Builders.Filter.Eq("Address", document.Address.ToHex()); + var update = Builders.Update.Set(doc => doc, bsonDocument); var upsertOne = new UpdateOneModel(filter, update) { IsUpsert = true }; _logger.Debug( "Address: {Address} - Stored at {CollectionName}", document.Address.ToHex(), - collectionName - ); + collectionName); return upsertOne; } - public async Task> GetSheetDocumentUpdateModel( + private async Task> GetSheetDocumentUpdateModelAsync( SheetDocument document, - CancellationToken cancellationToken = default - ) + CancellationToken cancellationToken = default) { var collectionName = CollectionNames.GetCollectionName(document.GetType()); var rawStateBytes = new Codec().Encode(document.RawState); @@ -283,8 +240,7 @@ public async Task> GetSheetDocumentUpdateModel( $"{document.Address.ToHex()}-rawstate", rawStateBytes, null, - cancellationToken - ); + cancellationToken); var bsonDocument = BsonDocument.Parse(document.ToJson()); var stateBsonDocument = bsonDocument.AsBsonDocument; @@ -298,27 +254,11 @@ public async Task> GetSheetDocumentUpdateModel( _logger.Debug( "Address: {Address} - Stored at {CollectionName}", document.Address.ToHex(), - collectionName - ); + collectionName); return upsertOne; } - public async Task GetProductsStateByAddress(Address address) - { - var filter = Builders.Filter.Eq("Address", address.ToHex()); - return await GetCollection().Find(filter).FirstOrDefaultAsync(); - } - - public async Task RemoveProduct(Guid productId) - { - var productFilter = Builders.Filter.Eq( - "Object.TradableItem.TradableId", - productId.ToString() - ); - await GetCollection().DeleteOneAsync(productFilter); - } - private static async Task RetrieveFromGridFs(GridFSBucket gridFs, ObjectId fileId) { var fileBytes = await gridFs.DownloadAsBytesAsync(fileId); From 27da53c9930bc253dcd80890695bd8a8ea680eae Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Thu, 19 Sep 2024 18:02:43 +0900 Subject: [PATCH 03/20] handle exceptions in CombinationSlotStateHandler --- .../CombinationSlotStateHandler.cs | 176 ++++++++---------- Mimir.Worker/ActionHandler/PetStateHandler.cs | 2 +- Mimir.Worker/Util/StateGetter.cs | 6 +- 3 files changed, 79 insertions(+), 105 deletions(-) diff --git a/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs b/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs index c2cdf9da..7972c304 100644 --- a/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs +++ b/Mimir.Worker/ActionHandler/CombinationSlotStateHandler.cs @@ -1,13 +1,13 @@ -using System.Globalization; +using System.Text.RegularExpressions; using Bencodex.Types; using Lib9c.Models.Extensions; +using Lib9c.Models.States; using Libplanet.Crypto; using Mimir.MongoDB; using Mimir.MongoDB.Bson; using Mimir.Worker.Exceptions; using Mimir.Worker.Services; using MongoDB.Driver; -using Nekoyume.Action; using Serilog; namespace Mimir.Worker.ActionHandler; @@ -17,120 +17,96 @@ public class CombinationSlotStateHandler(IStateService stateService, MongoDbServ stateService, store, "^combination_consumable[0-9]*$|^combination_equipment[0-9]*$|^event_consumable_item_crafts[0-9]*$|^item_enhancement[0-9]*$|^rapid_combination[0-9]*$", - Log.ForContext() - ) + Log.ForContext()) { protected override async Task TryHandleAction( string actionType, long processBlockIndex, IValue? actionPlainValueInternal, IClientSessionHandle? session = null, - CancellationToken stoppingToken = default - ) + CancellationToken stoppingToken = default) { + if (actionPlainValueInternal is not Dictionary actionValues) { - if (actionPlainValueInternal is not Dictionary actionValues) - { - throw new InvalidTypeOfActionPlainValueInternalException( - [ValueKind.Dictionary], - actionPlainValueInternal?.Kind - ); - } - - Address avatarAddress; - int slotIndex; - - if ( - System.Text.RegularExpressions.Regex.IsMatch( - actionType, - "^combination_consumable[0-9]*$" - ) - || System.Text.RegularExpressions.Regex.IsMatch( - actionType, - "^combination_equipment[0-9]*$" - ) - ) - { - avatarAddress = new Address(actionValues["a"]); - slotIndex = actionValues["s"].ToInteger(); - } - else if ( - System.Text.RegularExpressions.Regex.IsMatch(actionType, "^item_enhancement[0-9]*$") - ) - { - avatarAddress = new Address(actionValues["avatarAddress"]); - slotIndex = actionValues["slotIndex"].ToInteger(); - } - else if ( - System.Text.RegularExpressions.Regex.IsMatch( - actionType, - "^event_consumable_item_crafts[0-9]*$" - ) - ) - { - if (!(actionValues["l"] is List list)) - { - throw new ArgumentException("'l' must be a bencodex list"); - } - avatarAddress = new Address(list[0]); - slotIndex = list[3].ToInteger(); - } - else if ( - System.Text.RegularExpressions.Regex.IsMatch( - actionType, - "^rapid_combination[0-9]*$" - ) - ) - { - avatarAddress = new Address(actionValues["avatarAddress"]); - slotIndex = actionValues["slotIndex"].ToInteger(); - } - else - { - throw new ArgumentException($"Unknown actionType: {actionType}"); - } - - Logger.Information( - "CombinationSlotStateHandler, avatar: {avatarAddress}", - avatarAddress - ); - - var slotAddress = avatarAddress.Derive( - string.Format( - CultureInfo.InvariantCulture, - Nekoyume.Model.State.CombinationSlotState.DeriveFormat, - slotIndex - ) + var e = new InvalidTypeOfActionPlainValueInternalException( + [ValueKind.Dictionary], + actionPlainValueInternal?.Kind ); + Logger.Fatal( + e, + "Unexpected actionPlainValueInternal type: {ActionPlainValueInternalType}", + actionPlainValueInternal?.Kind); + return false; + } - var combinationSlotState = await StateGetter.GetCombinationSlotState(slotAddress); + Address avatarAddress; + int slotIndex; - if (combinationSlotState is null) + if (Regex.IsMatch(actionType, "^combination_consumable[0-9]*$") || + Regex.IsMatch(actionType, "^combination_equipment[0-9]*$")) + { + avatarAddress = new Address(actionValues["a"]); + slotIndex = actionValues["s"].ToInteger(); + } + else if (Regex.IsMatch(actionType, "^item_enhancement[0-9]*$")) + { + avatarAddress = new Address(actionValues["avatarAddress"]); + slotIndex = actionValues["slotIndex"].ToInteger(); + } + else if (Regex.IsMatch(actionType, "^event_consumable_item_crafts[0-9]*$")) + { + if (actionValues["l"] is not List list) { - Logger.Error( - "CombinationSlotState is null\navatar: {avatarAddress}, slotIndex: {slotIndex}", - avatarAddress, - slotIndex - ); - + var e = new ArgumentException("'l' must be a bencodex list"); + Logger.Fatal(e, "actionValues[\"l\"] is not a List"); return false; } - await Store.UpsertStateDataManyAsync( - CollectionNames.GetCollectionName(), - [ - new CombinationSlotStateDocument( - slotAddress, - avatarAddress, - slotIndex, - combinationSlotState - ) - ], - session, - stoppingToken - ); + avatarAddress = new Address(list[0]); + slotIndex = list[3].ToInteger(); + } + else if (Regex.IsMatch(actionType, "^rapid_combination[0-9]*$")) + { + avatarAddress = new Address(actionValues["avatarAddress"]); + slotIndex = actionValues["slotIndex"].ToInteger(); + } + else + { + var e = new ArgumentException($"Unknown actionType: {actionType}"); + Logger.Fatal(e, "Unknown actionType: {ActionType}", actionType); + return false; + } - return true; + Logger.Information("CombinationSlotStateHandler, avatar: {AvatarAddress}", avatarAddress); + + var slotAddress = Nekoyume.Model.State.CombinationSlotState.DeriveAddress(avatarAddress, slotIndex); + CombinationSlotState combinationSlotState; + try + { + combinationSlotState = await StateGetter.GetCombinationSlotStateAsync(slotAddress, stoppingToken); } + catch (StateNotFoundException e) + { + Logger.Fatal( + e, + "CombinationSlotState is null\navatar: {AvatarAddress}, slotIndex: {SlotIndex}", + avatarAddress, + slotIndex); + return false; + } + + var doc = new CombinationSlotStateDocument( + slotAddress, + avatarAddress, + slotIndex, + combinationSlotState); + await Store.UpsertStateDataManyAsync( + CollectionNames.GetCollectionName(), + [doc], + session, + stoppingToken + ); + + return true; } } diff --git a/Mimir.Worker/ActionHandler/PetStateHandler.cs b/Mimir.Worker/ActionHandler/PetStateHandler.cs index f9ce2ea1..0987bfc4 100644 --- a/Mimir.Worker/ActionHandler/PetStateHandler.cs +++ b/Mimir.Worker/ActionHandler/PetStateHandler.cs @@ -78,7 +78,7 @@ protected override async Task TryHandleAction( ) ); - var combinationSlotState = await StateGetter.GetCombinationSlotState(slotAddress); + var combinationSlotState = await StateGetter.GetCombinationSlotStateAsync(slotAddress); if (combinationSlotState is null) { diff --git a/Mimir.Worker/Util/StateGetter.cs b/Mimir.Worker/Util/StateGetter.cs index a2519100..d6b7fb6c 100644 --- a/Mimir.Worker/Util/StateGetter.cs +++ b/Mimir.Worker/Util/StateGetter.cs @@ -300,13 +300,11 @@ public async Task GetWorldBossKillRewardRecordState( return new WorldBossKillRewardRecord(state); } - public async Task GetCombinationSlotState( + public async Task GetCombinationSlotStateAsync( Address slotAddress, - CancellationToken stoppingToken = default - ) + CancellationToken stoppingToken = default) { var state = await _service.GetState(slotAddress, stoppingToken); - if (state is null) { throw new StateNotFoundException(slotAddress, typeof(CombinationSlotState)); From bc48cecf5a3c16af0770aa148658af03debf329a Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Thu, 19 Sep 2024 18:02:07 +0900 Subject: [PATCH 04/20] separate MimirBsonDocument.ToJson as extension method --- Mimir.MongoDB/Bson/MimirBsonDocument.cs | 20 +--------------- .../Extensions/MimirBsonDocumentExtensions.cs | 24 +++++++++++++++++++ Mimir.Worker/Services/MongoDbService.cs | 1 + 3 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs diff --git a/Mimir.MongoDB/Bson/MimirBsonDocument.cs b/Mimir.MongoDB/Bson/MimirBsonDocument.cs index ba1c0f5b..a25255db 100644 --- a/Mimir.MongoDB/Bson/MimirBsonDocument.cs +++ b/Mimir.MongoDB/Bson/MimirBsonDocument.cs @@ -1,23 +1,5 @@ using Libplanet.Crypto; -using Mimir.MongoDB.Json.Converters; -using Newtonsoft.Json; namespace Mimir.MongoDB.Bson; -public record MimirBsonDocument(Address Address) -{ - public static readonly JsonSerializerSettings JsonSerializerSettings = - new() - { - Formatting = Formatting.Indented, - NullValueHandling = NullValueHandling.Ignore, - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - Converters = [new BigIntegerToStringConverter()], - ContractResolver = new IgnoreBencodedContractResolver() - }; - - public string ToJson() - { - return JsonConvert.SerializeObject(this, JsonSerializerSettings); - } -} +public record MimirBsonDocument(Address Address); diff --git a/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs b/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs new file mode 100644 index 00000000..bec6900e --- /dev/null +++ b/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs @@ -0,0 +1,24 @@ +using Mimir.MongoDB.Bson; +using Mimir.MongoDB.Json.Converters; +using Newtonsoft.Json; + +namespace Mimir.MongoDB.Json.Extensions; + +public static class MimirBsonDocumentExtensions +{ + public static readonly JsonSerializerSettings JsonSerializerSettings = new() + { + Formatting = Formatting.None, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + Converters = + [ + new BigIntegerJsonConverter(), + new MaterialAndIntDictionaryJsonConverter(), + ], + ContractResolver = new IgnoreBencodedContractResolver(), + }; + + public static string ToJson(this MimirBsonDocument document) => + JsonConvert.SerializeObject(document, JsonSerializerSettings); +} diff --git a/Mimir.Worker/Services/MongoDbService.cs b/Mimir.Worker/Services/MongoDbService.cs index 35d25f17..623cb6a8 100644 --- a/Mimir.Worker/Services/MongoDbService.cs +++ b/Mimir.Worker/Services/MongoDbService.cs @@ -4,6 +4,7 @@ using Mimir.MongoDB; using Mimir.MongoDB.Bson; using Mimir.MongoDB.Bson.Serialization; +using Mimir.MongoDB.Json.Extensions; using Mimir.Worker.Constants; using MongoDB.Bson; using MongoDB.Driver; From 76d024838589d2847e8875c85a5ce1db1ff013c6 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Thu, 19 Sep 2024 19:24:17 +0900 Subject: [PATCH 05/20] introduce MaterialAndIntDictionaryJsonConverter --- .../MaterialAndIntDictionaryJsonConverter.cs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Mimir.MongoDB/Json/Converters/MaterialAndIntDictionaryJsonConverter.cs diff --git a/Mimir.MongoDB/Json/Converters/MaterialAndIntDictionaryJsonConverter.cs b/Mimir.MongoDB/Json/Converters/MaterialAndIntDictionaryJsonConverter.cs new file mode 100644 index 00000000..5cc8e0bc --- /dev/null +++ b/Mimir.MongoDB/Json/Converters/MaterialAndIntDictionaryJsonConverter.cs @@ -0,0 +1,60 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Json.Extensions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Mimir.MongoDB.Json.Converters; + +public class MaterialAndIntDictionaryJsonConverter : JsonConverter> +{ + public override Dictionary? ReadJson( + JsonReader reader, + Type objectType, + Dictionary? existingValue, + bool hasExistingValue, + JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + + var dictionary = new Dictionary(); + var jObject = JObject.Load(reader); + foreach (var property in jObject.Properties()) + { + var material = JsonConvert.DeserializeObject(property.Name); + if (material is null) + { + throw new JsonException($"Failed to deserialize {nameof(Material)}. {property.Name}"); + } + + var value = property.Value.ToObject(); + dictionary.Add(material, value); + } + + return dictionary; + } + + public override void WriteJson( + JsonWriter writer, + Dictionary? value, + JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + + writer.WriteStartObject(); + foreach (var kvp in value) + { + var key = JsonConvert.SerializeObject(kvp.Key, MimirBsonDocumentExtensions.JsonSerializerSettings); + writer.WritePropertyName(key); + writer.WriteValue(kvp.Value); + } + + writer.WriteEndObject(); + } +} From 359294f969b9163c3c7bb990c539eefc3829a864 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Thu, 19 Sep 2024 18:30:30 +0900 Subject: [PATCH 06/20] improve BigIntegerJsonConverter --- .../Converters/BigIntegerJsonConverter.cs | 42 +++++++++++++++++++ .../Converters/BigIntegerToStringConverter.cs | 22 ---------- 2 files changed, 42 insertions(+), 22 deletions(-) create mode 100644 Mimir.MongoDB/Json/Converters/BigIntegerJsonConverter.cs delete mode 100644 Mimir.MongoDB/Json/Converters/BigIntegerToStringConverter.cs diff --git a/Mimir.MongoDB/Json/Converters/BigIntegerJsonConverter.cs b/Mimir.MongoDB/Json/Converters/BigIntegerJsonConverter.cs new file mode 100644 index 00000000..91e7bcad --- /dev/null +++ b/Mimir.MongoDB/Json/Converters/BigIntegerJsonConverter.cs @@ -0,0 +1,42 @@ +using System.Numerics; +using Newtonsoft.Json; + +namespace Mimir.MongoDB.Json.Converters; + +public class BigIntegerJsonConverter : JsonConverter +{ + public override BigInteger ReadJson( + JsonReader reader, + Type objectType, + BigInteger existingValue, + bool hasExistingValue, + JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + throw new JsonSerializationException("Cannot convert null value to BigInteger."); + } + + if (reader.TokenType == JsonToken.String) + { + var value = (string)reader.Value!; + return BigInteger.Parse(value); + } + + if (reader.TokenType == JsonToken.Integer) + { + var value = (long)reader.Value!; + return new BigInteger(value); + } + + throw new JsonSerializationException($"Unexpected token type: {reader.TokenType}."); + } + + public override void WriteJson( + JsonWriter writer, + BigInteger value, + JsonSerializer serializer) + { + writer.WriteValue(value.ToString()); + } +} diff --git a/Mimir.MongoDB/Json/Converters/BigIntegerToStringConverter.cs b/Mimir.MongoDB/Json/Converters/BigIntegerToStringConverter.cs deleted file mode 100644 index 8e0547c9..00000000 --- a/Mimir.MongoDB/Json/Converters/BigIntegerToStringConverter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Numerics; -using Newtonsoft.Json; - -namespace Mimir.MongoDB.Json.Converters; - -public class BigIntegerToStringConverter : JsonConverter -{ - public override bool CanConvert(Type objectType) - { - return objectType == typeof(BigInteger); - } - - public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - writer.WriteValue(value.ToString()); - } -} From 2db0eb2074beaee53a3154449b8ef194356a1944 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Thu, 19 Sep 2024 22:07:45 +0900 Subject: [PATCH 07/20] fix argument type of ItemFactory.Create method --- .../CombinationConsumable5Result.cs | 2 +- .../DailyReward2Result.cs | 2 +- .../ItemEnhancement11Result.cs | 2 +- .../ItemEnhancement12Result.cs | 2 +- .../ItemEnhancement13Result.cs | 2 +- .../ItemEnhancement9Result.cs | 2 +- .../RapidCombination0Result.cs | 2 +- .../RapidCombination5Result.cs | 2 +- Lib9c.Models/Factories/ItemFactory.cs | 43 ++++++++++++------- Lib9c.Models/Items/InventoryItem.cs | 2 +- Lib9c.Models/Items/ShopItem.cs | 6 +-- Lib9c.Models/Market/ItemProduct.cs | 2 +- 12 files changed, 40 insertions(+), 29 deletions(-) diff --git a/Lib9c.Models/AttachmentActionResults/CombinationConsumable5Result.cs b/Lib9c.Models/AttachmentActionResults/CombinationConsumable5Result.cs index 4ec1050c..9c8c7f51 100644 --- a/Lib9c.Models/AttachmentActionResults/CombinationConsumable5Result.cs +++ b/Lib9c.Models/AttachmentActionResults/CombinationConsumable5Result.cs @@ -45,7 +45,7 @@ public CombinationConsumable5Result(IValue bencoded) : base(bencoded) Materials = ((List)d["materials"]) .Cast() .ToDictionary( - value => (Material)ItemFactory.Deserialize((Dictionary)value["material"]), + value => (Material)ItemFactory.Deserialize(value["material"]), value => value["count"].ToInteger()); Id = d["id"].ToGuid(); Gold = d["gold"].ToBigInteger(); diff --git a/Lib9c.Models/AttachmentActionResults/DailyReward2Result.cs b/Lib9c.Models/AttachmentActionResults/DailyReward2Result.cs index 66985b0d..5d38400a 100644 --- a/Lib9c.Models/AttachmentActionResults/DailyReward2Result.cs +++ b/Lib9c.Models/AttachmentActionResults/DailyReward2Result.cs @@ -36,7 +36,7 @@ public DailyReward2Result(IValue bencoded) : base(bencoded) Materials = ((List)d["materials"]) .Cast() .ToDictionary( - value => (Material)ItemFactory.Deserialize((Dictionary)value["material"]), + value => (Material)ItemFactory.Deserialize(value["material"]), value => value["count"].ToInteger()); Id = d["id"].ToGuid(); diff --git a/Lib9c.Models/AttachmentActionResults/ItemEnhancement11Result.cs b/Lib9c.Models/AttachmentActionResults/ItemEnhancement11Result.cs index 812d97ca..da1fc77c 100644 --- a/Lib9c.Models/AttachmentActionResults/ItemEnhancement11Result.cs +++ b/Lib9c.Models/AttachmentActionResults/ItemEnhancement11Result.cs @@ -61,7 +61,7 @@ public ItemEnhancement11Result(IValue bencoded) : base(bencoded) ActionPoint = d["actionPoint"].ToInteger(); EnhancementResult = d["enhancementResult"].ToEnum(); PreItemUsable = d.ContainsKey("preItemUsable") - ? (ItemUsable)ItemFactory.Deserialize((Dictionary)d["preItemUsable"]) + ? (ItemUsable)ItemFactory.Deserialize(d["preItemUsable"]) : null; Crystal = new FungibleAssetValue(d["c"]); } diff --git a/Lib9c.Models/AttachmentActionResults/ItemEnhancement12Result.cs b/Lib9c.Models/AttachmentActionResults/ItemEnhancement12Result.cs index 4bd7ab22..3ea28f3a 100644 --- a/Lib9c.Models/AttachmentActionResults/ItemEnhancement12Result.cs +++ b/Lib9c.Models/AttachmentActionResults/ItemEnhancement12Result.cs @@ -61,7 +61,7 @@ public ItemEnhancement12Result(IValue bencoded) : base(bencoded) ActionPoint = d["actionPoint"].ToInteger(); EnhancementResult = d["enhancementResult"].ToEnum(); PreItemUsable = d.ContainsKey("preItemUsable") - ? (ItemUsable)ItemFactory.Deserialize((Dictionary)d["preItemUsable"]) + ? (ItemUsable)ItemFactory.Deserialize(d["preItemUsable"]) : null; Crystal = new FungibleAssetValue(d["c"]); } diff --git a/Lib9c.Models/AttachmentActionResults/ItemEnhancement13Result.cs b/Lib9c.Models/AttachmentActionResults/ItemEnhancement13Result.cs index 6bca2304..7179487a 100644 --- a/Lib9c.Models/AttachmentActionResults/ItemEnhancement13Result.cs +++ b/Lib9c.Models/AttachmentActionResults/ItemEnhancement13Result.cs @@ -61,7 +61,7 @@ public ItemEnhancement13Result(IValue bencoded) : base(bencoded) ActionPoint = d["actionPoint"].ToInteger(); EnhancementResult = d["enhancementResult"].ToEnum(); PreItemUsable = d.ContainsKey("preItemUsable") - ? (ItemUsable)ItemFactory.Deserialize((Dictionary)d["preItemUsable"]) + ? (ItemUsable)ItemFactory.Deserialize(d["preItemUsable"]) : null; Crystal = new FungibleAssetValue(d["c"]); } diff --git a/Lib9c.Models/AttachmentActionResults/ItemEnhancement9Result.cs b/Lib9c.Models/AttachmentActionResults/ItemEnhancement9Result.cs index 825b5412..96b200ee 100644 --- a/Lib9c.Models/AttachmentActionResults/ItemEnhancement9Result.cs +++ b/Lib9c.Models/AttachmentActionResults/ItemEnhancement9Result.cs @@ -59,7 +59,7 @@ public ItemEnhancement9Result(IValue bencoded) : base(bencoded) ActionPoint = d["actionPoint"].ToInteger(); EnhancementResult = d["enhancementResult"].ToEnum(); PreItemUsable = d.ContainsKey("preItemUsable") - ? (ItemUsable)ItemFactory.Deserialize((Dictionary)d["preItemUsable"]) + ? (ItemUsable)ItemFactory.Deserialize(d["preItemUsable"]) : null; } } diff --git a/Lib9c.Models/AttachmentActionResults/RapidCombination0Result.cs b/Lib9c.Models/AttachmentActionResults/RapidCombination0Result.cs index 20337824..5aa7629b 100644 --- a/Lib9c.Models/AttachmentActionResults/RapidCombination0Result.cs +++ b/Lib9c.Models/AttachmentActionResults/RapidCombination0Result.cs @@ -34,7 +34,7 @@ public RapidCombination0Result(IValue bencoded) : base(bencoded) Cost = ((List)d["cost"]) .Cast() .ToDictionary( - value => (Material)ItemFactory.Deserialize((Dictionary)value["material"]), + value => (Material)ItemFactory.Deserialize(value["material"]), value => value["count"].ToInteger()); } } diff --git a/Lib9c.Models/AttachmentActionResults/RapidCombination5Result.cs b/Lib9c.Models/AttachmentActionResults/RapidCombination5Result.cs index 7fbb816f..1218d8bc 100644 --- a/Lib9c.Models/AttachmentActionResults/RapidCombination5Result.cs +++ b/Lib9c.Models/AttachmentActionResults/RapidCombination5Result.cs @@ -37,7 +37,7 @@ public RapidCombination5Result(IValue bencoded) : base(bencoded) Cost = ((List)d["cost"]) .Cast() .ToDictionary( - value => (Material)ItemFactory.Deserialize((Dictionary)value["material"]), + value => (Material)ItemFactory.Deserialize(value["material"]), value => value["count"].ToInteger()); } } diff --git a/Lib9c.Models/Factories/ItemFactory.cs b/Lib9c.Models/Factories/ItemFactory.cs index f5f7f7fb..0b873ff8 100644 --- a/Lib9c.Models/Factories/ItemFactory.cs +++ b/Lib9c.Models/Factories/ItemFactory.cs @@ -1,18 +1,28 @@ using Bencodex.Types; +using Lib9c.Models.Exceptions; using Lib9c.Models.Items; using ItemType = Nekoyume.Model.Item.ItemType; using ItemSubType = Nekoyume.Model.Item.ItemSubType; using static Lib9c.SerializeKeys; using Lib9c.Models.Extensions; +using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Factories; public static class ItemFactory { - public static ItemBase Deserialize(Dictionary serialized) + public static ItemBase Deserialize(IValue bencoded) { - if (serialized.TryGetValue((Text)"item_type", out var type) && - serialized.TryGetValue((Text)"item_sub_type", out var subType)) + if (bencoded is not Dictionary d) + { + throw new UnsupportedArgumentTypeException( + nameof(bencoded), + new[] { ValueKind.Dictionary }, + bencoded.Kind); + } + + if (d.TryGetValue((Text)"item_type", out var type) && + d.TryGetValue((Text)"item_sub_type", out var subType)) { var itemType = type.ToEnum(); var itemSubType = subType.ToEnum(); @@ -20,38 +30,39 @@ public static ItemBase Deserialize(Dictionary serialized) switch (itemType) { case ItemType.Consumable: - return new Consumable(serialized); + return new Consumable(d); case ItemType.Costume: - return new Costume(serialized); + return new Costume(d); case ItemType.Equipment: switch (itemSubType) { case ItemSubType.Weapon: - return new Weapon(serialized); + return new Weapon(d); case ItemSubType.Armor: - return new Armor(serialized); + return new Armor(d); case ItemSubType.Belt: - return new Belt(serialized); + return new Belt(d); case ItemSubType.Necklace: - return new Necklace(serialized); + return new Necklace(d); case ItemSubType.Ring: - return new Ring(serialized); + return new Ring(d); case ItemSubType.Aura: - return new Aura(serialized); + return new Aura(d); case ItemSubType.Grimoire: - return new Grimoire(serialized); + return new Grimoire(d); } + break; case ItemType.Material: - return serialized.ContainsKey(RequiredBlockIndexKey) - ? new TradableMaterial(serialized) - : new Material(serialized); + return d.ContainsKey(RequiredBlockIndexKey) + ? new TradableMaterial(d) + : new Material(d); default: throw new ArgumentOutOfRangeException(nameof(itemType)); } } - throw new ArgumentException($"Can't Deserialize Item {serialized}"); + throw new ArgumentException($"Can't Deserialize Item {d}"); } } diff --git a/Lib9c.Models/Items/InventoryItem.cs b/Lib9c.Models/Items/InventoryItem.cs index 96f99636..48354762 100644 --- a/Lib9c.Models/Items/InventoryItem.cs +++ b/Lib9c.Models/Items/InventoryItem.cs @@ -40,7 +40,7 @@ public InventoryItem(IValue bencoded) bencoded.Kind); } - Item = ItemFactory.Deserialize((Dictionary)d["item"]); + Item = ItemFactory.Deserialize(d["item"]); Count = (Integer)d["count"]; if (d.ContainsKey("l")) { diff --git a/Lib9c.Models/Items/ShopItem.cs b/Lib9c.Models/Items/ShopItem.cs index f6a3356b..d38e1071 100644 --- a/Lib9c.Models/Items/ShopItem.cs +++ b/Lib9c.Models/Items/ShopItem.cs @@ -87,13 +87,13 @@ public ShopItem(IValue bencoded) ProductId = d[LegacyProductIdKey].ToGuid(); Price = d[LegacyPriceKey].ToFungibleAssetValue(); ItemUsable = d.ContainsKey(LegacyItemUsableKey) - ? (ItemUsable)ItemFactory.Deserialize((Dictionary)d[LegacyItemUsableKey]) + ? (ItemUsable)ItemFactory.Deserialize(d[LegacyItemUsableKey]) : null; Costume = d.ContainsKey(LegacyCostumeKey) - ? (Costume)ItemFactory.Deserialize((Dictionary)d[LegacyCostumeKey]) + ? (Costume)ItemFactory.Deserialize(d[LegacyCostumeKey]) : null; TradableFungibleItem = d.ContainsKey(TradableFungibleItemKey) - ? (TradableMaterial)ItemFactory.Deserialize((Dictionary)d[TradableFungibleItemKey]) + ? (TradableMaterial)ItemFactory.Deserialize(d[TradableFungibleItemKey]) : null; TradableFungibleItemCount = d.ContainsKey(TradableFungibleItemCountKey) ? d[TradableFungibleItemCountKey].ToInteger() diff --git a/Lib9c.Models/Market/ItemProduct.cs b/Lib9c.Models/Market/ItemProduct.cs index b252ee02..feae3e7b 100644 --- a/Lib9c.Models/Market/ItemProduct.cs +++ b/Lib9c.Models/Market/ItemProduct.cs @@ -14,7 +14,7 @@ public class ItemProduct : Product, IBencodable public ItemProduct(List bencoded) : base(bencoded) { - TradableItem = ItemFactory.Deserialize((Dictionary)bencoded[6]); + TradableItem = ItemFactory.Deserialize(bencoded[6]); ItemCount = bencoded[7].ToInteger(); } From f7a9293dbd70ec857a91438a4dde495866b1e603 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 00:20:50 +0900 Subject: [PATCH 08/20] update item related models --- Lib9c.Models/Items/Armor.cs | 4 ++ Lib9c.Models/Items/Aura.cs | 4 ++ Lib9c.Models/Items/Belt.cs | 4 ++ Lib9c.Models/Items/Consumable.cs | 11 +++- Lib9c.Models/Items/Costume.cs | 9 ++- Lib9c.Models/Items/Equipment.cs | 9 ++- Lib9c.Models/Items/Grimoire.cs | 4 ++ Lib9c.Models/Items/Inventory.cs | 2 + Lib9c.Models/Items/InventoryItem.cs | 2 + Lib9c.Models/Items/ItemBase.cs | 6 ++ Lib9c.Models/Items/ItemUsable.cs | 9 ++- Lib9c.Models/Items/Material.cs | 23 ++++++- Lib9c.Models/Items/Necklace.cs | 4 ++ Lib9c.Models/Items/Ring.cs | 4 ++ Lib9c.Models/Items/ShopItem.cs | 2 + Lib9c.Models/Items/TradableMaterial.cs | 9 ++- Lib9c.Models/Items/Weapon.cs | 4 ++ Lib9c.Models/Skills/Skill.cs | 4 ++ Lib9c.Models/States/CombinationSlotState.cs | 71 +++++++++++---------- Lib9c.Models/Stats/DecimalStat.cs | 8 ++- Lib9c.Models/Stats/StatMap.cs | 4 ++ 21 files changed, 148 insertions(+), 49 deletions(-) diff --git a/Lib9c.Models/Items/Armor.cs b/Lib9c.Models/Items/Armor.cs index 1964f6b0..b75f57f2 100644 --- a/Lib9c.Models/Items/Armor.cs +++ b/Lib9c.Models/Items/Armor.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Armor : Equipment { + public Armor() + { + } + public Armor(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/Aura.cs b/Lib9c.Models/Items/Aura.cs index 27796419..d035f776 100644 --- a/Lib9c.Models/Items/Aura.cs +++ b/Lib9c.Models/Items/Aura.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Aura : Equipment { + public Aura() + { + } + public Aura(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/Belt.cs b/Lib9c.Models/Items/Belt.cs index f1cbef32..ffafc0e3 100644 --- a/Lib9c.Models/Items/Belt.cs +++ b/Lib9c.Models/Items/Belt.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Belt : Equipment { + public Belt() + { + } + public Belt(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/Consumable.cs b/Lib9c.Models/Items/Consumable.cs index b252c752..1dc52761 100644 --- a/Lib9c.Models/Items/Consumable.cs +++ b/Lib9c.Models/Items/Consumable.cs @@ -1,8 +1,8 @@ -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; using Lib9c.Models.Stats; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Items; @@ -10,16 +10,21 @@ namespace Lib9c.Models.Items; /// /// /// -public record Consumable : ItemUsable, IBencodable +public record Consumable : ItemUsable { - public List Stats { get; } + public List Stats { get; init; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded => ((Dictionary)base.Bencoded) .Add("stats", new List(Stats .OrderBy(i => i.StatType) .ThenByDescending(i => i.BaseValue) .Select(s => s.BencodedWithoutAdditionalValue))); + public Consumable() + { + } + public Consumable(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/Costume.cs b/Lib9c.Models/Items/Costume.cs index aa05389a..9d1748cf 100644 --- a/Lib9c.Models/Items/Costume.cs +++ b/Lib9c.Models/Items/Costume.cs @@ -1,22 +1,23 @@ -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using ValueKind = Bencodex.Types.ValueKind; using static Lib9c.SerializeKeys; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; namespace Lib9c.Models.Items; /// /// /// -public record Costume : ItemBase, IBencodable +public record Costume : ItemBase { public bool Equipped { get; } public string SpineResourcePath { get; } public Guid ItemId { get; } public long RequiredBlockIndex { get; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded { get @@ -32,6 +33,10 @@ public override IValue Bencoded } } + public Costume() + { + } + public Costume(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/Equipment.cs b/Lib9c.Models/Items/Equipment.cs index efbe9411..072c36a2 100644 --- a/Lib9c.Models/Items/Equipment.cs +++ b/Lib9c.Models/Items/Equipment.cs @@ -1,17 +1,17 @@ -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Stats; using ValueKind = Bencodex.Types.ValueKind; using static Lib9c.SerializeKeys; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; namespace Lib9c.Models.Items; /// /// /// -public record Equipment : ItemUsable, IBencodable +public record Equipment : ItemUsable { public bool Equipped { get; init; } public int Level { get; init; } @@ -22,6 +22,7 @@ public record Equipment : ItemUsable, IBencodable public int OptionCountFromCombination { get; init; } public bool MadeWithMimisbrunnrRecipe { get; init; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded { get @@ -52,6 +53,10 @@ public override IValue Bencoded } } + public Equipment() + { + } + public Equipment(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/Grimoire.cs b/Lib9c.Models/Items/Grimoire.cs index b26291b4..10d655b1 100644 --- a/Lib9c.Models/Items/Grimoire.cs +++ b/Lib9c.Models/Items/Grimoire.cs @@ -4,6 +4,10 @@ namespace Lib9c.Models.Items; public record Grimoire : Equipment { + public Grimoire() + { + } + public Grimoire(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/Inventory.cs b/Lib9c.Models/Items/Inventory.cs index d680c0cb..b37c3cf5 100644 --- a/Lib9c.Models/Items/Inventory.cs +++ b/Lib9c.Models/Items/Inventory.cs @@ -1,6 +1,7 @@ using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Items; @@ -12,6 +13,7 @@ public record Inventory : IBencodable { public List Items { get; init; } + [BsonIgnore, GraphQLIgnore] public IValue Bencoded => new List(Items .OrderBy(i => i.Item.Id) .ThenByDescending(i => i.Count) diff --git a/Lib9c.Models/Items/InventoryItem.cs b/Lib9c.Models/Items/InventoryItem.cs index 48354762..46322081 100644 --- a/Lib9c.Models/Items/InventoryItem.cs +++ b/Lib9c.Models/Items/InventoryItem.cs @@ -2,6 +2,7 @@ using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; using Nekoyume.Model.Item; using ItemFactory = Lib9c.Models.Factories.ItemFactory; using ValueKind = Bencodex.Types.ValueKind; @@ -17,6 +18,7 @@ public record InventoryItem : IBencodable public int Count { get; init; } public ILock? Lock { get; init; } + [BsonIgnore, GraphQLIgnore] public IValue Bencoded { get diff --git a/Lib9c.Models/Items/ItemBase.cs b/Lib9c.Models/Items/ItemBase.cs index 4ffe5a20..cc3b6681 100644 --- a/Lib9c.Models/Items/ItemBase.cs +++ b/Lib9c.Models/Items/ItemBase.cs @@ -2,6 +2,7 @@ using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Items; @@ -17,6 +18,7 @@ public record ItemBase : IBencodable public Nekoyume.Model.Item.ItemSubType ItemSubType { get; init; } public Nekoyume.Model.Elemental.ElementalType ElementalType { get; init; } + [BsonIgnore, GraphQLIgnore] public virtual IValue Bencoded => Dictionary.Empty .Add("id", Id.Serialize()) .Add("item_type", ItemType.Serialize()) @@ -24,6 +26,10 @@ public record ItemBase : IBencodable .Add("grade", Grade.Serialize()) .Add("elemental_type", ElementalType.Serialize()); + public ItemBase() + { + } + public ItemBase(IValue bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/ItemUsable.cs b/Lib9c.Models/Items/ItemUsable.cs index 5cbddc65..3c4ae2b5 100644 --- a/Lib9c.Models/Items/ItemUsable.cs +++ b/Lib9c.Models/Items/ItemUsable.cs @@ -1,10 +1,10 @@ -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; using Lib9c.Models.Factories; using Lib9c.Models.Skills; using Lib9c.Models.Stats; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Items; @@ -12,7 +12,7 @@ namespace Lib9c.Models.Items; /// /// /// -public record ItemUsable : ItemBase, IBencodable +public record ItemUsable : ItemBase { public Guid ItemId { get; init; } @@ -23,6 +23,7 @@ public record ItemUsable : ItemBase, IBencodable public List BuffSkills { get; init; } public long RequiredBlockIndex { get; init; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded => ((Dictionary)base.Bencoded) .Add("itemId", ItemId.Serialize()) .Add("statsMap", StatsMap.Bencoded) @@ -36,6 +37,10 @@ public record ItemUsable : ItemBase, IBencodable .Select(s => s.Bencoded))) .Add("requiredBlockIndex", RequiredBlockIndex.Serialize()); + public ItemUsable() + { + } + public ItemUsable(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/Material.cs b/Lib9c.Models/Items/Material.cs index 7a786993..390104f5 100644 --- a/Lib9c.Models/Items/Material.cs +++ b/Lib9c.Models/Items/Material.cs @@ -1,9 +1,9 @@ using System.Security.Cryptography; -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; using Libplanet.Common; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.Items; @@ -11,13 +11,18 @@ namespace Lib9c.Models.Items; /// /// /// -public record Material : ItemBase, IBencodable +public record Material : ItemBase { public HashDigest ItemId { get; init; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded => ((Dictionary)base.Bencoded) .Add("item_id", ItemId.Serialize()); + public Material() + { + } + public Material(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) @@ -28,9 +33,21 @@ public Material(IValue bencoded) : base(bencoded) bencoded.Kind); } - if (d.TryGetValue((Text) "item_id", out var itemId)) + if (d.TryGetValue((Text)"item_id", out var itemId)) { ItemId = itemId.ToItemId(); } } + + // public Material( + // int id, + // int grade, + // Nekoyume.Model.Item.ItemType itemType, + // Nekoyume.Model.Item.ItemSubType itemSubType, + // Nekoyume.Model.Elemental.ElementalType elementalType, + // HashDigest itemId) + // : base(id, grade, itemType, itemSubType, elementalType) + // { + // ItemId = itemId; + // } } diff --git a/Lib9c.Models/Items/Necklace.cs b/Lib9c.Models/Items/Necklace.cs index aaa8856b..c3c4eefb 100644 --- a/Lib9c.Models/Items/Necklace.cs +++ b/Lib9c.Models/Items/Necklace.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Necklace : Equipment { + public Necklace() + { + } + public Necklace(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/Ring.cs b/Lib9c.Models/Items/Ring.cs index 1c9d429d..ed4f86ed 100644 --- a/Lib9c.Models/Items/Ring.cs +++ b/Lib9c.Models/Items/Ring.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Ring : Equipment { + public Ring() + { + } + public Ring(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Items/ShopItem.cs b/Lib9c.Models/Items/ShopItem.cs index d38e1071..d6aa13d9 100644 --- a/Lib9c.Models/Items/ShopItem.cs +++ b/Lib9c.Models/Items/ShopItem.cs @@ -7,6 +7,7 @@ using ValueKind = Bencodex.Types.ValueKind; using static Lib9c.SerializeKeys; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; namespace Lib9c.Models.Items; @@ -33,6 +34,7 @@ public record ShopItem : IBencodable public int TradableFungibleItemCount { get; init; } public long ExpiredBlockIndex { get; init; } + [BsonIgnore, GraphQLIgnore] public IValue Bencoded { get diff --git a/Lib9c.Models/Items/TradableMaterial.cs b/Lib9c.Models/Items/TradableMaterial.cs index b67f44ab..fe1abd23 100644 --- a/Lib9c.Models/Items/TradableMaterial.cs +++ b/Lib9c.Models/Items/TradableMaterial.cs @@ -1,22 +1,27 @@ -using Bencodex; using Bencodex.Types; using Lib9c.Models.Exceptions; using ValueKind = Bencodex.Types.ValueKind; using static Lib9c.SerializeKeys; using Lib9c.Models.Extensions; +using MongoDB.Bson.Serialization.Attributes; namespace Lib9c.Models.Items; /// /// /// -public record TradableMaterial : Material, IBencodable +public record TradableMaterial : Material { public long RequiredBlockIndex { get; init; } + [BsonIgnore, GraphQLIgnore] public override IValue Bencoded => ((Dictionary)base.Bencoded) .Add(RequiredBlockIndexKey, RequiredBlockIndex.Serialize()); + public TradableMaterial() + { + } + public TradableMaterial(IValue bencoded) : base(bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Items/Weapon.cs b/Lib9c.Models/Items/Weapon.cs index c83605a6..326ac8c1 100644 --- a/Lib9c.Models/Items/Weapon.cs +++ b/Lib9c.Models/Items/Weapon.cs @@ -7,6 +7,10 @@ namespace Lib9c.Models.Items; /// public record Weapon : Equipment { + public Weapon() + { + } + public Weapon(IValue bencoded) : base(bencoded) { } diff --git a/Lib9c.Models/Skills/Skill.cs b/Lib9c.Models/Skills/Skill.cs index e77b2b61..7dd1e68b 100644 --- a/Lib9c.Models/Skills/Skill.cs +++ b/Lib9c.Models/Skills/Skill.cs @@ -52,6 +52,10 @@ public IValue Bencoded } } + public Skill() + { + } + public Skill(IValue bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/States/CombinationSlotState.cs b/Lib9c.Models/States/CombinationSlotState.cs index 5d7f193a..8b8117f8 100644 --- a/Lib9c.Models/States/CombinationSlotState.cs +++ b/Lib9c.Models/States/CombinationSlotState.cs @@ -1,21 +1,52 @@ using Bencodex; using Bencodex.Types; +using Lib9c.Models.AttachmentActionResults; using Lib9c.Models.Exceptions; using Lib9c.Models.Extensions; +using Lib9c.Models.Factories; +using MongoDB.Bson.Serialization.Attributes; using ValueKind = Bencodex.Types.ValueKind; namespace Lib9c.Models.States; -public class CombinationSlotState : IBencodable +/// +/// +/// +[BsonIgnoreExtraElements] +public record CombinationSlotState : IBencodable { public long UnlockBlockIndex { get; init; } public int UnlockStage { get; init; } - public long StartBlockIndex { get; init; } - - // public AttachmentActionResult? Result { get; init; } + public AttachmentActionResult? Result { get; init; } public int? PetId { get; init; } + [BsonIgnore, GraphQLIgnore] + public IValue Bencoded + { + get + { + var values = new Dictionary + { + [(Text)"unlockBlockIndex"] = UnlockBlockIndex.Serialize(), + [(Text)"unlockStage"] = UnlockStage.Serialize(), + [(Text)"startBlockIndex"] = StartBlockIndex.Serialize(), + }; + + if (Result != null) + { + values.Add((Text)"result", Result.Bencoded); + } + + if (PetId.HasValue) + { + values.Add((Text)"petId", PetId.Value.Serialize()); + } + + return new Dictionary(values); + } + } + public CombinationSlotState(IValue bencoded) { if (bencoded is not Dictionary d) @@ -30,10 +61,10 @@ public CombinationSlotState(IValue bencoded) UnlockBlockIndex = d["unlockBlockIndex"].ToLong(); UnlockStage = d["unlockStage"].ToInteger(); - // if (d.TryGetValue((Text)"result", out var result)) - // { - // Result = AttachmentActionResult.Deserialize((Dictionary)result); - // } + if (d.TryGetValue((Text)"result", out var result)) + { + Result = AttachmentActionResultFactory.Create(result); + } if (d.TryGetValue((Text)"startBlockIndex", out var startIndex)) { @@ -45,28 +76,4 @@ public CombinationSlotState(IValue bencoded) PetId = petId.ToNullableInteger(); } } - - public IValue Bencoded => Serialize(); - - public IValue Serialize() - { - var values = new Dictionary - { - [(Text)"unlockBlockIndex"] = UnlockBlockIndex.Serialize(), - [(Text)"unlockStage"] = UnlockStage.Serialize(), - [(Text)"startBlockIndex"] = StartBlockIndex.Serialize(), - }; - - // if (Result != null) - // { - // values.Add((Text)"result", Result.Serialize()); - // } - - if (PetId.HasValue) - { - values.Add((Text)"petId", PetId.Value.Serialize()); - } - - return new Dictionary(values); - } } diff --git a/Lib9c.Models/Stats/DecimalStat.cs b/Lib9c.Models/Stats/DecimalStat.cs index 41d8129b..49f18063 100644 --- a/Lib9c.Models/Stats/DecimalStat.cs +++ b/Lib9c.Models/Stats/DecimalStat.cs @@ -12,12 +12,10 @@ namespace Lib9c.Models.Stats; /// public record DecimalStat : IBencodable { + public StatType StatType { get; init; } public decimal BaseValue { get; init; } - public decimal AdditionalValue { get; init; } - public StatType StatType { get; } - public IValue Bencoded => Dictionary.Empty .Add("statType", StatType.Serialize()) .Add("value", BaseValue.Serialize()) @@ -31,6 +29,10 @@ public record DecimalStat : IBencodable .Add("type", StatType.Serialize()) .Add("value", BaseValue.Serialize()); + public DecimalStat() + { + } + public DecimalStat(IValue bencoded) { if (bencoded is not Dictionary d) diff --git a/Lib9c.Models/Stats/StatMap.cs b/Lib9c.Models/Stats/StatMap.cs index 356cee7d..e4a2f54e 100644 --- a/Lib9c.Models/Stats/StatMap.cs +++ b/Lib9c.Models/Stats/StatMap.cs @@ -20,6 +20,10 @@ public record StatMap : IBencodable kv.Key.Serialize(), kv.Value.Bencoded))); + public StatMap() + { + } + public StatMap(IValue bencoded) { if (bencoded is not Dictionary d) From 181d4629b08eb920a14c8cc77e428f5ee109fcd4 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 00:23:30 +0900 Subject: [PATCH 09/20] implement and register many BsonSerializers --- .../Serialization/SerializationRegistry.cs | 46 +++++++++ .../Lib9c/Items/ArmorSerializer.cs | 28 ++++++ .../Serializers/Lib9c/Items/AuraSerializer.cs | 28 ++++++ .../Serializers/Lib9c/Items/BeltSerializer.cs | 28 ++++++ .../Lib9c/Items/ConsumableSerializer.cs | 47 ++++++++++ .../Lib9c/Items/CostumeSerializer.cs | 27 ++++++ .../Lib9c/Items/EquipmentSerializer.cs | 93 +++++++++++++++++++ .../Lib9c/Items/GrimoireSerializer.cs | 28 ++++++ .../Lib9c/Items/ItemBaseSerializer.cs | 52 +++++++++++ .../Lib9c/Items/ItemUsableSerializer.cs | 48 ++++++++++ .../Lib9c/Items/MaterialSerializer.cs | 86 +++++++++++++++++ .../Lib9c/Items/NecklaceSerializer.cs | 28 ++++++ .../Serializers/Lib9c/Items/RingSerializer.cs | 28 ++++++ .../Lib9c/Items/TradableMaterialSerializer.cs | 82 ++++++++++++++++ .../Lib9c/Items/WeaponSerializer.cs | 28 ++++++ .../Lib9c/Sheets/SkillSheetRowSerializer.cs | 33 +++++++ .../Lib9c/Skills/SkillSerializer.cs | 34 +++++++ .../Lib9c/Stats/DecimalStatSerializer.cs | 30 ++++++ .../Lib9c/Stats/StatMapSerializer.cs | 44 +++++++++ .../Libplanet/AddressSerializer.cs | 12 +-- .../Libplanet/CurrencySerializer.cs | 42 +++++---- .../Libplanet/FungibleAssetValueSerializer.cs | 28 +++--- .../System/BigIntegerSerializer.cs | 12 +-- 23 files changed, 866 insertions(+), 46 deletions(-) create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Sheets/SkillSheetRowSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs create mode 100644 Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/StatMapSerializer.cs diff --git a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs index f1fb63c4..eaf7e2b9 100644 --- a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs +++ b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs @@ -1,15 +1,35 @@ using System.Numerics; +using Lib9c.Models.AttachmentActionResults; +using Lib9c.Models.Items; +using Lib9c.Models.Skills; +using Lib9c.Models.Stats; using Libplanet.Crypto; using Libplanet.Types.Assets; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.AttachmentActionResults; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Sheets; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; using Mimir.MongoDB.Bson.Serialization.Serializers.Libplanet; using Mimir.MongoDB.Bson.Serialization.Serializers.System; using MongoDB.Bson.Serialization; +using Nekoyume.TableData; namespace Mimir.MongoDB.Bson.Serialization; public static class SerializationRegistry { public static void Register() + { + RegisterClassMaps(); + RegisterSerializers(); + } + + private static void RegisterClassMaps() + { + } + + private static void RegisterSerializers() { // System BsonSerializer.RegisterSerializer(typeof(BigInteger), BigIntegerSerializer.Instance); @@ -18,5 +38,31 @@ public static void Register() BsonSerializer.RegisterSerializer(typeof(Address), AddressSerializer.Instance); BsonSerializer.RegisterSerializer(typeof(Currency), CurrencySerializer.Instance); BsonSerializer.RegisterSerializer(typeof(FungibleAssetValue), FungibleAssetValueSerializer.Instance); + + // Lib9c.Models.Items + BsonSerializer.RegisterSerializer(typeof(Armor), ArmorSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Aura), AuraSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Belt), BeltSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Consumable), ConsumableSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Costume), CostumeSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Equipment), EquipmentSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Grimoire), GrimoireSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(ItemBase), ItemBaseSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(ItemUsable), ItemUsableSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Material), MaterialSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Necklace), NecklaceSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Ring), RingSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(TradableMaterial), TradableMaterialSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(Weapon), WeaponSerializer.Instance); + + // Lib9c.Models.Skills + BsonSerializer.RegisterSerializer(typeof(Skill), SkillSerializer.Instance); + + // Lib9c.Models.Stats + BsonSerializer.RegisterSerializer(typeof(DecimalStat), DecimalStatSerializer.Instance); + BsonSerializer.RegisterSerializer(typeof(StatMap), StatMapSerializer.Instance); + + // Nekoyume.TableData + BsonSerializer.RegisterSerializer(typeof(SkillSheet.Row), SkillSheetRowSerializer.Instance); } } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs new file mode 100644 index 00000000..edf2cde4 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class ArmorSerializer : ClassSerializerBase +{ + public static readonly ArmorSerializer Instance = new(); + + public static Armor Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Armor Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs new file mode 100644 index 00000000..30df3cc6 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class AuraSerializer : ClassSerializerBase +{ + public static readonly AuraSerializer Instance = new(); + + public static Aura Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Aura Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs new file mode 100644 index 00000000..bedb7d44 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class BeltSerializer : ClassSerializerBase +{ + public static readonly BeltSerializer Instance = new(); + + public static Belt Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Belt Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs new file mode 100644 index 00000000..ccdb833e --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs @@ -0,0 +1,47 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class ConsumableSerializer : ClassSerializerBase +{ + public static readonly ConsumableSerializer Instance = new(); + + public static Consumable Deserialize(BsonDocument doc) => new() + { + Id = doc["Id"].AsInt32, + Grade = doc["Grade"].AsInt32, + ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, + ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, + ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemId = doc["ItemId"].AsGuid, + StatsMap = StatMapSerializer.Deserialize(doc["StatMap"].AsBsonDocument), + Skills = doc["Skills"].AsBsonArray + .Select(skill => SkillSerializer.Deserialize(skill.AsBsonDocument)) + .ToList(), + BuffSkills = doc["BuffSkills"].AsBsonArray + .Select(skill => SkillSerializer.Deserialize(skill.AsBsonDocument)) + .ToList(), + RequiredBlockIndex = doc["RequiredBlockIndex"].ToLong(), + Stats = doc["Stats"].AsBsonArray + .Select(stat => DecimalStatSerializer.Deserialize(stat.AsBsonDocument)) + .ToList(), + }; + + public override Consumable Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs new file mode 100644 index 00000000..bb574b72 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs @@ -0,0 +1,27 @@ +using Lib9c.Models.Items; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class CostumeSerializer : ClassSerializerBase +{ + public static readonly CostumeSerializer Instance = new(); + + public static Costume Deserialize(BsonDocument doc) => new() + { + }; + + public override Costume Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Costume value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs new file mode 100644 index 00000000..705c35e2 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs @@ -0,0 +1,93 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class EquipmentSerializer : ClassSerializerBase +{ + public static readonly EquipmentSerializer Instance = new(); + + public static Equipment Deserialize(BsonDocument doc) + { + if (!doc.TryGetValue("ItemType", out var itemTypeValue)) + { + throw new BsonSerializationException("Missing ItemType in document."); + } + + if (!doc.TryGetValue("ItemSubType", out var itemSubTypeValue)) + { + throw new BsonSerializationException("Missing itemSubTypeValue in document."); + } + + var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; + var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + switch (itemType) + { + case Nekoyume.Model.Item.ItemType.Equipment: + switch (itemSubType) + { + case Nekoyume.Model.Item.ItemSubType.Armor: + return ArmorSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Aura: + return AuraSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Belt: + return BeltSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Grimoire: + return GrimoireSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Necklace: + return NecklaceSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Ring: + return RingSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemSubType.Weapon: + return WeaponSerializer.Deserialize(doc); + } + + break; + } + + throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + } + + public static T Deserialize(BsonDocument doc) where T : Equipment, new() => new T + { + Id = doc["Id"].AsInt32, + Grade = doc["Grade"].AsInt32, + ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, + ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, + ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemId = doc["ItemId"].AsGuid, + StatsMap = StatMapSerializer.Deserialize(doc["StatMap"].AsBsonDocument), + Skills = doc["Skills"].AsBsonArray + .Select(skill => SkillSerializer.Deserialize(skill.AsBsonDocument)) + .ToList(), + BuffSkills = doc["BuffSkills"].AsBsonArray + .Select(skill => SkillSerializer.Deserialize(skill.AsBsonDocument)) + .ToList(), + RequiredBlockIndex = doc["RequiredBlockIndex"].ToLong(), + Equipped = doc["Equipped"].AsBoolean, + Level = doc["Level"].AsInt32, + Exp = doc["Exp"].ToLong(), + Stat = DecimalStatSerializer.Deserialize(doc["Stat"].AsBsonDocument), + SetId = doc["SetId"].AsInt32, + SpineResourcePath = doc["SpineResourcePath"].AsString, + OptionCountFromCombination = doc["OptionCountFromCombination"].AsInt32, + MadeWithMimisbrunnrRecipe = doc["MadeWithMimisbrunnrRecipe"].AsBoolean, + }; + + public override Equipment Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Equipment value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs new file mode 100644 index 00000000..785eb7cb --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class GrimoireSerializer : ClassSerializerBase +{ + public static readonly GrimoireSerializer Instance = new(); + + public static Grimoire Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Grimoire Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs new file mode 100644 index 00000000..9acc55df --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs @@ -0,0 +1,52 @@ +using Lib9c.Models.Items; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class ItemBaseSerializer : ClassSerializerBase +{ + public static readonly ItemBaseSerializer Instance = new(); + + public static ItemBase Deserialize(BsonDocument doc) + { + if (!doc.TryGetValue("ItemType", out var itemTypeValue)) + { + throw new BsonSerializationException("Missing ItemType in document."); + } + + if (!doc.TryGetValue("ItemSubType", out var itemSubTypeValue)) + { + throw new BsonSerializationException("Missing itemSubTypeValue in document."); + } + + var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; + var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + switch (itemType) + { + case Nekoyume.Model.Item.ItemType.Consumable: + return ItemUsableSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemType.Costume: + return CostumeSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemType.Equipment: + return ItemUsableSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemType.Material: + return MaterialSerializer.Deserialize(doc); + } + + throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + } + + public override ItemBase Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, ItemBase value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs new file mode 100644 index 00000000..d2fe8d0e --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs @@ -0,0 +1,48 @@ +using Lib9c.Models.Items; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class ItemUsableSerializer : ClassSerializerBase +{ + public static readonly ItemUsableSerializer Instance = new(); + + public static ItemUsable Deserialize(BsonDocument doc) + { + if (!doc.TryGetValue("ItemType", out var itemTypeValue)) + { + throw new BsonSerializationException("Missing ItemType in document."); + } + + if (!doc.TryGetValue("ItemSubType", out var itemSubTypeValue)) + { + throw new BsonSerializationException("Missing itemSubTypeValue in document."); + } + + var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; + var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + switch (itemType) + { + case Nekoyume.Model.Item.ItemType.Consumable: + return ConsumableSerializer.Deserialize(doc); + case Nekoyume.Model.Item.ItemType.Equipment: + return EquipmentSerializer.Deserialize(doc); + } + + throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + } + + public override ItemUsable Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, ItemUsable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs new file mode 100644 index 00000000..72012ddb --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs @@ -0,0 +1,86 @@ +using System.Security.Cryptography; +using Lib9c.Models.Items; +using Libplanet.Common; +using Mimir.MongoDB.Json.Extensions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; +using Newtonsoft.Json; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class MaterialSerializer : ClassSerializerBase +{ + public static readonly MaterialSerializer Instance = new(); + + public static Material Deserialize(BsonDocument doc) + { + if (!doc.TryGetValue("ItemType", out var itemTypeValue)) + { + throw new BsonSerializationException("Missing ItemType in document."); + } + + if (!doc.TryGetValue("ItemSubType", out var itemSubTypeValue)) + { + throw new BsonSerializationException("Missing itemSubTypeValue in document."); + } + + var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; + var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + if (itemType != Nekoyume.Model.Item.ItemType.Material) + { + throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + } + + if (doc.Contains("RequiredBlockIndex")) + { + return TradableMaterialSerializer.Deserialize(doc); + } + + return new Material + { + Id = doc["Id"].AsInt32, + Grade = doc["Grade"].AsInt32, + ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, + ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, + ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemId = HashDigest.FromString(doc["ItemId"].AsString), + }; + } + + public static Material Deserialize(string jsonString) + { + var material = JsonConvert.DeserializeObject( + jsonString, + MimirBsonDocumentExtensions.JsonSerializerSettings); + if (material is null) + { + throw new BsonSerializationException("Failed to deserialize Material from JSON string."); + } + + return material; + } + + public override Material Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var reader = context.Reader; + var bsonType = reader.GetCurrentBsonType(); + switch (bsonType) + { + case BsonType.Document: + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + case BsonType.String: + var jsonString = reader.ReadString(); + return Deserialize(jsonString); + default: + throw new BsonSerializationException($"Cannot deserialize Material from BsonType {bsonType}."); + } + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Material value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs new file mode 100644 index 00000000..7aee7987 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class NecklaceSerializer : ClassSerializerBase +{ + public static readonly NecklaceSerializer Instance = new(); + + public static Necklace Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Necklace Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs new file mode 100644 index 00000000..508e450d --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class RingSerializer : ClassSerializerBase +{ + public static readonly RingSerializer Instance = new(); + + public static Ring Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Ring Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs new file mode 100644 index 00000000..95b080bf --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs @@ -0,0 +1,82 @@ +using System.Security.Cryptography; +using Lib9c.Models.Items; +using Libplanet.Common; +using Mimir.MongoDB.Json.Extensions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; +using Newtonsoft.Json; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class TradableMaterialSerializer : ClassSerializerBase +{ + public static readonly TradableMaterialSerializer Instance = new(); + + public static TradableMaterial Deserialize(BsonDocument doc) + { + if (!doc.TryGetValue("ItemType", out var itemTypeValue)) + { + throw new BsonSerializationException("Missing ItemType in document."); + } + + if (!doc.TryGetValue("ItemSubType", out var itemSubTypeValue)) + { + throw new BsonSerializationException("Missing itemSubTypeValue in document."); + } + + var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; + var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + if (itemType != Nekoyume.Model.Item.ItemType.Material) + { + throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + } + + return new TradableMaterial + { + Id = doc["Id"].AsInt32, + Grade = doc["Grade"].AsInt32, + ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, + ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, + ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemId = HashDigest.FromString(doc["ItemId"].AsString), + RequiredBlockIndex = doc["RequiredBlockIndex"].AsInt64, + }; + } + + public static TradableMaterial Deserialize(string jsonString) + { + var material = JsonConvert.DeserializeObject( + jsonString, + MimirBsonDocumentExtensions.JsonSerializerSettings); + if (material is null) + { + throw new BsonSerializationException("Failed to deserialize Material from JSON string."); + } + + return material; + } + + public override TradableMaterial Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var reader = context.Reader; + var bsonType = reader.GetCurrentBsonType(); + switch (bsonType) + { + case BsonType.Document: + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + case BsonType.String: + var jsonString = reader.ReadString(); + return Deserialize(jsonString); + default: + throw new BsonSerializationException($"Cannot deserialize Material from BsonType {bsonType}."); + } + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TradableMaterial value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs new file mode 100644 index 00000000..decfeb6b --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs @@ -0,0 +1,28 @@ +using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; + +public class WeaponSerializer : ClassSerializerBase +{ + public static readonly WeaponSerializer Instance = new(); + + public static Weapon Deserialize(BsonDocument doc) => EquipmentSerializer.Deserialize(doc); + + public override Weapon Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Sheets/SkillSheetRowSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Sheets/SkillSheetRowSerializer.cs new file mode 100644 index 00000000..203daf5c --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Sheets/SkillSheetRowSerializer.cs @@ -0,0 +1,33 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; +using Nekoyume.TableData; +using Newtonsoft.Json; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Sheets; + +public class SkillSheetRowSerializer : ClassSerializerBase +{ + public static readonly SkillSheetRowSerializer Instance = new(); + + public static SkillSheet.Row Deserialize(BsonDocument doc) + { + var jsonString = doc.ToJson(); + return JsonConvert.DeserializeObject(jsonString) ?? + throw new JsonSerializationException( + "Failed to deserialize SkillSheet.Row from BSON document." + + $" jsonString: {jsonString}"); + } + + public override SkillSheet.Row Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, SkillSheet.Row value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs new file mode 100644 index 00000000..506563fc --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs @@ -0,0 +1,34 @@ +using Lib9c.Models.Skills; +using Mimir.MongoDB.Bson.Extensions; +using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Sheets; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; + +public class SkillSerializer : ClassSerializerBase +{ + public static readonly SkillSerializer Instance = new(); + + public static Skill Deserialize(BsonDocument doc) => new() + { + SkillRow = SkillSheetRowSerializer.Deserialize(doc["SkillRow"].AsBsonDocument), + Power = doc["Power"].ToLong(), + Chance = doc["Chance"].AsInt32, + StatPowerRatio = doc["StatPowerRatio"].AsInt32, + ReferencedStatType = (Nekoyume.Model.Stat.StatType)doc["ReferencedStatType"].AsInt32, + }; + + public override Skill Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, StatMap value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs new file mode 100644 index 00000000..417e0226 --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs @@ -0,0 +1,30 @@ +using Lib9c.Models.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; + +public class DecimalStatSerializer : ClassSerializerBase +{ + public static readonly DecimalStatSerializer Instance = new(); + + public static DecimalStat Deserialize(BsonDocument doc) => new() + { + StatType = (Nekoyume.Model.Stat.StatType)doc["StatType"].AsInt32, + BaseValue = doc["BaseValue"].AsDecimal, + AdditionalValue = doc["AdditionalValue"].AsDecimal, + }; + + public override DecimalStat Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, StatMap value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/StatMapSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/StatMapSerializer.cs new file mode 100644 index 00000000..20b52bce --- /dev/null +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/StatMapSerializer.cs @@ -0,0 +1,44 @@ +using Lib9c.Models.Stats; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Stats; + +public class StatMapSerializer : ClassSerializerBase +{ + public static readonly StatMapSerializer Instance = new(); + + public static StatMap Deserialize(BsonDocument doc) + { + var statMap = new StatMap + { + Value = new Dictionary(), + }; + var allStatTypes = Enum.GetValues(); + foreach (var targetStatType in allStatTypes) + { + if (!doc.TryGetValue(targetStatType.ToString(), out var targetStat)) + { + continue; + } + + var statDoc = targetStat.AsBsonDocument; + statMap.Value[targetStatType] = DecimalStatSerializer.Deserialize(statDoc); + } + + return statMap; + } + + public override StatMap Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var doc = BsonDocumentSerializer.Instance.Deserialize(context, args); + return Deserialize(doc); + } + + // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, StatMap value) + // { + // base.Serialize(context, args, value); + // } +} diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/AddressSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/AddressSerializer.cs index af269d6a..da845545 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/AddressSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/AddressSerializer.cs @@ -10,12 +10,6 @@ public class AddressSerializer : StructSerializerBase
{ public static readonly AddressSerializer Instance = new(); - public override void Serialize( - BsonSerializationContext context, - BsonSerializationArgs args, - Address value) => - context.Writer.WriteString(value.ToHex()); - public override Address Deserialize( BsonDeserializationContext context, BsonDeserializationArgs args) @@ -26,4 +20,10 @@ public override Address Deserialize( ? new Address(reader.ReadString()) : throw new UnexpectedTypeOfBsonValueException([BsonType.String], bsonType); } + + public override void Serialize( + BsonSerializationContext context, + BsonSerializationArgs args, + Address value) => + context.Writer.WriteString(value.ToHex()); } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/CurrencySerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/CurrencySerializer.cs index 11199592..454d57c9 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/CurrencySerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/CurrencySerializer.cs @@ -55,26 +55,6 @@ private static class Flags BigIntegerSerializer.Instance)), typeof((BigInteger, BigInteger)?)); - public override void Serialize( - BsonSerializationContext context, - BsonSerializationArgs args, - Currency value) - { - var writer = context.Writer; - writer.WriteStartDocument(); - writer.WriteName(ElementNames.Ticker); - writer.WriteString(value.Ticker); - writer.WriteName(ElementNames.DecimalPlaces); - _decimalPlacesInfo.Serializer.Serialize(context, value.DecimalPlaces); - writer.WriteName(ElementNames.Minters); - _mintersInfo.Serializer.Serialize(context, value.Minters); - writer.WriteName(ElementNames.TotalSupplyTrackable); - writer.WriteBoolean(value.TotalSupplyTrackable); - writer.WriteName(ElementNames.MaximumSupply); - _maximumSupplyInfo.Serializer.Serialize(context, value.MaximumSupply); - writer.WriteEndDocument(); - } - public override Currency Deserialize( BsonDeserializationContext context, BsonDeserializationArgs args) @@ -119,6 +99,28 @@ public override Currency Deserialize( : Currency.Uncapped(ticker, decimalPlaces, minters?.ToImmutableHashSet()); } +#pragma warning disable CS0618 // Type or member is obsolete return Currency.Legacy(ticker, decimalPlaces, minters?.ToImmutableHashSet()); +#pragma warning restore CS0618 // Type or member is obsolete + } + + public override void Serialize( + BsonSerializationContext context, + BsonSerializationArgs args, + Currency value) + { + var writer = context.Writer; + writer.WriteStartDocument(); + writer.WriteName(ElementNames.Ticker); + writer.WriteString(value.Ticker); + writer.WriteName(ElementNames.DecimalPlaces); + _decimalPlacesInfo.Serializer.Serialize(context, value.DecimalPlaces); + writer.WriteName(ElementNames.Minters); + _mintersInfo.Serializer.Serialize(context, value.Minters); + writer.WriteName(ElementNames.TotalSupplyTrackable); + writer.WriteBoolean(value.TotalSupplyTrackable); + writer.WriteName(ElementNames.MaximumSupply); + _maximumSupplyInfo.Serializer.Serialize(context, value.MaximumSupply); + writer.WriteEndDocument(); } } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/FungibleAssetValueSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/FungibleAssetValueSerializer.cs index 401d188c..c57db4e7 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/FungibleAssetValueSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Libplanet/FungibleAssetValueSerializer.cs @@ -36,20 +36,6 @@ private static class Flags BigIntegerSerializer.Instance, typeof(BigInteger)); - public override void Serialize( - BsonSerializationContext context, - BsonSerializationArgs args, - FungibleAssetValue value) - { - var writer = context.Writer; - writer.WriteStartDocument(); - writer.WriteName(ElementNames.Currency); - _currencyInfo.Serializer.Serialize(context, value.Currency); - writer.WriteName(ElementNames.RawValue); - _rawValueInfo.Serializer.Serialize(context, value.RawValue); - writer.WriteEndDocument(); - } - public override FungibleAssetValue Deserialize( BsonDeserializationContext context, BsonDeserializationArgs args) @@ -70,4 +56,18 @@ public override FungibleAssetValue Deserialize( }); return FungibleAssetValue.FromRawValue(currency, rawValue); } + + public override void Serialize( + BsonSerializationContext context, + BsonSerializationArgs args, + FungibleAssetValue value) + { + var writer = context.Writer; + writer.WriteStartDocument(); + writer.WriteName(ElementNames.Currency); + _currencyInfo.Serializer.Serialize(context, value.Currency); + writer.WriteName(ElementNames.RawValue); + _rawValueInfo.Serializer.Serialize(context, value.RawValue); + writer.WriteEndDocument(); + } } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/System/BigIntegerSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/System/BigIntegerSerializer.cs index 1917c4d6..ae6afec6 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/System/BigIntegerSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/System/BigIntegerSerializer.cs @@ -10,12 +10,6 @@ public class BigIntegerSerializer : StructSerializerBase { public static readonly BigIntegerSerializer Instance = new(); - public override void Serialize( - BsonSerializationContext context, - BsonSerializationArgs args, - BigInteger value) => - context.Writer.WriteString(value.ToString()); - public override BigInteger Deserialize( BsonDeserializationContext context, BsonDeserializationArgs args) @@ -26,4 +20,10 @@ public override BigInteger Deserialize( ? BigInteger.Parse(reader.ReadString()) : throw new UnexpectedTypeOfBsonValueException([BsonType.String], bsonType); } + + public override void Serialize( + BsonSerializationContext context, + BsonSerializationArgs args, + BigInteger value) => + context.Writer.WriteString(value.ToString()); } From 9efea108c30573737ea11bedcfd4fab5bec5c8a4 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 00:23:43 +0900 Subject: [PATCH 10/20] remove StatMapFactory --- Mimir/Factories/StatMapFactory.cs | 59 ------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 Mimir/Factories/StatMapFactory.cs diff --git a/Mimir/Factories/StatMapFactory.cs b/Mimir/Factories/StatMapFactory.cs deleted file mode 100644 index 79c94cda..00000000 --- a/Mimir/Factories/StatMapFactory.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Mimir.MongoDB.Bson.Extensions; -using MongoDB.Bson; -using Nekoyume.Model.Stat; - -namespace Mimir.Factories; - -/// -/// This class will be removed after the Mimir.Bson project is completed. -/// -/// , -/// and basically have the same structure, -/// and they are implements the same interfaces. -/// i.e. , -/// BsonDocument of these classes are also similar because of above reason. -/// So, we can create a factory class to convert between these classes. -/// -public static class StatMapFactory -{ - private static readonly Dictionary BsonKeys = - Enum.GetValues() - .ToDictionary( - e => e, - e => ($"Base{e}", $"Additional{e}")); - - public static StatMap Create(BsonDocument bsonDocument) - { - var statsMap = new StatMap(); - var statTypes = Enum.GetValues(); - foreach (var statType in statTypes) - { - var (baseKey, additionalKey) = BsonKeys[statType]; - if (bsonDocument.Contains(baseKey)) - { - var baseValue = bsonDocument[baseKey].ToLong(); - statsMap[statType].SetBaseValue(baseValue); - } - - if (bsonDocument.Contains(additionalKey)) - { - var additionalValue = bsonDocument[additionalKey].ToLong(); - statsMap[statType].SetAdditionalValue(additionalValue); - } - } - - return statsMap; - } - - public static StatMap Create(StatsMap statsMap) - { - var statMap = new StatMap(); - foreach (var (statType, baseValue, additionalValue) in statsMap.GetBaseAndAdditionalStats(ignoreZero: true)) - { - statMap[statType].SetBaseValue(baseValue); - statMap[statType].SetAdditionalValue(additionalValue); - } - - return statMap; - } -} From 3329d1b7b79f4eeaff0bfecba94ea29b71955495 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 00:24:08 +0900 Subject: [PATCH 11/20] add some words --- Mimir.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mimir.sln.DotSettings b/Mimir.sln.DotSettings index a61fe47c..50f4dd2a 100644 --- a/Mimir.sln.DotSettings +++ b/Mimir.sln.DotSettings @@ -1,5 +1,7 @@  + True True True True + True True \ No newline at end of file From e2f837ae7290dc0acf834ffef60c62ab9ad69ffa Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 09:55:07 +0900 Subject: [PATCH 12/20] fix compile error --- Lib9c.Models/States/CombinationSlotState.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib9c.Models/States/CombinationSlotState.cs b/Lib9c.Models/States/CombinationSlotState.cs index 8b8117f8..c8006621 100644 --- a/Lib9c.Models/States/CombinationSlotState.cs +++ b/Lib9c.Models/States/CombinationSlotState.cs @@ -61,10 +61,10 @@ public CombinationSlotState(IValue bencoded) UnlockBlockIndex = d["unlockBlockIndex"].ToLong(); UnlockStage = d["unlockStage"].ToInteger(); - if (d.TryGetValue((Text)"result", out var result)) - { - Result = AttachmentActionResultFactory.Create(result); - } + // if (d.TryGetValue((Text)"result", out var result)) + // { + // Result = AttachmentActionResultFactory.Create(result); + // } if (d.TryGetValue((Text)"startBlockIndex", out var startIndex)) { From de8258c3a354dd581d3ea1ebbc067b2732d5ddb2 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 10:02:25 +0900 Subject: [PATCH 13/20] fix compile errors --- Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs index eaf7e2b9..2d899f7a 100644 --- a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs +++ b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs @@ -1,5 +1,4 @@ using System.Numerics; -using Lib9c.Models.AttachmentActionResults; using Lib9c.Models.Items; using Lib9c.Models.Skills; using Lib9c.Models.Stats; From ef1f00cd659b2729a03c1fed5fef05511f7a8b72 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 10:03:50 +0900 Subject: [PATCH 14/20] fix compile error --- Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs index 2d899f7a..b650878d 100644 --- a/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs +++ b/Mimir.MongoDB/Bson/Serialization/SerializationRegistry.cs @@ -4,7 +4,6 @@ using Lib9c.Models.Stats; using Libplanet.Crypto; using Libplanet.Types.Assets; -using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.AttachmentActionResults; using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Items; using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Sheets; using Mimir.MongoDB.Bson.Serialization.Serializers.Lib9c.Skills; From 56140d0e34742d06be85d7cb795535469364262a Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 10:53:16 +0900 Subject: [PATCH 15/20] handle Costume --- Lib9c.Models/Items/Costume.cs | 8 ++++---- .../Serializers/Lib9c/Items/CostumeSerializer.cs | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Lib9c.Models/Items/Costume.cs b/Lib9c.Models/Items/Costume.cs index 9d1748cf..a04b3deb 100644 --- a/Lib9c.Models/Items/Costume.cs +++ b/Lib9c.Models/Items/Costume.cs @@ -12,10 +12,10 @@ namespace Lib9c.Models.Items; /// public record Costume : ItemBase { - public bool Equipped { get; } - public string SpineResourcePath { get; } - public Guid ItemId { get; } - public long RequiredBlockIndex { get; } + public bool Equipped { get; init; } + public string SpineResourcePath { get; init; } + public Guid ItemId { get; init; } + public long RequiredBlockIndex { get; init; } [BsonIgnore, GraphQLIgnore] public override IValue Bencoded diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs index bb574b72..bd1200bd 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs @@ -1,4 +1,5 @@ using Lib9c.Models.Items; +using Mimir.MongoDB.Bson.Extensions; using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; @@ -11,6 +12,15 @@ public class CostumeSerializer : ClassSerializerBase public static Costume Deserialize(BsonDocument doc) => new() { + Id = doc["Id"].AsInt32, + Grade = doc["Grade"].AsInt32, + ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, + ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, + ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + Equipped = doc["Equipped"].AsBoolean, + SpineResourcePath = doc["SpineResourcePath"].AsString, + ItemId = doc["ItemId"].AsGuid, + RequiredBlockIndex = doc["RequiredBlockIndex"].ToLong(), }; public override Costume Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) From 7635942cda016ae66b8fa09430fedd38158f42dc Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 14:08:13 +0900 Subject: [PATCH 16/20] fix comments --- .../Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/AuraSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/BeltSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/RingSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs | 2 +- .../Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs | 2 +- .../Serializers/Lib9c/Stats/DecimalStatSerializer.cs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs index edf2cde4..72048562 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ArmorSerializer.cs @@ -21,7 +21,7 @@ public override Armor Deserialize(BsonDeserializationContext context, BsonDeseri } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Armor value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs index 30df3cc6..67c7601f 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/AuraSerializer.cs @@ -21,7 +21,7 @@ public override Aura Deserialize(BsonDeserializationContext context, BsonDeseria } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Aura value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs index bedb7d44..ff54cdbd 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/BeltSerializer.cs @@ -21,7 +21,7 @@ public override Belt Deserialize(BsonDeserializationContext context, BsonDeseria } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Belt value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs index 785eb7cb..d482dcbb 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/GrimoireSerializer.cs @@ -21,7 +21,7 @@ public override Grimoire Deserialize(BsonDeserializationContext context, BsonDes } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Grimoire value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs index 7aee7987..8cd34656 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/NecklaceSerializer.cs @@ -21,7 +21,7 @@ public override Necklace Deserialize(BsonDeserializationContext context, BsonDes } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Necklace value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs index 508e450d..8d0d8c13 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/RingSerializer.cs @@ -21,7 +21,7 @@ public override Ring Deserialize(BsonDeserializationContext context, BsonDeseria } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Ring value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs index decfeb6b..52f45ef8 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/WeaponSerializer.cs @@ -21,7 +21,7 @@ public override Weapon Deserialize(BsonDeserializationContext context, BsonDeser } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Consumable value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Weapon value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs index 506563fc..5d1d1ac7 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs @@ -27,7 +27,7 @@ public override Skill Deserialize(BsonDeserializationContext context, BsonDeseri } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, StatMap value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Skill value) // { // base.Serialize(context, args, value); // } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs index 417e0226..62e96b55 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs @@ -23,7 +23,7 @@ public override DecimalStat Deserialize(BsonDeserializationContext context, Bson } // DO NOT OVERRIDE Serialize METHOD: Currently objects will be serialized to Json first. - // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, StatMap value) + // public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DecimalStat value) // { // base.Serialize(context, args, value); // } From 9489285f9d9cd4c014e8c2fc16c1189ed1d391e6 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 15:31:57 +0900 Subject: [PATCH 17/20] store enums as string to MongoDB --- .../Serializers/Lib9c/Items/ConsumableSerializer.cs | 6 +++--- .../Serializers/Lib9c/Items/CostumeSerializer.cs | 6 +++--- .../Serializers/Lib9c/Items/EquipmentSerializer.cs | 10 +++++----- .../Serializers/Lib9c/Items/ItemBaseSerializer.cs | 4 ++-- .../Serializers/Lib9c/Items/ItemUsableSerializer.cs | 4 ++-- .../Serializers/Lib9c/Items/MaterialSerializer.cs | 10 +++++----- .../Lib9c/Items/TradableMaterialSerializer.cs | 10 +++++----- .../Json/Extensions/MimirBsonDocumentExtensions.cs | 2 ++ 8 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs index ccdb833e..c8de0024 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ConsumableSerializer.cs @@ -16,9 +16,9 @@ public class ConsumableSerializer : ClassSerializerBase { Id = doc["Id"].AsInt32, Grade = doc["Grade"].AsInt32, - ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, - ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, - ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemType = Enum.Parse(doc["ItemType"].AsString), + ItemSubType = Enum.Parse(doc["ItemSubType"].AsString), + ElementalType = Enum.Parse(doc["ElementalType"].AsString), ItemId = doc["ItemId"].AsGuid, StatsMap = StatMapSerializer.Deserialize(doc["StatMap"].AsBsonDocument), Skills = doc["Skills"].AsBsonArray diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs index bd1200bd..04a1c4c6 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/CostumeSerializer.cs @@ -14,9 +14,9 @@ public class CostumeSerializer : ClassSerializerBase { Id = doc["Id"].AsInt32, Grade = doc["Grade"].AsInt32, - ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, - ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, - ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemType = Enum.Parse(doc["ItemType"].AsString), + ItemSubType = Enum.Parse(doc["ItemSubType"].AsString), + ElementalType = Enum.Parse(doc["ElementalType"].AsString), Equipped = doc["Equipped"].AsBoolean, SpineResourcePath = doc["SpineResourcePath"].AsString, ItemId = doc["ItemId"].AsGuid, diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs index 705c35e2..596d7ed6 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs @@ -24,8 +24,8 @@ public static Equipment Deserialize(BsonDocument doc) throw new BsonSerializationException("Missing itemSubTypeValue in document."); } - var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; - var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + var itemType = Enum.Parse(itemTypeValue.AsString); + var itemSubType = Enum.Parse(itemSubTypeValue.AsString); switch (itemType) { case Nekoyume.Model.Item.ItemType.Equipment: @@ -57,9 +57,9 @@ public static Equipment Deserialize(BsonDocument doc) { Id = doc["Id"].AsInt32, Grade = doc["Grade"].AsInt32, - ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, - ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, - ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemType = Enum.Parse(doc["ItemType"].AsString), + ItemSubType = Enum.Parse(doc["ItemSubType"].AsString), + ElementalType = Enum.Parse(doc["ElementalType"].AsString), ItemId = doc["ItemId"].AsGuid, StatsMap = StatMapSerializer.Deserialize(doc["StatMap"].AsBsonDocument), Skills = doc["Skills"].AsBsonArray diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs index 9acc55df..6b970ac1 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs @@ -21,8 +21,8 @@ public static ItemBase Deserialize(BsonDocument doc) throw new BsonSerializationException("Missing itemSubTypeValue in document."); } - var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; - var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + var itemType = Enum.Parse(itemTypeValue.AsString); + var itemSubType = Enum.Parse(itemSubTypeValue.AsString); switch (itemType) { case Nekoyume.Model.Item.ItemType.Consumable: diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs index d2fe8d0e..b8c8022a 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs @@ -21,8 +21,8 @@ public static ItemUsable Deserialize(BsonDocument doc) throw new BsonSerializationException("Missing itemSubTypeValue in document."); } - var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; - var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + var itemType = Enum.Parse(itemTypeValue.AsString); + var itemSubType = Enum.Parse(itemSubTypeValue.AsString); switch (itemType) { case Nekoyume.Model.Item.ItemType.Consumable: diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs index 72012ddb..aafed9f9 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/MaterialSerializer.cs @@ -25,8 +25,8 @@ public static Material Deserialize(BsonDocument doc) throw new BsonSerializationException("Missing itemSubTypeValue in document."); } - var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; - var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + var itemType = Enum.Parse(itemTypeValue.AsString); + var itemSubType = Enum.Parse(itemSubTypeValue.AsString); if (itemType != Nekoyume.Model.Item.ItemType.Material) { throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); @@ -41,9 +41,9 @@ public static Material Deserialize(BsonDocument doc) { Id = doc["Id"].AsInt32, Grade = doc["Grade"].AsInt32, - ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, - ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, - ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemType = itemType, + ItemSubType = itemSubType, + ElementalType = Enum.Parse(doc["ElementalType"].AsString), ItemId = HashDigest.FromString(doc["ItemId"].AsString), }; } diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs index 95b080bf..bf15df69 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/TradableMaterialSerializer.cs @@ -25,8 +25,8 @@ public static TradableMaterial Deserialize(BsonDocument doc) throw new BsonSerializationException("Missing itemSubTypeValue in document."); } - var itemType = (Nekoyume.Model.Item.ItemType)itemTypeValue.AsInt32; - var itemSubType = (Nekoyume.Model.Item.ItemSubType)itemSubTypeValue.AsInt32; + var itemType = Enum.Parse(itemTypeValue.AsString); + var itemSubType = Enum.Parse(itemSubTypeValue.AsString); if (itemType != Nekoyume.Model.Item.ItemType.Material) { throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); @@ -36,9 +36,9 @@ public static TradableMaterial Deserialize(BsonDocument doc) { Id = doc["Id"].AsInt32, Grade = doc["Grade"].AsInt32, - ItemType = (Nekoyume.Model.Item.ItemType)doc["ItemType"].AsInt32, - ItemSubType = (Nekoyume.Model.Item.ItemSubType)doc["ItemSubType"].AsInt32, - ElementalType = (Nekoyume.Model.Elemental.ElementalType)doc["ElementalType"].AsInt32, + ItemType = itemType, + ItemSubType = itemSubType, + ElementalType = Enum.Parse(doc["ElementalType"].AsString), ItemId = HashDigest.FromString(doc["ItemId"].AsString), RequiredBlockIndex = doc["RequiredBlockIndex"].AsInt64, }; diff --git a/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs b/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs index bec6900e..a270a5d1 100644 --- a/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs +++ b/Mimir.MongoDB/Json/Extensions/MimirBsonDocumentExtensions.cs @@ -1,6 +1,7 @@ using Mimir.MongoDB.Bson; using Mimir.MongoDB.Json.Converters; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace Mimir.MongoDB.Json.Extensions; @@ -15,6 +16,7 @@ public static class MimirBsonDocumentExtensions [ new BigIntegerJsonConverter(), new MaterialAndIntDictionaryJsonConverter(), + new StringEnumConverter(), ], ContractResolver = new IgnoreBencodedContractResolver(), }; From 3c3dbd029d0bef11441edb4f484698a0b6b82f15 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 15:37:57 +0900 Subject: [PATCH 18/20] fix switch styles --- .../Lib9c/Items/EquipmentSerializer.cs | 40 ++++++++----------- .../Lib9c/Items/ItemBaseSerializer.cs | 20 ++++------ .../Lib9c/Items/ItemUsableSerializer.cs | 14 +++---- 3 files changed, 30 insertions(+), 44 deletions(-) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs index 596d7ed6..82cf6b9b 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/EquipmentSerializer.cs @@ -26,31 +26,23 @@ public static Equipment Deserialize(BsonDocument doc) var itemType = Enum.Parse(itemTypeValue.AsString); var itemSubType = Enum.Parse(itemSubTypeValue.AsString); - switch (itemType) + return itemType switch { - case Nekoyume.Model.Item.ItemType.Equipment: - switch (itemSubType) - { - case Nekoyume.Model.Item.ItemSubType.Armor: - return ArmorSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Aura: - return AuraSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Belt: - return BeltSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Grimoire: - return GrimoireSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Necklace: - return NecklaceSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Ring: - return RingSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemSubType.Weapon: - return WeaponSerializer.Deserialize(doc); - } - - break; - } - - throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + Nekoyume.Model.Item.ItemType.Equipment => itemSubType switch + { + Nekoyume.Model.Item.ItemSubType.Armor => ArmorSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Aura => AuraSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Belt => BeltSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Grimoire => GrimoireSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Necklace => NecklaceSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Ring => RingSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemSubType.Weapon => WeaponSerializer.Deserialize(doc), + _ => throw new BsonSerializationException( + $"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"), + }, + _ => throw new BsonSerializationException( + $"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"), + }; } public static T Deserialize(BsonDocument doc) where T : Equipment, new() => new T diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs index 6b970ac1..f726f02a 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemBaseSerializer.cs @@ -23,19 +23,15 @@ public static ItemBase Deserialize(BsonDocument doc) var itemType = Enum.Parse(itemTypeValue.AsString); var itemSubType = Enum.Parse(itemSubTypeValue.AsString); - switch (itemType) + return itemType switch { - case Nekoyume.Model.Item.ItemType.Consumable: - return ItemUsableSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemType.Costume: - return CostumeSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemType.Equipment: - return ItemUsableSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemType.Material: - return MaterialSerializer.Deserialize(doc); - } - - throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + Nekoyume.Model.Item.ItemType.Consumable or + Nekoyume.Model.Item.ItemType.Equipment => ItemUsableSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemType.Costume => CostumeSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemType.Material => MaterialSerializer.Deserialize(doc), + _ => throw new BsonSerializationException( + $"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"), + }; } public override ItemBase Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs index b8c8022a..b8ace20a 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Items/ItemUsableSerializer.cs @@ -23,15 +23,13 @@ public static ItemUsable Deserialize(BsonDocument doc) var itemType = Enum.Parse(itemTypeValue.AsString); var itemSubType = Enum.Parse(itemSubTypeValue.AsString); - switch (itemType) + return itemType switch { - case Nekoyume.Model.Item.ItemType.Consumable: - return ConsumableSerializer.Deserialize(doc); - case Nekoyume.Model.Item.ItemType.Equipment: - return EquipmentSerializer.Deserialize(doc); - } - - throw new BsonSerializationException($"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"); + Nekoyume.Model.Item.ItemType.Consumable => ConsumableSerializer.Deserialize(doc), + Nekoyume.Model.Item.ItemType.Equipment => EquipmentSerializer.Deserialize(doc), + _ => throw new BsonSerializationException( + $"Unsupported ItemType: {itemType} or ItemSubType: {itemSubType}"), + }; } public override ItemUsable Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) From eeb89dda5ed6967a9d7c52b39757319820830427 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 15:38:08 +0900 Subject: [PATCH 19/20] add word --- Mimir.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/Mimir.sln.DotSettings b/Mimir.sln.DotSettings index 50f4dd2a..717f9669 100644 --- a/Mimir.sln.DotSettings +++ b/Mimir.sln.DotSettings @@ -2,6 +2,7 @@ True True True + True True True True \ No newline at end of file From 33243a2e64d3de57ea9c551632b1b20523aa1a4d Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Wed, 25 Sep 2024 15:44:59 +0900 Subject: [PATCH 20/20] parse enums from string --- .../Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs | 2 +- .../Serializers/Lib9c/Stats/DecimalStatSerializer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs index 5d1d1ac7..636d54a9 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Skills/SkillSerializer.cs @@ -17,7 +17,7 @@ public class SkillSerializer : ClassSerializerBase Power = doc["Power"].ToLong(), Chance = doc["Chance"].AsInt32, StatPowerRatio = doc["StatPowerRatio"].AsInt32, - ReferencedStatType = (Nekoyume.Model.Stat.StatType)doc["ReferencedStatType"].AsInt32, + ReferencedStatType = Enum.Parse(doc["ReferencedStatType"].AsString), }; public override Skill Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) diff --git a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs index 62e96b55..09f345ed 100644 --- a/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs +++ b/Mimir.MongoDB/Bson/Serialization/Serializers/Lib9c/Stats/DecimalStatSerializer.cs @@ -11,7 +11,7 @@ public class DecimalStatSerializer : ClassSerializerBase public static DecimalStat Deserialize(BsonDocument doc) => new() { - StatType = (Nekoyume.Model.Stat.StatType)doc["StatType"].AsInt32, + StatType = Enum.Parse(doc["StatType"].AsString), BaseValue = doc["BaseValue"].AsDecimal, AdditionalValue = doc["AdditionalValue"].AsDecimal, };