Ejemplo n.º 1
0
        public void Execute(bool exist, int level, int monsterCollectionRound, int prevLevel, long blockIndex)
        {
            Address monsterCollectionAddress = MonsterCollectionState0.DeriveAddress(_signer, monsterCollectionRound);

            if (exist)
            {
                List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[prevLevel].Rewards;
                MonsterCollectionState0 prevMonsterCollectionState     = new MonsterCollectionState0(monsterCollectionAddress, prevLevel, 0, _tableSheets.MonsterCollectionRewardSheet);
                _initialState = _initialState.SetState(monsterCollectionAddress, prevMonsterCollectionState.Serialize());
                Assert.All(prevMonsterCollectionState.RewardLevelMap, kv => Assert.Equal(rewards, kv.Value));
            }

            AgentState prevAgentState = _initialState.GetAgentState(_signer);

            while (prevAgentState.MonsterCollectionRound < monsterCollectionRound)
            {
                prevAgentState.IncreaseCollectionRound();
            }

            _initialState = _initialState.SetState(_signer, prevAgentState.Serialize());

            Currency currency = _initialState.GetGoldCurrency();

            for (int i = 1; i < level + 1; i++)
            {
                if (i > prevLevel)
                {
                    MonsterCollectionSheet.Row row = _tableSheets.MonsterCollectionSheet[i];
                    _initialState = _initialState.MintAsset(_signer, row.RequiredGold * currency);
                }
            }

            MonsterCollect0 action = new MonsterCollect0
            {
                level           = level,
                collectionRound = monsterCollectionRound,
            };

            IAccountStateDelta nextState = action.Execute(new ActionContext
            {
                PreviousStates = _initialState,
                Signer         = _signer,
                BlockIndex     = blockIndex,
            });

            MonsterCollectionState0 nextMonsterCollectionState = new MonsterCollectionState0((Dictionary)nextState.GetState(monsterCollectionAddress));
            AgentState nextAgentState = nextState.GetAgentState(_signer);

            Assert.Equal(level, nextMonsterCollectionState.Level);
            Assert.Equal(0 * currency, nextState.GetBalance(_signer, currency));
            Assert.Equal(monsterCollectionRound, nextAgentState.MonsterCollectionRound);
            long rewardLevel = nextMonsterCollectionState.GetRewardLevel(blockIndex);

            for (long i = rewardLevel; i < 4; i++)
            {
                List <MonsterCollectionRewardSheet.RewardInfo> expected = _tableSheets.MonsterCollectionRewardSheet[level].Rewards;
                Assert.Equal(expected, nextMonsterCollectionState.RewardLevelMap[i + 1]);
            }
        }
Ejemplo n.º 2
0
        public static bool TryGetAgentAvatarStates(
            this IAccountStateDelta states,
            Address agentAddress,
            Address avatarAddress,
            out AgentState agentState,
            out AvatarState avatarState
            )
        {
            avatarState = null;
            agentState  = states.GetAgentState(agentAddress);
            if (agentState is null)
            {
                return(false);
            }
            if (!agentState.avatarAddresses.ContainsValue(avatarAddress))
            {
                Log.Error(
                    "The avatar {0} does not belong to the agent {1}.",
                    avatarAddress.ToHex(),
                    agentAddress.ToHex()
                    );

                return(false);
            }

            avatarState = states.GetAvatarState(avatarAddress);
            return(!(avatarState is null));
        }
Ejemplo n.º 3
0
        public static bool TryGetAgentAvatarStatesV2(
            this IAccountStateDelta states,
            Address agentAddress,
            Address avatarAddress,
            out AgentState agentState,
            out AvatarState avatarState
            )
        {
            avatarState = null;
            agentState  = states.GetAgentState(agentAddress);
            if (agentState is null)
            {
                return(false);
            }
            if (!agentState.avatarAddresses.ContainsValue(avatarAddress))
            {
                throw new AgentStateNotContainsAvatarAddressException(
                          $"The avatar {avatarAddress.ToHex()} does not belong to the agent {agentAddress.ToHex()}.");
            }

            try
            {
                avatarState = states.GetAvatarStateV2(avatarAddress);
            }
            catch (FailedLoadStateException)
            {
                // BackWardCompatible.
                avatarState = states.GetAvatarState(avatarAddress);
            }
            return(!(avatarState is null));
        }
Ejemplo n.º 4
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states            = context.PreviousStates;
            Address            collectionAddress = MonsterCollectionState0.DeriveAddress(context.Signer, collectRound);

            if (context.Rehearsal)
            {
                return(states
                       .SetState(collectionAddress, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, collectionAddress, context.Signer));
            }

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

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (!states.TryGetState(collectionAddress, out Dictionary stateDict))
            {
                throw new FailedLoadStateException($"Aborted as the monster collection state failed to load.");
            }

            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(stateDict);
            Currency               currency = states.GetGoldCurrency();
            FungibleAssetValue     balance  = 0 * currency;
            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();
            int currentLevel = monsterCollectionState.Level;

            if (currentLevel <= level || level <= 0)
            {
                throw new InvalidLevelException($"The level must be greater than 0 and less than {currentLevel}.");
            }

            if (monsterCollectionState.End)
            {
                throw new MonsterCollectionExpiredException($"{collectionAddress} has already expired on {monsterCollectionState.ExpiredBlockIndex}");
            }

            long rewardLevel = monsterCollectionState.GetRewardLevel(context.BlockIndex);
            MonsterCollectionRewardSheet monsterCollectionRewardSheet = states.GetSheet <MonsterCollectionRewardSheet>();

            monsterCollectionState.Update(level, rewardLevel, monsterCollectionRewardSheet);
            for (int i = currentLevel; i > level; i--)
            {
                balance += monsterCollectionSheet[i].RequiredGold * currency;
            }

            return(states
                   .SetState(collectionAddress, monsterCollectionState.Serialize())
                   .TransferAsset(collectionAddress, context.Signer, balance));
        }
Ejemplo n.º 5
0
        public void AddAndUnlockOption()
        {
            var agentState = _initialState.GetAgentState(_agentAddress);
            var subRecipe  = _tableSheets.EquipmentItemSubRecipeSheetV2.Last;

            Assert.NotNull(subRecipe);
            var equipment = (Necklace)ItemFactory.CreateItemUsable(
                _tableSheets.EquipmentItemSheet[10411000],
                Guid.NewGuid(),
                default);

            Assert.Equal(0, equipment.optionCountFromCombination);
            CombinationEquipment.AddAndUnlockOption(
                agentState,
                equipment,
                _random,
                subRecipe,
                _tableSheets.EquipmentItemOptionSheet,
                _tableSheets.SkillSheet
                );
            Assert.True(equipment.optionCountFromCombination > 0);
        }
Ejemplo n.º 6
0
        public static bool TryGetAgentAvatarStates(
            this IAccountStateDelta states,
            Address agentAddress,
            Address avatarAddress,
            out AgentState agentState,
            out AvatarState avatarState
            )
        {
            avatarState = null;
            agentState  = states.GetAgentState(agentAddress);
            if (agentState is null)
            {
                return(false);
            }
            if (!agentState.avatarAddresses.ContainsValue(avatarAddress))
            {
                throw new AgentStateNotContainsAvatarAddressException(
                          $"The avatar {avatarAddress.ToHex()} does not belong to the agent {agentAddress.ToHex()}.");
            }

            avatarState = states.GetAvatarState(avatarAddress);
            return(!(avatarState is null));
        }
        public void Execute(int rewardLevel, int prevRewardLevel, int collectionLevel)
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
            MonsterCollectionState0 monsterCollectionState         = new MonsterCollectionState0(collectionAddress, 1, 0, _tableSheets.MonsterCollectionRewardSheet);

            for (int i = 0; i < prevRewardLevel; i++)
            {
                int level = i + 1;
                MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), _avatarAddress, rewards);
                monsterCollectionState.UpdateRewardMap(level, result, i * MonsterCollectionState0.RewardInterval);
            }

            List <MonsterCollectionRewardSheet.RewardInfo> collectionRewards = _tableSheets.MonsterCollectionRewardSheet[collectionLevel].Rewards;

            monsterCollectionState.Update(collectionLevel, rewardLevel, _tableSheets.MonsterCollectionRewardSheet);
            for (long i = rewardLevel; i < 4; i++)
            {
                Assert.Equal(collectionRewards, monsterCollectionState.RewardLevelMap[i + 1]);
            }

            Dictionary <int, int> rewardExpectedMap = new Dictionary <int, int>();

            foreach (var(key, value) in monsterCollectionState.RewardLevelMap)
            {
                if (monsterCollectionState.RewardMap.ContainsKey(key) || key > rewardLevel)
                {
                    continue;
                }

                foreach (var info in value)
                {
                    if (rewardExpectedMap.ContainsKey(info.ItemId))
                    {
                        rewardExpectedMap[info.ItemId] += info.Quantity;
                    }
                    else
                    {
                        rewardExpectedMap[info.ItemId] = info.Quantity;
                    }
                }
            }

            AvatarState prevAvatarState = _state.GetAvatarState(_avatarAddress);

            Assert.Empty(prevAvatarState.mailBox);

            Currency currency        = _state.GetGoldCurrency();
            int      collectionRound = _state.GetAgentState(_signer).MonsterCollectionRound;

            _state = _state
                     .SetState(collectionAddress, monsterCollectionState.Serialize());

            FungibleAssetValue balance = 0 * currency;

            if (rewardLevel == 4)
            {
                foreach (var row in _tableSheets.MonsterCollectionSheet)
                {
                    if (row.Level <= collectionLevel)
                    {
                        balance += row.RequiredGold * currency;
                    }
                }

                collectionRound += 1;
                _state           = _state
                                   .MintAsset(collectionAddress, balance);
            }

            Assert.Equal(prevRewardLevel, monsterCollectionState.RewardLevel);
            Assert.Equal(0, _state.GetAgentState(_signer).MonsterCollectionRound);

            ClaimMonsterCollectionReward0 action = new ClaimMonsterCollectionReward0
            {
                avatarAddress   = _avatarAddress,
                collectionRound = 0,
            };

            IAccountStateDelta nextState = action.Execute(new ActionContext
            {
                PreviousStates = _state,
                Signer         = _signer,
                BlockIndex     = rewardLevel * MonsterCollectionState0.RewardInterval,
                Random         = new TestRandom(),
            });

            MonsterCollectionState0 nextMonsterCollectionState = new MonsterCollectionState0((Dictionary)nextState.GetState(collectionAddress));

            Assert.Equal(rewardLevel, nextMonsterCollectionState.RewardLevel);

            AvatarState nextAvatarState = nextState.GetAvatarState(_avatarAddress);

            foreach (var(itemId, qty) in rewardExpectedMap)
            {
                Assert.True(nextAvatarState.inventory.HasItem(itemId, qty));
            }

            Assert.Equal(rewardLevel - prevRewardLevel, nextAvatarState.mailBox.Count);
            Assert.All(nextAvatarState.mailBox, mail =>
            {
                Assert.IsType <MonsterCollectionMail>(mail);
                MonsterCollectionMail monsterCollectionMail = (MonsterCollectionMail)mail;
                Assert.IsType <MonsterCollectionResult>(monsterCollectionMail.attachment);
                MonsterCollectionResult result = (MonsterCollectionResult)monsterCollectionMail.attachment;
                Assert.Equal(result.id, mail.id);
            });

            for (int i = 0; i < nextMonsterCollectionState.RewardLevel; i++)
            {
                int level = i + 1;
                List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = _tableSheets.MonsterCollectionRewardSheet[collectionLevel].Rewards;
                Assert.Contains(level, nextMonsterCollectionState.RewardMap.Keys);
                Assert.Equal(_avatarAddress, nextMonsterCollectionState.RewardMap[level].avatarAddress);
            }

            Assert.Equal(0 * currency, nextState.GetBalance(collectionAddress, currency));
            Assert.Equal(balance, nextState.GetBalance(_signer, currency));
            Assert.Equal(collectionRound, nextState.GetAgentState(_signer).MonsterCollectionRound);
            Assert.Equal(nextMonsterCollectionState.End, rewardLevel == 4);
        }
Ejemplo n.º 8
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states = context.PreviousStates;
            Address            monsterCollectionAddress = MonsterCollectionState0.DeriveAddress(context.Signer, collectionRound);

            if (context.Rehearsal)
            {
                return(states
                       .SetState(monsterCollectionAddress, MarkChanged)
                       .SetState(context.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, monsterCollectionAddress));
            }

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

            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (agentState.MonsterCollectionRound != collectionRound)
            {
                throw new InvalidMonsterCollectionRoundException(
                          $"Expected collection round is {agentState.MonsterCollectionRound}, but actual collection round is {collectionRound}.");
            }

            if (!monsterCollectionSheet.TryGetValue(level, out MonsterCollectionSheet.Row _))
            {
                throw new SheetRowNotFoundException(nameof(MonsterCollectionSheet), level);
            }

            Currency currency = states.GetGoldCurrency();
            // Set default gold value.
            FungibleAssetValue requiredGold = currency * 0;
            FungibleAssetValue balance      = states.GetBalance(context.Signer, states.GetGoldCurrency());

            MonsterCollectionState0 monsterCollectionState;
            int currentLevel = 1;
            MonsterCollectionRewardSheet monsterCollectionRewardSheet = states.GetSheet <MonsterCollectionRewardSheet>();

            if (states.TryGetState(monsterCollectionAddress, out Dictionary stateDict))
            {
                monsterCollectionState = new MonsterCollectionState0(stateDict);

                if (monsterCollectionState.ExpiredBlockIndex < context.BlockIndex)
                {
                    throw new MonsterCollectionExpiredException(
                              $"{monsterCollectionAddress} has already expired on {monsterCollectionState.ExpiredBlockIndex}");
                }

                if (monsterCollectionState.Level >= level)
                {
                    throw new InvalidLevelException($"The level must be greater than {monsterCollectionState.Level}.");
                }

                currentLevel = monsterCollectionState.Level + 1;
                long rewardLevel = monsterCollectionState.GetRewardLevel(context.BlockIndex);
                monsterCollectionState.Update(level, rewardLevel, monsterCollectionRewardSheet);
            }
            else
            {
                monsterCollectionState = new MonsterCollectionState0(monsterCollectionAddress, level, context.BlockIndex, monsterCollectionRewardSheet);
            }

            for (int i = currentLevel; i < level + 1; i++)
            {
                requiredGold += currency * monsterCollectionSheet[i].RequiredGold;
            }

            if (balance < requiredGold)
            {
                throw new InsufficientBalanceException(context.Signer, requiredGold,
                                                       $"There is no sufficient balance for {context.Signer}: {balance} < {requiredGold}");
            }
            states = states.TransferAsset(context.Signer, monsterCollectionAddress, requiredGold);
            states = states.SetState(monsterCollectionAddress, monsterCollectionState.Serialize());
            return(states);
        }
Ejemplo n.º 9
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states = context.PreviousStates;

            if (context.Rehearsal)
            {
                return(states
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 0), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 1), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 2), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 3), MarkChanged)
                       .SetState(context.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 0))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 1))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 2))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 3)));
            }

            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (level < 0 || level > 0 && !monsterCollectionSheet.TryGetValue(level, out MonsterCollectionSheet.Row _))
            {
                throw new MonsterCollectionLevelException();
            }

            Currency currency = states.GetGoldCurrency();
            // Set default gold value.
            FungibleAssetValue requiredGold             = currency * 0;
            Address            monsterCollectionAddress = MonsterCollectionState.DeriveAddress(
                context.Signer,
                agentState.MonsterCollectionRound
                );

            if (states.TryGetState(monsterCollectionAddress, out Dictionary stateDict))
            {
                var existingStates = new MonsterCollectionState(stateDict);
                int previousLevel  = existingStates.Level;
                // Check collection level and required block index
                if (level < previousLevel && existingStates.IsLocked(context.BlockIndex))
                {
                    throw new RequiredBlockIndexException();
                }

                if (level == previousLevel)
                {
                    throw new MonsterCollectionLevelException();
                }

                if (existingStates.CalculateStep(context.BlockIndex) > 0)
                {
                    throw new MonsterCollectionExistingClaimableException();
                }

                // Refund holding NCG to user
                FungibleAssetValue gold = states.GetBalance(monsterCollectionAddress, currency);
                states = states.TransferAsset(monsterCollectionAddress, context.Signer, gold);
            }

            if (level == 0)
            {
                return(states.SetState(monsterCollectionAddress, new Null()));
            }

            FungibleAssetValue balance = states.GetBalance(context.Signer, currency);
            var monsterCollectionState = new MonsterCollectionState(monsterCollectionAddress, level, context.BlockIndex);

            for (int i = 0; i < level; i++)
            {
                requiredGold += currency * monsterCollectionSheet[i + 1].RequiredGold;
            }

            if (balance < requiredGold)
            {
                throw new InsufficientBalanceException(context.Signer, requiredGold,
                                                       $"There is no sufficient balance for {context.Signer}: {balance} < {requiredGold}");
            }
            states = states.TransferAsset(context.Signer, monsterCollectionAddress, requiredGold);
            states = states.SetState(monsterCollectionAddress, monsterCollectionState.Serialize());
            return(states);
        }