Exemplo n.º 1
0
        public void Serialize()
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);
            Dictionary serialized = (Dictionary)monsterCollectionState.Serialize();

            Assert.Equal(serialized, new MonsterCollectionState0(serialized).Serialize());
        }
Exemplo n.º 2
0
        public void SerializeV2()
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000);
            Dictionary serialized = (Dictionary)monsterCollectionState.SerializeV2();

            Assert.Equal(serialized, new MonsterCollectionState0(serialized).SerializeV2());
        }
        public void Execute_Throw_RequiredBlockIndexException(long startedBlockIndex, long blockIndex)
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            MonsterCollectionState0 monsterCollectionState         = new MonsterCollectionState0(collectionAddress, 1, startedBlockIndex, _tableSheets.MonsterCollectionRewardSheet);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
            MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), _avatarAddress, rewards);

            monsterCollectionState.UpdateRewardMap(1, result, 0);

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

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

            Assert.Throws <RequiredBlockIndexException>(() => action.Execute(new ActionContext
            {
                PreviousStates = _state,
                Signer         = _signer,
                BlockIndex     = blockIndex,
            })
                                                        );
        }
Exemplo n.º 4
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]);
            }
        }
Exemplo n.º 5
0
        public void Execute_Throw_MonsterCollectionExpiredException()
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(collectionAddress, 2, 0, _tableSheets.MonsterCollectionRewardSheet);

            for (int i = 0; i < MonsterCollectionState0.RewardCapacity; i++)
            {
                MonsterCollectionResult monsterCollectionResult = new MonsterCollectionResult(Guid.NewGuid(), default, new List <MonsterCollectionRewardSheet.RewardInfo>());
Exemplo n.º 6
0
        public void UpdateRewardMap_Throw_ArgumentOutOfRangeException(long rewardLevel)
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);

            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
            MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), _address, rewards);

            Assert.Throws <ArgumentOutOfRangeException>(() => monsterCollectionState.UpdateRewardMap(rewardLevel, result, 0));
        }
Exemplo n.º 7
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));
        }
Exemplo n.º 8
0
        public void SerializeV2_DotNet_API()
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000);
            var formatter = new BinaryFormatter();

            using var ms = new MemoryStream();
            formatter.Serialize(ms, monsterCollectionState);
            ms.Seek(0, SeekOrigin.Begin);

            var deserialized = (MonsterCollectionState0)formatter.Deserialize(ms);

            Assert.Equal(monsterCollectionState.SerializeV2(), deserialized.SerializeV2());
        }
Exemplo n.º 9
0
        public void Execute(int prevLevel, int collectionLevel, long blockIndex)
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = _tableSheets.MonsterCollectionRewardSheet[prevLevel].Rewards;
            MonsterCollectionState0 monsterCollectionState             = new MonsterCollectionState0(collectionAddress, prevLevel, 0, _tableSheets.MonsterCollectionRewardSheet);
            Currency           currency = _state.GetGoldCurrency();
            FungibleAssetValue balance  = 0 * currency;

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

            Assert.All(monsterCollectionState.RewardLevelMap, kv => Assert.Equal(rewardInfos, kv.Value));

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

            CancelMonsterCollect action = new CancelMonsterCollect
            {
                collectRound = 0,
                level        = collectionLevel,
            };

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

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

            Assert.Equal(collectionLevel, nextMonsterCollectionState.Level);
            Assert.Equal(0 * currency, nextState.GetBalance(collectionAddress, currency));
            Assert.Equal(balance, nextState.GetBalance(_signer, currency));

            long rewardLevel = nextMonsterCollectionState.GetRewardLevel(blockIndex);
            List <MonsterCollectionRewardSheet.RewardInfo> nextRewardInfos = _tableSheets.MonsterCollectionRewardSheet[collectionLevel].Rewards;

            for (long i = rewardLevel; i < 4; i++)
            {
                Assert.Equal(nextRewardInfos, nextMonsterCollectionState.RewardLevelMap[i + 1]);
            }
        }
Exemplo n.º 10
0
        public void UpdateRewardMap()
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);

            Assert.Empty(monsterCollectionState.RewardMap);

            Address avatarAddress = default;
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
            MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), avatarAddress, rewards);

            monsterCollectionState.UpdateRewardMap(1, result, 14000);
            Assert.Single(monsterCollectionState.RewardMap);
            Assert.Equal(result, monsterCollectionState.RewardMap[1]);
            Assert.Equal(14000, monsterCollectionState.ReceivedBlockIndex);
            Assert.Equal(1, monsterCollectionState.RewardLevel);
        }
Exemplo n.º 11
0
        public void Update(long rewardLevel)
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);

            Assert.Equal(1, monsterCollectionState.Level);
            Assert.Equal(10000, monsterCollectionState.StartedBlockIndex);
            Assert.Equal(MonsterCollectionState0.RewardInterval * 4 + 10000, monsterCollectionState.ExpiredBlockIndex);

            monsterCollectionState.Update(2, rewardLevel, _tableSheets.MonsterCollectionRewardSheet);
            Assert.Equal(2, monsterCollectionState.Level);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[2].Rewards;

            for (long i = rewardLevel; i < 4; i++)
            {
                Assert.Equal(rewards, monsterCollectionState.RewardLevelMap[i + 1]);
            }
        }
Exemplo n.º 12
0
        public void Execute_Throw_InvalidLevelException(int prevLevel, int level)
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            MonsterCollectionState0 prevMonsterCollectionState = new MonsterCollectionState0(collectionAddress, prevLevel, 0, _tableSheets.MonsterCollectionRewardSheet);

            _initialState = _initialState.SetState(collectionAddress, prevMonsterCollectionState.Serialize());

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

            Assert.Throws <InvalidLevelException>(() => action.Execute(new ActionContext
            {
                PreviousStates = _initialState,
                Signer         = _signer,
                BlockIndex     = 1,
            }));
        }
        public void Execute_Throw_InsufficientBalanceException()
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(collectionAddress, 1, 0, _tableSheets.MonsterCollectionRewardSheet);

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

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

            Assert.Throws <InsufficientBalanceException>(() => action.Execute(new ActionContext
            {
                PreviousStates = _state,
                Signer         = _signer,
                BlockIndex     = MonsterCollectionState0.ExpirationIndex,
                Random         = new TestRandom(),
            })
                                                         );
        }
Exemplo n.º 14
0
        public void Execute_Throw_MonsterCollectionExpiredException()
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            MonsterCollectionState0 prevMonsterCollectionState = new MonsterCollectionState0(collectionAddress, 1, 0, _tableSheets.MonsterCollectionRewardSheet);

            Assert.Equal(MonsterCollectionState0.ExpirationIndex, prevMonsterCollectionState.ExpiredBlockIndex);

            _initialState = _initialState.SetState(collectionAddress, prevMonsterCollectionState.Serialize());

            MonsterCollect0 action = new MonsterCollect0
            {
                level           = 2,
                collectionRound = 0,
            };

            Assert.Throws <MonsterCollectionExpiredException>(() => action.Execute(new ActionContext
            {
                PreviousStates = _initialState,
                Signer         = _signer,
                BlockIndex     = prevMonsterCollectionState.ExpiredBlockIndex + 1,
            }));
        }
Exemplo n.º 15
0
        public void Rehearsal()
        {
            Address         collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 1);
            MonsterCollect0 action            = new MonsterCollect0
            {
                level           = 1,
                collectionRound = 1,
            };
            IAccountStateDelta nextState = action.Execute(new ActionContext
            {
                PreviousStates = new State(),
                Signer         = _signer,
                Rehearsal      = true,
            });

            List <Address> updatedAddresses = new List <Address>()
            {
                _signer,
                collectionAddress,
            };

            Assert.Equal(updatedAddresses.ToImmutableHashSet(), nextState.UpdatedAddresses);
        }
        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);
        }
Exemplo n.º 17
0
 public void UpdateRewardMap_Throw_AlreadyReceivedException()
 {
     MonsterCollectionState0 monsterCollectionState         = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);
     List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
     MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), default, rewards);
Exemplo n.º 18
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);
        }
Exemplo n.º 19
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states            = context.PreviousStates;
            Address            collectionAddress = MonsterCollectionState0.DeriveAddress(context.Signer, collectionRound);

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

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

            if (!states.TryGetAgentAvatarStates(context.Signer, avatarAddress, out AgentState agentState, out AvatarState avatarState))
            {
                throw new FailedLoadStateException($"Aborted as the avatar state of the signer 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);

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

            if (!monsterCollectionState.CanReceive(context.BlockIndex))
            {
                throw new RequiredBlockIndexException(
                          $"{collectionAddress} is not available yet; it will be available after {Math.Max(monsterCollectionState.StartedBlockIndex, monsterCollectionState.ReceivedBlockIndex) + MonsterCollectionState0.RewardInterval}");
            }

            long      rewardLevel = monsterCollectionState.GetRewardLevel(context.BlockIndex);
            ItemSheet itemSheet   = states.GetItemSheet();

            for (int i = 0; i < rewardLevel; i++)
            {
                int level = i + 1;
                if (level <= monsterCollectionState.RewardLevel)
                {
                    continue;
                }

                List <MonsterCollectionRewardSheet.RewardInfo> rewards = monsterCollectionState.RewardLevelMap[level];
                Guid id = context.Random.GenerateRandomGuid();
                MonsterCollectionResult result = new MonsterCollectionResult(id, avatarAddress, rewards);
                MonsterCollectionMail   mail   = new MonsterCollectionMail(result, context.BlockIndex, id, context.BlockIndex);
                avatarState.Update(mail);
                foreach (var rewardInfo in rewards)
                {
                    var row  = itemSheet[rewardInfo.ItemId];
                    var item = row is MaterialItemSheet.Row materialRow
                        ? ItemFactory.CreateTradableMaterial(materialRow)
                        : ItemFactory.CreateItem(row, context.Random);
                    avatarState.inventory.AddItem2(item, rewardInfo.Quantity);
                }
                monsterCollectionState.UpdateRewardMap(level, result, context.BlockIndex);
            }

            // Return gold at the end of monster collect.
            if (rewardLevel == 4)
            {
                MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();
                Currency currency = states.GetGoldCurrency();
                // Set default gold value.
                FungibleAssetValue gold = currency * 0;
                for (int i = 0; i < monsterCollectionState.Level; i++)
                {
                    int level = i + 1;
                    gold += currency * monsterCollectionSheet[level].RequiredGold;
                }
                agentState.IncreaseCollectionRound();
                states = states.SetState(context.Signer, agentState.Serialize());
                if (gold > currency * 0)
                {
                    states = states.TransferAsset(collectionAddress, context.Signer, gold);
                }
            }

            return(states
                   .SetState(avatarAddress, avatarState.Serialize())
                   .SetState(collectionAddress, monsterCollectionState.Serialize()));
        }