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); }
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())); }