From 9a0405b539aa2dc82d66f514e3262f0fae616b90 Mon Sep 17 00:00:00 2001 From: upa-r-upa Date: Mon, 25 Mar 2024 21:40:58 +0900 Subject: [PATCH] feat: Add dungeon detail subscription field --- backend/app/Savor22b/Constants/Addresses.cs | 11 +++- .../GraphTypes/Types/DungeonStateType.cs | 17 +++++- backend/app/Savor22b/Model/Dungeon.cs | 31 +++++++++++ .../States/DungeonConquestHistoryState.cs | 53 +++++++++++++++++++ .../Savor22b/States/DungeonHistoryState.cs | 26 ++++++++- .../app/Savor22b/States/GlobalDungeonState.cs | 53 +++++++++++++++++++ .../app/Savor22b/States/UserDungeonState.cs | 16 +++++- 7 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 backend/app/Savor22b/States/DungeonConquestHistoryState.cs create mode 100644 backend/app/Savor22b/States/GlobalDungeonState.cs diff --git a/backend/app/Savor22b/Constants/Addresses.cs b/backend/app/Savor22b/Constants/Addresses.cs index 0b85ca56..63415344 100644 --- a/backend/app/Savor22b/Constants/Addresses.cs +++ b/backend/app/Savor22b/Constants/Addresses.cs @@ -4,6 +4,13 @@ namespace Savor22b.Constants; public static class Addresses { - public static readonly Address ShopVaultAddress = new Address("0000000000000000000000000000000000000000"); - public static readonly Address UserHouseDataAddress = new Address("0000000000000000000000000000000000000001"); + public static readonly Address ShopVaultAddress = new Address( + "0000000000000000000000000000000000000000" + ); + public static readonly Address UserHouseDataAddress = new Address( + "0000000000000000000000000000000000000001" + ); + public static readonly Address DungeonDataAddress = new Address( + "0000000000000000000000000000000000000002" + ); } diff --git a/backend/app/Savor22b/GraphTypes/Types/DungeonStateType.cs b/backend/app/Savor22b/GraphTypes/Types/DungeonStateType.cs index 94a66233..1bfc93d0 100644 --- a/backend/app/Savor22b/GraphTypes/Types/DungeonStateType.cs +++ b/backend/app/Savor22b/GraphTypes/Types/DungeonStateType.cs @@ -1,11 +1,14 @@ namespace Savor22b.GraphTypes.Types; using GraphQL.Types; +using Libplanet; +using Libplanet.Blockchain; +using Libplanet.Explorer.GraphTypes; using Savor22b.Model; public class DungeonStateType : ObjectGraphType { - public DungeonStateType() + public DungeonStateType(BlockChain blockChain) { Field>( "name", @@ -49,5 +52,17 @@ public DungeonStateType() return seeds; } ); + + Field>( + "isConquest", + description: "현재 던전이 점령 되었는지의 여부입니다.", + resolve: context => context.Source.IsConquest(blockChain) + ); + + Field( + "conquestUserAddress", + description: "현재 던전을 점령하고 있는 유저의 Address입니다.", + resolve: context => context.Source.CurrentConquestUserAddress(blockChain) + ); } } diff --git a/backend/app/Savor22b/Model/Dungeon.cs b/backend/app/Savor22b/Model/Dungeon.cs index 1cf4f55d..58ccdf9b 100644 --- a/backend/app/Savor22b/Model/Dungeon.cs +++ b/backend/app/Savor22b/Model/Dungeon.cs @@ -1,4 +1,9 @@ using System.Collections.Immutable; +using Bencodex.Types; +using Libplanet; +using Libplanet.Blockchain; +using Savor22b.Constants; +using Savor22b.States; namespace Savor22b.Model; @@ -10,4 +15,30 @@ public class Dungeon public int ID { get; set; } public int VillageId { get; set; } public ImmutableList RewardSeedIdList { get; set; } + + private static GlobalDungeonState GetGlobalDungeonState(BlockChain blockChain) + { + GlobalDungeonState globalDungeonState = blockChain.GetState(Addresses.DungeonDataAddress) + is Dictionary stateEncoded + ? new GlobalDungeonState(stateEncoded) + : new GlobalDungeonState(); + + return globalDungeonState; + } + + public bool IsConquest(BlockChain blockChain) + { + GlobalDungeonState globalDungeonState = GetGlobalDungeonState(blockChain); + + return globalDungeonState.DungeonStatus.ContainsKey(ID.ToString()); + } + + public Address? CurrentConquestUserAddress(BlockChain blockChain) + { + GlobalDungeonState globalDungeonState = GetGlobalDungeonState(blockChain); + + return globalDungeonState.DungeonStatus.TryGetValue(ID.ToString(), out Address address) + ? address + : default; + } } diff --git a/backend/app/Savor22b/States/DungeonConquestHistoryState.cs b/backend/app/Savor22b/States/DungeonConquestHistoryState.cs new file mode 100644 index 00000000..da150e2e --- /dev/null +++ b/backend/app/Savor22b/States/DungeonConquestHistoryState.cs @@ -0,0 +1,53 @@ +namespace Savor22b.States; + +using Bencodex.Types; +using Libplanet; +using Libplanet.Headless.Extensions; + +public class DungeonConquestHistoryState : State +{ + public long BlockIndex { get; private set; } + public int DungeonId { get; private set; } + public Address TargetUserAddress { get; private set; } + public int DungeonConquestStatus { get; private set; } + + public DungeonConquestHistoryState( + long blockIndex, + int dungeonId, + Address targetUserAddress, + int dungeonConquestStatus + ) + { + BlockIndex = blockIndex; + DungeonId = dungeonId; + TargetUserAddress = targetUserAddress; + DungeonConquestStatus = dungeonConquestStatus; + } + + public DungeonConquestHistoryState(Dictionary encoded) + { + BlockIndex = encoded[nameof(BlockIndex)].ToLong(); + DungeonId = encoded[nameof(DungeonId)].ToInteger(); + TargetUserAddress = encoded[nameof(TargetUserAddress)].ToAddress(); + DungeonConquestStatus = encoded[nameof(DungeonConquestStatus)].ToInteger(); + } + + public IValue Serialize() + { + var pairs = new[] + { + new KeyValuePair((Text)nameof(BlockIndex), BlockIndex.Serialize()), + new KeyValuePair((Text)nameof(DungeonId), DungeonId.Serialize()), + new KeyValuePair( + (Text)nameof(TargetUserAddress), + TargetUserAddress.ToBencodex() + ), + new KeyValuePair( + (Text)nameof(DungeonConquestStatus), + DungeonConquestStatus.Serialize() + ), + }; + + return new Dictionary(pairs); + } +} diff --git a/backend/app/Savor22b/States/DungeonHistoryState.cs b/backend/app/Savor22b/States/DungeonHistoryState.cs index 4ea396e8..2e481b29 100644 --- a/backend/app/Savor22b/States/DungeonHistoryState.cs +++ b/backend/app/Savor22b/States/DungeonHistoryState.cs @@ -1,5 +1,6 @@ namespace Savor22b.States; +using System.Collections.Immutable; using Bencodex.Types; using Libplanet.Headless.Extensions; @@ -7,17 +8,32 @@ public class DungeonHistoryState : State { public long BlockIndex { get; private set; } public int DungeonId { get; private set; } + public int DungeonClearStatus { get; private set; } + public ImmutableList DungeonClearRewardSeedIdList { get; private set; } - public DungeonHistoryState(long blockIndex, int dungeonId) + public DungeonHistoryState( + long blockIndex, + int dungeonId, + int dungeonClearStatus, + ImmutableList dungeonClearRewardSeedIdList + ) { BlockIndex = blockIndex; DungeonId = dungeonId; + DungeonClearStatus = dungeonClearStatus; + DungeonClearRewardSeedIdList = dungeonClearRewardSeedIdList; } public DungeonHistoryState(Dictionary encoded) { BlockIndex = encoded[nameof(BlockIndex)].ToLong(); DungeonId = encoded[nameof(DungeonId)].ToInteger(); + DungeonClearStatus = encoded[nameof(DungeonClearStatus)].ToInteger(); + DungeonClearRewardSeedIdList = ( + (Bencodex.Types.List)encoded[nameof(DungeonClearRewardSeedIdList)] + ) + .Select(e => e.ToInteger()) + .ToImmutableList(); } public IValue Serialize() @@ -26,6 +42,14 @@ public IValue Serialize() { new KeyValuePair((Text)nameof(BlockIndex), BlockIndex.Serialize()), new KeyValuePair((Text)nameof(DungeonId), DungeonId.Serialize()), + new KeyValuePair( + (Text)nameof(DungeonClearStatus), + DungeonClearStatus.Serialize() + ), + new KeyValuePair( + (Text)nameof(DungeonClearRewardSeedIdList), + new List(DungeonClearRewardSeedIdList.Select(e => e.Serialize())) + ), }; return new Dictionary(pairs); diff --git a/backend/app/Savor22b/States/GlobalDungeonState.cs b/backend/app/Savor22b/States/GlobalDungeonState.cs new file mode 100644 index 00000000..e8341187 --- /dev/null +++ b/backend/app/Savor22b/States/GlobalDungeonState.cs @@ -0,0 +1,53 @@ +namespace Savor22b.States; + +using Libplanet.Headless.Extensions; + +using Bencodex.Types; +using Libplanet; + +public class GlobalDungeonState : State +{ + public Dictionary DungeonStatus { get; private set; } + + public GlobalDungeonState() + { + DungeonStatus = new Dictionary(); + } + + public GlobalDungeonState(Dictionary dungeonStatus) + { + DungeonStatus = dungeonStatus; + } + + public GlobalDungeonState(Bencodex.Types.Dictionary encoded) + { + if (encoded.TryGetValue((Text)nameof(DungeonStatus), out var dungeonStatus)) + { + DungeonStatus = ((Bencodex.Types.Dictionary)dungeonStatus).ToDictionary( + pair => ((Bencodex.Types.Text)pair.Key).Value, + pair => pair.Value.ToAddress() + ); + } + else + { + DungeonStatus = new Dictionary(); + } + } + + public IValue Serialize() + { + var pairs = new[] + { + new KeyValuePair( + (Text)nameof(DungeonStatus), + new Dictionary( + DungeonStatus.Select( + e => new KeyValuePair((Text)e.Key, e.Value.ToBencodex()) + ) + ) + ), + }; + + return new Dictionary(pairs); + } +} diff --git a/backend/app/Savor22b/States/UserDungeonState.cs b/backend/app/Savor22b/States/UserDungeonState.cs index 41425b7c..9c68e4ea 100644 --- a/backend/app/Savor22b/States/UserDungeonState.cs +++ b/backend/app/Savor22b/States/UserDungeonState.cs @@ -9,15 +9,21 @@ public class UserDungeonState : State public static readonly int DungeonKeyChargeIntervalBlock = 12; public ImmutableList DungeonHistories { get; private set; } + public ImmutableList DungeonConquestHistories { get; private set; } public UserDungeonState() { DungeonHistories = ImmutableList.Empty; + DungeonConquestHistories = ImmutableList.Empty; } - public UserDungeonState(ImmutableList dungeonKeyHistories) + public UserDungeonState( + ImmutableList dungeonKeyHistories, + ImmutableList dungeonConquestHistories + ) { DungeonHistories = dungeonKeyHistories; + DungeonConquestHistories = dungeonConquestHistories; } public UserDungeonState(Dictionary encoded) @@ -32,6 +38,10 @@ public UserDungeonState(Dictionary encoded) { DungeonHistories = ImmutableList.Empty; } + + DungeonConquestHistories = ((List)encoded[nameof(DungeonConquestHistories)]) + .Select(element => new DungeonConquestHistoryState((Dictionary)element)) + .ToImmutableList(); } public IValue Serialize() @@ -43,6 +53,10 @@ public IValue Serialize() (Text)nameof(DungeonHistories), new List(DungeonHistories.Select(element => element.Serialize())) ), + new KeyValuePair( + (Text)nameof(DungeonConquestHistories), + new List(DungeonConquestHistories.Select(element => element.Serialize())) + ), } ); }