Exemple #1
0
        /// <summary>
        /// TableSheetsState를 기준으로 초기화합니다.
        /// </summary>
        /// <param name="tableSheetsState">기준으로 삼을 상태입니다.</param>
        public void InitializeWithTableSheetsState(TableSheetsState tableSheetsState)
        {
            foreach (var pair in tableSheetsState.TableSheets)
            {
                SetToSheet(pair.Key, pair.Value);
            }

            ItemSheetInitialize();
            QuestSheetInitialize();
        }
Exemple #2
0
        public static TableSheets FromTableSheetsState(TableSheetsState tableSheetsState)
        {
            if (Cache.TryGetValue(tableSheetsState, out var cached))
            {
                return(cached);
            }

            var tableSheets = new TableSheets();

            tableSheets.InitializeWithTableSheetsState(tableSheetsState);

            Cache.Add(tableSheetsState, tableSheets);
            return(tableSheets);
        }
Exemple #3
0
 protected override void LoadPlainValueInternal(IImmutableDictionary <string, IValue> plainValue)
 {
     RankingState           = new RankingState((Bencodex.Types.Dictionary)plainValue["ranking_state"]);
     ShopState              = new ShopState((Bencodex.Types.Dictionary)plainValue["shop_state"]);
     TableSheetsState       = new TableSheetsState((Bencodex.Types.Dictionary)plainValue["table_sheets_state"]);
     GameConfigState        = new GameConfigState((Bencodex.Types.Dictionary)plainValue["game_config_state"]);
     RedeemCodeState        = new RedeemCodeState((Bencodex.Types.Dictionary)plainValue["redeem_code_state"]);
     AdminAddressState      = new AdminState((Bencodex.Types.Dictionary)plainValue["admin_address_state"]);
     ActivatedAccountsState = new ActivatedAccountsState(
         (Bencodex.Types.Dictionary)plainValue["activated_accounts_state"]
         );
     GoldCurrencyState = new GoldCurrencyState(
         (Bencodex.Types.Dictionary)plainValue["gold_currency_state"]
         );
 }
Exemple #4
0
 public CombinationConsumableTest()
 {
     _agentAddress  = default;
     _avatarAddress = _agentAddress.Derive("avatar");
     _slotAddress   = _avatarAddress.Derive(
         string.Format(
             CultureInfo.InvariantCulture,
             CombinationSlotState.DeriveFormat,
             0
             )
         );
     _tableSheetsState = TableSheetsImporter.ImportTableSheets();
     _tableSheets      = TableSheets.FromTableSheetsState(_tableSheetsState);
     _random           = new ItemEnhancementTest.TestRandom();
 }
Exemple #5
0
        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);
        }
Exemple #6
0
        public static TableSheets FromTableSheetsState(TableSheetsState tableSheetsState)
        {
            if (Cache.TryGetValue(tableSheetsState, out var cached))
            {
                return(cached);
            }

            var tableSheets = new TableSheets();

            tableSheets.InitializeWithTableSheetsState(tableSheetsState);

            // Avoid Exception when run parallel tests
            try
            {
                Cache.Add(tableSheetsState, tableSheets);
            }
            catch (ArgumentException e)
            {
                Console.WriteLine(e);
            }
            return(tableSheets);
        }
        public ItemEnhancementTest()
        {
            var sheets     = new Dictionary <string, string>();
            var currentDir = Path.GetDirectoryName(Directory.GetCurrentDirectory());

            Debug.Assert(currentDir != null, nameof(currentDir) + " != null");
            var baseDir = currentDir.Split(nameof(Lib9c))[0];
            var dir     = Path.Combine(baseDir, "nekoyume", "Assets", "AddressableAssets", "TableCSV");
            var files   = Directory.GetFiles(dir, "*.csv", SearchOption.AllDirectories);

            foreach (var filePath in files)
            {
                var fileName = Path.GetFileName(filePath);
                if (fileName.EndsWith(".csv"))
                {
                    fileName = fileName.Split(".csv")[0];
                }

                sheets[fileName] = File.ReadAllText(filePath);
            }

            _tableSheetsState = new TableSheetsState(sheets);
            _random           = new TestRandom();
        }
Exemple #8
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IActionContext ctx    = context;
            var            states = ctx.PreviousStates;

            if (ctx.Rehearsal)
            {
                return(states
                       .SetState(TableSheetsState.Address, MarkChanged)
                       .SetState(GameConfigState.Address, MarkChanged));
            }

            CheckPermission(context);

            var tableSheetsState = TableSheetsState.FromActionContext(ctx);

            Log.Debug($"[{ctx.BlockIndex}] {TableName} was patched by {ctx.Signer.ToHex()}\n" +
                      "before:\n" +
                      (tableSheetsState.TableSheets.TryGetValue(TableName, out string value) ? value : string.Empty) +
                      "\n" +
                      "after:\n" +
                      TableCsv
                      );

            TableSheetsState nextState = tableSheetsState.UpdateTableSheet(TableName, TableCsv);

            states = states.SetState(TableSheetsState.Address, nextState.Serialize());

            if (TableName == nameof(GameConfigSheet))
            {
                var gameConfigState = new GameConfigState(TableCsv);
                states = states.SetState(GameConfigState.Address, gameConfigState.Serialize());
            }

            return(states);
        }
Exemple #9
0
 public RedeemCodeTest()
 {
     _tableSheetsState = TableSheetsImporter.ImportTableSheets();
     _tableSheets      = TableSheets.FromTableSheetsState(_tableSheetsState);
 }
Exemple #10
0
        public static TableSheets FromActionContext(IActionContext ctx)
        {
            var tableSheetsState = TableSheetsState.FromActionContext(ctx);

            return(FromTableSheetsState(tableSheetsState));
        }
Exemple #11
0
        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()));
        }
Exemple #12
0
 public RankingBattleTest()
 {
     _tableSheetsState = TableSheetsImporter.ImportTableSheets();
 }
Exemple #13
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));
            }

            if (AvatarAddress.Equals(EnemyAddress))
            {
                return(LogError(context, "Aborted as the signer tried to battle for themselves."));
            }

            if (!states.TryGetAgentAvatarStates(ctx.Signer, AvatarAddress, out var agentState,
                                                out var avatarState))
            {
                return(LogError(context, "Aborted as the avatar state of the signer was failed to load."));
            }

            // 도전자의 장비가 유효한지 검사한다.
            // 피도전자의 장비도 검사해야 하는가는 모르겠다. 이후에 필요하다면 추가하는 것으로 한다.
            if (!avatarState.ValidateEquipments(equipmentIds, context.BlockIndex))
            {
                // 장비가 유효하지 않은 에러.
                return(LogError(context, "Aborted as the equipment is invalid."));
            }

            if (!avatarState.worldInformation.TryGetUnlockedWorldByStageClearedBlockIndex(out var world))
            {
                return(LogError(context, "Aborted as the WorldInformation was failed to load or not cleared yet."));
            }

            if (world.StageClearedId < GameConfig.RequireClearedStageLevel.ActionsInRankingBoard)
            {
                // 스테이지 클리어 부족 에러.
                return(LogError(
                           context,
                           "Aborted as the signer is not cleared the minimum stage level required to battle with other players yet: {ClearedLevel} < {RequiredLevel}.",
                           world.StageClearedId,
                           GameConfig.RequireClearedStageLevel.ActionsInRankingBoard
                           ));
            }

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

            var enemyAvatarState = states.GetAvatarState(EnemyAddress);

            if (enemyAvatarState is null)
            {
                return(LogError(
                           context,
                           "Aborted as the avatar state of the opponent ({OpponentAddress}) was failed to load.",
                           EnemyAddress
                           ));
            }

            var weeklyArenaState = states.GetWeeklyArenaState(WeeklyArenaAddress);

            //FIXME 오류던지게 고쳐야함
            if (weeklyArenaState.Ended)
            {
                return(LogError(context, "Aborted as the weekly arena state already ended."));
            }

            if (!weeklyArenaState.ContainsKey(AvatarAddress))
            {
                return(LogError(context, "Aborted as the weekly arena state was failed to load."));
            }

            var arenaInfo = weeklyArenaState[AvatarAddress];

            if (arenaInfo.DailyChallengeCount <= 0)
            {
                return(LogError(context, "Aborted as the arena state reached the daily limit."));
            }

            if (!arenaInfo.Active)
            {
                FungibleAssetValue agentBalance = states.GetBalance(ctx.Signer, states.GetGoldCurrency());

                if (agentBalance >= new FungibleAssetValue(agentBalance.Currency, EntranceFee, 0))
                {
                    states = states.TransferAsset(
                        ctx.Signer,
                        WeeklyArenaAddress,
                        new FungibleAssetValue(
                            states.GetGoldCurrency(),
                            EntranceFee,
                            0
                            )
                        );
                    arenaInfo.Activate();
                }
                else
                {
                    return(LogError(
                               context,
                               "Aborted as the signer's balance ({Balance}) is insufficient to pay entrance fee/stake ({EntranceFee}).",
                               agentBalance,
                               EntranceFee
                               ));
                }
            }

            if (!weeklyArenaState.ContainsKey(EnemyAddress))
            {
                return(LogError(
                           context,
                           "Aborted as the opponent ({OpponentAddress}) is not registered in the weekly arena state.",
                           EnemyAddress
                           ));
            }

            Log.Debug(weeklyArenaState.address.ToHex());

            var tableSheetState = TableSheetsState.FromActionContext(ctx);
            var tableSheets     = TableSheets.FromTableSheetsState(tableSheetState);

            var simulator = new RankingSimulator(
                ctx.Random,
                avatarState,
                enemyAvatarState,
                consumableIds,
                tableSheets,
                StageId);

            simulator.Simulate();

            simulator.Log.diffScore = arenaInfo.Update(avatarState, weeklyArenaState[EnemyAddress], simulator.Result);
            simulator.Log.score     = arenaInfo.Score;

            Result = simulator.Log;

            foreach (var itemBase in simulator.Reward)
            {
                avatarState.inventory.AddItem(itemBase);
            }

            return(states
                   .SetState(ctx.Signer, agentState.Serialize())
                   .SetState(WeeklyArenaAddress, weeklyArenaState.Serialize())
                   .SetState(AvatarAddress, avatarState.Serialize()));
        }
Exemple #14
0
 public void Dispose()
 {
     _tableSheetsState = null;
 }
Exemple #15
0
 public ItemEnhancementTest()
 {
     _tableSheetsState = TableSheetsImporter.ImportTableSheets();
     _random           = new TestRandom();
 }