Skip to content

Commit

Permalink
Merge pull request #2026 from planetarium/release/0.3.0
Browse files Browse the repository at this point in the history
Merge `Release/0.3.0` into development
  • Loading branch information
U-lis authored Jul 21, 2023
2 parents 416798e + d3ce96e commit 3a30163
Show file tree
Hide file tree
Showing 47 changed files with 456 additions and 443 deletions.
11 changes: 7 additions & 4 deletions .Lib9c.Tests/Action/CreateAvatarTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ public CreateAvatarTest()
_tableSheets = new TableSheets(TableSheetsImporter.ImportSheets());
}

[Fact]
public void Execute()
[Theory]
[InlineData(0L, 600_000)]
[InlineData(7_210_000L, 600_000)]
[InlineData(7_210_001L, 200_000)]
public void Execute(long blockIndex, int expected)
{
var action = new CreateAvatar()
{
Expand Down Expand Up @@ -58,7 +61,7 @@ public void Execute()
{
PreviousState = state,
Signer = _agentAddress,
BlockIndex = 0,
BlockIndex = blockIndex,
});

var avatarAddress = _agentAddress.Derive(
Expand All @@ -77,7 +80,7 @@ public void Execute()
);
Assert.True(agentState.avatarAddresses.Any());
Assert.Equal("test", nextAvatarState.name);
Assert.Equal(600_000 * CrystalCalculator.CRYSTAL, nextState.GetBalance(_agentAddress, CrystalCalculator.CRYSTAL));
Assert.Equal(expected * CrystalCalculator.CRYSTAL, nextState.GetBalance(_agentAddress, CrystalCalculator.CRYSTAL));
}

[Theory]
Expand Down
34 changes: 34 additions & 0 deletions .Lib9c.Tests/Action/HitHelperTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace Lib9c.Tests.Action
{
using System;
using Nekoyume.Battle;
using Xunit;

public class HitHelperTest
{
[Fact]
public void GetHitStep2()
{
// copy from previous logic
int GetHitStep2Legacy(int attackerHit, int defenderHit)
{
attackerHit = Math.Max(1, attackerHit);
defenderHit = Math.Max(1, defenderHit);
var additionalCorrection = (int)((attackerHit - defenderHit / 3m) / defenderHit * 100);
return Math.Min(
Math.Max(additionalCorrection, HitHelper.GetHitStep2AdditionalCorrectionMin),
HitHelper.GetHitStep2AdditionalCorrectionMax);
}

for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
var legacy = GetHitStep2Legacy(i, j);
var current = HitHelper.GetHitStep2(i, j);
Assert.True(legacy == current, $"{i}, {j}, {legacy}, {current}");
}
}
}
}
}
34 changes: 32 additions & 2 deletions .Lib9c.Tests/Model/Skill/CombatTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void CalculateDEFAndDamageReduction(int def, int drv, int drr, int enemyA
var normalAttack = new NormalAttack(skillRow, 0, 100, default, StatType.NONE);

var prevHP = _player.CurrentHP;
normalAttack.Use(_enemy, 1, new List<StatBuff>());
normalAttack.Use(_enemy, 1, new List<StatBuff>(), false);
var currentHP = _player.CurrentHP;
var damage = prevHP - currentHP;

Expand All @@ -100,11 +100,41 @@ public void CalculateCritDamage(int cdmg, int atk, int expectedDamage)
var normalAttack = new NormalAttack(skillRow, 0, 100, default, StatType.NONE);

var prevHP = _player.CurrentHP;
normalAttack.Use(_enemy, 1, new List<StatBuff>());
normalAttack.Use(_enemy, 1, new List<StatBuff>(), false);
var currentHP = _player.CurrentHP;
var damage = prevHP - currentHP;

Assert.Equal(expectedDamage, damage);
}

[Fact]
public void Thorn()
{
var prevHP = _enemy.CurrentHP;
var skill = _enemy.GiveThornDamage(1);
var currentHP = _enemy.CurrentHP;
// get 1dmg from thorn
Assert.Equal(prevHP - 1, currentHP);
Assert.Equal(prevHP, skill.Character.CurrentHP);
var skillInfo = Assert.Single(skill.SkillInfos);
Assert.Equal(currentHP, skillInfo.Target!.CurrentHP);
}

[Fact]
public void Bleed()
{
var actionBuffSheet = _tableSheets.ActionBuffSheet;
var row = actionBuffSheet.Values.First();
var bleed = Assert.IsType<Bleed>(BuffFactory.GetActionBuff(_enemy.Stats, row));
var dmg = bleed.Power;
var prevHP = _player.CurrentHP;
var skill = bleed.GiveEffect(_player, 1);
var currentHP = _player.CurrentHP;
// get dmg from bleed
Assert.Equal(prevHP - dmg, currentHP);
Assert.Equal(prevHP, skill.Character.CurrentHP);
var skillInfo = Assert.Single(skill.SkillInfos);
Assert.Equal(currentHP, skillInfo.Target!.CurrentHP);
}
}
}
21 changes: 12 additions & 9 deletions .Lib9c.Tests/Model/Skill/NormalAttackTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ public NormalAttackTest(ITestOutputHelper outputHelper)
.CreateLogger();
}

[Fact]
public void Use()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Use(bool copyCharacter)
{
var sheets = TableSheetsImporter.ImportSheets();
var tableSheets = new TableSheets(sheets);
Expand Down Expand Up @@ -65,7 +67,8 @@ public void Use()
StageSimulator.GetWaveRewards(
random,
tableSheets.StageSheet[1],
tableSheets.MaterialItemSheet)
tableSheets.MaterialItemSheet),
copyCharacter
);
var player = new Player(avatarState, simulator);

Expand All @@ -79,13 +82,13 @@ public void Use()
var battleStatusSkill = normalAttack.Use(
player,
0,
new List<StatBuff>());
new List<StatBuff>(),
copyCharacter);
Assert.NotNull(battleStatusSkill);
Assert.Single(battleStatusSkill.SkillInfos);

var skillInfo = battleStatusSkill.SkillInfos.FirstOrDefault();
Assert.NotNull(skillInfo);
Assert.Equal(enemy.Id, skillInfo.Target.Id);
Assert.Equal(!copyCharacter, battleStatusSkill.Character is null);
var skillInfo = Assert.Single(battleStatusSkill.SkillInfos);
Assert.Equal(enemy.Id, skillInfo.CharacterId);
Assert.Equal(!copyCharacter, skillInfo.Target is null);
}
}
}
68 changes: 32 additions & 36 deletions Lib9c.MessagePack/AccountStateDelta.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,35 @@ public struct AccountStateDelta : IAccountStateDelta
private IImmutableDictionary<Address, IValue> _states;
private IImmutableDictionary<(Address, Currency), BigInteger> _balances;
private IImmutableDictionary<Currency, BigInteger> _totalSupplies;

public IImmutableSet<Address> UpdatedAddresses => _states.Keys.ToImmutableHashSet();

public IImmutableSet<Address> StateUpdatedAddresses => _states.Keys.ToImmutableHashSet();

public IImmutableSet<(Address, Currency)> UpdatedFungibleAssets =>
_balances.Keys.ToImmutableHashSet();
private MockAccountDelta _delta;

public IImmutableSet<(Address, Currency)> TotalUpdatedFungibleAssets =>
ImmutableHashSet<(Address, Currency)>.Empty;

public IImmutableSet<Currency> UpdatedTotalSupplyCurrencies =>
_totalSupplies.Keys.ToImmutableHashSet();

public AccountStateDelta(
IImmutableDictionary<Address, IValue> states,
IImmutableDictionary<(Address, Currency), BigInteger> balances,
IImmutableDictionary<Currency, BigInteger> totalSupplies
)
{
_delta = new MockAccountDelta(states, balances, totalSupplies);
_states = states;
_balances = balances;
_totalSupplies = totalSupplies;
}

public AccountStateDelta(Dictionary states, List balances, Dictionary totalSupplies)
: this(
states.ToImmutableDictionary(
kv => new Address(kv.Key),
kv => kv.Value),
balances.Cast<Dictionary>().ToImmutableDictionary(
record => (new Address(((Binary)record["address"]).ByteArray), new Currency((Dictionary)record["currency"])),
record => (BigInteger)(Integer)record["amount"]),
totalSupplies.ToImmutableDictionary(
kv => new Currency(new Codec().Decode((Binary)kv.Key)),
kv => (BigInteger)(Integer)kv.Value))
{
// This assumes `states` consists of only Binary keys:
_states = states.ToImmutableDictionary(
kv => new Address(kv.Key),
kv => kv.Value
);

_balances = balances.Cast<Dictionary>().ToImmutableDictionary(
record => (new Address(((Binary)record["address"]).ByteArray), new Currency((Dictionary)record["currency"])),
record => (BigInteger)(Integer)record["amount"]
);

// This assumes `totalSupplies` consists of only Binary keys:
_totalSupplies = totalSupplies.ToImmutableDictionary(
kv => new Currency(new Codec().Decode((Binary)kv.Key)),
kv => (BigInteger)(Integer)kv.Value
);
}

public AccountStateDelta(IValue serialized)
Expand All @@ -77,7 +63,7 @@ public AccountStateDelta(byte[] bytes)
{
}

public IAccountDelta Delta => new MockAccountDelta();
public IAccountDelta Delta => _delta;

public IValue? GetState(Address address) =>
_states.ContainsKey(address)
Expand Down Expand Up @@ -245,18 +231,28 @@ public ValidatorSet GetValidatorSet()

private class MockAccountDelta : IAccountDelta
{
public MockAccountDelta()
private IImmutableDictionary<Address, IValue> _states;
private IImmutableDictionary<(Address, Currency), BigInteger> _fungibles;
private IImmutableDictionary<Currency, BigInteger> _totalSupplies;

public MockAccountDelta(
IImmutableDictionary<Address, IValue> states,
IImmutableDictionary<(Address, Currency), BigInteger> balances,
IImmutableDictionary<Currency, BigInteger> totalSupplies)
{
_states = states;
_fungibles = balances;
_totalSupplies = totalSupplies;
}

public IImmutableSet<Address> UpdatedAddresses => ImmutableHashSet<Address>.Empty;
public IImmutableSet<Address> StateUpdatedAddresses => ImmutableHashSet<Address>.Empty;
public IImmutableDictionary<Address, IValue> States => ImmutableDictionary<Address, IValue>.Empty;
public IImmutableSet<Address> FungibleUpdatedAddresses => ImmutableHashSet<Address>.Empty;
public IImmutableSet<(Address, Currency)> UpdatedFungibleAssets => ImmutableHashSet<(Address, Currency)>.Empty;
public IImmutableDictionary<(Address, Currency), BigInteger> Fungibles => ImmutableDictionary<(Address, Currency), BigInteger>.Empty;
public IImmutableSet<Currency> UpdatedTotalSupplyCurrencies => ImmutableHashSet<Currency>.Empty;
public IImmutableDictionary<Currency, BigInteger> TotalSupplies => ImmutableDictionary<Currency, BigInteger>.Empty;
public IImmutableSet<Address> UpdatedAddresses => StateUpdatedAddresses.Union(FungibleUpdatedAddresses);
public IImmutableSet<Address> StateUpdatedAddresses => _states.Keys.ToImmutableHashSet();
public IImmutableDictionary<Address, IValue> States => _states;
public IImmutableSet<Address> FungibleUpdatedAddresses => _fungibles.Keys.Select(pair => pair.Item1).ToImmutableHashSet();
public IImmutableSet<(Address, Currency)> UpdatedFungibleAssets => _fungibles.Keys.ToImmutableHashSet();
public IImmutableDictionary<(Address, Currency), BigInteger> Fungibles => _fungibles;
public IImmutableSet<Currency> UpdatedTotalSupplyCurrencies => _totalSupplies.Keys.ToImmutableHashSet();
public IImmutableDictionary<Currency, BigInteger> TotalSupplies => _totalSupplies;
public ValidatorSet? ValidatorSet => null;
}
}
Expand Down
5 changes: 4 additions & 1 deletion Lib9c/Action/CreateAvatar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,16 @@ public override IAccountStateDelta Execute(IActionContext context)
Log.Verbose("{AddressesHex}CreateAvatar CreateAvatarState: {Elapsed}", addressesHex, sw.Elapsed);
var ended = DateTimeOffset.UtcNow;
Log.Debug("{AddressesHex}CreateAvatar Total Executed Time: {Elapsed}", addressesHex, ended - started);
// TODO delete check blockIndex hard-fork this action
// Fix invalid mint crystal balance in internal network. main-net always mint 200_000
var mintingValue = context.BlockIndex > 7_210_000L ? 200_000 : 600_000;
return states
.SetState(signer, agentState.Serialize())
.SetState(inventoryAddress, avatarState.inventory.Serialize())
.SetState(worldInformationAddress, avatarState.worldInformation.Serialize())
.SetState(questListAddress, avatarState.questList.Serialize())
.SetState(avatarAddress, avatarState.SerializeV2())
.MintAsset(ctx, signer, 600_000 * CrystalCalculator.CRYSTAL);
.MintAsset(ctx, signer, mintingValue * CrystalCalculator.CRYSTAL);
}
}
}
2 changes: 2 additions & 0 deletions Lib9c/Action/CreateAvatar8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Nekoyume.Action
/// </summary>
[Serializable]
[ActionType("create_avatar8")]
[ActionObsolete(ActionObsoleteConfig.V200040ObsoleteIndex)]
public class CreateAvatar8 : GameAction, ICreateAvatarV2
{
public const string DeriveFormat = "avatar-state-{0}";
Expand Down Expand Up @@ -68,6 +69,7 @@ protected override void LoadPlainValueInternal(IImmutableDictionary<string, IVal
public override IAccountStateDelta Execute(IActionContext context)
{
context.UseGas(1);
CheckObsolete(ActionObsoleteConfig.V200040ObsoleteIndex, context);
IActionContext ctx = context;
var signer = ctx.Signer;
var states = ctx.PreviousState;
Expand Down
40 changes: 26 additions & 14 deletions Lib9c/Action/HackAndSlash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,14 @@ public IAccountStateDelta Execute(
}
}

var stageWaveRow = sheets.GetSheet<StageWaveSheet>()[StageId];
var enemySkillSheet = sheets.GetSheet<EnemySkillSheet>();
var costumeStatSheet = sheets.GetSheet<CostumeStatSheet>();
var stageCleared = !isNotClearedStage;
var starCount = 0;
for (var i = 0; i < TotalPlayCount; i++)
{
var rewards = StageSimulator.GetWaveRewards(random, stageRow, materialItemSheet);
sw.Restart();
// First simulating will use Foods and Random Skills.
// Remainder simulating will not use Foods.
Expand All @@ -453,13 +459,14 @@ public IAccountStateDelta Execute(
WorldId,
StageId,
stageRow,
sheets.GetSheet<StageWaveSheet>()[StageId],
avatarState.worldInformation.IsStageCleared(StageId),
stageWaveRow,
stageCleared,
StageRewardExpHelper.GetExp(avatarState.level, StageId),
simulatorSheets,
sheets.GetSheet<EnemySkillSheet>(),
sheets.GetSheet<CostumeStatSheet>(),
StageSimulator.GetWaveRewards(random, stageRow, materialItemSheet));
enemySkillSheet,
costumeStatSheet,
rewards,
false);
sw.Stop();
Log.Verbose("{AddressesHex}HAS Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed);

Expand All @@ -471,13 +478,17 @@ public IAccountStateDelta Execute(
sw.Restart();
if (simulator.Log.IsClear)
{
simulator.Player.worldInformation.ClearStage(
WorldId,
StageId,
blockIndex,
worldSheet,
worldUnlockSheet
);
if (!stageCleared)
{
avatarState.worldInformation.ClearStage(
WorldId,
StageId,
blockIndex,
worldSheet,
worldUnlockSheet
);
stageCleared = true;
}
sw.Stop();
Log.Verbose("{AddressesHex}HAS ClearStage: {Elapsed}", addressesHex, sw.Elapsed);
}
Expand All @@ -504,9 +515,8 @@ public IAccountStateDelta Execute(
player.eventMapForBeforeV100310.Clear();
}

starCount += simulator.Log.clearedWaveNumber;
avatarState.Update(simulator);
// Update CrystalRandomSkillState.Stars by clearedWaveNumber. (add)
skillState?.Update(simulator.Log.clearedWaveNumber, crystalStageBuffSheet);

sw.Stop();
Log.Verbose(
Expand All @@ -526,6 +536,8 @@ public IAccountStateDelta Execute(
Log.Verbose("{AddressesHex}HAS loop Simulate: {Elapsed}, Count: {PlayCount}",
addressesHex, sw.Elapsed, TotalPlayCount);

// Update CrystalRandomSkillState.Stars by clearedWaveNumber. (add)
skillState?.Update(starCount, crystalStageBuffSheet);
sw.Restart();
avatarState.UpdateQuestRewards(materialItemSheet);
avatarState.updatedAt = blockIndex;
Expand Down
2 changes: 2 additions & 0 deletions Lib9c/ActionObsoleteConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public static class ActionObsoleteConfig

public const long V200031ObsoleteIndex = 7_206_000;

public const long V200040ObsoleteIndex = 7_330_000L;

// While v200020, the action obsolete wasn't work well.
// So other previous `V*ObsoletedIndex`s lost its meaning and
// this block index will replace them.
Expand Down
Loading

0 comments on commit 3a30163

Please sign in to comment.