public IAccountStateDelta WeeklyArenaRankingBoard(IActionContext ctx, IAccountStateDelta states) { var index = Math.Max((int)ctx.BlockIndex / GameConfig.WeeklyArenaInterval, 0); var weekly = states.GetWeeklyArenaState(index); var nextIndex = index + 1; var nextWeekly = states.GetWeeklyArenaState(nextIndex); if (nextWeekly is null) { nextWeekly = new WeeklyArenaState(nextIndex); states = states.SetState(nextWeekly.address, nextWeekly.Serialize()); } if (ctx.BlockIndex % GameConfig.WeeklyArenaInterval == 0 && index > 0) { var prevWeekly = states.GetWeeklyArenaState(index - 1); if (!prevWeekly.Ended) { prevWeekly.End(); weekly.Update(prevWeekly, ctx.BlockIndex); states = states.SetState(prevWeekly.address, prevWeekly.Serialize()); states = states.SetState(weekly.address, weekly.Serialize()); } } else if (ctx.BlockIndex - weekly.ResetIndex >= GameConfig.DailyArenaInterval) { weekly.ResetCount(ctx.BlockIndex); states = states.SetState(weekly.address, weekly.Serialize()); } return(states); }
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()); } }
public void Serialize() { var address = default(Address); var state = new WeeklyArenaState(address); var serialized = (Dictionary)state.Serialize(); var deserialized = new WeeklyArenaState(serialized); Assert.Equal(state.address, deserialized.address); }
public RankingBattleTest(ITestOutputHelper outputHelper) { _initialState = new State(); var sheets = TableSheetsImporter.ImportSheets(); foreach (var(key, value) in sheets) { _initialState = _initialState.SetState( Addresses.TableSheet.Derive(key), value.Serialize()); } _tableSheets = new TableSheets(sheets); var rankingMapAddress = new PrivateKey().ToAddress(); var(agent1State, avatar1State) = GetAgentStateWithAvatarState( sheets, _tableSheets, rankingMapAddress); _agent1Address = agent1State.address; _avatar1Address = avatar1State.address; var(agent2State, avatar2State) = GetAgentStateWithAvatarState( sheets, _tableSheets, rankingMapAddress); var agent2Address = agent2State.address; _avatar2Address = avatar2State.address; var weeklyArenaState = new WeeklyArenaState(ArenaIndex); weeklyArenaState.SetV2(avatar1State, _tableSheets.CharacterSheet, _tableSheets.CostumeStatSheet); weeklyArenaState[_avatar1Address].Activate(); weeklyArenaState.SetV2(avatar2State, _tableSheets.CharacterSheet, _tableSheets.CostumeStatSheet); weeklyArenaState[_avatar2Address].Activate(); _weeklyArenaAddress = weeklyArenaState.address; _initialState = _initialState .SetState(_agent1Address, agent1State.Serialize()) .SetState(_avatar1Address, avatar1State.Serialize()) .SetState(agent2Address, agent2State.Serialize()) .SetState(_avatar2Address, avatar2State.Serialize()) .SetState(Addresses.GameConfig, new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize()) .SetState(_weeklyArenaAddress, weeklyArenaState.Serialize()); Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .WriteTo.TestOutput(outputHelper) .CreateLogger(); }
public void ExecuteCreateNextWeeklyArenaState() { var weekly = new WeeklyArenaState(0); var state = _baseState .SetState(weekly.address, weekly.Serialize()); var action = new RewardGold(); var nextState = action.Execute(new ActionContext() { PreviousStates = state, Miner = default,
public void WeeklyArenaRankingBoard(bool resetCount, bool updateNext) { var weekly = new WeeklyArenaState(0); weekly.Set(_avatarState, _tableSheets.CharacterSheet); weekly[_avatarState.address].Update(weekly[_avatarState.address], BattleLog.Result.Lose); var gameConfigState = new GameConfigState(); gameConfigState.Set(_tableSheets.GameConfigSheet); var state = _baseState .SetState(weekly.address, weekly.Serialize()) .SetState(gameConfigState.address, gameConfigState.Serialize()); var blockIndex = 0; if (resetCount) { blockIndex = gameConfigState.DailyArenaInterval; } if (updateNext) { weekly[_avatarState.address].Activate(); blockIndex = gameConfigState.WeeklyArenaInterval; // Avoid NRE in test case. var nextWeekly = new WeeklyArenaState(1); state = state .SetState(weekly.address, weekly.Serialize()) .SetState(nextWeekly.address, nextWeekly.Serialize()); } Assert.False(weekly.Ended); Assert.Equal(4, weekly[_avatarState.address].DailyChallengeCount); var action = new RewardGold(); var ctx = new ActionContext() { BlockIndex = blockIndex, PreviousStates = _baseState, Miner = default,
public RankingBattle4Test() { _initialState = new State(); var sheets = TableSheetsImporter.ImportSheets(); foreach (var(key, value) in sheets) { _initialState = _initialState.SetState( Addresses.TableSheet.Derive(key), value.Serialize()); } _tableSheets = new TableSheets(sheets); var rankingMapAddress = new PrivateKey().ToAddress(); var(agent1State, avatar1State) = GetAgentStateWithAvatarState( sheets, _tableSheets, rankingMapAddress); _agent1Address = agent1State.address; _avatar1Address = avatar1State.address; var(agent2State, avatar2State) = GetAgentStateWithAvatarState( sheets, _tableSheets, rankingMapAddress); var agent2Address = agent2State.address; _avatar2Address = avatar2State.address; var weeklyArenaState = new WeeklyArenaState(0); weeklyArenaState.Set(avatar1State, _tableSheets.CharacterSheet); weeklyArenaState[_avatar1Address].Activate(); weeklyArenaState.Set(avatar2State, _tableSheets.CharacterSheet); weeklyArenaState[_avatar2Address].Activate(); _weeklyArenaAddress = weeklyArenaState.address; _initialState = _initialState .SetState(_agent1Address, agent1State.Serialize()) .SetState(_avatar1Address, avatar1State.Serialize()) .SetState(agent2Address, agent2State.Serialize()) .SetState(_avatar2Address, avatar2State.Serialize()) .SetState(_weeklyArenaAddress, weeklyArenaState.Serialize()); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { return(states.SetState(ctx.Miner, MarkChanged)); } var index = Math.Max((int)ctx.BlockIndex / GameConfig.WeeklyArenaInterval, 0); var weekly = states.GetWeeklyArenaState(index); var nextIndex = index + 1; var nextWeekly = states.GetWeeklyArenaState(nextIndex); if (nextWeekly is null) { nextWeekly = new WeeklyArenaState(nextIndex); states = states.SetState(nextWeekly.address, nextWeekly.Serialize()); } if (ctx.BlockIndex % GameConfig.WeeklyArenaInterval == 0 && index > 0) { var prevWeekly = states.GetWeeklyArenaState(index - 1); if (!prevWeekly.Ended) { prevWeekly.End(); weekly.Update(prevWeekly, ctx.BlockIndex); states = states.SetState(prevWeekly.address, prevWeekly.Serialize()); states = states.SetState(weekly.address, weekly.Serialize()); } } else if (ctx.BlockIndex - weekly.ResetIndex >= GameConfig.DailyArenaInterval) { weekly.ResetCount(ctx.BlockIndex); states = states.SetState(weekly.address, weekly.Serialize()); } return(states.TransferAsset( GoldCurrencyState.Address, ctx.Miner, states.GetGoldCurrency(), Gold )); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { return(states.SetState(ArenaAddress, MarkChanged)); } if (!(states.GetState(ArenaAddress) is null)) { return(states); } var arenaState = new WeeklyArenaState(ArenaAddress); return(states.SetState(ArenaAddress, arenaState.Serialize())); }
public MimisbrunnrBattle2Test() { var sheets = TableSheetsImporter.ImportSheets(); _tableSheets = new TableSheets(sheets); var privateKey = new PrivateKey(); _agentAddress = privateKey.PublicKey.ToAddress(); var agentState = new AgentState(_agentAddress); _avatarAddress = _agentAddress.Derive("avatar"); _rankingMapAddress = _avatarAddress.Derive("ranking_map"); var avatarState = new AvatarState( _avatarAddress, _agentAddress, 0, _tableSheets.GetAvatarSheets(), new GameConfigState(sheets[nameof(GameConfigSheet)]), _rankingMapAddress ) { level = 400, }; agentState.avatarAddresses.Add(0, _avatarAddress); _weeklyArenaState = new WeeklyArenaState(0); _initialState = new State() .SetState(_weeklyArenaState.address, _weeklyArenaState.Serialize()) .SetState(_agentAddress, agentState.Serialize()) .SetState(_avatarAddress, avatarState.Serialize()) .SetState(_rankingMapAddress, new RankingMapState(_rankingMapAddress).Serialize()); foreach (var(key, value) in sheets) { _initialState = _initialState .SetState(Addresses.TableSheet.Derive(key), value.Serialize()); } }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; var weeklyArenaState = new WeeklyArenaState(0); if (ctx.Rehearsal) { states = states.SetState(RankingState.Address, MarkChanged); states = states.SetState(ShopState.Address, MarkChanged); states = states.SetState(TableSheetsState.Address, MarkChanged); states = states.SetState(weeklyArenaState.address, MarkChanged); states = states.SetState(GameConfigState.Address, MarkChanged); states = states.SetState(RedeemCodeState.Address, MarkChanged); states = states.SetState(AdminState.Address, MarkChanged); states = states.SetState(ActivatedAccountsState.Address, MarkChanged); states = states.SetState(GoldCurrencyState.Address, MarkChanged); states = states.SetState(Addresses.GoldDistribution, MarkChanged); return(states); } if (ctx.BlockIndex != 0) { return(states); } states = states .SetState(weeklyArenaState.address, weeklyArenaState.Serialize()) .SetState(RankingState.Address, RankingState.Serialize()) .SetState(ShopState.Address, ShopState.Serialize()) .SetState(TableSheetsState.Address, TableSheetsState.Serialize()) .SetState(GameConfigState.Address, GameConfigState.Serialize()) .SetState(RedeemCodeState.Address, RedeemCodeState.Serialize()) .SetState(AdminState.Address, AdminAddressState.Serialize()) .SetState(ActivatedAccountsState.Address, ActivatedAccountsState.Serialize()) .SetState(GoldCurrencyState.Address, GoldCurrencyState.Serialize()) .SetState(Addresses.GoldDistribution, GoldDistributions.Select(v => v.Serialize()).Serialize()); states = states.MintAsset(GoldCurrencyState.Address, GoldCurrencyState.Currency, 1000000000); return(states); }
public IAccountStateDelta ResetChallengeCount(IActionContext ctx, IAccountStateDelta states) { var gameConfigState = states.GetGameConfigState(); var index = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0); var weeklyAddress = WeeklyArenaState.DeriveAddress(index); var rawWeekly = (Dictionary)states.GetState(weeklyAddress); var resetIndex = rawWeekly["resetIndex"].ToLong(); if (ctx.BlockIndex - resetIndex >= gameConfigState.DailyArenaInterval) { var weekly = new WeeklyArenaState(rawWeekly); if (resetIndex >= RankingBattle.UpdateTargetBlockIndex) { // Reset count each ArenaInfo. weekly.ResetIndex = ctx.BlockIndex; var listAddress = weeklyAddress.Derive("address_list"); if (states.TryGetState(listAddress, out List rawList)) { var addressList = rawList.ToList(StateExtensions.ToAddress); foreach (var address in addressList) { var infoAddress = weeklyAddress.Derive(address.ToByteArray()); if (states.TryGetState(infoAddress, out Dictionary rawInfo)) { var info = new ArenaInfo(rawInfo); info.ResetCount(); states = states.SetState(infoAddress, info.Serialize()); } } } } else { // Run legacy ResetCount. weekly.ResetCount(ctx.BlockIndex); } states = states.SetState(weeklyAddress, weekly.Serialize()); } return(states); }
public IAccountStateDelta WeeklyArenaRankingBoard2(IActionContext ctx, IAccountStateDelta states) { var gameConfigState = states.GetGameConfigState(); var index = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0); var weeklyAddress = WeeklyArenaState.DeriveAddress(index); var rawWeekly = (Dictionary)states.GetState(weeklyAddress); var nextIndex = index + 1; var nextWeekly = states.GetWeeklyArenaState(nextIndex); if (nextWeekly is null) { nextWeekly = new WeeklyArenaState(nextIndex); states = states.SetState(nextWeekly.address, nextWeekly.Serialize()); } var resetIndex = rawWeekly["resetIndex"].ToLong(); // Beginning block of a new weekly arena. if (ctx.BlockIndex % gameConfigState.WeeklyArenaInterval == 0 && index > 0) { var prevWeeklyAddress = WeeklyArenaState.DeriveAddress(index - 1); var rawPrevWeekly = (Dictionary)states.GetState(prevWeeklyAddress); if (!rawPrevWeekly["ended"].ToBoolean()) { rawPrevWeekly = rawPrevWeekly.SetItem("ended", true.Serialize()); var weekly = new WeeklyArenaState(rawWeekly); var prevWeekly = new WeeklyArenaState(rawPrevWeekly); weekly.Update(prevWeekly, ctx.BlockIndex); states = states.SetState(prevWeeklyAddress, rawPrevWeekly); states = states.SetState(weeklyAddress, weekly.Serialize()); } } else if (ctx.BlockIndex - resetIndex >= gameConfigState.DailyArenaInterval) { var weekly = new WeeklyArenaState(rawWeekly); weekly.ResetCount(ctx.BlockIndex); states = states.SetState(weeklyAddress, weekly.Serialize()); } return(states); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; var inventoryAddress = avatarAddress.Derive(LegacyInventoryKey); var worldInformationAddress = avatarAddress.Derive(LegacyWorldInformationKey); var questListAddress = avatarAddress.Derive(LegacyQuestListKey); if (ctx.Rehearsal) { states = states.SetState(RankingMapAddress, MarkChanged); states = states.SetState(avatarAddress, MarkChanged); states = states.SetState(WeeklyArenaAddress, MarkChanged); states = states .SetState(inventoryAddress, MarkChanged) .SetState(worldInformationAddress, MarkChanged) .SetState(questListAddress, MarkChanged); return(states.SetState(ctx.Signer, MarkChanged)); } CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context); var addressesHex = GetSignerAndOtherAddressesHex(context, avatarAddress); var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}HAS exec started", addressesHex); if (!states.TryGetAvatarStateV2(ctx.Signer, avatarAddress, out AvatarState avatarState)) { throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the signer was failed to load."); } sw.Stop(); Log.Verbose("{AddressesHex}HAS Get AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (avatarState.RankingMapAddress != RankingMapAddress) { throw new InvalidAddressException($"{addressesHex}Invalid ranking map address"); } // worldId와 stageId가 유효한지 확인합니다. var worldSheet = states.GetSheet <WorldSheet>(); if (!worldSheet.TryGetValue(worldId, out var worldRow, false)) { throw new SheetRowNotFoundException(addressesHex, nameof(WorldSheet), worldId); } if (stageId < worldRow.StageBegin || stageId > worldRow.StageEnd) { throw new SheetRowColumnException( $"{addressesHex}{worldId} world is not contains {worldRow.Id} stage: " + $"{worldRow.StageBegin}-{worldRow.StageEnd}"); } var stageSheet = states.GetSheet <StageSheet>(); if (!stageSheet.TryGetValue(stageId, out var stageRow)) { throw new SheetRowNotFoundException(addressesHex, nameof(StageSheet), stageId); } var worldInformation = avatarState.worldInformation; if (!worldInformation.TryGetWorld(worldId, out var world)) { // NOTE: Add new World from WorldSheet worldInformation.AddAndUnlockNewWorld(worldRow, ctx.BlockIndex, worldSheet); } if (!world.IsUnlocked) { throw new InvalidWorldException($"{addressesHex}{worldId} is locked."); } if (world.StageBegin != worldRow.StageBegin || world.StageEnd != worldRow.StageEnd) { worldInformation.UpdateWorld(worldRow); } if (world.IsStageCleared && stageId > world.StageClearedId + 1 || !world.IsStageCleared && stageId != world.StageBegin) { throw new InvalidStageException( $"{addressesHex}Aborted as the stage ({worldId}/{stageId}) is not cleared; " + $"cleared stage: {world.StageClearedId}" ); } avatarState.ValidateEquipmentsV2(equipments, context.BlockIndex); avatarState.ValidateConsumable(foods, context.BlockIndex); avatarState.ValidateCostume(costumes); var costumeStatSheet = states.GetSheet <CostumeStatSheet>(); sw.Restart(); if (avatarState.actionPoint < stageRow.CostAP) { throw new NotEnoughActionPointException( $"{addressesHex}Aborted due to insufficient action point: " + $"{avatarState.actionPoint} < {stageRow.CostAP}" ); } avatarState.actionPoint -= stageRow.CostAP; var items = equipments.Concat(costumes); avatarState.EquipItems(items); sw.Stop(); Log.Verbose("{AddressesHex}HAS Unequip items: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); // Update QuestList only when QuestSheet.Count is greater than QuestList.Count var questList = avatarState.questList; var questSheet = states.GetQuestSheet(); if (questList.Count() < questSheet.Count) { questList.UpdateList( 2, questSheet, states.GetSheet <QuestRewardSheet>(), states.GetSheet <QuestItemRewardSheet>(), states.GetSheet <EquipmentItemRecipeSheet>()); } sw.Stop(); Log.Verbose("{AddressesHex}HAS Update QuestList: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var characterSheet = states.GetSheet <CharacterSheet>(); var simulator = new StageSimulator( ctx.Random, avatarState, foods, worldId, stageId, states.GetStageSimulatorSheets(), costumeStatSheet, StageSimulator.ConstructorVersionV100025); sw.Stop(); Log.Verbose("{AddressesHex}HAS Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); simulator.Simulate4(); sw.Stop(); Log.Verbose("{AddressesHex}HAS Simulator.SimulateV2(): {Elapsed}", addressesHex, sw.Elapsed); Log.Verbose( "{AddressesHex}Execute HackAndSlash({AvatarAddress}); worldId: {WorldId}, stageId: {StageId}, result: {Result}, " + "clearWave: {ClearWave}, totalWave: {TotalWave}", addressesHex, avatarAddress, worldId, stageId, simulator.Log.result, simulator.Log.clearedWaveNumber, simulator.Log.waveCount ); sw.Restart(); if (simulator.Log.IsClear) { var worldUnlockSheet = states.GetSheet <WorldUnlockSheet>(); simulator.Player.worldInformation.ClearStage( worldId, stageId, ctx.BlockIndex, worldSheet, worldUnlockSheet ); } sw.Stop(); Log.Verbose("{AddressesHex}HAS ClearStage: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); avatarState.Update(simulator); var materialSheet = states.GetSheet <MaterialItemSheet>(); avatarState.UpdateQuestRewards2(materialSheet); avatarState.updatedAt = ctx.BlockIndex; avatarState.mailBox.CleanUp(); states = states .SetState(avatarAddress, avatarState.SerializeV2()) .SetState(inventoryAddress, avatarState.inventory.Serialize()) .SetState(worldInformationAddress, avatarState.worldInformation.Serialize()) .SetState(questListAddress, avatarState.questList.Serialize()); sw.Stop(); Log.Verbose("{AddressesHex}HAS Set AvatarState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (states.TryGetState(RankingMapAddress, out Dictionary d) && simulator.Log.IsClear) { var ranking = new RankingMapState(d); ranking.Update(avatarState); sw.Stop(); Log.Verbose("{AddressesHex}HAS Update RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var serialized = ranking.Serialize(); sw.Stop(); Log.Verbose("{AddressesHex}HAS Serialize RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); states = states.SetState(RankingMapAddress, serialized); } sw.Stop(); Log.Verbose("{AddressesHex}HAS Set RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (simulator.Log.stageId >= GameConfig.RequireClearedStageLevel.ActionsInRankingBoard && simulator.Log.IsClear && states.TryGetState(WeeklyArenaAddress, out Dictionary weeklyDict)) { var weekly = new WeeklyArenaState(weeklyDict); if (!weekly.Ended) { if (weekly.ContainsKey(avatarAddress)) { var info = weekly[avatarAddress]; info.UpdateV2(avatarState, characterSheet, costumeStatSheet); weekly.Update(info); } else { weekly.SetV2(avatarState, characterSheet, costumeStatSheet); } sw.Stop(); Log.Verbose("{AddressesHex}HAS Update WeeklyArenaState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var weeklySerialized = weekly.Serialize(); sw.Stop(); Log.Verbose("{AddressesHex}HAS Serialize RankingState: {Elapsed}", addressesHex, sw.Elapsed); states = states.SetState(weekly.address, weeklySerialized); } } var ended = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}HAS 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) { states = states.SetState(RankingMapAddress, MarkChanged); states = states.SetState(avatarAddress, MarkChanged); states = states.SetState(WeeklyArenaAddress, MarkChanged); return(states.SetState(ctx.Signer, MarkChanged)); } var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Debug("HAS exec started."); if (!states.TryGetAvatarState(ctx.Signer, avatarAddress, out AvatarState avatarState)) { throw new FailedLoadStateException("Aborted as the avatar state of the signer was failed to load."); } sw.Stop(); Log.Debug("HAS Get AgentAvatarStates: {Elapsed}", sw.Elapsed); sw.Restart(); if (avatarState.RankingMapAddress != RankingMapAddress) { throw new InvalidAddressException("Invalid ranking map address"); } // worldId와 stageId가 유효한지 확인합니다. var worldSheet = states.GetSheet <WorldSheet>(); if (!worldSheet.TryGetValue(worldId, out var worldRow, false)) { throw new SheetRowNotFoundException(nameof(WorldSheet), worldId); } if (stageId < worldRow.StageBegin || stageId > worldRow.StageEnd) { throw new SheetRowColumnException( $"{worldId} world is not contains {worldRow.Id} stage: " + $"{worldRow.StageBegin}-{worldRow.StageEnd}"); } var stageSheet = states.GetSheet <StageSheet>(); if (!stageSheet.TryGetValue(stageId, out var stageRow)) { throw new SheetRowNotFoundException(nameof(StageSheet), stageId); } var worldInformation = avatarState.worldInformation; if (!worldInformation.TryGetWorld(worldId, out var world)) { // NOTE: Add new World from WorldSheet worldInformation.AddAndUnlockNewWorld(worldRow, ctx.BlockIndex, worldSheet); } if (!world.IsUnlocked) { throw new InvalidWorldException($"{worldId} is locked."); } if (world.StageBegin != worldRow.StageBegin || world.StageEnd != worldRow.StageEnd) { worldInformation.UpdateWorld(worldRow); } if (world.IsStageCleared && stageId > world.StageClearedId + 1 || !world.IsStageCleared && stageId != world.StageBegin) { throw new InvalidStageException( $"Aborted as the stage ({worldId}/{stageId}) is not cleared; " + $"cleared stage: {world.StageClearedId}" ); } avatarState.ValidateEquipments(equipments, context.BlockIndex); avatarState.ValidateConsumable(foods, context.BlockIndex); avatarState.ValidateCostume(new HashSet <int>(costumes)); var costumeStatSheet = states.GetSheet <CostumeStatSheet>(); sw.Restart(); if (avatarState.actionPoint < stageRow.CostAP) { throw new NotEnoughActionPointException( $"Aborted due to insufficient action point: " + $"{avatarState.actionPoint} < {stageRow.CostAP}" ); } avatarState.actionPoint -= stageRow.CostAP; avatarState.EquipCostumes(new HashSet <int>(costumes)); avatarState.EquipEquipments(equipments); sw.Stop(); Log.Debug("HAS Unequip items: {Elapsed}", sw.Elapsed); sw.Restart(); var characterSheet = states.GetSheet <CharacterSheet>(); var simulator = new StageSimulator( ctx.Random, avatarState, foods, worldId, stageId, states.GetStageSimulatorSheets(), costumeStatSheet ); sw.Stop(); Log.Debug("HAS Initialize Simulator: {Elapsed}", sw.Elapsed); sw.Restart(); simulator.Simulate(); sw.Stop(); Log.Debug("HAS Simulator.Simulate(): {Elapsed}", sw.Elapsed); Log.Debug( "Execute HackAndSlash({AvatarAddress}); worldId: {WorldId}, stageId: {StageId}, result: {Result}, " + "clearWave: {ClearWave}, totalWave: {TotalWave}", avatarAddress, worldId, stageId, simulator.Log.result, simulator.Log.clearedWaveNumber, simulator.Log.waveCount ); sw.Restart(); if (simulator.Log.IsClear) { var worldUnlockSheet = states.GetSheet <WorldUnlockSheet>(); simulator.Player.worldInformation.ClearStage( worldId, stageId, ctx.BlockIndex, worldSheet, worldUnlockSheet ); } sw.Stop(); Log.Debug("HAS ClearStage: {Elapsed}", sw.Elapsed); sw.Restart(); avatarState.Update(simulator); var materialSheet = states.GetSheet <MaterialItemSheet>(); avatarState.UpdateQuestRewards(materialSheet); avatarState.updatedAt = ctx.BlockIndex; states = states.SetState(avatarAddress, avatarState.Serialize()); sw.Stop(); Log.Debug("HAS Set AvatarState: {Elapsed}", sw.Elapsed); sw.Restart(); if (states.TryGetState(RankingMapAddress, out Dictionary d) && simulator.Log.IsClear) { var ranking = new RankingMapState(d); ranking.Update(avatarState); sw.Stop(); Log.Debug("HAS Update RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); var serialized = ranking.Serialize(); sw.Stop(); Log.Debug("HAS Serialize RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); states = states.SetState(RankingMapAddress, serialized); } sw.Stop(); Log.Debug("HAS Set RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); if (simulator.Log.stageId >= GameConfig.RequireClearedStageLevel.ActionsInRankingBoard && simulator.Log.IsClear && states.TryGetState(WeeklyArenaAddress, out Dictionary weeklyDict)) { var weekly = new WeeklyArenaState(weeklyDict); if (!weekly.Ended) { if (weekly.ContainsKey(avatarAddress)) { var info = weekly[avatarAddress]; info.Update(avatarState, characterSheet, costumeStatSheet); weekly.Update(info); } else { weekly.SetV2(avatarState, characterSheet, costumeStatSheet); } sw.Stop(); Log.Debug("HAS Update WeeklyArenaState: {Elapsed}", sw.Elapsed); sw.Restart(); var weeklySerialized = weekly.Serialize(); sw.Stop(); Log.Debug("HAS Serialize RankingState: {Elapsed}", sw.Elapsed); states = states.SetState(weekly.address, weeklySerialized); } } Result = simulator.Log; var ended = DateTimeOffset.UtcNow; Log.Debug("HAS Total Executed Time: {Elapsed}", ended - started); return(states); }
public void Execute() { var tableSheets = TableSheets.FromTableSheetsState(_tableSheetsState); var itemId = tableSheets.WeeklyArenaRewardSheet.Values.First().Reward.ItemId; var privateKey = new PrivateKey(); var agentAddress = privateKey.PublicKey.ToAddress(); var agent = new AgentState(agentAddress); var avatarAddress = agentAddress.Derive("avatar"); var avatarState = new AvatarState(avatarAddress, agentAddress, 0, tableSheets, new GameConfigState()) { level = 10, }; avatarState.worldInformation.ClearStage( 1, GameConfig.RequireClearedStageLevel.ActionsInRankingBoard, 1, tableSheets.WorldSheet, tableSheets.WorldUnlockSheet ); agent.avatarAddresses.Add(0, avatarAddress); Assert.False(avatarState.inventory.HasItem(itemId)); var avatarAddress2 = agentAddress.Derive("avatar2"); var avatarState2 = new AvatarState(avatarAddress2, agentAddress, 0, tableSheets, new GameConfigState()); avatarState2.worldInformation.ClearStage( 1, GameConfig.RequireClearedStageLevel.ActionsInRankingBoard, 1, tableSheets.WorldSheet, tableSheets.WorldUnlockSheet ); agent.avatarAddresses.Add(1, avatarAddress); var weekly = new WeeklyArenaState(0); weekly.Set(avatarState, tableSheets.CharacterSheet); weekly[avatarAddress].Activate(); weekly.Set(avatarState2, tableSheets.CharacterSheet); weekly[avatarAddress2].Activate(); var state = new State(ImmutableDictionary <Address, IValue> .Empty .Add(_tableSheetsState.address, _tableSheetsState.Serialize()) .Add(weekly.address, weekly.Serialize()) .Add(agentAddress, agent.Serialize()) .Add(avatarAddress, avatarState.Serialize()) .Add(avatarAddress2, avatarState2.Serialize())); var action = new RankingBattle { AvatarAddress = avatarAddress, EnemyAddress = avatarAddress2, WeeklyArenaAddress = weekly.address, costumeIds = new List <int>(), equipmentIds = new List <Guid>(), consumableIds = new List <Guid>(), }; Assert.Null(action.Result); var nextState = action.Execute(new ActionContext() { PreviousStates = state, Signer = agentAddress, Random = new ItemEnhancementTest.TestRandom(), Rehearsal = false, }); var newState = nextState.GetAvatarState(avatarAddress); var newWeeklyState = nextState.GetWeeklyArenaState(0); Assert.True(newState.inventory.HasItem(itemId)); Assert.NotNull(action.Result); Assert.Contains(typeof(GetReward), action.Result.Select(e => e.GetType())); Assert.Equal(BattleLog.Result.Win, action.Result.result); Assert.True(newWeeklyState[avatarAddress].Score > weekly[avatarAddress].Score); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { states = states.SetState(RankingMapAddress, MarkChanged); states = states.SetState(avatarAddress, MarkChanged); return(states.SetState(WeeklyArenaAddress, MarkChanged)); } var addressesHex = GetSignerAndOtherAddressesHex(context, avatarAddress); var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}Mimisbrunnr exec started", addressesHex); if (!states.TryGetAvatarState(ctx.Signer, avatarAddress, out AvatarState avatarState)) { throw new FailedLoadStateException($"{addressesHex}Aborted as the avatar state of the signer was failed to load."); } sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Get AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (avatarState.RankingMapAddress != RankingMapAddress) { throw new InvalidAddressException($"{addressesHex}Invalid ranking map address"); } var worldSheet = states.GetSheet <WorldSheet>(); var worldUnlockSheet = states.GetSheet <WorldUnlockSheet>(); if (!worldSheet.TryGetValue(worldId, out var worldRow, false)) { throw new SheetRowNotFoundException(nameof(WorldSheet), worldId); } if (stageId < worldRow.StageBegin || stageId > worldRow.StageEnd) { throw new SheetRowColumnException( $"{addressesHex}{worldId} world is not contains {worldRow.Id} stage: " + $"{worldRow.StageBegin}-{worldRow.StageEnd}"); } var stageSheet = states.GetSheet <StageSheet>(); if (!stageSheet.TryGetValue(stageId, out var stageRow)) { throw new SheetRowNotFoundException(addressesHex, nameof(StageSheet), stageId); } var worldInformation = avatarState.worldInformation; if (!worldInformation.TryGetWorld(worldId, out var world)) { // NOTE: Add new World from WorldSheet worldInformation.AddAndUnlockMimisbrunnrWorld(worldRow, ctx.BlockIndex, worldSheet, worldUnlockSheet); if (!worldInformation.TryGetWorld(worldId, out world)) { // Do nothing. } } if (!world.IsUnlocked) { var worldUnlockSheetRow = worldUnlockSheet.OrderedList.FirstOrDefault(row => row.WorldIdToUnlock == worldId); if (!(worldUnlockSheetRow is null) && worldInformation.IsWorldUnlocked(worldUnlockSheetRow.WorldId) && worldInformation.IsStageCleared(worldUnlockSheetRow.StageId)) { worldInformation.UnlockWorld(worldId, ctx.BlockIndex, worldSheet); if (!worldInformation.TryGetWorld(worldId, out world)) { // Do nothing. } } } if (!world.IsUnlocked) { throw new InvalidWorldException($"{addressesHex}{worldId} is locked."); } if (world.StageBegin != worldRow.StageBegin || world.StageEnd != worldRow.StageEnd) { worldInformation.UpdateWorld(worldRow); } if (world.IsStageCleared && stageId > world.StageClearedId + 1 || !world.IsStageCleared && stageId != world.StageBegin) { throw new InvalidStageException( $"{addressesHex}Aborted as the stage ({worldId}/{stageId}) is not cleared; " + $"cleared stage: {world.StageClearedId}" ); } sw.Restart(); var mimisbrunnrSheet = states.GetSheet <MimisbrunnrSheet>(); if (!mimisbrunnrSheet.TryGetValue(stageId, out var mimisbrunnrSheetRow)) { throw new SheetRowNotFoundException(addressesHex, "MimisbrunnrSheet", stageId); } foreach (var equipmentId in equipments) { if (avatarState.inventory.TryGetNonFungibleItem(equipmentId, out ItemUsable itemUsable)) { var elementalType = ((Equipment)itemUsable).ElementalType; if (!mimisbrunnrSheetRow.ElementalTypes.Exists(x => x == elementalType)) { throw new InvalidElementalException( $"{addressesHex}ElementalType of {equipmentId} does not match."); } } } sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Check Equipments ElementalType: {Elapsed}", addressesHex, sw.Elapsed); avatarState.ValidateEquipments(equipments, context.BlockIndex); avatarState.ValidateConsumable(foods, context.BlockIndex); avatarState.ValidateCostume(costumes); sw.Restart(); if (avatarState.actionPoint < stageRow.CostAP) { throw new NotEnoughActionPointException( $"{addressesHex}Aborted due to insufficient action point: " + $"{avatarState.actionPoint} < {stageRow.CostAP}" ); } avatarState.actionPoint -= stageRow.CostAP; var equippableItem = new List <Guid>(); equippableItem.AddRange(costumes); equippableItem.AddRange(equipments); avatarState.EquipItems(equippableItem); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Unequip items: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var costumeStatSheet = states.GetSheet <CostumeStatSheet>(); var simulator = new StageSimulator( ctx.Random, avatarState, foods, worldId, stageId, states.GetStageSimulatorSheets(), costumeStatSheet ); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); simulator.Simulate(); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Simulator.Simulate(): {Elapsed}", addressesHex, sw.Elapsed); Log.Verbose( "{AddressesHex}Execute Mimisbrunnr({AvatarAddress}); worldId: {WorldId}, stageId: {StageId}, result: {Result}, " + "clearWave: {ClearWave}, totalWave: {TotalWave}", addressesHex, avatarAddress, worldId, stageId, simulator.Log.result, simulator.Log.clearedWaveNumber, simulator.Log.waveCount ); sw.Restart(); if (simulator.Log.IsClear) { simulator.Player.worldInformation.ClearStage( worldId, stageId, ctx.BlockIndex, worldSheet, worldUnlockSheet ); } sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr ClearStage: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); avatarState.Update(simulator); var materialSheet = states.GetSheet <MaterialItemSheet>(); avatarState.UpdateQuestRewards(materialSheet); avatarState.updatedAt = ctx.BlockIndex; avatarState.mailBox.CleanUp(); states = states.SetState(avatarAddress, avatarState.Serialize()); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Set AvatarState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (states.TryGetState(RankingMapAddress, out Dictionary d) && simulator.Log.IsClear) { var ranking = new RankingMapState(d); ranking.Update(avatarState); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Update RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var serialized = ranking.Serialize(); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Serialize RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); states = states.SetState(RankingMapAddress, serialized); } sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Set RankingState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (simulator.Log.stageId >= GameConfig.RequireClearedStageLevel.ActionsInRankingBoard && simulator.Log.IsClear && states.TryGetState(WeeklyArenaAddress, out Dictionary weeklyDict)) { var weekly = new WeeklyArenaState(weeklyDict); if (!weekly.Ended) { var characterSheet = states.GetSheet <CharacterSheet>(); if (weekly.ContainsKey(avatarAddress)) { var info = weekly[avatarAddress]; info.Update(avatarState, characterSheet, costumeStatSheet); weekly.Update(info); } else { weekly.SetV2(avatarState, characterSheet, costumeStatSheet); } sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Update WeeklyArenaState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var weeklySerialized = weekly.Serialize(); sw.Stop(); Log.Verbose("{AddressesHex}Mimisbrunnr Serialize RankingState: {Elapsed}", addressesHex, sw.Elapsed); states = states.SetState(weekly.address, weeklySerialized); } } Result = simulator.Log; var ended = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}Mimisbrunnr Total Executed Time: {Elapsed}", addressesHex, ended - started); return(states); }
public IAccountStateDelta PrepareNextArena(IActionContext ctx, IAccountStateDelta states) { var gameConfigState = states.GetGameConfigState(); var index = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0); var weeklyAddress = WeeklyArenaState.DeriveAddress(index); var rawWeekly = (Dictionary)states.GetState(weeklyAddress); var nextIndex = index + 1; var nextWeekly = states.GetWeeklyArenaState(nextIndex); if (nextWeekly is null) { nextWeekly = new WeeklyArenaState(nextIndex); states = states.SetState(nextWeekly.address, nextWeekly.Serialize()); } // Beginning block of a new weekly arena. if (ctx.BlockIndex % gameConfigState.WeeklyArenaInterval == 0 && index > 0) { var prevWeeklyAddress = WeeklyArenaState.DeriveAddress(index - 1); var rawPrevWeekly = (Dictionary)states.GetState(prevWeeklyAddress); if (!rawPrevWeekly["ended"].ToBoolean()) { rawPrevWeekly = rawPrevWeekly.SetItem("ended", true.Serialize()); var weekly = new WeeklyArenaState(rawWeekly); var prevWeekly = new WeeklyArenaState(rawPrevWeekly); var listAddress = weekly.address.Derive("address_list"); // Set ArenaInfo, address list for new RankingBattle. var addressList = states.TryGetState(listAddress, out List rawList) ? rawList.ToList(StateExtensions.ToAddress) : new List <Address>(); if (ctx.BlockIndex >= RankingBattle.UpdateTargetBlockIndex) { weekly.ResetIndex = ctx.BlockIndex; // Copy Map to address list. if (ctx.BlockIndex == RankingBattle.UpdateTargetBlockIndex) { foreach (var kv in prevWeekly.Map) { var address = kv.Key; var lazyInfo = kv.Value; var info = new ArenaInfo(lazyInfo.State); states = states.SetState( weeklyAddress.Derive(address.ToByteArray()), info.Serialize()); if (!addressList.Contains(address)) { addressList.Add(address); } } } else { // Copy addresses from prev weekly address list. var prevListAddress = prevWeekly.address.Derive("address_list"); if (states.TryGetState(prevListAddress, out List prevRawList)) { var prevList = prevRawList.ToList(StateExtensions.ToAddress); foreach (var address in prevList.Where(address => !addressList.Contains(address))) { addressList.Add(address); } } // Copy ArenaInfo from prev ArenaInfo. foreach (var address in addressList) { if (states.TryGetState( prevWeekly.address.Derive(address.ToByteArray()), out Dictionary rawInfo)) { var prevInfo = new ArenaInfo(rawInfo); var info = new ArenaInfo(prevInfo); states = states.SetState( weeklyAddress.Derive(address.ToByteArray()), info.Serialize()); } } } // Set address list. states = states.SetState(listAddress, addressList.Aggregate(List.Empty, (current, address) => current.Add(address.Serialize()))); } // Run legacy Update. else { weekly.Update(prevWeekly, ctx.BlockIndex); } states = states.SetState(prevWeeklyAddress, rawPrevWeekly); states = states.SetState(weeklyAddress, weekly.Serialize()); } } return(states); }
public WeeklyArenaStateUpdateScenarioTest() { _initialState = new Tests.Action.State(); var sheets = TableSheetsImporter.ImportSheets(); foreach (var(key, value) in sheets) { _initialState = _initialState.SetState( Addresses.TableSheet.Derive(key), value.Serialize()); } var tableSheets = new TableSheets(sheets); var rankingMapAddress = new PrivateKey().ToAddress(); _agent1Address = new PrivateKey().ToAddress(); _avatar1Address = new PrivateKey().ToAddress(); var agentState = new AgentState(_agent1Address); var avatarState = new AvatarState( _avatar1Address, _agent1Address, 0, tableSheets.GetAvatarSheets(), new GameConfigState(sheets[nameof(GameConfigSheet)]), rankingMapAddress ) { worldInformation = new WorldInformation( 0, tableSheets.WorldSheet, Math.Max( tableSheets.StageSheet.First?.Id ?? 1, GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)), level = 100, }; agentState.avatarAddresses.Add(0, _avatar1Address); var agent2Address = new PrivateKey().ToAddress(); _avatar2Address = new PrivateKey().ToAddress(); var agent2State = new AgentState(agent2Address); var avatar2State = new AvatarState( _avatar2Address, agent2Address, 0, tableSheets.GetAvatarSheets(), new GameConfigState(sheets[nameof(GameConfigSheet)]), rankingMapAddress ) { worldInformation = new WorldInformation( 0, tableSheets.WorldSheet, Math.Max( tableSheets.StageSheet.First?.Id ?? 1, GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)), level = 100, }; agent2State.avatarAddresses.Add(0, _avatar2Address); var agent3Address = new PrivateKey().ToAddress(); _avatar3Address = new PrivateKey().ToAddress(); var agent3State = new AgentState(agent3Address); var avatar3State = new AvatarState( _avatar3Address, agent2Address, 0, tableSheets.GetAvatarSheets(), new GameConfigState(sheets[nameof(GameConfigSheet)]), rankingMapAddress ) { worldInformation = new WorldInformation( 0, tableSheets.WorldSheet, Math.Max( tableSheets.StageSheet.First?.Id ?? 1, GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)), level = 100, }; agent3State.avatarAddresses.Add(0, _avatar3Address); var prevWeeklyArenaState = new WeeklyArenaState(RankingBattle.UpdateTargetWeeklyArenaIndex - 2); var weeklyArenaState = new WeeklyArenaState(RankingBattle.UpdateTargetWeeklyArenaIndex - 1); weeklyArenaState.SetV2(avatarState, tableSheets.CharacterSheet, tableSheets.CostumeStatSheet); weeklyArenaState[_avatar1Address].Activate(); weeklyArenaState.SetV2(avatar2State, tableSheets.CharacterSheet, tableSheets.CostumeStatSheet); weeklyArenaState[_avatar2Address].Activate(); _weeklyArenaAddress = WeeklyArenaState.DeriveAddress(RankingBattle.UpdateTargetWeeklyArenaIndex); var gold = new GoldCurrencyState(new Currency("NCG", 2, minter: null)); _initialState = _initialState .SetState(_agent1Address, agentState.Serialize()) .SetState(_avatar1Address, avatarState.Serialize()) .SetState(agent2Address, agent2State.Serialize()) .SetState(_avatar2Address, avatar2State.Serialize()) .SetState(agent3Address, agent2State.Serialize()) .SetState(_avatar3Address, avatar2State.Serialize()) .SetState(Addresses.GameConfig, new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize()) .SetState(prevWeeklyArenaState.address, prevWeeklyArenaState.Serialize()) .SetState(weeklyArenaState.address, weeklyArenaState.Serialize()) .SetState(_weeklyArenaAddress, new WeeklyArenaState(RankingBattle.UpdateTargetWeeklyArenaIndex).Serialize()) .SetState(GoldCurrencyState.Address, gold.Serialize()) .SetState(Addresses.GoldDistribution, GoldDistributionTest.Fixture.Select(v => v.Serialize()).Serialize()) .MintAsset(GoldCurrencyState.Address, gold.Currency * 100000000000); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { states = states.SetState(RankingState.Address, MarkChanged); states = states.SetState(avatarAddress, MarkChanged); states = states.SetState(WeeklyArenaAddress, MarkChanged); return(states.SetState(ctx.Signer, MarkChanged)); } var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Debug("HAS exec started."); if (!states.TryGetAgentAvatarStates( ctx.Signer, avatarAddress, out AgentState agentState, out AvatarState avatarState)) { return(LogError( context, "Aborted as the avatar state of the signer was failed to load.")); } sw.Stop(); Log.Debug("HAS Get AgentAvatarStates: {Elapsed}", sw.Elapsed); sw.Restart(); var tableSheetState = TableSheetsState.FromActionContext(ctx); sw.Stop(); Log.Debug("HAS Get TableSheetsState: {Elapsed}", sw.Elapsed); sw.Restart(); var tableSheets = TableSheets.FromTableSheetsState(tableSheetState); sw.Stop(); Log.Debug("HAS Initialize TableSheets: {Elapsed}", sw.Elapsed); // worldId와 stageId가 유효한지 확인합니다. if (!tableSheets.WorldSheet.TryGetValue(worldId, out var worldRow)) { return(LogError( context, "Not fount {WorldId} in TableSheets.WorldSheet.", worldId )); } if (stageId < worldRow.StageBegin || stageId > worldRow.StageEnd) { return(LogError( context, "{WorldId} world is not contains {StageId} stage: {StageBegin}-{StageEnd}", stageId, worldRow.Id, worldRow.StageBegin, worldRow.StageEnd )); } if (!tableSheets.StageSheet.TryGetValue(stageId, out var stageRow)) { return(LogError( context, "Not fount stage id in TableSheets.StageSheet: {StageId}", stageId )); } var worldInformation = avatarState.worldInformation; if (!worldInformation.TryGetWorld(worldId, out var world)) { // NOTE: 이 경우는 아바타 생성 시에는 WorldSheet에 없던 worldId가 새로 추가된 경우로 볼 수 있습니다. if (!worldInformation.TryAddWorld(worldRow, out world)) { return(LogError(context, "Failed to add {WorldId} world to WorldInformation.", worldId)); } } if (!world.IsUnlocked) { return(LogError(context, "Aborted as the world {WorldId} is locked.", worldId)); } if (world.StageBegin != worldRow.StageBegin || world.StageEnd != worldRow.StageEnd) { // NOTE: 이 경우는 아바타 생성 이후에 worldId가 포함하는 stageId의 범위가 바뀐 경우로 볼 수 있습니다. if (!worldInformation.TryUpdateWorld(worldRow, out world)) { return(LogError(context, "Failed to update {WorldId} world in WorldInformation.", worldId)); } if (world.StageBegin != worldRow.StageBegin || world.StageEnd != worldRow.StageEnd) { return(LogError(context, "Failed to update {WorldId} world in WorldInformation.", worldId)); } } if (world.IsStageCleared && stageId > world.StageClearedId + 1 || !world.IsStageCleared && stageId != world.StageBegin) { return(LogError( context, "Aborted as the stage ({WorldId}/{StageId}) is not cleared; cleared stage: {StageClearedId}", worldId, stageId, world.StageClearedId )); } // 장비가 유효한지 검사한다. if (!avatarState.ValidateEquipments(equipments, context.BlockIndex)) { // 장비가 유효하지 않은 에러. return(LogError(context, "Aborted as the equipment is invalid.")); } sw.Restart(); if (avatarState.actionPoint < stageRow.CostAP) { return(LogError( context, "Aborted due to insufficient action point: {ActionPointBalance} < {ActionCost}", avatarState.actionPoint, stageRow.CostAP )); } avatarState.actionPoint -= stageRow.CostAP; avatarState.EquipCostumes(costumes); avatarState.EquipEquipments(equipments); sw.Stop(); Log.Debug("HAS Unequip items: {Elapsed}", sw.Elapsed); sw.Restart(); var simulator = new StageSimulator( ctx.Random, avatarState, foods, worldId, stageId, tableSheets ); sw.Stop(); Log.Debug("HAS Initialize Simulator: {Elapsed}", sw.Elapsed); sw.Restart(); simulator.Simulate(); sw.Stop(); Log.Debug("HAS Simulator.Simulate(): {Elapsed}", sw.Elapsed); Log.Debug( "Execute HackAndSlash({AvatarAddress}); worldId: {WorldId}, stageId: {StageId}, result: {Result}, " + "clearWave: {ClearWave}, totalWave: {TotalWave}", avatarAddress, worldId, stageId, simulator.Log.result, simulator.Log.clearedWaveNumber, simulator.Log.waveCount ); sw.Restart(); if (simulator.Log.IsClear) { try { simulator.Player.worldInformation.ClearStage( worldId, stageId, ctx.BlockIndex, tableSheets.WorldSheet, tableSheets.WorldUnlockSheet ); } catch (FailedToUnlockWorldException e) { Log.Error(e.Message); throw; } } sw.Stop(); Log.Debug("HAS ClearStage: {Elapsed}", sw.Elapsed); sw.Restart(); avatarState.Update(simulator); avatarState.UpdateQuestRewards(ctx); avatarState.updatedAt = DateTimeOffset.UtcNow; states = states.SetState(avatarAddress, avatarState.Serialize()); sw.Stop(); Log.Debug("HAS Set AvatarState: {Elapsed}", sw.Elapsed); sw.Restart(); if (states.TryGetState(RankingState.Address, out Dictionary d) && simulator.Log.IsClear) { var ranking = new RankingState(d); ranking.Update(avatarState); sw.Stop(); Log.Debug("HAS Update RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); var serialized = ranking.Serialize(); sw.Stop(); Log.Debug("HAS Serialize RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); states = states.SetState(RankingState.Address, serialized); } sw.Stop(); Log.Debug("HAS Set RankingState: {Elapsed}", sw.Elapsed); sw.Restart(); if (states.TryGetState(WeeklyArenaAddress, out Dictionary weeklyDict)) { var weekly = new WeeklyArenaState(weeklyDict); if (!weekly.Ended) { if (weekly.ContainsKey(avatarAddress)) { var info = weekly[avatarAddress]; info.Update(avatarState, tableSheets.CharacterSheet); weekly.Update(info); } else { weekly.Set(avatarState, tableSheets.CharacterSheet); } sw.Stop(); Log.Debug("HAS Update WeeklyArenaState: {Elapsed}", sw.Elapsed); sw.Restart(); var weeklySerialized = weekly.Serialize(); sw.Stop(); Log.Debug("HAS Serialize RankingState: {Elapsed}", sw.Elapsed); states = states.SetState(weekly.address, weeklySerialized); } } Result = simulator.Log; var ended = DateTimeOffset.UtcNow; Log.Debug("HAS Total Executed Time: {Elapsed}", ended - started); return(states.SetState(ctx.Signer, agentState.Serialize())); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; var weeklyArenaState = new WeeklyArenaState(0); var rankingState = new RankingState(Ranking); if (ctx.Rehearsal) { states = states.SetState(RankingState.Address, MarkChanged); states = states.SetState(ShopState.Address, MarkChanged); #pragma warning disable LAA1002 states = TableSheets .Aggregate(states, (current, pair) => current.SetState(Addresses.TableSheet.Derive(pair.Key), MarkChanged)); states = rankingState.RankingMap .Aggregate(states, (current, pair) => current.SetState(pair.Key, MarkChanged)); #pragma warning restore LAA1002 states = states.SetState(weeklyArenaState.address, MarkChanged); states = states.SetState(GameConfigState.Address, MarkChanged); states = states.SetState(RedeemCodeState.Address, MarkChanged); states = states.SetState(AdminState.Address, MarkChanged); states = states.SetState(ActivatedAccountsState.Address, MarkChanged); states = states.SetState(GoldCurrencyState.Address, MarkChanged); states = states.SetState(Addresses.GoldDistribution, MarkChanged); foreach (var rawPending in PendingActivations) { states = states.SetState( new PendingActivationState((Bencodex.Types.Dictionary)rawPending).address, MarkChanged ); } states = states.SetState(AuthorizedMinersState.Address, MarkChanged); states = states.SetState(CreditsState.Address, MarkChanged); return(states); } if (ctx.BlockIndex != 0) { return(states); } #pragma warning disable LAA1002 states = TableSheets .Aggregate(states, (current, pair) => current.SetState(Addresses.TableSheet.Derive(pair.Key), pair.Value.Serialize())); states = rankingState.RankingMap .Aggregate(states, (current, pair) => current.SetState(pair.Key, new RankingMapState(pair.Key).Serialize())); #pragma warning restore LAA1002 states = states .SetState(weeklyArenaState.address, weeklyArenaState.Serialize()) .SetState(RankingState.Address, Ranking) .SetState(ShopState.Address, Shop) .SetState(GameConfigState.Address, GameConfig) .SetState(RedeemCodeState.Address, RedeemCode) .SetState(AdminState.Address, AdminAddress) .SetState(ActivatedAccountsState.Address, ActivatedAccounts) .SetState(GoldCurrencyState.Address, GoldCurrency) .SetState(Addresses.GoldDistribution, GoldDistributions); if (!(AuthorizedMiners is null)) { states = states.SetState( AuthorizedMinersState.Address, AuthorizedMiners ); } foreach (var rawPeding in PendingActivations) { states = states.SetState( new PendingActivationState((Bencodex.Types.Dictionary)rawPeding).address, rawPeding ); } if (!(Credits is null)) { states = states.SetState(CreditsState.Address, Credits); } var currency = new GoldCurrencyState(GoldCurrency).Currency; states = states.MintAsset(GoldCurrencyState.Address, currency * 1000000000); return(states); }