Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/new enhancement #2079

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d117d81
Introduce exp field in Equipment model
U-lis Aug 10, 2023
6a8d658
Update test to validate exp value
U-lis Aug 10, 2023
c146de5
Merge branch 'development' into feature/new-enhancement
U-lis Aug 10, 2023
5eed253
Change EquipmentExpKey to avoid duplication
U-lis Aug 11, 2023
fcc3197
Change exp data type to long to avoid build error at BigInteger field
U-lis Aug 11, 2023
bfb3356
Backup old version
U-lis Aug 17, 2023
14cb51e
Specify Action version
U-lis Aug 17, 2023
ee662c5
Introduce SetLevel function to set to required level at once
U-lis Aug 17, 2023
1a7d676
Introduce IItemEnhancementV4
U-lis Aug 17, 2023
4c691bc
Update related actions to apply old action name
U-lis Aug 17, 2023
3089664
Introduce EquipmentItemUpgradePoint CSV and sheet model
U-lis Aug 17, 2023
a06c4c3
Update data structure of CSVs
U-lis Aug 17, 2023
d03f078
Apply new data model
U-lis Aug 17, 2023
ebb57f5
Update backed-up test
U-lis Aug 17, 2023
326c0fa
Introduce ItemEnhancement12 action
U-lis Aug 17, 2023
9423eba
Update ItemEnhancement action
U-lis Aug 18, 2023
a33beb2
Merge branch 'development' into feature/new-enhancement
U-lis Aug 18, 2023
b5b3b50
Merge branch 'feature/new-enhancement' of github.com:U-lis/lib9c into…
U-lis Aug 18, 2023
3385958
Fix wrong test values
U-lis Aug 18, 2023
926ea45
Update ItemEnhancement action
U-lis Aug 18, 2023
33d2d5c
Specify ItemEnhancement version
U-lis Aug 18, 2023
e75ee20
Fix broken ActionEvaluationTest
U-lis Aug 18, 2023
7610b6c
Fix broken RapidCombination tests
U-lis Aug 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .Lib9c.Tests/Action/ActionEvaluationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ private ActionBase GetAction(Type type)
AuthorizedMiners = Dictionary.Empty,
Credits = Dictionary.Empty,
},
ItemEnhancement _ => new ItemEnhancement(),
ItemEnhancement _ => new ItemEnhancement
{
materialIds = new List<Guid>(),
},
MigrationActivatedAccountsState _ => new MigrationActivatedAccountsState(),
MigrationAvatarState _ => new MigrationAvatarState
{
Expand Down
234 changes: 234 additions & 0 deletions .Lib9c.Tests/Action/ItemEnhancement11Test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
namespace Lib9c.Tests.Action
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Extensions;
using Nekoyume.Helper;
using Nekoyume.Model.Item;
using Nekoyume.Model.Mail;
using Nekoyume.Model.State;
using Xunit;
using static Nekoyume.Action.ItemEnhancement11;
using static SerializeKeys;

public class ItemEnhancement11Test
{
private readonly TableSheets _tableSheets;
private readonly Address _agentAddress;
private readonly Address _avatarAddress;
private readonly AvatarState _avatarState;
private readonly Currency _currency;
private IAccountStateDelta _initialState;

public ItemEnhancement11Test()
{
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");
_avatarState = new AvatarState(
_avatarAddress,
_agentAddress,
0,
_tableSheets.GetAvatarSheets(),
new GameConfigState(),
default
);

agentState.avatarAddresses.Add(0, _avatarAddress);

#pragma warning disable CS0618
// Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
_currency = Currency.Legacy("NCG", 2, null);
#pragma warning restore CS0618
var gold = new GoldCurrencyState(_currency);
var slotAddress = _avatarAddress.Derive(string.Format(CultureInfo.InvariantCulture, CombinationSlotState.DeriveFormat, 0));

var context = new ActionContext();
_initialState = new MockStateDelta()
.SetState(_agentAddress, agentState.Serialize())
.SetState(_avatarAddress, _avatarState.Serialize())
.SetState(slotAddress, new CombinationSlotState(slotAddress, 0).Serialize())
.SetState(GoldCurrencyState.Address, gold.Serialize())
.MintAsset(context, GoldCurrencyState.Address, gold.Currency * 100000000000)
.TransferAsset(context, Addresses.GoldCurrency, _agentAddress, gold.Currency * 1000);

Assert.Equal(gold.Currency * 99999999000, _initialState.GetBalance(Addresses.GoldCurrency, gold.Currency));
Assert.Equal(gold.Currency * 1000, _initialState.GetBalance(_agentAddress, gold.Currency));

foreach (var (key, value) in sheets)
{
_initialState = _initialState.SetState(Addresses.TableSheet.Derive(key), value.Serialize());
}
}

[Theory]
[InlineData(0, 1000, true, 0, 1, EnhancementResult.Success, 0, 0, false)]
[InlineData(6, 980, true, 0, 7, EnhancementResult.Success, 0, 0, false)]
[InlineData(0, 1000, false, 1, 1, EnhancementResult.GreatSuccess, 0, 0, false)]
[InlineData(6, 980, false, 10, 6, EnhancementResult.Fail, 0, 320, false)]
[InlineData(6, 980, false, 10, 6, EnhancementResult.Fail, 2, 480, false)]
[InlineData(0, 1000, true, 0, 1, EnhancementResult.Success, 0, 0, true)]
[InlineData(6, 980, true, 0, 7, EnhancementResult.Success, 0, 0, true)]
[InlineData(0, 1000, false, 1, 1, EnhancementResult.GreatSuccess, 0, 0, true)]
[InlineData(6, 980, false, 10, 6, EnhancementResult.Fail, 0, 320, true)]
[InlineData(6, 980, false, 10, 6, EnhancementResult.Fail, 2, 480, true)]
public void Execute(
int level,
int expectedGold,
bool backward,
int randomSeed,
int expectedLevel,
EnhancementResult expected,
int monsterCollectLevel,
int expectedCrystal,
bool stake
)
{
var context = new ActionContext();
var row = _tableSheets.EquipmentItemSheet.Values.First(r => r.Grade == 1);
var equipment = (Equipment)ItemFactory.CreateItemUsable(row, default, 0, level);
var materialId = Guid.NewGuid();
var material = (Equipment)ItemFactory.CreateItemUsable(row, materialId, 0, level);

_avatarState.inventory.AddItem(equipment, count: 1);
_avatarState.inventory.AddItem(material, count: 1);

var result = new CombinationConsumable5.ResultModel()
{
id = default,
gold = 0,
actionPoint = 0,
recipeId = 1,
materials = new Dictionary<Material, int>(),
itemUsable = equipment,
};
var preItemUsable = new Equipment((Dictionary)equipment.Serialize());

for (var i = 0; i < 100; i++)
{
var mail = new CombinationMail(result, i, default, 0);
_avatarState.Update(mail);
}

_avatarState.worldInformation.ClearStage(1, 1, 1, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);

var slotAddress =
_avatarAddress.Derive(string.Format(CultureInfo.InvariantCulture, CombinationSlotState.DeriveFormat, 0));

Assert.Equal(level, equipment.level);

if (backward)
{
_initialState = _initialState.SetState(_avatarAddress, _avatarState.Serialize());
}
else
{
_initialState = _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());
}

if (monsterCollectLevel > 0)
{
var requiredGold = _tableSheets.StakeRegularRewardSheet.OrderedRows
.First(r => r.Level == monsterCollectLevel).RequiredGold;
if (stake)
{
// StakeState;
var stakeStateAddress = StakeState.DeriveAddress(_agentAddress);
var stakeState = new StakeState(stakeStateAddress, 1);
_initialState = _initialState
.SetState(stakeStateAddress, stakeState.SerializeV2())
.MintAsset(context, stakeStateAddress, requiredGold * _currency);
}
else
{
var mcAddress = MonsterCollectionState.DeriveAddress(_agentAddress, 0);
_initialState = _initialState.SetState(
mcAddress,
new MonsterCollectionState(mcAddress, monsterCollectLevel, 0).Serialize()
)
.MintAsset(context, mcAddress, requiredGold * _currency);
}
}

var action = new ItemEnhancement11()
{
itemId = default,
materialId = materialId,
avatarAddress = _avatarAddress,
slotIndex = 0,
};

var nextState = action.Execute(new ActionContext()
{
PreviousState = _initialState,
Signer = _agentAddress,
BlockIndex = 1,
Random = new TestRandom(randomSeed),
});

var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0);
var resultEquipment = (Equipment)slotState.Result.itemUsable;
var nextAvatarState = nextState.GetAvatarState(_avatarAddress);
Assert.Equal(default, resultEquipment.ItemId);
Assert.Equal(expectedLevel, resultEquipment.level);
Assert.Equal(expectedGold * _currency, nextState.GetBalance(_agentAddress, _currency));

var arenaSheet = _tableSheets.ArenaSheet;
var arenaData = arenaSheet.GetRoundByBlockIndex(1);
var feeStoreAddress = Addresses.GetBlacksmithFeeAddress(arenaData.ChampionshipId, arenaData.Round);
Assert.Equal(
(1000 - expectedGold) * _currency,
nextState.GetBalance(feeStoreAddress, _currency)
);
Assert.Equal(30, nextAvatarState.mailBox.Count);

var costRow = _tableSheets.EnhancementCostSheetV2
.OrderedList
.First(x => x.Grade == 1 && x.Level == level + 1);
var stateDict = (Dictionary)nextState.GetState(slotAddress);
var slot = new CombinationSlotState(stateDict);
var slotResult = (ResultModel)slot.Result;
Assert.Equal(expected, slotResult.enhancementResult);

switch (slotResult.enhancementResult)
{
case EnhancementResult.GreatSuccess:
var baseAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMax.NormalizeFromTenThousandths() + 1);
var extraAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMax.NormalizeFromTenThousandths() + 1);
Assert.Equal((int)(baseAtk + extraAtk), resultEquipment.StatsMap.ATK);
break;
case EnhancementResult.Success:
var baseMinAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMin.NormalizeFromTenThousandths() + 1);
var baseMaxAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMax.NormalizeFromTenThousandths() + 1);
var extraMinAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMin.NormalizeFromTenThousandths() + 1);
var extraMaxAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMax.NormalizeFromTenThousandths() + 1);
Assert.InRange(resultEquipment.StatsMap.ATK, baseMinAtk + extraMinAtk, baseMaxAtk + extraMaxAtk + 1);
break;
case EnhancementResult.Fail:
Assert.Equal(preItemUsable.StatsMap.ATK, resultEquipment.StatsMap.ATK);
break;
}

Assert.Equal(preItemUsable.TradableId, slotResult.preItemUsable.TradableId);
Assert.Equal(preItemUsable.TradableId, resultEquipment.TradableId);
Assert.Equal(costRow.Cost, slotResult.gold);
Assert.Equal(expectedCrystal * CrystalCalculator.CRYSTAL, slotResult.CRYSTAL);
}
}
}
8 changes: 4 additions & 4 deletions .Lib9c.Tests/Action/ItemEnhancement9Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,23 @@ public void Execute(int level, int expectedGold, bool backward)
var slot = new CombinationSlotState(stateDict);
var slotResult = (ItemEnhancement9.ResultModel)slot.Result;

switch ((ItemEnhancement.EnhancementResult)slotResult.enhancementResult)
switch ((ItemEnhancement9.EnhancementResult)slotResult.enhancementResult)
{
case ItemEnhancement.EnhancementResult.GreatSuccess:
case ItemEnhancement9.EnhancementResult.GreatSuccess:
var baseAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMax.NormalizeFromTenThousandths() + 1);
var extraAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMax.NormalizeFromTenThousandths() + 1);
Assert.Equal((int)(baseAtk + extraAtk), resultEquipment.StatsMap.ATK);
Assert.Equal(preItemUsable.level + 1, resultEquipment.level);
break;
case ItemEnhancement.EnhancementResult.Success:
case ItemEnhancement9.EnhancementResult.Success:
var baseMinAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMin.NormalizeFromTenThousandths() + 1);
var baseMaxAtk = preItemUsable.StatsMap.BaseATK * (costRow.BaseStatGrowthMax.NormalizeFromTenThousandths() + 1);
var extraMinAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMin.NormalizeFromTenThousandths() + 1);
var extraMaxAtk = preItemUsable.StatsMap.AdditionalATK * (costRow.ExtraStatGrowthMax.NormalizeFromTenThousandths() + 1);
Assert.InRange(resultEquipment.StatsMap.ATK, (int)(baseMinAtk + extraMinAtk), (int)(baseMaxAtk + extraMaxAtk) + 1);
Assert.Equal(preItemUsable.level + 1, resultEquipment.level);
break;
case ItemEnhancement.EnhancementResult.Fail:
case ItemEnhancement9.EnhancementResult.Fail:
Assert.Equal(preItemUsable.StatsMap.ATK, resultEquipment.StatsMap.ATK);
Assert.Equal(preItemUsable.level, resultEquipment.level);
break;
Expand Down
Loading
Loading