Exemple #1
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IActionContext ctx    = context;
            var            states = ctx.PreviousStates;

            if (ctx.Rehearsal)
            {
                return(states.SetState(ctx.Signer, MarkChanged)
                       .SetState(AvatarAddress, MarkChanged)
                       .SetState(WeeklyArenaAddress, MarkChanged)
                       .SetState(ctx.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, ctx.Signer, WeeklyArenaAddress));
            }

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

            var addressesHex = GetSignerAndOtherAddressesHex(context, AvatarAddress, EnemyAddress);

            var sw = new Stopwatch();

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

            Log.Verbose(
                "{AddressesHex}RankingBattle exec started. costume: ({CostumeIds}), equipment: ({EquipmentIds})",
                addressesHex,
                string.Join(",", costumeIds),
                string.Join(",", equipmentIds)
                );

            if (AvatarAddress.Equals(EnemyAddress))
            {
                throw new InvalidAddressException($"{addressesHex}Aborted as the signer tried to battle for themselves.");
            }

            if (!states.TryGetAvatarState(ctx.Signer, AvatarAddress, out var avatarState))
            {
                throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the signer was failed to load.");
            }

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Get AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            avatarState.ValidateEquipments(equipmentIds, context.BlockIndex);
            avatarState.ValidateConsumable(consumableIds, context.BlockIndex);

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Validate Equipments: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            if (!avatarState.worldInformation.TryGetUnlockedWorldByStageClearedBlockIndex(out var world) ||
                world.StageClearedId < GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)
            {
                throw new NotEnoughClearedStageLevelException(
                          addressesHex,
                          GameConfig.RequireClearedStageLevel.ActionsInRankingBoard,
                          world.StageClearedId);
            }

            avatarState.EquipCostumes(new HashSet <int>(costumeIds));
            avatarState.EquipEquipments(equipmentIds);
            avatarState.ValidateCostume(new HashSet <int>(costumeIds));

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Equip Equipments: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            var enemyAvatarState = states.GetAvatarState(EnemyAddress);

            if (enemyAvatarState is null)
            {
                throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the opponent ({EnemyAddress}) was failed to load.");
            }

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Get Enemy AvatarState: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            var weeklyArenaState = states.GetWeeklyArenaState(WeeklyArenaAddress);

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Get WeeklyArenaState ({Address}): {Elapsed}", addressesHex, WeeklyArenaAddress, sw.Elapsed);
            sw.Restart();

            if (weeklyArenaState.Ended)
            {
                throw new WeeklyArenaStateAlreadyEndedException(
                          addressesHex + WeeklyArenaStateAlreadyEndedException.BaseMessage);
            }

            if (!weeklyArenaState.ContainsKey(AvatarAddress))
            {
                throw new WeeklyArenaStateNotContainsAvatarAddressException(addressesHex, AvatarAddress);
            }

            var arenaInfo = weeklyArenaState[AvatarAddress];

            if (arenaInfo.DailyChallengeCount <= 0)
            {
                throw new NotEnoughWeeklyArenaChallengeCountException(
                          addressesHex + NotEnoughWeeklyArenaChallengeCountException.BaseMessage);
            }

            if (!arenaInfo.Active)
            {
                arenaInfo.Activate();
            }

            if (!weeklyArenaState.ContainsKey(EnemyAddress))
            {
                throw new WeeklyArenaStateNotContainsAvatarAddressException(addressesHex, EnemyAddress);
            }

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Validate ArenaInfo: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            var costumeStatSheet = states.GetSheet <CostumeStatSheet>();

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Get CostumeStatSheet: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            var simulator = new RankingSimulator(
                ctx.Random,
                avatarState,
                enemyAvatarState,
                consumableIds,
                states.GetRankingSimulatorSheets(),
                StageId,
                arenaInfo,
                weeklyArenaState[EnemyAddress],
                costumeStatSheet);

            simulator.SimulateV1();

            sw.Stop();
            Log.Verbose(
                "{AddressesHex}RankingBattle Simulate() with equipment:({Equipment}), costume:({Costume}): {Elapsed}",
                addressesHex,
                string.Join(",", simulator.Player.Equipments.Select(r => r.ItemId)),
                string.Join(",", simulator.Player.Costumes.Select(r => r.ItemId)),
                sw.Elapsed
                );

            Log.Verbose(
                "{AddressesHex}Execute RankingBattle({AvatarAddress}); result: {Result} event count: {EventCount}",
                addressesHex,
                AvatarAddress,
                simulator.Log.result,
                simulator.Log.Count
                );
            sw.Restart();

            Result = simulator.Log;

            foreach (var itemBase in simulator.Reward.OrderBy(i => i.Id))
            {
                Log.Verbose(
                    "{AddressesHex}RankingBattle Add Reward Item({ItemBaseId}): {Elapsed}",
                    addressesHex,
                    itemBase.Id,
                    sw.Elapsed);
                avatarState.inventory.AddItem2(itemBase);
            }

            states = states.SetState(WeeklyArenaAddress, weeklyArenaState.Serialize());

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Serialize WeeklyArenaState: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            states = states.SetState(AvatarAddress, avatarState.Serialize());

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Serialize AvatarState: {Elapsed}", addressesHex, sw.Elapsed);
            sw.Restart();

            var ended = DateTimeOffset.UtcNow;

            Log.Verbose("{AddressesHex}RankingBattle Total Executed Time: {Elapsed}", addressesHex, ended - started);
            return(states);
        }
Exemple #2
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IActionContext ctx    = context;
            var            states = ctx.PreviousStates;

            if (ctx.Rehearsal)
            {
                return(states.SetState(ctx.Signer, MarkChanged)
                       .SetState(AvatarAddress, MarkChanged)
                       .SetState(WeeklyArenaAddress, MarkChanged)
                       .SetState(ctx.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, ctx.Signer, WeeklyArenaAddress));
            }

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

            var addressesHex = GetSignerAndOtherAddressesHex(context, AvatarAddress, EnemyAddress);

            Log.Warning("ranking_battle is deprecated. Please use ranking_battle2");
            if (AvatarAddress.Equals(EnemyAddress))
            {
                throw new InvalidAddressException($"{addressesHex}Aborted as the signer tried to battle for themselves.");
            }

            if (!states.TryGetAgentAvatarStates(
                    ctx.Signer,
                    AvatarAddress,
                    out var agentState,
                    out var avatarState))
            {
                throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the signer was failed to load.");
            }

            var costumes = new HashSet <int>(costumeIds);

            avatarState.ValidateEquipments(equipmentIds, context.BlockIndex);
            avatarState.ValidateConsumable(consumableIds, context.BlockIndex);
            avatarState.ValidateCostume(costumes);

            if (!avatarState.worldInformation.TryGetUnlockedWorldByStageClearedBlockIndex(out var world) ||
                world.StageClearedId < GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)
            {
                throw new NotEnoughClearedStageLevelException(
                          addressesHex,
                          GameConfig.RequireClearedStageLevel.ActionsInRankingBoard,
                          world.StageClearedId);
            }

            avatarState.EquipCostumes(costumes);
            avatarState.EquipEquipments(equipmentIds);

            var enemyAvatarState = states.GetAvatarState(EnemyAddress);

            if (enemyAvatarState is null)
            {
                throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the opponent ({EnemyAddress}) was failed to load.");
            }

            var weeklyArenaState = states.GetWeeklyArenaState(WeeklyArenaAddress);

            if (weeklyArenaState.Ended)
            {
                throw new WeeklyArenaStateAlreadyEndedException(
                          addressesHex + WeeklyArenaStateAlreadyEndedException.BaseMessage);
            }

            if (!weeklyArenaState.ContainsKey(AvatarAddress))
            {
                throw new WeeklyArenaStateNotContainsAvatarAddressException(addressesHex, AvatarAddress);
            }

            var arenaInfo = weeklyArenaState[AvatarAddress];

            if (arenaInfo.DailyChallengeCount <= 0)
            {
                throw new NotEnoughWeeklyArenaChallengeCountException(
                          addressesHex + NotEnoughWeeklyArenaChallengeCountException.BaseMessage);
            }

            if (!arenaInfo.Active)
            {
                FungibleAssetValue agentBalance = default;
                try
                {
                    agentBalance = states.GetBalance(ctx.Signer, states.GetGoldCurrency());
                }
                catch (InvalidOperationException)
                {
                    throw new NotEnoughFungibleAssetValueException(addressesHex, EntranceFee, agentBalance);
                }

                if (agentBalance >= new FungibleAssetValue(agentBalance.Currency, EntranceFee, 0))
                {
                    states = states.TransferAsset(
                        ctx.Signer,
                        WeeklyArenaAddress,
                        new FungibleAssetValue(
                            states.GetGoldCurrency(),
                            EntranceFee,
                            0
                            )
                        );
                    arenaInfo.Activate();
                }
                else
                {
                    throw new NotEnoughFungibleAssetValueException(addressesHex, EntranceFee, agentBalance);
                }
            }

            if (!weeklyArenaState.ContainsKey(EnemyAddress))
            {
                throw new WeeklyArenaStateNotContainsAvatarAddressException(addressesHex, EnemyAddress);
            }

            Log.Verbose("{WeeklyArenaStateAddress}", weeklyArenaState.address.ToHex());

            var simulator = new RankingSimulator(
                ctx.Random,
                avatarState,
                enemyAvatarState,
                consumableIds,
                states.GetRankingSimulatorSheets(),
                StageId,
                arenaInfo,
                weeklyArenaState[EnemyAddress]);

            simulator.SimulateV1();

            Result = simulator.Log;

            foreach (var itemBase in simulator.Reward.OrderBy(i => i.Id))
            {
                avatarState.inventory.AddItem2(itemBase);
            }

            return(states
                   .SetState(ctx.Signer, agentState.Serialize())
                   .SetState(WeeklyArenaAddress, weeklyArenaState.Serialize())
                   .SetState(AvatarAddress, avatarState.Serialize()));
        }