public void ExecuteThrowNotEnoughMaterialException() { var row = _tableSheets.EquipmentItemRecipeSheet.Values.First(); const int requiredStage = GameConfig.RequireClearedStageLevel.CombinationEquipmentAction; for (var i = 1; i < requiredStage + 1; i++) { _avatarState.worldInformation.ClearStage( 1, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet ); } _initialState = _initialState.SetState(_avatarAddress, _avatarState.Serialize()); var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = row.Id, SlotIndex = 0, }; Assert.Throws <NotEnoughMaterialException>(() => action.Execute(new ActionContext() { PreviousStates = _initialState, Signer = _agentAddress, Random = new ItemEnhancementTest.TestRandom(), })); }
public void ExecuteWithSubRecipe() { var row = _tableSheets.EquipmentItemRecipeSheet.Values.First(r => r.SubRecipeIds.Any()); var subRecipeId = row.SubRecipeIds.First(); var materialRow = _tableSheets.MaterialItemSheet[row.MaterialId]; var material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, row.MaterialCount); var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheet.Values.First(r => r.Id == subRecipeId); foreach (var materialInfo in subRecipeRow.Materials) { materialRow = _tableSheets.MaterialItemSheet[materialInfo.Id]; material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, materialInfo.Count); } for (var i = 1; i < row.UnlockStage + 1; i++) { _avatarState.worldInformation.ClearStage( 1, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet ); } _initialState = _initialState.SetState(_avatarAddress, _avatarState.Serialize()); var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = row.Id, SubRecipeId = subRecipeId, SlotIndex = 0, }; var nextState = action.Execute(new ActionContext() { PreviousStates = _initialState, Signer = _agentAddress, BlockIndex = 1, Random = _random, }); var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0); Assert.NotNull(slotState.Result); Assert.NotNull(slotState.Result.itemUsable); }
public void ExecuteThrowCombinationSlotUnlockException() { var row = _tableSheets.EquipmentItemRecipeSheet.Values.First(r => r.SubRecipeIds.Any()); var subRecipeId = row.SubRecipeIds.First(); var materialRow = _tableSheets.MaterialItemSheet[row.MaterialId]; var material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, row.MaterialCount); var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheet.Values.First(r => r.Id == subRecipeId); foreach (var materialInfo in subRecipeRow.Materials) { materialRow = _tableSheets.MaterialItemSheet[materialInfo.Id]; material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, materialInfo.Count); } for (var i = 1; i < row.UnlockStage + 1; i++) { _avatarState.worldInformation.ClearStage( 1, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet ); } _initialState = _initialState .SetState(_avatarAddress, _avatarState.Serialize()) .SetState( _slotAddress, new CombinationSlotState(_slotAddress, row.UnlockStage + 10).Serialize() ); var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = row.Id, SubRecipeId = subRecipeId, SlotIndex = 0, }; Assert.Throws <CombinationSlotUnlockException>(() => action.Execute(new ActionContext() { PreviousStates = _initialState, Signer = _agentAddress, Random = new ItemEnhancementTest.TestRandom(), })); }
public void ExecuteThrowFailedLoadStateException() { var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = 1, SubRecipeId = 1, SlotIndex = 0, }; Assert.Throws <FailedLoadStateException>(() => action.Execute(new ActionContext() { PreviousStates = new State(), Signer = _agentAddress, Random = new ItemEnhancementTest.TestRandom(), })); }
public void Execute() { var row = _tableSheets.EquipmentItemRecipeSheet.Values.First(); var materialRow = _tableSheets.MaterialItemSheet[row.MaterialId]; var material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, row.MaterialCount); const int requiredStage = GameConfig.RequireClearedStageLevel.CombinationEquipmentAction; for (var i = 1; i < requiredStage + 1; i++) { _avatarState.worldInformation.ClearStage( 1, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet ); } _initialState = _initialState.SetState(_avatarAddress, _avatarState.Serialize()); var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = row.Id, SlotIndex = 0, }; var nextState = action.Execute(new ActionContext() { PreviousStates = _initialState, Signer = _agentAddress, BlockIndex = 1, Random = _random, }); var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0); Assert.NotNull(slotState.Result); Assert.NotNull(slotState.Result.itemUsable); }
public void Rehearsal() { var action = new CombinationEquipment { avatarAddress = _avatarAddress, slotIndex = 0, recipeId = 1, subRecipeId = 255, }; var slotAddress = _avatarAddress.Derive( string.Format( CultureInfo.InvariantCulture, CombinationSlotState.DeriveFormat, 0 ) ); var updatedAddresses = new List <Address> { _agentAddress, _avatarAddress, slotAddress, _avatarAddress.Derive(LegacyInventoryKey), _avatarAddress.Derive(LegacyWorldInformationKey), _avatarAddress.Derive(LegacyQuestListKey), Addresses.Blacksmith, }; var state = new State(); var nextState = action.Execute(new ActionContext { PreviousStates = state, Signer = _agentAddress, BlockIndex = 0, Rehearsal = true, }); Assert.Equal(updatedAddresses.ToImmutableHashSet(), nextState.UpdatedAddresses); }
public void ExecuteThrowNotEnoughClearedStageLevelException() { const int requiredStage = GameConfig.RequireClearedStageLevel.CombinationEquipmentAction; var row = _tableSheets.EquipmentItemRecipeSheet.Values.First(r => r.UnlockStage > requiredStage); var materialRow = _tableSheets.MaterialItemSheet[row.MaterialId]; var material = ItemFactory.CreateItem(materialRow, _random); _avatarState.inventory.AddItem(material, row.MaterialCount); for (var i = 1; i < requiredStage + 1; i++) { _avatarState.worldInformation.ClearStage( 1, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet ); } _initialState = _initialState.SetState(_avatarAddress, _avatarState.Serialize()); var action = new CombinationEquipment() { AvatarAddress = _avatarAddress, RecipeId = row.Id, SlotIndex = 0, }; Assert.Throws <NotEnoughClearedStageLevelException>(() => action.Execute(new ActionContext() { PreviousStates = _initialState, Signer = _agentAddress, Random = new TestRandom(), })); }
public void Case(int randomSeed, int[] optionNumbers) { var gameConfigState = _initialState.GetGameConfigState(); Assert.NotNull(gameConfigState); var recipeRow = _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Any()); var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2[recipeRow.SubRecipeIds.First()]; var combinationEquipmentAction = new CombinationEquipment { avatarAddress = _avatarAddress, slotIndex = 0, recipeId = recipeRow.Id, subRecipeId = subRecipeRow.Id, }; var inventoryValue = _initialState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); var inventoryState = new Inventory((List)inventoryValue); inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId), recipeRow.MaterialCount); foreach (var materialInfo in subRecipeRow.Materials) { inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id), materialInfo.Count); } var worldInformation = new WorldInformation( 0, _tableSheets.WorldSheet, recipeRow.UnlockStage); var nextState = _initialState .SetState(_inventoryAddress, inventoryState.Serialize()) .SetState(_worldInformationAddress, worldInformation.Serialize()); var random = new TestRandom(randomSeed); nextState = combinationEquipmentAction.Execute(new ActionContext { PreviousStates = nextState, BlockIndex = 0, Random = random, Signer = _agentAddress, }); var slot0Value = nextState.GetState(_slot0Address); Assert.NotNull(slot0Value); var slot0State = new CombinationSlotState((Dictionary)slot0Value); Assert.NotNull(slot0State.Result.itemUsable); var equipment = (Equipment)slot0State.Result.itemUsable; var additionalStats = equipment.StatsMap .GetAdditionalStats(true) .ToArray(); var skills = equipment.Skills; Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination); var optionSheet = _tableSheets.EquipmentItemOptionSheet; var mainAdditionalStatMin = 0; var mainAdditionalStatMax = 0; var requiredBlockIndex = 0; foreach (var optionNumber in optionNumbers) { var optionInfo = subRecipeRow.Options[optionNumber - 1]; requiredBlockIndex += optionInfo.RequiredBlockIndex; var optionRow = optionSheet[optionInfo.Id]; if (optionRow.StatMin > 0 || optionRow.StatMax > 0) { if (optionRow.StatType == equipment.UniqueStatType) { mainAdditionalStatMin += optionRow.StatMin; mainAdditionalStatMax += optionRow.StatMax; continue; } var additionalStatValue = additionalStats .First(e => e.statType == optionRow.StatType) .additionalValue; Assert.True(additionalStatValue >= optionRow.StatMin); Assert.True(additionalStatValue <= optionRow.StatMax + 1); } else if (optionRow.SkillId != default) { var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId); Assert.True(skill.Chance >= optionRow.SkillChanceMin); Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1); Assert.True(skill.Power >= optionRow.SkillDamageMin); Assert.True(skill.Power <= optionRow.SkillDamageMax + 1); } } var mainAdditionalStatValue = additionalStats .First(e => e.statType == equipment.UniqueStatType) .additionalValue; Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin); Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1); Assert.Equal(requiredBlockIndex + 1, slot0State.RequiredBlockIndex); // FIXME // https://github.com/planetarium/lib9c/pull/517#discussion_r679218764 // The tests after this line should be finished. However, since then the logic is being developed by // different developers in different branches. I wrote a test beforehand, but it's failing. // I plan to move to another branch after this PR is merged and finish writing the tests. return; if (requiredBlockIndex == 0) { return; } var hourglassRow = _tableSheets.MaterialItemSheet .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass) .Value; inventoryValue = nextState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); inventoryState = new Inventory((List)inventoryValue); Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _)); var hourglassCount = requiredBlockIndex * gameConfigState.HourglassPerBlock; inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id), hourglassCount); Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses)); Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count)); nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize()); var rapidCombinationAction = new RapidCombination { avatarAddress = _avatarAddress, slotIndex = 0, }; nextState = rapidCombinationAction.Execute(new ActionContext { PreviousStates = nextState, BlockIndex = 1, Random = random, Signer = _agentAddress, }); inventoryValue = nextState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); inventoryState = new Inventory((List)inventoryValue); Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _)); }
private void Execute(bool backward, int recipeId, int?subRecipeId, int mintNCG) { var currency = new Currency("NCG", 2, minter: null); var row = _tableSheets.EquipmentItemRecipeSheet[recipeId]; var requiredStage = row.UnlockStage; var costActionPoint = row.RequiredActionPoint; var costNCG = row.RequiredGold * currency; var materialRow = _tableSheets.MaterialItemSheet[row.MaterialId]; var material = ItemFactory.CreateItem(materialRow, _random); var avatarState = _initialState.GetAvatarState(_avatarAddress); var previousActionPoint = avatarState.actionPoint; var previousResultEquipmentCount = avatarState.inventory.Equipments.Count(e => e.Id == row.ResultEquipmentId); var previousMailCount = avatarState.mailBox.Count; avatarState.worldInformation = new WorldInformation( 0, _tableSheets.WorldSheet, requiredStage); avatarState.inventory.AddItem(material, row.MaterialCount); if (subRecipeId.HasValue) { var subRow = _tableSheets.EquipmentItemSubRecipeSheetV2[subRecipeId.Value]; costActionPoint += subRow.RequiredActionPoint; costNCG += subRow.RequiredGold * currency; foreach (var materialInfo in subRow.Materials) { material = ItemFactory.CreateItem(_tableSheets.MaterialItemSheet[materialInfo.Id], _random); avatarState.inventory.AddItem(material, materialInfo.Count); } } IAccountStateDelta previousState; if (backward) { previousState = _initialState.SetState(_avatarAddress, avatarState.Serialize()); } else { previousState = _initialState .SetState(_avatarAddress.Derive(LegacyInventoryKey), avatarState.inventory.Serialize()) .SetState( _avatarAddress.Derive(LegacyWorldInformationKey), avatarState.worldInformation.Serialize()) .SetState(_avatarAddress.Derive(LegacyQuestListKey), avatarState.questList.Serialize()) .SetState(_avatarAddress, avatarState.SerializeV2()); } previousState = previousState.MintAsset(_agentAddress, mintNCG * currency); var goldCurrencyState = previousState.GetGoldCurrency(); var previousNCG = previousState.GetBalance(_agentAddress, goldCurrencyState); Assert.Equal(mintNCG * currency, previousNCG); var action = new CombinationEquipment { avatarAddress = _avatarAddress, slotIndex = 0, recipeId = recipeId, subRecipeId = subRecipeId, }; var nextState = action.Execute(new ActionContext { PreviousStates = previousState, Signer = _agentAddress, BlockIndex = 1, Random = _random, }); var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0); Assert.NotNull(slotState.Result); Assert.NotNull(slotState.Result.itemUsable); if (subRecipeId.HasValue) { Assert.True(((Equipment)slotState.Result.itemUsable).optionCountFromCombination > 0); } else { Assert.Equal(0, ((Equipment)slotState.Result.itemUsable).optionCountFromCombination); } var nextAvatarState = nextState.GetAvatarStateV2(_avatarAddress); Assert.Equal(previousActionPoint - costActionPoint, nextAvatarState.actionPoint); Assert.Equal(previousMailCount + 1, nextAvatarState.mailBox.Count); Assert.IsType <CombinationMail>(nextAvatarState.mailBox.First()); Assert.Equal( previousResultEquipmentCount + 1, nextAvatarState.inventory.Equipments.Count(e => e.Id == row.ResultEquipmentId)); var agentGold = nextState.GetBalance(_agentAddress, goldCurrencyState); Assert.Equal(previousNCG - costNCG, agentGold); var blackSmithGold = nextState.GetBalance(Addresses.Blacksmith, goldCurrencyState); Assert.Equal(costNCG, blackSmithGold); }
public void Case(int randomSeed, int[] optionNumbers) { var gameConfigState = _initialState.GetGameConfigState(); Assert.NotNull(gameConfigState); var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2.OrderedList.First(e => e.Options.Count == 4 && e.RequiredBlockIndex > GameConfig.RequiredAppraiseBlock && e.RequiredGold == 0); var recipeRow = _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Contains(subRecipeRow.Id)); var combinationEquipmentAction = new CombinationEquipment { avatarAddress = _avatarAddress, slotIndex = 0, recipeId = recipeRow.Id, subRecipeId = subRecipeRow.Id, }; var inventoryValue = _initialState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); var inventoryState = new Inventory((List)inventoryValue); inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId), recipeRow.MaterialCount); foreach (var materialInfo in subRecipeRow.Materials) { inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id), materialInfo.Count); } var worldInformation = new WorldInformation( 0, _tableSheets.WorldSheet, recipeRow.UnlockStage); var nextState = _initialState .SetState(_inventoryAddress, inventoryState.Serialize()) .SetState(_worldInformationAddress, worldInformation.Serialize()); var random = new TestRandom(randomSeed); nextState = combinationEquipmentAction.Execute(new ActionContext { PreviousStates = nextState, BlockIndex = 0, Random = random, Signer = _agentAddress, }); var slot0Value = nextState.GetState(_slot0Address); Assert.NotNull(slot0Value); var slot0State = new CombinationSlotState((Dictionary)slot0Value); Assert.NotNull(slot0State.Result.itemUsable); var equipment = (Equipment)slot0State.Result.itemUsable; var additionalStats = equipment.StatsMap .GetAdditionalStats(true) .ToArray(); var skills = equipment.Skills; Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination); var optionSheet = _tableSheets.EquipmentItemOptionSheet; var mainAdditionalStatMin = 0; var mainAdditionalStatMax = 0; var requiredBlockIndex = recipeRow.RequiredBlockIndex + subRecipeRow.RequiredBlockIndex; var orderedOptions = subRecipeRow.Options .OrderByDescending(e => e.Ratio) .ThenBy(e => e.RequiredBlockIndex) .ThenBy(e => e.Id) .ToArray(); foreach (var optionNumber in optionNumbers) { var optionInfo = orderedOptions[optionNumber - 1]; requiredBlockIndex += optionInfo.RequiredBlockIndex; var optionRow = optionSheet[optionInfo.Id]; if (optionRow.StatMin > 0 || optionRow.StatMax > 0) { if (optionRow.StatType == equipment.UniqueStatType) { mainAdditionalStatMin += optionRow.StatMin; mainAdditionalStatMax += optionRow.StatMax; continue; } var additionalStatValue = additionalStats .First(e => e.statType == optionRow.StatType) .additionalValue; Assert.True(additionalStatValue >= optionRow.StatMin); Assert.True(additionalStatValue <= optionRow.StatMax + 1); } else if (optionRow.SkillId != default) { var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId); Assert.True(skill.Chance >= optionRow.SkillChanceMin); Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1); Assert.True(skill.Power >= optionRow.SkillDamageMin); Assert.True(skill.Power <= optionRow.SkillDamageMax + 1); } } var mainAdditionalStatValue = additionalStats .First(e => e.statType == equipment.UniqueStatType) .additionalValue; Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin); Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1); Assert.Equal(requiredBlockIndex, slot0State.RequiredBlockIndex); if (requiredBlockIndex == 0) { return; } var hourglassRow = _tableSheets.MaterialItemSheet .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass) .Value; inventoryValue = nextState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); inventoryState = new Inventory((List)inventoryValue); Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _)); var diff = slot0State.RequiredBlockIndex - GameConfig.RequiredAppraiseBlock; var hourglassCount = RapidCombination0.CalculateHourglassCount(gameConfigState, diff); inventoryState.AddFungibleItem( ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id), hourglassCount); Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses)); Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count)); nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize()); var rapidCombinationAction = new RapidCombination { avatarAddress = _avatarAddress, slotIndex = 0, }; nextState = rapidCombinationAction.Execute(new ActionContext { PreviousStates = nextState, BlockIndex = GameConfig.RequiredAppraiseBlock, Random = random, Signer = _agentAddress, }); inventoryValue = nextState.GetState(_inventoryAddress); Assert.NotNull(inventoryValue); inventoryState = new Inventory((List)inventoryValue); Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _)); }