Esempio n. 1
0
        public void SerializeCombinationSlotStateWithResult()
        {
            var address = new PrivateKey().PublicKey.ToAddress();
            var state   = new CombinationSlotState(address, 1);
            var item    = ItemFactory.CreateItemUsable(_tableSheets.EquipmentItemSheet.Values.First(), Guid.Empty,
                                                       default);
            var result = new CombinationConsumable.ResultModel
            {
                actionPoint = 1,
                gold        = 1,
                materials   = new Dictionary <Nekoyume.Model.Item.Material, int>(),
                itemUsable  = item
            };

            state.Update(result, 1, 10);
            var serialized = (Dictionary)state.Serialize();

            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"address"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"unlockBlockIndex"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"unlockStage"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"result"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"startBlockIndex"));
            var deserialize = new CombinationSlotState(serialized);

            Assert.AreEqual(state.UnlockStage, deserialize.UnlockStage);
            Assert.AreEqual(state.UnlockBlockIndex, deserialize.UnlockBlockIndex);
            Assert.AreEqual(state.address, deserialize.address);
            Assert.AreEqual(state.Result.itemUsable, deserialize.Result.itemUsable);
            Assert.AreEqual(state.StartBlockIndex, deserialize.StartBlockIndex);
        }
Esempio n. 2
0
        public void SetCombinationSlotState(CombinationSlotState state)
        {
            state = LocalLayer.Instance.Modify(state);
            CombinationSlotStates[state.address] = state;

            CombinationSlotStateSubject.OnNext(state);
        }
Esempio n. 3
0
        public static bool TryGetResultId(this CombinationSlotState state, out Guid resultId)
        {
            if (state?.Result is null)
            {
                return(false);
            }

            switch (state.Result)
            {
            case Buy7.BuyerResult r:
                resultId = r.id;
                break;

            case Buy7.SellerResult r:
                resultId = r.id;
                break;

            case DailyReward2.DailyRewardResult r:
                resultId = r.id;
                break;

            case ItemEnhancement.ResultModel r:
                resultId = r.id;
                break;

            case ItemEnhancement7.ResultModel r:
                resultId = r.id;
                break;

            case MonsterCollectionResult r:
                resultId = r.id;
                break;

            case CombinationConsumable5.ResultModel r:
                resultId = r.id;
                break;

            case RapidCombination5.ResultModel r:
                resultId = r.id;
                break;

            case SellCancellation.Result r:
                resultId = r.id;
                break;

            case SellCancellation7.Result r:
                resultId = r.id;
                break;

            case SellCancellation8.Result r:
                resultId = r.id;
                break;

            default:
                return(false);
            }

            return(true);
        }
Esempio n. 4
0
        public void CombinationSlotState()
        {
            var address = new PrivateKey().PublicKey.ToAddress();
            var state   = new CombinationSlotState(address, 1);

            Assert.AreEqual(address, state.address);
            Assert.AreEqual(1, state.UnlockStage);
            Assert.AreEqual(0, state.UnlockBlockIndex);
        }
Esempio n. 5
0
 public static void ResetCombinationSlot(CombinationSlotState slot)
 {
     LocalLayer.Instance
     .ResetCombinationSlotModifiers <CombinationSlotBlockIndexModifier>(
         slot.address);
     LocalLayer.Instance
     .ResetCombinationSlotModifiers <CombinationSlotBlockIndexAndResultModifier>(
         slot.address);
 }
Esempio n. 6
0
        public HackAndSlash10Test()
        {
            _sheets      = TableSheetsImporter.ImportSheets();
            _tableSheets = new TableSheets(_sheets);

            var privateKey = new PrivateKey();

            _agentAddress = privateKey.PublicKey.ToAddress();
            var agentState = new AgentState(_agentAddress);

            _avatarAddress = _agentAddress.Derive("avatar");
            var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);

            _rankingMapAddress = _avatarAddress.Derive("ranking_map");
            _avatarState       = new AvatarState(
                _avatarAddress,
                _agentAddress,
                0,
                _tableSheets.GetAvatarSheets(),
                gameConfigState,
                _rankingMapAddress
                )
            {
                level = 100,
            };
            _inventoryAddress        = _avatarAddress.Derive(LegacyInventoryKey);
            _worldInformationAddress = _avatarAddress.Derive(LegacyWorldInformationKey);
            _questListAddress        = _avatarAddress.Derive(LegacyQuestListKey);
            agentState.avatarAddresses.Add(0, _avatarAddress);

            _weeklyArenaState = new WeeklyArenaState(0);

            _initialState = new State()
                            .SetState(_weeklyArenaState.address, _weeklyArenaState.Serialize())
                            .SetState(_agentAddress, agentState.SerializeV2())
                            .SetState(_avatarAddress, _avatarState.SerializeV2())
                            .SetState(_inventoryAddress, _avatarState.inventory.Serialize())
                            .SetState(_worldInformationAddress, _avatarState.worldInformation.Serialize())
                            .SetState(_questListAddress, _avatarState.questList.Serialize())
                            .SetState(_rankingMapAddress, new RankingMapState(_rankingMapAddress).Serialize())
                            .SetState(gameConfigState.address, gameConfigState.Serialize());

            foreach (var(key, value) in _sheets)
            {
                _initialState = _initialState
                                .SetState(Addresses.TableSheet.Derive(key), value.Serialize());
            }

            foreach (var address in _avatarState.combinationSlotAddresses)
            {
                var slotState = new CombinationSlotState(
                    address,
                    GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
                _initialState = _initialState.SetState(address, slotState.Serialize());
            }
        }
Esempio n. 7
0
        public void CombinationSlotStateUpdate()
        {
            var address = new PrivateKey().PublicKey.ToAddress();
            var state   = new CombinationSlotState(address, 1);
            var result  = new CombinationConsumable.ResultModel();

            state.Update(result, 1, 10);
            Assert.AreEqual(result, state.Result);
            Assert.AreEqual(10, state.UnlockBlockIndex);
            Assert.AreEqual(1, state.StartBlockIndex);
        }
Esempio n. 8
0
        private void SetSlot(CombinationSlotState state)
        {
            var avatarState = States.Instance.CurrentAvatarState;

            if (avatarState is null)
            {
                return;
            }

            UpdateSlot(state);
        }
Esempio n. 9
0
        public void SetData(CombinationSlotState state, long blockIndex, int slotIndex)
        {
            lockText.text = string.Format(
                L10nManager.Localize("UI_UNLOCK_CONDITION_STAGE"),
                state.UnlockStage);
            _data      = state;
            _slotIndex = slotIndex;
            var unlock = States.Instance.CurrentAvatarState?.worldInformation
                         .IsStageCleared(state.UnlockStage) ?? false;

            lockText.gameObject.SetActive(!unlock);
            lockImage.gameObject.SetActive(!unlock);
            unlockText.gameObject.SetActive(false);
            progressText.gameObject.SetActive(false);
            progressBar.gameObject.SetActive(false);
            if (unlock)
            {
                var canUse = state.Validate(States.Instance.CurrentAvatarState, blockIndex);
                if (state.Result is null)
                {
                    resultView.Clear();
                }
                else
                {
                    canUse = canUse && state.Result.itemUsable.RequiredBlockIndex <= blockIndex;
                    if (canUse)
                    {
                        resultView.Clear();
                    }
                    else
                    {
                        resultView.SetData(new Item(state.Result.itemUsable));
                    }

                    progressText.text = state.Result.itemUsable.GetLocalizedName();
                }

                unlockText.gameObject.SetActive(canUse);
                progressText.gameObject.SetActive(!canUse);
                progressBar.gameObject.SetActive(!canUse);
                SubscribeOnBlockIndex(blockIndex);
                Widget.Find <BottomMenu>()?.UpdateCombinationNotification();
            }

            progressBar.maxValue = state.RequiredBlockIndex;
            progressBar.value    = blockIndex - state.StartBlockIndex;
            sliderText.text      = $"({progressBar.value} / {progressBar.maxValue})";
        }
Esempio n. 10
0
        public void SerializeCombinationSlotStateWithOutResult()
        {
            var address    = new PrivateKey().PublicKey.ToAddress();
            var state      = new CombinationSlotState(address, 1);
            var serialized = (Dictionary)state.Serialize();

            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"address"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"unlockBlockIndex"));
            Assert.IsTrue(serialized.ContainsKey((IKey)(Text)"unlockStage"));
            Assert.IsFalse(serialized.ContainsKey((IKey)(Text)"result"));
            var deserialize = new CombinationSlotState(serialized);

            Assert.AreEqual(state.UnlockStage, deserialize.UnlockStage);
            Assert.AreEqual(state.UnlockBlockIndex, deserialize.UnlockBlockIndex);
            Assert.AreEqual(state.address, deserialize.address);
        }
Esempio n. 11
0
        public static bool TryGetMail(
            this CombinationSlotState state,
            long blockIndex,
            long requiredBlockIndex,
            out CombinationMail combinationMail,
            out ItemEnhanceMail itemEnhanceMail)
        {
            combinationMail = null;
            itemEnhanceMail = null;

            if (!state.TryGetResultId(out var resultId))
            {
                return(false);
            }

            switch (state.Result)
            {
            case ItemEnhancement.ResultModel r:
                itemEnhanceMail = new ItemEnhanceMail(
                    r,
                    blockIndex,
                    resultId,
                    requiredBlockIndex);
                return(true);

            case ItemEnhancement7.ResultModel r:
                itemEnhanceMail = new ItemEnhanceMail(
                    r,
                    blockIndex,
                    resultId,
                    requiredBlockIndex);
                return(true);

            case CombinationConsumable5.ResultModel r:
                combinationMail = new CombinationMail(
                    r,
                    blockIndex,
                    resultId,
                    requiredBlockIndex);
                return(true);

            default:
                return(false);
            }
        }
Esempio n. 12
0
 private void UpdateSlot(CombinationSlotState state)
 {
     for (var i = 0; i < slots.Length; i++)
     {
         var slot    = slots[i];
         var address = States.Instance.CurrentAvatarState.address.Derive(
             string.Format(
                 CultureInfo.InvariantCulture,
                 CombinationSlotState.DeriveFormat,
                 i
                 )
             );
         if (address == state.address)
         {
             slot.SetData(state, _blockIndex, i);
             break;
         }
     }
 }
Esempio n. 13
0
        public CombinationSlotState Modify(CombinationSlotState state)
        {
            if (state is null)
            {
                return(null);
            }

            var address = state.address;

            if (!_combinationSlotModifierInfos.ContainsKey(address))
            {
                return(state);
            }

            var modifierInfo = _combinationSlotModifierInfos[address];

            return(modifierInfo is null
                ? state
                : PostModify(state, modifierInfo));
        }
Esempio n. 14
0
        private void SetCombinationSlotStates(AvatarState avatarState)
        {
            if (avatarState is null)
            {
                LocalLayer.Instance.InitializeCombinationSlotsByCurrentAvatarState(null);

                return;
            }

            LocalLayer.Instance.InitializeCombinationSlotsByCurrentAvatarState(avatarState);
            for (var i = 0; i < avatarState.combinationSlotAddresses.Count; i++)
            {
                var slotAddress = avatarState.address.Derive(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        CombinationSlotState.DeriveFormat,
                        i
                        )
                    );
                var slotState = new CombinationSlotState(
                    (Dictionary)Game.Game.instance.Agent.GetState(slotAddress));
                SetCombinationSlotState(slotState);
            }
        }
Esempio n. 15
0
        public async Task Query()
        {
            const string query = @"
            {
                address
                unlockBlockIndex
                unlockStage
                startBlockIndex
            }";

            Address address = default;
            CombinationSlotState combinationSlotState = new CombinationSlotState(address, 1);
            var queryResult = await ExecuteQueryAsync <CombinationSlotStateType>(query, source : combinationSlotState);

            var expected = new Dictionary <string, object>()
            {
                ["address"]          = address.ToString(),
                ["unlockBlockIndex"] = 0,
                ["unlockStage"]      = 1,
                ["startBlockIndex"]  = 0,
            };

            Assert.Equal(expected, queryResult.Data);
        }
Esempio n. 16
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IActionContext ctx           = context;
            var            states        = ctx.PreviousStates;
            var            avatarAddress = ctx.Signer.Derive(
                string.Format(
                    CultureInfo.InvariantCulture,
                    DeriveFormat,
                    index
                    )
                );

            if (ctx.Rehearsal)
            {
                states = states.SetState(ctx.Signer, MarkChanged);
                for (var i = 0; i < AvatarState.CombinationSlotCapacity; i++)
                {
                    var slotAddress = avatarAddress.Derive(
                        string.Format(
                            CultureInfo.InvariantCulture,
                            CombinationSlotState.DeriveFormat,
                            i
                            )
                        );
                    states = states.SetState(slotAddress, MarkChanged);
                }

                return(states
                       .SetState(avatarAddress, MarkChanged)
                       .SetState(Addresses.Ranking, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, GoldCurrencyState.Address, context.Signer));
            }

            CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context);

            var addressesHex = GetSignerAndOtherAddressesHex(context, avatarAddress);

            if (!Regex.IsMatch(name, GameConfig.AvatarNickNamePattern))
            {
                throw new InvalidNamePatternException(
                          $"{addressesHex}Aborted as the input name {name} does not follow the allowed name pattern.");
            }

            var sw = new Stopwatch();

            sw.Start();
            var started = DateTimeOffset.UtcNow;

            Log.Verbose("{AddressesHex}CreateAvatar exec started", addressesHex);
            AgentState existingAgentState = states.GetAgentState(ctx.Signer);
            var        agentState         = existingAgentState ?? new AgentState(ctx.Signer);
            var        avatarState        = states.GetAvatarState(avatarAddress);

            if (!(avatarState is null))
            {
                throw new InvalidAddressException(
                          $"{addressesHex}Aborted as there is already an avatar at {avatarAddress}.");
            }

            if (!(0 <= index && index < GameConfig.SlotCount))
            {
                throw new AvatarIndexOutOfRangeException(
                          $"{addressesHex}Aborted as the index is out of range #{index}.");
            }

            if (agentState.avatarAddresses.ContainsKey(index))
            {
                throw new AvatarIndexAlreadyUsedException(
                          $"{addressesHex}Aborted as the signer already has an avatar at index #{index}.");
            }
            sw.Stop();
            Log.Verbose("{AddressesHex}CreateAvatar Get AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            Log.Verbose("{AddressesHex}Execute CreateAvatar; player: {AvatarAddress}", addressesHex, avatarAddress);

            agentState.avatarAddresses.Add(index, avatarAddress);

            // Avoid NullReferenceException in test
            var materialItemSheet = ctx.PreviousStates.GetSheet <MaterialItemSheet>();

            var rankingState = ctx.PreviousStates.GetRankingState();

            var rankingMapAddress = rankingState.UpdateRankingMap(avatarAddress);

            avatarState = CreateAvatar0.CreateAvatarState(name, avatarAddress, ctx, materialItemSheet, rankingMapAddress);

            if (hair < 0)
            {
                hair = 0;
            }
            if (lens < 0)
            {
                lens = 0;
            }
            if (ear < 0)
            {
                ear = 0;
            }
            if (tail < 0)
            {
                tail = 0;
            }

            avatarState.Customize(hair, lens, ear, tail);

            foreach (var address in avatarState.combinationSlotAddresses)
            {
                var slotState =
                    new CombinationSlotState(address, GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
                states = states.SetState(address, slotState.Serialize());
            }

            avatarState.UpdateQuestRewards2(materialItemSheet);

            sw.Stop();
            Log.Verbose("{AddressesHex}CreateAvatar CreateAvatarState: {Elapsed}", addressesHex, sw.Elapsed);
            var ended = DateTimeOffset.UtcNow;

            Log.Verbose("{AddressesHex}CreateAvatar Total Executed Time: {Elapsed}", addressesHex, ended - started);
            return(states
                   .SetState(ctx.Signer, agentState.Serialize())
                   .SetState(Addresses.Ranking, rankingState.Serialize())
                   .SetState(avatarAddress, avatarState.Serialize()));
        }
Esempio n. 17
0
        public CombinationAndRapidCombinationTest(ITestOutputHelper outputHelper)
        {
            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Verbose()
                         .WriteTo.TestOutput(outputHelper)
                         .CreateLogger();

            var sheets = TableSheetsImporter.ImportSheets();

            _tableSheets = new TableSheets(sheets);

            var gold            = new GoldCurrencyState(new Currency("NCG", 2, minter: null));
            var gameConfigState = new GameConfigState(sheets[nameof(GameConfigSheet)]);

            _agentAddress  = new PrivateKey().ToAddress();
            _avatarAddress = _agentAddress.Derive("avatar");
            _slot0Address  = _avatarAddress.Derive(
                string.Format(
                    CultureInfo.InvariantCulture,
                    CombinationSlotState.DeriveFormat,
                    0
                    )
                );
            var slot0State = new CombinationSlotState(
                _slot0Address,
                GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);

            var agentState = new AgentState(_agentAddress);

            agentState.avatarAddresses[0] = _avatarAddress;

            var avatarState = new AvatarState(
                _avatarAddress,
                _agentAddress,
                1,
                _tableSheets.GetAvatarSheets(),
                gameConfigState,
                default
                )
            {
                worldInformation = new WorldInformation(
                    0,
                    _tableSheets.WorldSheet,
                    GameConfig.RequireClearedStageLevel.CombinationEquipmentAction),
            };

            _inventoryAddress        = _avatarAddress.Derive(LegacyInventoryKey);
            _worldInformationAddress = _avatarAddress.Derive(LegacyWorldInformationKey);
            _questListAddress        = _avatarAddress.Derive(LegacyQuestListKey);

            _initialState = new Tests.Action.State()
                            .SetState(GoldCurrencyState.Address, gold.Serialize())
                            .SetState(gameConfigState.address, gameConfigState.Serialize())
                            .SetState(_agentAddress, agentState.Serialize())
                            .SetState(_avatarAddress, avatarState.SerializeV2())
                            .SetState(_inventoryAddress, avatarState.inventory.Serialize())
                            .SetState(_worldInformationAddress, avatarState.worldInformation.Serialize())
                            .SetState(_questListAddress, avatarState.questList.Serialize())
                            .SetState(_slot0Address, slot0State.Serialize());

            foreach (var(key, value) in sheets)
            {
                _initialState = _initialState
                                .SetState(Addresses.TableSheet.Derive(key), value.Serialize());
            }
        }
Esempio n. 18
0
        public void Case(int randomSeed, int[] optionNumbers)
        {
            var gameConfigState = _initialState.GetGameConfigState();

            Assert.NotNull(gameConfigState);

            var recipeRow    = _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Any());
            var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2[recipeRow.SubRecipeIds.First()];
            var combinationEquipmentAction = new CombinationEquipment
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
                recipeId      = recipeRow.Id,
                subRecipeId   = subRecipeRow.Id,
            };

            var inventoryValue = _initialState.GetState(_inventoryAddress);

            Assert.NotNull(inventoryValue);
            var inventoryState = new Inventory((List)inventoryValue);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId),
                recipeRow.MaterialCount);
            foreach (var materialInfo in subRecipeRow.Materials)
            {
                inventoryState.AddFungibleItem(
                    ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id),
                    materialInfo.Count);
            }

            var worldInformation = new WorldInformation(
                0,
                _tableSheets.WorldSheet,
                recipeRow.UnlockStage);

            var nextState = _initialState
                            .SetState(_inventoryAddress, inventoryState.Serialize())
                            .SetState(_worldInformationAddress, worldInformation.Serialize());

            var random = new TestRandom(randomSeed);

            nextState = combinationEquipmentAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 0,
                Random         = random,
                Signer         = _agentAddress,
            });

            var slot0Value = nextState.GetState(_slot0Address);

            Assert.NotNull(slot0Value);
            var slot0State = new CombinationSlotState((Dictionary)slot0Value);

            Assert.NotNull(slot0State.Result.itemUsable);
            var equipment       = (Equipment)slot0State.Result.itemUsable;
            var additionalStats = equipment.StatsMap
                                  .GetAdditionalStats(true)
                                  .ToArray();
            var skills = equipment.Skills;

            Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination);
            var optionSheet           = _tableSheets.EquipmentItemOptionSheet;
            var mainAdditionalStatMin = 0;
            var mainAdditionalStatMax = 0;
            var requiredBlockIndex    = 0;

            foreach (var optionNumber in optionNumbers)
            {
                var optionInfo = subRecipeRow.Options[optionNumber - 1];
                requiredBlockIndex += optionInfo.RequiredBlockIndex;
                var optionRow = optionSheet[optionInfo.Id];
                if (optionRow.StatMin > 0 || optionRow.StatMax > 0)
                {
                    if (optionRow.StatType == equipment.UniqueStatType)
                    {
                        mainAdditionalStatMin += optionRow.StatMin;
                        mainAdditionalStatMax += optionRow.StatMax;
                        continue;
                    }

                    var additionalStatValue = additionalStats
                                              .First(e => e.statType == optionRow.StatType)
                                              .additionalValue;
                    Assert.True(additionalStatValue >= optionRow.StatMin);
                    Assert.True(additionalStatValue <= optionRow.StatMax + 1);
                }
                else if (optionRow.SkillId != default)
                {
                    var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId);
                    Assert.True(skill.Chance >= optionRow.SkillChanceMin);
                    Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1);
                    Assert.True(skill.Power >= optionRow.SkillDamageMin);
                    Assert.True(skill.Power <= optionRow.SkillDamageMax + 1);
                }
            }

            var mainAdditionalStatValue = additionalStats
                                          .First(e => e.statType == equipment.UniqueStatType)
                                          .additionalValue;

            Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin);
            Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1);
            Assert.Equal(requiredBlockIndex + 1, slot0State.RequiredBlockIndex);

            // FIXME
            // https://github.com/planetarium/lib9c/pull/517#discussion_r679218764
            // The tests after this line should be finished. However, since then the logic is being developed by
            // different developers in different branches. I wrote a test beforehand, but it's failing.
            // I plan to move to another branch after this PR is merged and finish writing the tests.
            return;

            if (requiredBlockIndex == 0)
            {
                return;
            }

            var hourglassRow = _tableSheets.MaterialItemSheet
                               .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass)
                               .Value;

            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));

            var hourglassCount = requiredBlockIndex * gameConfigState.HourglassPerBlock;

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id),
                hourglassCount);
            Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses));
            Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count));
            nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize());

            var rapidCombinationAction = new RapidCombination
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
            };

            nextState = rapidCombinationAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 1,
                Random         = random,
                Signer         = _agentAddress,
            });
            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));
        }
Esempio n. 19
0
 public static void OnNext(CombinationSlotState slotState)
 {
     CombinationSlotState.OnNext(slotState);
 }
Esempio n. 20
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            var data           = TestbedHelper.LoadData <TestbedSell>("TestbedSell");
            var addedItemInfos = data.Items
                                 .Select(item => new TestbedHelper.AddedItemInfo(
                                             context.Random.GenerateRandomGuid(),
                                             context.Random.GenerateRandomGuid()))
                                 .ToList();

            var agentAddress = _privateKey.PublicKey.ToAddress();
            var states       = context.PreviousStates;

            var avatarAddress = agentAddress.Derive(
                string.Format(
                    CultureInfo.InvariantCulture,
                    CreateAvatar.DeriveFormat,
                    _slotIndex
                    )
                );
            var inventoryAddress        = avatarAddress.Derive(LegacyInventoryKey);
            var worldInformationAddress = avatarAddress.Derive(LegacyWorldInformationKey);
            var questListAddress        = avatarAddress.Derive(LegacyQuestListKey);
            var orderReceiptAddress     = OrderDigestListState.DeriveAddress(avatarAddress);

            if (context.Rehearsal)
            {
                states = states.SetState(agentAddress, MarkChanged);
                for (var i = 0; i < AvatarState.CombinationSlotCapacity; i++)
                {
                    var slotAddress = avatarAddress.Derive(
                        string.Format(CultureInfo.InvariantCulture,
                                      CombinationSlotState.DeriveFormat, i));
                    states = states.SetState(slotAddress, MarkChanged);
                }

                states = states.SetState(avatarAddress, MarkChanged)
                         .SetState(Addresses.Ranking, MarkChanged)
                         .SetState(worldInformationAddress, MarkChanged)
                         .SetState(questListAddress, MarkChanged)
                         .SetState(inventoryAddress, MarkChanged);

                for (var i = 0; i < data.Items.Length; i++)
                {
                    var itemAddress  = Addresses.GetItemAddress(addedItemInfos[i].TradableId);
                    var orderAddress = Order.DeriveAddress(addedItemInfos[i].OrderId);
                    var shopAddress  = ShardedShopStateV2.DeriveAddress(
                        data.Items[i].ItemSubType,
                        addedItemInfos[i].OrderId);

                    states = states.SetState(avatarAddress, MarkChanged)
                             .SetState(inventoryAddress, MarkChanged)
                             .MarkBalanceChanged(GoldCurrencyMock, agentAddress,
                                                 GoldCurrencyState.Address)
                             .SetState(orderReceiptAddress, MarkChanged)
                             .SetState(itemAddress, MarkChanged)
                             .SetState(orderAddress, MarkChanged)
                             .SetState(shopAddress, MarkChanged);
                }

                return(states);
            }

            // Create Agent and avatar
            var existingAgentState = states.GetAgentState(agentAddress);
            var agentState         = existingAgentState ?? new AgentState(agentAddress);
            var avatarState        = states.GetAvatarState(avatarAddress);

            if (!(avatarState is null))
            {
                throw new InvalidAddressException(
                          $"Aborted as there is already an avatar at {avatarAddress}.");
            }

            if (agentState.avatarAddresses.ContainsKey(_slotIndex))
            {
                throw new AvatarIndexAlreadyUsedException(
                          $"borted as the signer already has an avatar at index #{_slotIndex}.");
            }

            agentState.avatarAddresses.Add(_slotIndex, avatarAddress);

            var rankingState      = context.PreviousStates.GetRankingState();
            var rankingMapAddress = rankingState.UpdateRankingMap(avatarAddress);

            avatarState = TestbedHelper.CreateAvatarState(data.avatar.Name,
                                                          agentAddress,
                                                          avatarAddress,
                                                          context.BlockIndex,
                                                          context.PreviousStates.GetAvatarSheets(),
                                                          context.PreviousStates.GetSheet <WorldSheet>(),
                                                          context.PreviousStates.GetGameConfigState(),
                                                          rankingMapAddress);

            // Add item
            var costumeItemSheet    = context.PreviousStates.GetSheet <CostumeItemSheet>();
            var equipmentItemSheet  = context.PreviousStates.GetSheet <EquipmentItemSheet>();
            var optionSheet         = context.PreviousStates.GetSheet <EquipmentItemOptionSheet>();
            var skillSheet          = context.PreviousStates.GetSheet <SkillSheet>();
            var materialItemSheet   = context.PreviousStates.GetSheet <MaterialItemSheet>();
            var consumableItemSheet = context.PreviousStates.GetSheet <ConsumableItemSheet>();

            for (var i = 0; i < data.Items.Length; i++)
            {
                TestbedHelper.AddItem(costumeItemSheet,
                                      equipmentItemSheet,
                                      optionSheet,
                                      skillSheet,
                                      materialItemSheet,
                                      consumableItemSheet,
                                      context.Random,
                                      data.Items[i], addedItemInfos[i], avatarState);
            }

            avatarState.Customize(0, 0, 0, 0);

            foreach (var address in avatarState.combinationSlotAddresses)
            {
                var slotState =
                    new CombinationSlotState(address,
                                             GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
                states = states.SetState(address, slotState.Serialize());
            }

            avatarState.UpdateQuestRewards(materialItemSheet);
            states = states.SetState(agentAddress, agentState.Serialize())
                     .SetState(Addresses.Ranking, rankingState.Serialize())
                     .SetState(inventoryAddress, avatarState.inventory.Serialize())
                     .SetState(worldInformationAddress, avatarState.worldInformation.Serialize())
                     .SetState(questListAddress, avatarState.questList.Serialize())
                     .SetState(avatarAddress, avatarState.SerializeV2());

            // for sell
            for (var i = 0; i < data.Items.Length; i++)
            {
                var itemAddress  = Addresses.GetItemAddress(addedItemInfos[i].TradableId);
                var orderAddress = Order.DeriveAddress(addedItemInfos[i].OrderId);
                var shopAddress  = ShardedShopStateV2.DeriveAddress(
                    data.Items[i].ItemSubType,
                    addedItemInfos[i].OrderId);

                var balance =
                    context.PreviousStates.GetBalance(agentAddress, states.GetGoldCurrency());
                var price = new FungibleAssetValue(balance.Currency, data.Items[i].Price, 0);
                var order = OrderFactory.Create(agentAddress, avatarAddress,
                                                addedItemInfos[i].OrderId,
                                                price,
                                                addedItemInfos[i].TradableId,
                                                context.BlockIndex,
                                                data.Items[i].ItemSubType,
                                                data.Items[i].Count);

                Orders.Add(order);
                order.Validate(avatarState, data.Items[i].Count);
                var tradableItem = order.Sell(avatarState);

                var shardedShopState =
                    states.TryGetState(shopAddress, out Dictionary serializedState)
                        ? new ShardedShopStateV2(serializedState)
                        : new ShardedShopStateV2(shopAddress);
                var costumeStatSheet = states.GetSheet <CostumeStatSheet>();
                var orderDigest      = order.Digest(avatarState, costumeStatSheet);
                shardedShopState.Add(orderDigest, context.BlockIndex);
                var orderReceiptList =
                    states.TryGetState(orderReceiptAddress, out Dictionary receiptDict)
                        ? new OrderDigestListState(receiptDict)
                        : new OrderDigestListState(orderReceiptAddress);
                orderReceiptList.Add(orderDigest);

                states = states.SetState(orderReceiptAddress, orderReceiptList.Serialize())
                         .SetState(inventoryAddress, avatarState.inventory.Serialize())
                         .SetState(avatarAddress, avatarState.SerializeV2())
                         .SetState(itemAddress, tradableItem.Serialize())
                         .SetState(orderAddress, order.Serialize())
                         .SetState(shopAddress, shardedShopState.Serialize());
            }

            result.SellerAgentAddress  = agentAddress;
            result.SellerAvatarAddress = avatarAddress;
            result.ItemInfos           = new List <ItemInfos>();
            for (var i = 0; i < data.Items.Length; i++)
            {
                result.ItemInfos.Add(new ItemInfos(
                                         addedItemInfos[i].OrderId,
                                         addedItemInfos[i].TradableId,
                                         data.Items[i].ItemSubType,
                                         data.Items[i].Price,
                                         data.Items[i].Count));
            }
            return(states);
        }
Esempio n. 21
0
        public void Pop(CombinationSlotState state, int slotIndex)
        {
            _slotIndex = slotIndex;
            CombinationConsumable.ResultModel result;
            CombinationConsumable.ResultModel chainResult;
            try
            {
                result = (CombinationConsumable.ResultModel)state.Result;
                var chainState = new CombinationSlotState((Dictionary)Game.Game.instance.Agent.GetState(state.address));
                chainResult = (CombinationConsumable.ResultModel)chainState.Result;
            }
            catch (InvalidCastException)
            {
                return;
            }
            var subRecipeEnabled = result.subRecipeId.HasValue;

            materialPanel.gameObject.SetActive(false);
            optionView.gameObject.SetActive(false);
            switch (result.itemType)
            {
            case ItemType.Equipment:
            {
                var recipeRow =
                    Game.Game.instance.TableSheets.EquipmentItemRecipeSheet.Values.First(r =>
                                                                                         r.Id == result.recipeId);

                recipeCellView.Set(recipeRow);
                if (subRecipeEnabled)
                {
                    optionView.Show(
                        result.itemUsable.GetLocalizedName(),
                        (int)result.subRecipeId,
                        new EquipmentItemSubRecipeSheet.MaterialInfo(
                            recipeRow.MaterialId,
                            recipeRow.MaterialCount),
                        false
                        );
                }
                else
                {
                    materialPanel.SetData(recipeRow, null, false);
                    materialPanel.gameObject.SetActive(true);
                }

                break;
            }

            case ItemType.Consumable:
            {
                var recipeRow =
                    Game.Game.instance.TableSheets.ConsumableItemRecipeSheet.Values.First(r =>
                                                                                          r.Id == result.recipeId);

                recipeCellView.Set(recipeRow);
                materialPanel.SetData(recipeRow, false, true);
                materialPanel.gameObject.SetActive(true);
                break;
            }
            }

            submitButton.HideAP();
            submitButton.HideNCG();
            var diff = result.itemUsable.RequiredBlockIndex - Game.Game.instance.Agent.BlockIndex;

            if (diff < 0)
            {
                submitButton.SetSubmitText(
                    L10nManager.Localize("UI_COMBINATION_WAITING"),
                    L10nManager.Localize("UI_RAPID_COMBINATION")
                    );
                submitButton.SetSubmittable(result.id == chainResult?.id);
                submitButton.HideHourglass();
            }
            else
            {
                _cost = Action.RapidCombination.CalculateHourglassCount(
                    States.Instance.GameConfigState,
                    diff);
                _row = Game.Game.instance.TableSheets.MaterialItemSheet.Values
                       .First(r => r.ItemSubType == ItemSubType.Hourglass);
                var isEnough =
                    States.Instance.CurrentAvatarState.inventory.HasItem(_row.ItemId, _cost);

                var count = States.Instance.CurrentAvatarState.inventory
                            .TryGetMaterial(_row.ItemId, out var glass) ? glass.count : 0;

                if (result.id == chainResult?.id)
                {
                    submitButton.SetSubmitText(
                        L10nManager.Localize("UI_RAPID_COMBINATION"));
                    submitButton.SetSubmittable(isEnough);
                }
                else
                {
                    submitButton.SetSubmitText(
                        L10nManager.Localize("UI_COMBINATION_WAITING"));
                    submitButton.SetSubmittable(false);
                }

                submitButton.ShowHourglass(_cost, count);
            }

            base.Show();
        }
Esempio n. 22
0
 public override CombinationSlotState Modify(CombinationSlotState state)
 {
     state.Update(_blockIndex);
     return(state);
 }
        public void Case(int randomSeed, int[] optionNumbers)
        {
            var gameConfigState = _initialState.GetGameConfigState();

            Assert.NotNull(gameConfigState);

            var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2.OrderedList.First(e =>
                                                                                            e.Options.Count == 4 &&
                                                                                            e.RequiredBlockIndex > GameConfig.RequiredAppraiseBlock &&
                                                                                            e.RequiredGold == 0);
            var recipeRow =
                _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Contains(subRecipeRow.Id));
            var combinationEquipmentAction = new CombinationEquipment
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
                recipeId      = recipeRow.Id,
                subRecipeId   = subRecipeRow.Id,
            };

            var inventoryValue = _initialState.GetState(_inventoryAddress);

            Assert.NotNull(inventoryValue);

            var inventoryState = new Inventory((List)inventoryValue);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId),
                recipeRow.MaterialCount);
            foreach (var materialInfo in subRecipeRow.Materials)
            {
                inventoryState.AddFungibleItem(
                    ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id),
                    materialInfo.Count);
            }

            var worldInformation = new WorldInformation(
                0,
                _tableSheets.WorldSheet,
                recipeRow.UnlockStage);

            var nextState = _initialState
                            .SetState(_inventoryAddress, inventoryState.Serialize())
                            .SetState(_worldInformationAddress, worldInformation.Serialize());

            var random = new TestRandom(randomSeed);

            nextState = combinationEquipmentAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 0,
                Random         = random,
                Signer         = _agentAddress,
            });

            var slot0Value = nextState.GetState(_slot0Address);

            Assert.NotNull(slot0Value);

            var slot0State = new CombinationSlotState((Dictionary)slot0Value);

            Assert.NotNull(slot0State.Result.itemUsable);

            var equipment       = (Equipment)slot0State.Result.itemUsable;
            var additionalStats = equipment.StatsMap
                                  .GetAdditionalStats(true)
                                  .ToArray();
            var skills = equipment.Skills;

            Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination);

            var optionSheet           = _tableSheets.EquipmentItemOptionSheet;
            var mainAdditionalStatMin = 0;
            var mainAdditionalStatMax = 0;
            var requiredBlockIndex    = recipeRow.RequiredBlockIndex + subRecipeRow.RequiredBlockIndex;
            var orderedOptions        = subRecipeRow.Options
                                        .OrderByDescending(e => e.Ratio)
                                        .ThenBy(e => e.RequiredBlockIndex)
                                        .ThenBy(e => e.Id)
                                        .ToArray();

            foreach (var optionNumber in optionNumbers)
            {
                var optionInfo = orderedOptions[optionNumber - 1];
                requiredBlockIndex += optionInfo.RequiredBlockIndex;
                var optionRow = optionSheet[optionInfo.Id];
                if (optionRow.StatMin > 0 || optionRow.StatMax > 0)
                {
                    if (optionRow.StatType == equipment.UniqueStatType)
                    {
                        mainAdditionalStatMin += optionRow.StatMin;
                        mainAdditionalStatMax += optionRow.StatMax;
                        continue;
                    }

                    var additionalStatValue = additionalStats
                                              .First(e => e.statType == optionRow.StatType)
                                              .additionalValue;
                    Assert.True(additionalStatValue >= optionRow.StatMin);
                    Assert.True(additionalStatValue <= optionRow.StatMax + 1);
                }
                else if (optionRow.SkillId != default)
                {
                    var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId);
                    Assert.True(skill.Chance >= optionRow.SkillChanceMin);
                    Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1);
                    Assert.True(skill.Power >= optionRow.SkillDamageMin);
                    Assert.True(skill.Power <= optionRow.SkillDamageMax + 1);
                }
            }

            var mainAdditionalStatValue = additionalStats
                                          .First(e => e.statType == equipment.UniqueStatType)
                                          .additionalValue;

            Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin);
            Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1);
            Assert.Equal(requiredBlockIndex, slot0State.RequiredBlockIndex);

            if (requiredBlockIndex == 0)
            {
                return;
            }

            var hourglassRow = _tableSheets.MaterialItemSheet
                               .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass)
                               .Value;

            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));

            var diff           = slot0State.RequiredBlockIndex - GameConfig.RequiredAppraiseBlock;
            var hourglassCount = RapidCombination0.CalculateHourglassCount(gameConfigState, diff);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id),
                hourglassCount);
            Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses));
            Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count));
            nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize());

            var rapidCombinationAction = new RapidCombination
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
            };

            nextState = rapidCombinationAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = GameConfig.RequiredAppraiseBlock,
                Random         = random,
                Signer         = _agentAddress,
            });
            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));
        }
Esempio n. 24
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IActionContext ctx    = context;
            var            states = ctx.PreviousStates;

            if (ctx.Rehearsal)
            {
                states = states.SetState(ctx.Signer, MarkChanged);
                for (var i = 0; i < AvatarState.CombinationSlotCapacity; i++)
                {
                    var slotAddress = avatarAddress.Derive(
                        string.Format(
                            CultureInfo.InvariantCulture,
                            CombinationSlotState.DeriveFormat,
                            i
                            )
                        );
                    states = states.SetState(slotAddress, MarkChanged);
                }

                return(states
                       .SetState(avatarAddress, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, GoldCurrencyState.Address, context.Signer));
            }

            if (!Regex.IsMatch(name, GameConfig.AvatarNickNamePattern))
            {
                return(LogError(
                           context,
                           "Aborted as the input name {@Name} does not follow the allowed name pattern.",
                           name
                           ));
            }

            var sw = new Stopwatch();

            sw.Start();
            var started = DateTimeOffset.UtcNow;

            Log.Debug("CreateAvatar exec started.");
            AgentState existingAgentState = states.GetAgentState(ctx.Signer);
            var        agentState         = existingAgentState ?? new AgentState(ctx.Signer);
            var        avatarState        = states.GetAvatarState(avatarAddress);

            if (!(avatarState is null))
            {
                return(LogError(context, "Aborted as there is already an avatar at {Address}.", avatarAddress));
            }

            if (agentState.avatarAddresses.ContainsKey(index))
            {
                return(LogError(context, "Aborted as the signer already has an avatar at index #{Index}.", index));
            }
            sw.Stop();
            Log.Debug("CreateAvatar Get AgentAvatarStates: {Elapsed}", sw.Elapsed);
            sw.Restart();

            if (existingAgentState is null)
            {
                // 첫 아바타 생성이면 계정당 기본 소지금 부여.
                states = states.TransferAsset(
                    GoldCurrencyState.Address,
                    ctx.Signer,
                    states.GetGoldCurrency(),
                    InitialGoldBalance
                    );
            }

            Log.Debug("Execute CreateAvatar; player: {AvatarAddress}", avatarAddress);

            agentState.avatarAddresses.Add(index, avatarAddress);

            // Avoid NullReferenceException in test
            avatarState = CreateAvatarState(name, avatarAddress, ctx);

            if (hair < 0)
            {
                hair = 0;
            }
            if (lens < 0)
            {
                lens = 0;
            }
            if (ear < 0)
            {
                ear = 0;
            }
            if (tail < 0)
            {
                tail = 0;
            }

            avatarState.Customize(hair, lens, ear, tail);

            foreach (var address in avatarState.combinationSlotAddresses)
            {
                var slotState =
                    new CombinationSlotState(address, GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
                states = states.SetState(address, slotState.Serialize());
            }

            avatarState.UpdateQuestRewards(ctx);

            sw.Stop();
            Log.Debug("CreateAvatar CreateAvatarState: {Elapsed}", sw.Elapsed);
            var ended = DateTimeOffset.UtcNow;

            Log.Debug("CreateAvatar Total Executed Time: {Elapsed}", ended - started);
            return(states
                   .SetState(ctx.Signer, agentState.Serialize())
                   .SetState(avatarAddress, avatarState.Serialize()));
        }