コード例 #1
0
 public EnemyPlayer(EnemyPlayerDigest enemyPlayerDigest,
                    CharacterSheet characterSheet,
                    CharacterLevelSheet levelSheet,
                    EquipmentItemSetEffectSheet equipmentItemSetEffectSheet
                    ) : base(
         enemyPlayerDigest.Level,
         characterSheet,
         levelSheet,
         equipmentItemSetEffectSheet)
 {
     NameWithHash        = enemyPlayerDigest.NameWithHash;
     weapon              = null;
     armor               = null;
     belt                = null;
     necklace            = null;
     ring                = null;
     monsterMap          = new CollectionMap();
     eventMap            = new CollectionMap();
     hairIndex           = enemyPlayerDigest.HairIndex;
     lensIndex           = enemyPlayerDigest.LensIndex;
     earIndex            = enemyPlayerDigest.EarIndex;
     tailIndex           = enemyPlayerDigest.TailIndex;
     equipments          = enemyPlayerDigest.Equipments as List <Equipment>;
     costumes            = enemyPlayerDigest.Costumes as List <Costume>;
     characterLevelSheet = levelSheet;
     AttackCountMax      = AttackCountHelper.GetCountMax(Level);
     SetEquipmentStat(equipmentItemSetEffectSheet);
 }
コード例 #2
0
        public void Serialize()
        {
            var digest       = new EnemyPlayerDigest(_avatarState);
            var serialized   = digest.Serialize();
            var deserialized = new EnemyPlayerDigest((List)serialized);

            Assert.Equal(serialized, deserialized.Serialize());
        }
コード例 #3
0
        public void Constructor()
        {
            var digest = new EnemyPlayerDigest(_avatarState);

            Assert.Equal(_avatarState.NameWithHash, digest.NameWithHash);
            Assert.Equal(_avatarState.characterId, digest.CharacterId);
            Assert.Equal(_avatarState.level, digest.Level);
            Assert.Equal(2, digest.HairIndex);
            Assert.Equal(3, digest.LensIndex);
            Assert.Equal(4, digest.EarIndex);
            Assert.Equal(5, digest.TailIndex);
            Assert.Single(digest.Equipments);
            Assert.Single(digest.Costumes);

            var enemyPlayer = new EnemyPlayer(
                digest,
                _tableSheets.CharacterSheet,
                _tableSheets.CharacterLevelSheet,
                _tableSheets.EquipmentItemSetEffectSheet);

            Assert.Single(enemyPlayer.Equipments);
            Assert.Single(enemyPlayer.Costumes);
        }
コード例 #4
0
ファイル: RankingBattle10.cs プロジェクト: planetarium/lib9c
        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)
            {
                return(states
                       .SetState(avatarAddress, MarkChanged)
                       .SetState(weeklyArenaAddress, MarkChanged)
                       .SetState(inventoryAddress, MarkChanged)
                       .SetState(worldInformationAddress, MarkChanged)
                       .SetState(questListAddress, MarkChanged));
            }

            // Avoid InvalidBlockStateRootHashException
            if (ctx.BlockIndex == 680341 && Id.Equals(new Guid("df37dbd8-5703-4dff-918b-ad22ee4c34c6")))
            {
                return(states);
            }

            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.TryGetAvatarStateV2(ctx.Signer, avatarAddress, out var avatarState, out bool migrationRequired))
            {
                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();
            var sheets = states.GetSheets(
                containRankingSimulatorSheets: true,
                sheetTypes: new[]
            {
                typeof(CharacterSheet),
                typeof(CostumeStatSheet),
            });

            sw.Stop();
            Log.Verbose("{AddressesHex}HAS Get Sheets: {Elapsed}", addressesHex, sw.Elapsed);

            sw.Restart();
            var items = equipmentIds.Concat(costumeIds);

            avatarState.ValidateEquipmentsV2(equipmentIds, context.BlockIndex);
            avatarState.ValidateCostume(costumeIds);

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

            avatarState.EquipItems(items);

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Equip 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 enemyAvatarState;

            try
            {
                enemyAvatarState = states.GetAvatarStateV2(enemyAddress);
            }
            // BackWard compatible.
            catch (FailedLoadStateException)
            {
                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();

            if (!states.TryGetState(weeklyArenaAddress, out Dictionary rawWeeklyArenaState))
            {
                return(states);
            }

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

            bool       arenaEnded     = rawWeeklyArenaState["ended"].ToBoolean();
            Dictionary weeklyArenaMap = (Dictionary)rawWeeklyArenaState["map"];

            if (arenaEnded)
            {
                throw new WeeklyArenaStateAlreadyEndedException();
            }

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

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

            IKey arenaKey = (IKey)avatarAddress.Serialize();

            if (!weeklyArenaMap.ContainsKey(arenaKey))
            {
                var characterSheet = sheets.GetSheet <CharacterSheet>();
                var newInfo        = new ArenaInfo(avatarState, characterSheet, costumeStatSheet, false);
                weeklyArenaMap =
                    (Dictionary)weeklyArenaMap.Add(arenaKey, newInfo.Serialize());
                sw.Stop();
                Log.Verbose("{AddressesHex}RankingBattle Set AvatarInfo: {Elapsed}", addressesHex, sw.Elapsed);
                sw.Restart();
            }

            var arenaInfo = new ArenaInfo((Dictionary)weeklyArenaMap[arenaKey]);

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

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

            IKey enemyKey = (IKey)enemyAddress.Serialize();

            if (!weeklyArenaMap.ContainsKey(enemyKey))
            {
                throw new WeeklyArenaStateNotContainsAvatarAddressException(addressesHex, enemyAddress);
            }

            var enemyArenaInfo = new ArenaInfo((Dictionary)weeklyArenaMap[enemyKey]);

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

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

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

            ArenaInfo      = new ArenaInfo((Dictionary)weeklyArenaMap[arenaKey]);
            EnemyArenaInfo = new ArenaInfo((Dictionary)weeklyArenaMap[enemyKey]);
            var rankingSheets     = sheets.GetRankingSimulatorSheets();
            var player            = new Player(avatarState, rankingSheets);
            var enemyPlayerDigest = new EnemyPlayerDigest(enemyAvatarState);
            var simulator         = new RankingSimulator(
                ctx.Random,
                player,
                enemyPlayerDigest,
                new List <Guid>(),
                rankingSheets,
                StageId,
                arenaInfo,
                enemyArenaInfo,
                costumeStatSheet);

            simulator.Simulate();

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

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

            var arenaMapDict = new Dictionary <IKey, IValue>();

            foreach (var kv in weeklyArenaMap)
            {
                var key   = kv.Key;
                var value = kv.Value;
                if (key.Equals(arenaKey))
                {
                    value = arenaInfo.Serialize();
                }

                if (key.Equals(enemyKey))
                {
                    value = enemyArenaInfo.Serialize();
                }

                arenaMapDict[key] = value;
            }

            var weeklyArenaDict = new Dictionary <IKey, IValue>();

            foreach (var kv in rawWeeklyArenaState)
            {
                weeklyArenaDict[kv.Key] = kv.Key.Equals((Text)"map")
                    ? new Dictionary(arenaMapDict)
                    : kv.Value;
            }

            states = states.SetState(weeklyArenaAddress, new Dictionary(weeklyArenaDict));

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

            states = states
                     .SetState(inventoryAddress, avatarState.inventory.Serialize())
                     .SetState(questListAddress, avatarState.questList.Serialize());

            if (migrationRequired)
            {
                states = states
                         .SetState(worldInformationAddress, avatarState.worldInformation.Serialize())
                         .SetState(avatarAddress, avatarState.SerializeV2());
            }

            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);
            EnemyPlayerDigest = enemyPlayerDigest;
            return(states);
        }
コード例 #5
0
ファイル: RankingBattle.cs プロジェクト: planetarium/lib9c
        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)
            {
                return(states
                       .SetState(avatarAddress, MarkChanged)
                       .SetState(weeklyArenaAddress, MarkChanged)
                       .SetState(inventoryAddress, MarkChanged)
                       .SetState(worldInformationAddress, MarkChanged)
                       .SetState(questListAddress, MarkChanged));
            }

            // Avoid InvalidBlockStateRootHashException
            if (ctx.BlockIndex == 680341 && Id.Equals(new Guid("df37dbd8-5703-4dff-918b-ad22ee4c34c6")))
            {
                return(states);
            }

            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.TryGetAvatarStateV2(ctx.Signer, avatarAddress, out var avatarState, out bool migrationRequired))
            {
                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();
            var sheets = states.GetSheets(
                containRankingSimulatorSheets: true,
                sheetTypes: new[]
            {
                typeof(CharacterSheet),
                typeof(CostumeStatSheet),
            });

            sw.Stop();
            Log.Verbose("{AddressesHex}HAS Get Sheets: {Elapsed}", addressesHex, sw.Elapsed);

            sw.Restart();
            var items = equipmentIds.Concat(costumeIds);

            avatarState.ValidateEquipmentsV2(equipmentIds, context.BlockIndex);
            avatarState.ValidateCostume(costumeIds);

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

            avatarState.EquipItems(items);

            sw.Stop();
            Log.Verbose("{AddressesHex}RankingBattle Equip 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 enemyAvatarState;

            try
            {
                enemyAvatarState = states.GetAvatarStateV2(enemyAddress);
            }
            // BackWard compatible.
            catch (FailedLoadStateException)
            {
                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 costumeStatSheet = sheets.GetSheet <CostumeStatSheet>();

            if (!states.TryGetState(weeklyArenaAddress, out Dictionary rawWeeklyArenaState))
            {
                return(states);
            }

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

            bool arenaEnded = rawWeeklyArenaState["ended"].ToBoolean();

            if (arenaEnded)
            {
                throw new WeeklyArenaStateAlreadyEndedException();
            }

            if (context.BlockIndex >= UpdateTargetBlockIndex)
            {
                // Run updated model
                var       arenaInfoAddress = weeklyArenaAddress.Derive(avatarAddress.ToByteArray());
                ArenaInfo arenaInfo;
                var       characterSheet     = sheets.GetSheet <CharacterSheet>();
                var       addressListAddress = weeklyArenaAddress.Derive("address_list");
                bool      listCheck          = false;
                if (!states.TryGetState(arenaInfoAddress, out Dictionary rawArenaInfo))
                {
                    arenaInfo    = new ArenaInfo(avatarState, characterSheet, costumeStatSheet, true);
                    listCheck    = true;
                    rawArenaInfo = (Dictionary)arenaInfo.Serialize();
                }
                else
                {
                    arenaInfo = new ArenaInfo(rawArenaInfo);
                }

                var       enemyInfoAddress = weeklyArenaAddress.Derive(enemyAddress.ToByteArray());
                ArenaInfo enemyInfo;
                if (!states.TryGetState(enemyInfoAddress, out Dictionary rawEnemyInfo))
                {
                    enemyInfo = new ArenaInfo(enemyAvatarState, characterSheet, costumeStatSheet,
                                              true);
                    listCheck    = true;
                    rawEnemyInfo = (Dictionary)enemyInfo.Serialize();
                }
                else
                {
                    enemyInfo = new ArenaInfo(rawEnemyInfo);
                }

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

                ArenaInfo      = new ArenaInfo(rawArenaInfo);
                EnemyArenaInfo = new ArenaInfo(rawEnemyInfo);
                var rankingSheets     = sheets.GetRankingSimulatorSheets();
                var player            = new Player(avatarState, rankingSheets);
                var enemyPlayerDigest = new EnemyPlayerDigest(enemyAvatarState);
                var simulator         = new RankingSimulator(
                    ctx.Random,
                    player,
                    enemyPlayerDigest,
                    new List <Guid>(),
                    rankingSheets,
                    StageId,
                    arenaInfo,
                    enemyInfo,
                    costumeStatSheet);

                simulator.Simulate();

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

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

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

                states = states
                         .SetState(inventoryAddress, avatarState.inventory.Serialize())
                         .SetState(arenaInfoAddress, arenaInfo.Serialize())
                         .SetState(enemyInfoAddress, enemyInfo.Serialize())
                         .SetState(questListAddress, avatarState.questList.Serialize());

                if (migrationRequired)
                {
                    states = states
                             .SetState(worldInformationAddress, avatarState.worldInformation.Serialize())
                             .SetState(avatarAddress, avatarState.SerializeV2());
                }

                if (listCheck)
                {
                    var addressList = states.TryGetState(addressListAddress, out List rawAddressList)
                        ? rawAddressList.ToList(StateExtensions.ToAddress)
                        : new List <Address>();

                    if (!addressList.Contains(avatarAddress))
                    {
                        addressList.Add(avatarAddress);
                    }

                    if (!addressList.Contains(enemyAddress))
                    {
                        addressList.Add(enemyAddress);
                    }

                    states = states.SetState(addressListAddress,
                                             addressList.Aggregate(List.Empty,
                                                                   (current, address) => current.Add(address.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);
                EnemyPlayerDigest = enemyPlayerDigest;
                return(states);
            }
            // Run Backward compatible
            return(BackwardCompatibleExecute(rawWeeklyArenaState, sheets, avatarState, costumeStatSheet, sw, addressesHex, enemyAvatarState, ctx, states, inventoryAddress, questListAddress, migrationRequired, worldInformationAddress, started));
        }