diff --git a/.Lib9c.DevExtensions.Tests/Action/CreateOrReplaceAvatarTest.cs b/.Lib9c.DevExtensions.Tests/Action/CreateOrReplaceAvatarTest.cs
index 702f89f8e8..948b3e6400 100644
--- a/.Lib9c.DevExtensions.Tests/Action/CreateOrReplaceAvatarTest.cs
+++ b/.Lib9c.DevExtensions.Tests/Action/CreateOrReplaceAvatarTest.cs
@@ -9,6 +9,7 @@
using Lib9c.Tests.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -30,7 +31,7 @@ public class CreateOrReplaceAvatarTest
public CreateOrReplaceAvatarTest()
{
- _initialStates = new World(new MockWorldState());
+ _initialStates = new World(MockUtil.MockModernWorldState);
#pragma warning disable CS0618
var ncgCurrency = Currency.Legacy("NCG", 2, null);
diff --git a/.Lib9c.DevExtensions.Tests/Action/FaucetCurrencyTest.cs b/.Lib9c.DevExtensions.Tests/Action/FaucetCurrencyTest.cs
index 2205f5c2e9..7b4fd7f1f4 100644
--- a/.Lib9c.DevExtensions.Tests/Action/FaucetCurrencyTest.cs
+++ b/.Lib9c.DevExtensions.Tests/Action/FaucetCurrencyTest.cs
@@ -2,6 +2,7 @@
using Lib9c.Tests.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume.Model.State;
using Nekoyume.Module;
@@ -30,9 +31,8 @@ public FaucetCurrencyTest(ITestOutputHelper outputHelper)
_crystal = Currency.Legacy("CRYSTAL", 18, null);
#pragma warning restore CS0618
- _initialState = new World(
- new MockWorldState()
- .AddBalance(GoldCurrencyState.Address, _ncg * int.MaxValue));
+ _initialState = new World(MockWorldState.CreateModern()
+ .SetBalance(GoldCurrencyState.Address, _ncg * int.MaxValue));
var goldCurrencyState = new GoldCurrencyState(_ncg);
_agentAddress = new PrivateKey().Address;
diff --git a/.Lib9c.DevExtensions.Tests/Action/FaucetRuneTest.cs b/.Lib9c.DevExtensions.Tests/Action/FaucetRuneTest.cs
index ae007716b1..293c5e5bb7 100644
--- a/.Lib9c.DevExtensions.Tests/Action/FaucetRuneTest.cs
+++ b/.Lib9c.DevExtensions.Tests/Action/FaucetRuneTest.cs
@@ -17,6 +17,7 @@
using Xunit;
using Xunit.Abstractions;
using static Lib9c.SerializeKeys;
+using Libplanet.Mocks;
namespace Lib9c.DevExtensions.Tests.Action
{
@@ -33,7 +34,7 @@ public FaucetRuneTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/AccountExtensions.cs b/.Lib9c.Tests/AccountExtensions.cs
deleted file mode 100644
index b1d821da39..0000000000
--- a/.Lib9c.Tests/AccountExtensions.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-namespace Lib9c.Tests
-{
- using Lib9c.Tests.Action;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Libplanet.Store.Trie;
-
- public static class AccountExtensions
- {
- private static readonly byte[] _conversionTable =
- {
- 48, // '0'
- 49, // '1'
- 50, // '2'
- 51, // '3'
- 52, // '4'
- 53, // '5'
- 54, // '6'
- 55, // '7'
- 56, // '8'
- 57, // '9'
- 97, // 'a'
- 98, // 'b'
- 99, // 'c'
- 100, // 'd'
- 101, // 'e'
- 102, // 'f'
- };
-
- ///
- /// A rather shrewed method of removing value from an account.
- /// This can be very slow depending on the size of the state.
- /// For test backward compatibility only. Should not be used in production.
- ///
- /// The account to remove the value from.
- /// The address of the value to remove.
- ///
- /// A new instance with the value removed.
- ///
- public static IAccount SetNull(this IAccount account, Address address)
- {
- var trie = new MockAccountState().Trie;
- var path = ToStateKey(address);
- foreach (var kv in account.Trie.IterateValues())
- {
- trie = kv.Path.Equals(path)
- ? trie
- : trie.Set(kv.Path, kv.Value);
- }
-
- return new Account(new AccountState(trie));
- }
-
- private static KeyBytes ToStateKey(Address address)
- {
- var addressBytes = address.ByteArray;
- byte[] buffer = new byte[addressBytes.Length * 2];
- for (int i = 0; i < addressBytes.Length; i++)
- {
- buffer[i * 2] = _conversionTable[addressBytes[i] >> 4];
- buffer[i * 2 + 1] = _conversionTable[addressBytes[i] & 0xf];
- }
-
- return new KeyBytes(buffer);
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/AccountStateDeltaExtensionsTest.cs b/.Lib9c.Tests/Action/AccountStateDeltaExtensionsTest.cs
index 569fc4f694..526186afe0 100644
--- a/.Lib9c.Tests/Action/AccountStateDeltaExtensionsTest.cs
+++ b/.Lib9c.Tests/Action/AccountStateDeltaExtensionsTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Helper;
using Nekoyume.Model.Coupons;
@@ -46,7 +47,7 @@ public AccountStateDeltaExtensionsTest()
public void SetWorldBossKillReward(int level, int expectedRune, int expectedCrystal, Type exc)
{
var context = new ActionContext();
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var rewardInfoAddress = new PrivateKey().Address;
var rewardRecord = new WorldBossKillRewardRecord();
for (int i = 0; i < level; i++)
@@ -106,7 +107,7 @@ public void SetWorldBossKillReward(int level, int expectedRune, int expectedCrys
[Fact]
public void SetCouponWallet()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var guid1 = new Guid("6856AE42-A820-4041-92B0-5D7BAA52F2AA");
var guid2 = new Guid("701BA698-CCB9-4FC7-B88F-7CB8C707D135");
var guid3 = new Guid("910296E7-34E4-45D7-9B4E-778ED61F278B");
@@ -162,7 +163,7 @@ public void Mead(int agentBalance)
var mead = Currencies.Mead;
var price = RequestPledge.DefaultRefillMead * mead;
ActionContext context = new ActionContext();
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
agentContractAddress,
List.Empty.Add(patron.Serialize()).Add(true.Serialize()))
diff --git a/.Lib9c.Tests/Action/AccountStateViewExtensionsTest.cs b/.Lib9c.Tests/Action/AccountStateViewExtensionsTest.cs
index 993eef78ad..748db0cfd5 100644
--- a/.Lib9c.Tests/Action/AccountStateViewExtensionsTest.cs
+++ b/.Lib9c.Tests/Action/AccountStateViewExtensionsTest.cs
@@ -9,6 +9,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Tests.Extensions;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -49,7 +50,7 @@ public AccountStateViewExtensionsTest()
[Fact]
public void TryGetAvatarStateEmptyAddress()
{
- var states = new World(new MockWorldState());
+ var states = new World(MockUtil.MockModernWorldState);
Assert.False(states.TryGetAvatarState(default, default, out _));
}
@@ -57,7 +58,7 @@ public void TryGetAvatarStateEmptyAddress()
[Fact]
public void TryGetAvatarStateAddressKeyNotFoundException()
{
- var states = new World(new MockWorldState()).SetLegacyState(default, Dictionary.Empty);
+ var states = new World(MockUtil.MockModernWorldState).SetLegacyState(default, Dictionary.Empty);
Assert.False(states.TryGetAvatarState(default, default, out _));
}
@@ -65,7 +66,7 @@ public void TryGetAvatarStateAddressKeyNotFoundException()
[Fact]
public void TryGetAvatarStateKeyNotFoundException()
{
- var states = new World(new MockWorldState())
+ var states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
default,
Dictionary.Empty
@@ -78,7 +79,7 @@ public void TryGetAvatarStateKeyNotFoundException()
[Fact]
public void TryGetAvatarStateInvalidCastException()
{
- var states = new World(new MockWorldState()).SetLegacyState(default, default(Text));
+ var states = new World(MockUtil.MockModernWorldState).SetLegacyState(default, default(Text));
Assert.False(states.TryGetAvatarState(default, default, out _));
}
@@ -86,7 +87,7 @@ public void TryGetAvatarStateInvalidCastException()
[Fact]
public void TryGetAvatarStateInvalidAddress()
{
- var states = new World(new MockWorldState()).SetAvatarState(default, _avatarState);
+ var states = new World(MockUtil.MockModernWorldState).SetAvatarState(default, _avatarState);
Assert.False(states.TryGetAvatarState(Addresses.GameConfig, _avatarAddress, out _));
}
@@ -94,7 +95,7 @@ public void TryGetAvatarStateInvalidAddress()
[Fact]
public void GetAvatarStateV2()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
states = states
.SetAvatarState(_avatarAddress, _avatarState);
@@ -118,12 +119,12 @@ public void GetAvatarStateV2_Throw_FailedLoadStateException(string account)
_ => throw new ArgumentException(),
};
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
states = states
.SetAvatarState(_avatarAddress, _avatarState);
states = states.SetAccount(
accountAddress,
- states.GetAccount(accountAddress).SetNull(_avatarAddress));
+ states.GetAccount(accountAddress).RemoveState(_avatarAddress));
var exc = Assert.Throws(() => states.GetAvatarState(_avatarAddress));
Assert.Contains(account, exc.Message);
}
@@ -133,7 +134,7 @@ public void GetAvatarStateV2_Throw_FailedLoadStateException(string account)
[InlineData(false)]
public void TryGetAvatarState(bool backward)
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
if (backward)
{
states = states
@@ -151,7 +152,7 @@ public void TryGetAvatarState(bool backward)
[Fact]
public void GetStatesAsDict()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var dict = new Dictionary
{
{ new PrivateKey().Address, Null.Value },
@@ -178,7 +179,7 @@ public void GetStatesAsDict()
[Fact]
public void GetSheets()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
SheetsExtensionsTest.InitSheets(
states,
out _,
@@ -205,7 +206,7 @@ public void GetSheets()
[InlineData(true)]
public void GetCrystalCostState(bool exist)
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
int expectedCount = exist ? 1 : 0;
FungibleAssetValue expectedCrystal = exist
? 100 * CrystalCalculator.CRYSTAL
@@ -238,7 +239,7 @@ public void GetCrystalCostStates(long blockIndex, bool previousWeeklyExist)
Address previousCostAddress = Addresses.GetWeeklyCrystalCostAddress(weeklyIndex - 1);
Address beforePreviousCostAddress = Addresses.GetWeeklyCrystalCostAddress(weeklyIndex - 2);
var crystalCostState = new CrystalCostState(default, 100 * CrystalCalculator.CRYSTAL);
- IWorld state = new World(new MockWorldState())
+ IWorld state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(dailyCostAddress, crystalCostState.Serialize())
.SetLegacyState(weeklyCostAddress, crystalCostState.Serialize())
.SetLegacyState(previousCostAddress, crystalCostState.Serialize())
@@ -268,7 +269,7 @@ public void GetCrystalCostStates(long blockIndex, bool previousWeeklyExist)
[Fact]
public void GetCouponWallet()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var guid1 = new Guid("6856AE42-A820-4041-92B0-5D7BAA52F2AA");
var guid2 = new Guid("701BA698-CCB9-4FC7-B88F-7CB8C707D135");
var guid3 = new Guid("910296E7-34E4-45D7-9B4E-778ED61F278B");
diff --git a/.Lib9c.Tests/Action/ActionContextExtensionsTest.cs b/.Lib9c.Tests/Action/ActionContextExtensionsTest.cs
index 50dd23f3b0..6af16f6417 100644
--- a/.Lib9c.Tests/Action/ActionContextExtensionsTest.cs
+++ b/.Lib9c.Tests/Action/ActionContextExtensionsTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -143,7 +144,7 @@ public static IEnumerable IsPreviewNetTestcases()
[MemberData(nameof(IsMainNetTestcases))]
public void IsMainNet(GoldCurrencyState goldCurrencyState, bool expected)
{
- var state = new World(new MockWorldState()).SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize());
+ var state = new World(MockUtil.MockModernWorldState).SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize());
IActionContext context = new ActionContext
{
PreviousState = state,
diff --git a/.Lib9c.Tests/Action/ActionEvaluationTest.cs b/.Lib9c.Tests/Action/ActionEvaluationTest.cs
index d6ee4a2392..a897fbbff2 100644
--- a/.Lib9c.Tests/Action/ActionEvaluationTest.cs
+++ b/.Lib9c.Tests/Action/ActionEvaluationTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Formatters;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using MessagePack;
using MessagePack.Resolvers;
@@ -34,7 +35,7 @@ public ActionEvaluationTest()
#pragma warning restore CS0618
_signer = new PrivateKey().Address;
_sender = new PrivateKey().Address;
- _states = new World(new MockWorldState())
+ _states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(_signer, (Text)"ANYTHING")
.SetLegacyState(default, Dictionary.Empty.Add("key", "value"))
.MintAsset(context, _signer, _currency * 10000);
diff --git a/.Lib9c.Tests/Action/ActivateAccount0Test.cs b/.Lib9c.Tests/Action/ActivateAccount0Test.cs
deleted file mode 100644
index 2066fd1040..0000000000
--- a/.Lib9c.Tests/Action/ActivateAccount0Test.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System.Collections.Immutable;
- using Bencodex.Types;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Nekoyume.Action;
- using Nekoyume.Model;
- using Nekoyume.Model.State;
- using Nekoyume.Module;
- using Xunit;
-
- public class ActivateAccount0Test
- {
- [Fact]
- public void Execute()
- {
- var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
- var privateKey = new PrivateKey();
- (ActivationKey activationKey, PendingActivationState pendingActivation) =
- ActivationKey.Create(privateKey, nonce);
- var state = new World(
- new MockWorldState()
- .SetState(
- ReservedAddresses.LegacyAccount,
- ActivatedAccountsState.Address,
- new ActivatedAccountsState().Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
- pendingActivation.address,
- pendingActivation.Serialize()));
-
- ActivateAccount0 action = activationKey.CreateActivateAccount0(nonce);
- IWorld nextState = action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = default,
- BlockIndex = 1,
- });
-
- var activatedAccounts = new ActivatedAccountsState(
- (Dictionary)nextState.GetLegacyState(ActivatedAccountsState.Address)
- );
- Assert.Equal(
- new[] { default(Address) }.ToImmutableHashSet(),
- activatedAccounts.Accounts);
- }
-
- [Fact]
- public void ExecuteWithInvalidSignature()
- {
- var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
- var privateKey = new PrivateKey();
- (ActivationKey activationKey, PendingActivationState pendingActivation) =
- ActivationKey.Create(privateKey, nonce);
- var state = new World(
- new MockWorldState()
- .SetState(
- ReservedAddresses.LegacyAccount,
- ActivatedAccountsState.Address,
- new ActivatedAccountsState().Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
- pendingActivation.address,
- pendingActivation.Serialize()));
-
- // 잘못된 논스를 넣습니다.
- ActivateAccount0 action = activationKey.CreateActivateAccount0(new byte[] { 0x00, });
- Assert.Throws(() =>
- {
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = default,
- BlockIndex = 1,
- });
- });
- }
-
- [Fact]
- public void ExecuteWithNonExistsPending()
- {
- var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
- var privateKey = new PrivateKey();
- (ActivationKey activationKey, PendingActivationState pendingActivation) =
- ActivationKey.Create(privateKey, nonce);
-
- // state에는 pendingActivation에 해당하는 대기가 없는 상태를 가정합니다.
- var state = new World(
- new MockWorldState()
- .SetState(
- ReservedAddresses.LegacyAccount,
- ActivatedAccountsState.Address,
- new ActivatedAccountsState().Serialize()));
-
- ActivateAccount0 action = activationKey.CreateActivateAccount0(nonce);
- Assert.Throws(() =>
- {
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = default,
- BlockIndex = 1,
- });
- });
- }
-
- [Fact]
- public void ExecuteWithNonExistsAccounts()
- {
- var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
- var privateKey = new PrivateKey();
- (ActivationKey activationKey, PendingActivationState pendingActivation) =
- ActivationKey.Create(privateKey, nonce);
-
- // state가 올바르게 초기화되지 않은 상태를 가정합니다.
- var state = new World(new MockWorldState());
-
- ActivateAccount0 action = activationKey.CreateActivateAccount0(nonce);
- Assert.Throws(() =>
- {
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = default,
- BlockIndex = 1,
- });
- });
- }
-
- [Fact]
- public void ForbidReusingActivationKey()
- {
- var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
- var privateKey = new PrivateKey();
- (ActivationKey activationKey, PendingActivationState pendingActivation) =
- ActivationKey.Create(privateKey, nonce);
- var state = new World(
- new MockWorldState()
- .SetState(
- ReservedAddresses.LegacyAccount,
- ActivatedAccountsState.Address,
- new ActivatedAccountsState().Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
- pendingActivation.address,
- pendingActivation.Serialize()));
-
- ActivateAccount0 action = activationKey.CreateActivateAccount0(nonce);
- IWorld nextState = action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = default,
- BlockIndex = 1,
- });
-
- Assert.Throws(() =>
- {
- action.Execute(new ActionContext()
- {
- PreviousState = nextState,
- Signer = new Address("399bddF9F7B6d902ea27037B907B2486C9910730"),
- BlockIndex = 2,
- });
- });
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/ActivateAccountTest.cs b/.Lib9c.Tests/Action/ActivateAccountTest.cs
index 752ea3dbac..0aa531f1bf 100644
--- a/.Lib9c.Tests/Action/ActivateAccountTest.cs
+++ b/.Lib9c.Tests/Action/ActivateAccountTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model;
using Nekoyume.Model.State;
@@ -25,7 +26,7 @@ public void Execute(bool invalid, bool pendingExist, bool alreadyActivated, Type
ActivationKey.Create(privateKey, nonce);
Address activatedAddress = default(Address).Derive(ActivationKey.DeriveKey);
- IWorld state = new World(new MockWorldState());
+ IWorld state = new World(MockUtil.MockModernWorldState);
if (pendingExist)
{
diff --git a/.Lib9c.Tests/Action/ActivateCollectionTest.cs b/.Lib9c.Tests/Action/ActivateCollectionTest.cs
index 40ecd9fe93..fd48733be3 100644
--- a/.Lib9c.Tests/Action/ActivateCollectionTest.cs
+++ b/.Lib9c.Tests/Action/ActivateCollectionTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.Collection;
@@ -50,7 +51,7 @@ public ActivateCollectionTest()
};
agentState.avatarAddresses.Add(0, _avatarAddress);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(_agentAddress, agentState)
.SetAvatarState(_avatarAddress, avatarState, true, true, true, true)
.SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
diff --git a/.Lib9c.Tests/Action/AddActivatedAccountTest.cs b/.Lib9c.Tests/Action/AddActivatedAccountTest.cs
index 41c7e4e9fd..9a4240fc54 100644
--- a/.Lib9c.Tests/Action/AddActivatedAccountTest.cs
+++ b/.Lib9c.Tests/Action/AddActivatedAccountTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using System;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model;
using Nekoyume.Model.State;
@@ -19,9 +20,8 @@ public class AddActivatedAccountTest
public void Execute(bool isAdmin, long blockIndex, bool alreadyActivated, Type exc)
{
var admin = new Address("8d9f76aF8Dc5A812aCeA15d8bf56E2F790F47fd7");
- IWorld state = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, new AdminState(admin, 100).Serialize()));
+ IWorld state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, new AdminState(admin, 100).Serialize());
var newComer = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var activatedAddress = newComer.Derive(ActivationKey.DeriveKey);
if (alreadyActivated)
diff --git a/.Lib9c.Tests/Action/AddRedeemCodeTest.cs b/.Lib9c.Tests/Action/AddRedeemCodeTest.cs
index c9cdb81c6c..7e04a39cdf 100644
--- a/.Lib9c.Tests/Action/AddRedeemCodeTest.cs
+++ b/.Lib9c.Tests/Action/AddRedeemCodeTest.cs
@@ -2,6 +2,7 @@ namespace Lib9c.Tests.Action
{
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -16,9 +17,8 @@ public void CheckPermission()
{
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var initStates = new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize());
- var state = new World(initStates);
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
var action = new AddRedeemCode
{
redeemCsv = "New Value",
@@ -68,7 +68,7 @@ public void Execute()
{
Signer = adminAddress,
BlockIndex = 0,
- PreviousState = new World(new MockWorldState())
+ PreviousState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.Admin, adminState.Serialize())
.SetLegacyState(Addresses.RedeemCode, new RedeemCodeState(new RedeemCodeListSheet()).Serialize()),
});
@@ -90,7 +90,7 @@ public void ExecuteThrowSheetRowValidateException()
var sheet = new RedeemCodeListSheet();
sheet.Set(csv);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.RedeemCode, new RedeemCodeState(sheet).Serialize());
var action = new AddRedeemCode
diff --git a/.Lib9c.Tests/Action/ApprovePledgeTest.cs b/.Lib9c.Tests/Action/ApprovePledgeTest.cs
index fef336d40d..f0aaddfcef 100644
--- a/.Lib9c.Tests/Action/ApprovePledgeTest.cs
+++ b/.Lib9c.Tests/Action/ApprovePledgeTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -20,7 +21,7 @@ public void Execute(int mead)
var address = new PrivateKey().Address;
var patron = new PrivateKey().Address;
var contractAddress = address.Derive(nameof(RequestPledge));
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
contractAddress,
List.Empty.Add(patron.Serialize()).Add(false.Serialize()).Add(mead.Serialize())
@@ -62,7 +63,7 @@ public void Execute_Throw_Exception(bool invalidPatron, bool alreadyContract, Ty
contract = List.Empty.Add(patron.Serialize()).Add(true.Serialize());
}
- IWorld states = new World(new MockWorldState()).SetLegacyState(contractAddress, contract);
+ IWorld states = new World(MockUtil.MockModernWorldState).SetLegacyState(contractAddress, contract);
var action = new ApprovePledge
{
diff --git a/.Lib9c.Tests/Action/ArenahelperTest.cs b/.Lib9c.Tests/Action/ArenahelperTest.cs
index cda73b8043..7f94084a3e 100644
--- a/.Lib9c.Tests/Action/ArenahelperTest.cs
+++ b/.Lib9c.Tests/Action/ArenahelperTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -35,7 +36,7 @@ public ArenaHelperTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
var tableSheets = new TableSheets(sheets);
diff --git a/.Lib9c.Tests/Action/BattleArenaTest.cs b/.Lib9c.Tests/Action/BattleArenaTest.cs
index 23397678b2..76b680273e 100644
--- a/.Lib9c.Tests/Action/BattleArenaTest.cs
+++ b/.Lib9c.Tests/Action/BattleArenaTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -47,7 +48,7 @@ public BattleArenaTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialStates = new World(new MockWorldState());
+ _initialStates = new World(MockUtil.MockModernWorldState);
_sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in _sheets)
diff --git a/.Lib9c.Tests/Action/BurnAssetTest.cs b/.Lib9c.Tests/Action/BurnAssetTest.cs
index 5a05f505c6..5d90e088b0 100644
--- a/.Lib9c.Tests/Action/BurnAssetTest.cs
+++ b/.Lib9c.Tests/Action/BurnAssetTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Exceptions;
using Nekoyume.Module;
@@ -20,17 +21,14 @@ public BurnAssetTest()
{
_signer = new PrivateKey().Address;
_prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_signer, Currencies.Crystal * 100)
.SetBalance(
_signer.Derive(string.Format(
CultureInfo.InvariantCulture,
CreateAvatar.DeriveFormat,
- 1
- )),
- Currencies.DailyRewardRune * 20
- )
- );
+ 1)),
+ Currencies.DailyRewardRune * 20));
}
[Fact]
diff --git a/.Lib9c.Tests/Action/Buy7Test.cs b/.Lib9c.Tests/Action/Buy7Test.cs
index 08543d57c3..508cb5e3b6 100644
--- a/.Lib9c.Tests/Action/Buy7Test.cs
+++ b/.Lib9c.Tests/Action/Buy7Test.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -40,7 +41,7 @@ public Buy7Test(ITestOutputHelper outputHelper)
.CreateLogger();
var context = new ActionContext();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -444,7 +445,7 @@ public void Execute_Throw_FailedLoadStateException()
Assert.Throws(() => action.Execute(new ActionContext()
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
RandomSeed = 0,
Signer = _buyerAgentAddress,
})
diff --git a/.Lib9c.Tests/Action/BuyMultipleTest.cs b/.Lib9c.Tests/Action/BuyMultipleTest.cs
index 5aae102522..3f212dd6bb 100644
--- a/.Lib9c.Tests/Action/BuyMultipleTest.cs
+++ b/.Lib9c.Tests/Action/BuyMultipleTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using System.Numerics;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -35,7 +36,7 @@ public BuyMultipleTest(ITestOutputHelper outputHelper)
.CreateLogger();
var context = new ActionContext();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -407,7 +408,7 @@ public void ExecuteThrowInvalidAddressException()
Assert.Throws(() => action.Execute(new ActionContext()
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
RandomSeed = 0,
Signer = _buyerAgentAddress,
})
@@ -426,7 +427,7 @@ public void ExecuteThrowFailedLoadStateException()
Assert.Throws(() => action.Execute(new ActionContext()
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
RandomSeed = 0,
Signer = _buyerAgentAddress,
})
diff --git a/.Lib9c.Tests/Action/BuyProductTest.cs b/.Lib9c.Tests/Action/BuyProductTest.cs
index 509175c5ee..20327a1570 100644
--- a/.Lib9c.Tests/Action/BuyProductTest.cs
+++ b/.Lib9c.Tests/Action/BuyProductTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -46,7 +47,7 @@ public BuyProductTest(ITestOutputHelper outputHelper)
.CreateLogger();
var context = new ActionContext();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/BuyTest.cs b/.Lib9c.Tests/Action/BuyTest.cs
index 9ad40c8916..ceb1408701 100644
--- a/.Lib9c.Tests/Action/BuyTest.cs
+++ b/.Lib9c.Tests/Action/BuyTest.cs
@@ -11,6 +11,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Tests.TestHelper;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -45,7 +46,7 @@ public BuyTest(ITestOutputHelper outputHelper)
.CreateLogger();
var context = new ActionContext();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/CancelProductRegistration0Test.cs b/.Lib9c.Tests/Action/CancelProductRegistrationTest.cs
similarity index 94%
rename from .Lib9c.Tests/Action/CancelProductRegistration0Test.cs
rename to .Lib9c.Tests/Action/CancelProductRegistrationTest.cs
index 97b097daaa..c25149aa93 100644
--- a/.Lib9c.Tests/Action/CancelProductRegistration0Test.cs
+++ b/.Lib9c.Tests/Action/CancelProductRegistrationTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -17,7 +18,7 @@ namespace Lib9c.Tests.Action
using Xunit;
using Xunit.Abstractions;
- public class CancelProductRegistration0Test
+ public class CancelProductRegistrationTest
{
private readonly IWorld _initialState;
private readonly Address _agentAddress;
@@ -26,14 +27,14 @@ public class CancelProductRegistration0Test
private readonly TableSheets _tableSheets;
private readonly GameConfigState _gameConfigState;
- public CancelProductRegistration0Test(ITestOutputHelper outputHelper)
+ public CancelProductRegistrationTest(ITestOutputHelper outputHelper)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -84,7 +85,7 @@ public void Execute_Throw_InvalidAddressException(
bool invalidAgentAddress
)
{
- var action = new CancelProductRegistration0
+ var action = new CancelProductRegistration
{
AvatarAddress = _avatarAddress,
ProductInfos = new List
@@ -159,7 +160,7 @@ public void Execute_Throw_ProductNotFoundException()
(List)nexState.GetLegacyState(ProductsState.DeriveAddress(_avatarAddress)));
var productId = Assert.Single(productsState.ProductIds);
- var action = new CancelProductRegistration0
+ var action = new CancelProductRegistration
{
AvatarAddress = _avatarAddress,
ProductInfos = new List
@@ -196,12 +197,12 @@ public void Execute_Throw_ProductNotFoundException()
public void Execute_Throw_ArgumentOutOfRangeException()
{
var productInfos = new List();
- for (int i = 0; i < CancelProductRegistration0.Capacity + 1; i++)
+ for (int i = 0; i < CancelProductRegistration.Capacity + 1; i++)
{
productInfos.Add(new ItemProductInfo());
}
- var action = new CancelProductRegistration0
+ var action = new CancelProductRegistration
{
AvatarAddress = _avatarAddress,
ProductInfos = productInfos,
diff --git a/.Lib9c.Tests/Action/ChargeActionPointTest.cs b/.Lib9c.Tests/Action/ChargeActionPointTest.cs
index 258b691cdd..2b57f745f7 100644
--- a/.Lib9c.Tests/Action/ChargeActionPointTest.cs
+++ b/.Lib9c.Tests/Action/ChargeActionPointTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.Item;
@@ -46,7 +47,7 @@ public ChargeActionPointTest()
};
agent.avatarAddresses.Add(0, _avatarAddress);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.GameConfig, gameConfigState.Serialize())
.SetAgentState(_agentAddress, agent)
.SetAvatarState(_avatarAddress, avatarState);
diff --git a/.Lib9c.Tests/Action/ClaimItemsTest.cs b/.Lib9c.Tests/Action/ClaimItemsTest.cs
index c74ddb646d..d358703d7a 100644
--- a/.Lib9c.Tests/Action/ClaimItemsTest.cs
+++ b/.Lib9c.Tests/Action/ClaimItemsTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -36,7 +37,7 @@ public ClaimItemsTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
diff --git a/.Lib9c.Tests/Action/ClaimRaidRewardTest.cs b/.Lib9c.Tests/Action/ClaimRaidRewardTest.cs
index d2a07dfead..541bb31d29 100644
--- a/.Lib9c.Tests/Action/ClaimRaidRewardTest.cs
+++ b/.Lib9c.Tests/Action/ClaimRaidRewardTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Helper;
@@ -20,7 +21,7 @@ public ClaimRaidRewardTest()
{
var tableCsv = TableSheetsImporter.ImportSheets();
_tableSheets = new TableSheets(tableCsv);
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
foreach (var kv in tableCsv)
{
_state = _state.SetLegacyState(Addresses.GetSheetAddress(kv.Key), kv.Value.Serialize());
diff --git a/.Lib9c.Tests/Action/ClaimWorldBossKillRewardTest.cs b/.Lib9c.Tests/Action/ClaimWorldBossKillRewardTest.cs
index ce8f01a076..cafdbc156e 100644
--- a/.Lib9c.Tests/Action/ClaimWorldBossKillRewardTest.cs
+++ b/.Lib9c.Tests/Action/ClaimWorldBossKillRewardTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -27,7 +28,7 @@ public void Execute(long blockIndex, Type exc)
var tableSheets = new TableSheets(sheets);
Address agentAddress = new PrivateKey().Address;
Address avatarAddress = new PrivateKey().Address;
- IWorld state = new World(new MockWorldState());
+ IWorld state = new World(MockUtil.MockModernWorldState);
var runeWeightSheet = new RuneWeightSheet();
runeWeightSheet.Set(@"id,boss_id,rank,rune_id,weight
diff --git a/.Lib9c.Tests/Action/CombinationConsumableTest.cs b/.Lib9c.Tests/Action/CombinationConsumableTest.cs
new file mode 100644
index 0000000000..00116f45b5
--- /dev/null
+++ b/.Lib9c.Tests/Action/CombinationConsumableTest.cs
@@ -0,0 +1,134 @@
+namespace Lib9c.Tests.Action
+{
+ using System.Globalization;
+ using System.Linq;
+ using Libplanet.Action;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Model;
+ using Nekoyume.Model.Item;
+ using Nekoyume.Model.Mail;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Xunit;
+
+ public class CombinationConsumableTest
+ {
+ private readonly Address _agentAddress;
+ private readonly Address _avatarAddress;
+ private readonly IRandom _random;
+ private readonly TableSheets _tableSheets;
+ private IWorld _initialState;
+
+ public CombinationConsumableTest()
+ {
+ _agentAddress = new PrivateKey().Address;
+ _avatarAddress = _agentAddress.Derive("avatar");
+ var slotAddress = _avatarAddress.Derive(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0
+ )
+ );
+ var sheets = TableSheetsImporter.ImportSheets();
+ _random = new TestRandom();
+ _tableSheets = new TableSheets(sheets);
+
+ var agentState = new AgentState(_agentAddress);
+ agentState.avatarAddresses[0] = _avatarAddress;
+
+ var gameConfigState = new GameConfigState();
+
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 1,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ default
+ );
+
+#pragma warning disable CS0618
+ // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
+ var gold = new GoldCurrencyState(Currency.Legacy("NCG", 2, null));
+#pragma warning restore CS0618
+
+ _initialState = new World(MockUtil.MockModernWorldState)
+ .SetAgentState(_agentAddress, agentState)
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(
+ slotAddress,
+ new CombinationSlotState(
+ slotAddress,
+ GameConfig.RequireClearedStageLevel.CombinationConsumableAction).Serialize())
+ .SetLegacyState(GameConfigState.Address, gold.Serialize());
+
+ foreach (var (key, value) in sheets)
+ {
+ _initialState =
+ _initialState.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+ }
+
+ [Fact]
+ public void Execute()
+ {
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ var row = _tableSheets.ConsumableItemRecipeSheet.Values.First();
+ var costActionPoint = row.RequiredActionPoint;
+ foreach (var materialInfo in row.Materials)
+ {
+ var materialRow = _tableSheets.MaterialItemSheet[materialInfo.Id];
+ var material = ItemFactory.CreateItem(materialRow, _random);
+ avatarState.inventory.AddItem(material, materialInfo.Count);
+ }
+
+ var previousActionPoint = avatarState.actionPoint;
+ var previousResultConsumableCount =
+ avatarState.inventory.Equipments.Count(e => e.Id == row.ResultConsumableItemId);
+ var previousMailCount = avatarState.mailBox.Count;
+
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _tableSheets.WorldSheet,
+ GameConfig.RequireClearedStageLevel.CombinationConsumableAction);
+
+ IWorld previousState = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var action = new CombinationConsumable
+ {
+ avatarAddress = _avatarAddress,
+ recipeId = row.Id,
+ slotIndex = 0,
+ };
+
+ var nextState = action.Execute(new ActionContext
+ {
+ PreviousState = previousState,
+ Signer = _agentAddress,
+ BlockIndex = 1,
+ RandomSeed = _random.Seed,
+ });
+
+ var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0);
+ Assert.NotNull(slotState.Result);
+ Assert.NotNull(slotState.Result.itemUsable);
+
+ var consumable = (Consumable)slotState.Result.itemUsable;
+ Assert.NotNull(consumable);
+
+ var nextAvatarState = nextState.GetAvatarState(_avatarAddress);
+ Assert.Equal(previousActionPoint - costActionPoint, nextAvatarState.actionPoint);
+ Assert.Equal(previousMailCount + 1, nextAvatarState.mailBox.Count);
+ Assert.IsType(nextAvatarState.mailBox.First());
+ Assert.Equal(
+ previousResultConsumableCount + 1,
+ nextAvatarState.inventory.Consumables.Count(e => e.Id == row.ResultConsumableItemId));
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/CombinationEquipmentTest.cs b/.Lib9c.Tests/Action/CombinationEquipmentTest.cs
index e790df9d75..fe9b374b27 100644
--- a/.Lib9c.Tests/Action/CombinationEquipmentTest.cs
+++ b/.Lib9c.Tests/Action/CombinationEquipmentTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -76,7 +77,7 @@ public CombinationEquipmentTest(ITestOutputHelper outputHelper)
_slotAddress,
0);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(_slotAddress, combinationSlotState.Serialize())
.SetLegacyState(GoldCurrencyState.Address, gold.Serialize());
diff --git a/.Lib9c.Tests/Action/Common/MockAccountState.cs b/.Lib9c.Tests/Action/Common/MockAccountState.cs
deleted file mode 100644
index ed31addbf5..0000000000
--- a/.Lib9c.Tests/Action/Common/MockAccountState.cs
+++ /dev/null
@@ -1,219 +0,0 @@
-#nullable enable
-namespace Lib9c.Tests.Action
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Numerics;
- using System.Security.Cryptography;
- using Bencodex.Types;
- using Libplanet.Action.State;
- using Libplanet.Common;
- using Libplanet.Crypto;
- using Libplanet.Store;
- using Libplanet.Store.Trie;
- using Libplanet.Types.Assets;
- using Libplanet.Types.Consensus;
-
- ///
- /// A mock implementation of with various overloaded methods for
- /// improving QoL.
- ///
- ///
- /// All methods are pretty self-explanatory with no side-effects. There are some caveats:
- ///
- ///
- /// Every balance related operation can accept a negative amount. Each behave as expected.
- /// That is, adding negative amount would decrease the balance.
- ///
- ///
- /// Negative balance is allowed for all cases. This includes total supply.
- ///
- ///
- /// Total supply is not automatically tracked. That is, changing the balance associated
- /// with an does not change the total supply in any way.
- /// Total supply must be explicitly set if needed.
- ///
- ///
- /// There are only few restrictions that apply for manipulating this object, mostly
- /// pertaining to total supplies:
- ///
- ///
- /// It is not possible to set a total supply amount for a currency that is
- /// not trackable.
- ///
- ///
- /// It is not possible to set a total supply amount that is over the currency's
- /// capped maximum total supply.
- ///
- ///
- ///
- ///
- ///
- public class MockAccountState : IAccountState
- {
- private readonly IStateStore _stateStore;
-
- public MockAccountState()
- : this(new TrieStateStore(new MemoryKeyValueStore()), null)
- {
- }
-
- public MockAccountState(
- IStateStore stateStore,
- HashDigest? stateRootHash = null)
- {
- _stateStore = stateStore;
- Trie = stateStore.GetStateRoot(stateRootHash);
- }
-
- public ITrie Trie { get; }
-
- public IValue? GetState(Address address) =>
- Trie.Get(MockKeyConverters.ToStateKey(address));
-
- public IReadOnlyList GetStates(IReadOnlyList addresses) =>
- addresses.Select(GetState).ToList();
-
- public FungibleAssetValue GetBalance(Address address, Currency currency) =>
- Trie.Get(MockKeyConverters.ToFungibleAssetKey(address, currency)) is Integer rawValue
- ? FungibleAssetValue.FromRawValue(currency, rawValue)
- : currency * 0;
-
- public FungibleAssetValue GetTotalSupply(Currency currency)
- {
- if (!currency.TotalSupplyTrackable)
- {
- var msg =
- $"The total supply value of the currency {currency} is not trackable " +
- "because it is a legacy untracked currency which might have been" +
- "established before the introduction of total supply tracking support.";
- throw new TotalSupplyNotTrackableException(msg, currency);
- }
-
- return Trie.Get(MockKeyConverters.ToTotalSupplyKey(currency)) is Integer rawValue
- ? FungibleAssetValue.FromRawValue(currency, rawValue)
- : currency * 0;
- }
-
- public ValidatorSet GetValidatorSet() =>
- Trie.Get(MockKeyConverters.ValidatorSetKey) is List list
- ? new ValidatorSet(list)
- : new ValidatorSet();
-
- public MockAccountState SetState(Address address, IValue state) =>
- new MockAccountState(
- _stateStore,
- _stateStore.Commit(Trie.Set(MockKeyConverters.ToStateKey(address), state)).Hash);
-
- public MockAccountState SetBalance(
- Address address, FungibleAssetValue amount) =>
- SetBalance((address, amount.Currency), amount.RawValue);
-
- public MockAccountState SetBalance(
- Address address, Currency currency, BigInteger rawAmount) =>
- SetBalance((address, currency), rawAmount);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState SetBalance(
- (Address Address, Currency Currency) pair, BigInteger rawAmount) =>
- new MockAccountState(
- _stateStore,
- _stateStore.Commit(
- Trie.Set(
- MockKeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency),
- new Integer(rawAmount))).Hash);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockAccountState AddBalance(Address address, FungibleAssetValue amount) =>
- AddBalance((address, amount.Currency), amount.RawValue);
-
- public MockAccountState AddBalance(
- Address address, Currency currency, BigInteger rawAmount) =>
- AddBalance((address, currency), rawAmount);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState AddBalance(
- (Address Address, Currency Currency) pair, BigInteger rawAmount) =>
- SetBalance(
- pair,
- (Trie.Get(MockKeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency)) is
- Integer amount ? amount : 0) + rawAmount);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockAccountState SubtractBalance(
- Address address, FungibleAssetValue amount) =>
- SubtractBalance((address, amount.Currency), amount.RawValue);
-
- public MockAccountState SubtractBalance(
- Address address, Currency currency, BigInteger rawAmount) =>
- SubtractBalance((address, currency), rawAmount);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState SubtractBalance(
- (Address Address, Currency Currency) pair, BigInteger rawAmount) =>
- SetBalance(
- pair,
- (Trie.Get(MockKeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency)) is
- Integer amount ? amount : 0) - rawAmount);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockAccountState TransferBalance(
- Address sender, Address recipient, FungibleAssetValue amount) =>
- TransferBalance(sender, recipient, amount.Currency, amount.RawValue);
-
- public MockAccountState TransferBalance(
- Address sender, Address recipient, Currency currency, BigInteger rawAmount) =>
- SubtractBalance(sender, currency, rawAmount).AddBalance(recipient, currency, rawAmount);
-
- public MockAccountState SetTotalSupply(FungibleAssetValue amount) =>
- SetTotalSupply(amount.Currency, amount.RawValue);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState SetTotalSupply(Currency currency, BigInteger rawAmount) =>
- currency.TotalSupplyTrackable
- ? !(currency.MaximumSupply is FungibleAssetValue maximumSupply) ||
- rawAmount <= maximumSupply.RawValue
- ? new MockAccountState(
- _stateStore,
- _stateStore.Commit(
- Trie.Set(MockKeyConverters.ToTotalSupplyKey(currency), new Integer(rawAmount))).Hash)
- : throw new ArgumentException(
- $"Given {currency}'s total supply is capped at {maximumSupply.RawValue} " +
- $"and cannot be set to {rawAmount}.")
- : throw new ArgumentException(
- $"Given {currency} is not trackable.");
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockAccountState AddTotalSupply(FungibleAssetValue amount) =>
- AddTotalSupply(amount.Currency, amount.RawValue);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState AddTotalSupply(Currency currency, BigInteger rawAmount) =>
- SetTotalSupply(
- currency,
- (Trie.Get(MockKeyConverters.ToTotalSupplyKey(currency)) is
- Integer amount ? amount : 0) + rawAmount);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockAccountState SubtractTotalSupply(FungibleAssetValue amount) =>
- SubtractTotalSupply(amount.Currency, amount.RawValue);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState SubtractTotalSupply(Currency currency, BigInteger rawAmount) =>
- SetTotalSupply(
- currency,
- (Trie.Get(MockKeyConverters.ToTotalSupplyKey(currency)) is
- Integer amount ? amount : 0) - rawAmount);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState SetValidator(Validator validator) =>
- new MockAccountState(
- _stateStore,
- _stateStore.Commit(
- Trie.Set(MockKeyConverters.ValidatorSetKey, GetValidatorSet().Update(validator).Bencoded)).Hash);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- }
-}
diff --git a/.Lib9c.Tests/Action/Common/MockKeyConverters.cs b/.Lib9c.Tests/Action/Common/MockKeyConverters.cs
deleted file mode 100644
index 44d0239eac..0000000000
--- a/.Lib9c.Tests/Action/Common/MockKeyConverters.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using Libplanet.Crypto;
- using Libplanet.Store.Trie;
- using Libplanet.Types.Assets;
-
- internal static class MockKeyConverters
- {
- // "___"
- internal static readonly KeyBytes ValidatorSetKey =
- new KeyBytes(new byte[] { _underScore, _underScore, _underScore });
-
- private const byte _underScore = 95; // '_'
-
- private static readonly byte[] _conversionTable =
- {
- 48, // '0'
- 49, // '1'
- 50, // '2'
- 51, // '3'
- 52, // '4'
- 53, // '5'
- 54, // '6'
- 55, // '7'
- 56, // '8'
- 57, // '9'
- 97, // 'a'
- 98, // 'b'
- 99, // 'c'
- 100, // 'd'
- 101, // 'e'
- 102, // 'f'
- };
-
- // $"{ByteUtil.Hex(address.ByteArray)}"
- internal static KeyBytes ToStateKey(Address address)
- {
- var addressBytes = address.ByteArray;
- byte[] buffer = new byte[addressBytes.Length * 2];
- for (int i = 0; i < addressBytes.Length; i++)
- {
- buffer[i * 2] = _conversionTable[addressBytes[i] >> 4];
- buffer[i * 2 + 1] = _conversionTable[addressBytes[i] & 0xf];
- }
-
- return new KeyBytes(buffer);
- }
-
- // $"_{ByteUtil.Hex(address.ByteArray)}_{ByteUtil.Hex(currency.Hash.ByteArray)}"
- internal static KeyBytes ToFungibleAssetKey(Address address, Currency currency)
- {
- var addressBytes = address.ByteArray;
- var currencyBytes = currency.Hash.ByteArray;
- byte[] buffer = new byte[addressBytes.Length * 2 + currencyBytes.Length * 2 + 2];
-
- buffer[0] = _underScore;
- for (int i = 0; i < addressBytes.Length; i++)
- {
- buffer[1 + i * 2] = _conversionTable[addressBytes[i] >> 4];
- buffer[1 + i * 2 + 1] = _conversionTable[addressBytes[i] & 0xf];
- }
-
- var offset = addressBytes.Length * 2;
- buffer[offset + 1] = _underScore;
- for (int i = 0; i < currencyBytes.Length; i++)
- {
- buffer[offset + 2 + i * 2] = _conversionTable[currencyBytes[i] >> 4];
- buffer[offset + 2 + i * 2 + 1] = _conversionTable[currencyBytes[i] & 0xf];
- }
-
- return new KeyBytes(buffer);
- }
-
- internal static KeyBytes ToFungibleAssetKey(
- (Address Address, Currency Currency) pair) =>
- ToFungibleAssetKey(pair.Address, pair.Currency);
-
- // $"__{ByteUtil.Hex(currency.Hash.ByteArray)}"
- internal static KeyBytes ToTotalSupplyKey(Currency currency)
- {
- var currencyBytes = currency.Hash.ByteArray;
- byte[] buffer = new byte[currencyBytes.Length * 2 + 2];
-
- buffer[0] = _underScore;
- buffer[1] = _underScore;
-
- for (int i = 0; i < currencyBytes.Length; i++)
- {
- buffer[2 + i * 2] = _conversionTable[currencyBytes[i] >> 4];
- buffer[2 + i * 2 + 1] = _conversionTable[currencyBytes[i] & 0xf];
- }
-
- return new KeyBytes(buffer);
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/Common/MockWorldState.cs b/.Lib9c.Tests/Action/Common/MockWorldState.cs
deleted file mode 100644
index a19f62ffe1..0000000000
--- a/.Lib9c.Tests/Action/Common/MockWorldState.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System.Numerics;
- using System.Security.Cryptography;
- using Bencodex.Types;
- using Libplanet.Action.State;
- using Libplanet.Common;
- using Libplanet.Crypto;
- using Libplanet.Store;
- using Libplanet.Store.Trie;
- using Libplanet.Types.Assets;
- using Libplanet.Types.Consensus;
-
- public class MockWorldState : IWorldState
- {
- private readonly IStateStore _stateStore;
-
- public MockWorldState()
- : this(new TrieStateStore(new MemoryKeyValueStore()), null)
- {
- }
-
- public MockWorldState(
- IStateStore stateStore,
- HashDigest? stateRootHash = null)
- {
- _stateStore = stateStore;
- Trie = stateStore.GetStateRoot(stateRootHash);
- Legacy = false;
- }
-
- public ITrie Trie { get; }
-
- public bool Legacy { get; private set; }
-
- public IAccountState GetAccountState(Address address) => GetMockAccountState(address);
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockAccountState GetMockAccountState(Address address)
- => Legacy
- ? new MockAccountState(_stateStore, Trie.Hash)
- : new MockAccountState(
- _stateStore,
- Trie.Get(MockKeyConverters.ToStateKey(address)) is { } stateRootNotNull
- ? new HashDigest(stateRootNotNull)
- : null);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
-#pragma warning disable SA1118 // Parameter should not span multiple lines
- public MockWorldState SetAccountState(Address address, IAccountState accountState)
- => Legacy
- ? new MockWorldState(_stateStore, accountState.Trie.Hash)
- : new MockWorldState(
- _stateStore,
- _stateStore.Commit(
- Trie.Set(
- MockKeyConverters.ToStateKey(address),
- new Binary(accountState.Trie.Hash.ByteArray))).Hash);
-#pragma warning restore SA1118 // Parameter should not span multiple lines
-
- public MockWorldState SetState(Address accountAddress, Address address, IValue state)
- => SetAccountState(accountAddress, GetMockAccountState(accountAddress).SetState(address, state));
-
- public MockWorldState SetBalance(
- Address address,
- FungibleAssetValue amount)
- => SetBalance((address, amount.Currency), amount.RawValue);
-
- public MockWorldState SetBalance(
- Address address, Currency currency, BigInteger rawAmount)
- => SetBalance((address, currency), rawAmount);
-
- public MockWorldState SetBalance(
- (Address Address, Currency Currency) pair,
- BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .SetBalance((pair.Address, pair.Currency), rawAmount));
-
- public MockWorldState AddBalance(
- Address address, FungibleAssetValue amount)
- => AddBalance((address, amount.Currency), amount.RawValue);
-
- public MockWorldState AddBalance(
- Address address, Currency currency, BigInteger rawAmount)
- => AddBalance((address, currency), rawAmount);
-
- public MockWorldState AddBalance(
- (Address Address, Currency Currency) pair,
- BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .AddBalance(pair, rawAmount));
-
- public MockWorldState SubtractBalance(
- Address address, FungibleAssetValue amount)
- => SubtractBalance((address, amount.Currency), amount.RawValue);
-
- public MockWorldState SubtractBalance(
- Address address, Currency currency, BigInteger rawAmount)
- => SubtractBalance((address, currency), rawAmount);
-
- public MockWorldState SubtractBalance(
- (Address Address, Currency Currency) pair,
- BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .SubtractBalance(pair, rawAmount));
-
- public MockWorldState TransferBalance(
- Address sender,
- Address recipient,
- FungibleAssetValue amount) =>
- TransferBalance(
- sender,
- recipient,
- amount.Currency,
- amount.RawValue);
-
- public MockWorldState TransferBalance(
- Address sender,
- Address recipient,
- Currency currency,
- BigInteger rawAmount)
- => SubtractBalance(sender, currency, rawAmount)
- .AddBalance(recipient, currency, rawAmount);
-
- public MockWorldState SetTotalSupply(FungibleAssetValue amount)
- => SetTotalSupply(amount.Currency, amount.RawValue);
-
- public MockWorldState SetTotalSupply(Currency currency, BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .SetTotalSupply(currency, rawAmount));
-
- public MockWorldState AddTotalSupply(FungibleAssetValue amount)
- => AddTotalSupply(amount.Currency, amount.RawValue);
-
- public MockWorldState AddTotalSupply(Currency currency, BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .AddTotalSupply(currency, rawAmount));
-
- public MockWorldState SubtractTotalSupply(FungibleAssetValue amount)
- => SubtractTotalSupply(amount.Currency, amount.RawValue);
-
- public MockWorldState SubtractTotalSupply(Currency currency, BigInteger rawAmount)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .SubtractTotalSupply(currency, rawAmount));
-
- public MockWorldState SetValidator(Validator validator)
- => SetAccountState(
- ReservedAddresses.LegacyAccount,
- GetMockAccountState(ReservedAddresses.LegacyAccount)
- .SetValidator(validator));
- }
-}
diff --git a/.Lib9c.Tests/Action/Coupons/IssueCouponsTest.cs b/.Lib9c.Tests/Action/Coupons/IssueCouponsTest.cs
index 340c00d8c1..77999b3573 100644
--- a/.Lib9c.Tests/Action/Coupons/IssueCouponsTest.cs
+++ b/.Lib9c.Tests/Action/Coupons/IssueCouponsTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action.Coupons
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.State;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Action.Coupons;
using Nekoyume.Model.Coupons;
@@ -19,7 +20,7 @@ public class IssueCouponsTest
[Fact]
public void Execute()
{
- IWorld state = new World(new MockWorldState())
+ IWorld state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
AdminState.Address,
new AdminState(CouponsFixture.AgentAddress1, 1)
diff --git a/.Lib9c.Tests/Action/Coupons/RedeemCouponTest.cs b/.Lib9c.Tests/Action/Coupons/RedeemCouponTest.cs
index c06a3390f5..21261a98da 100644
--- a/.Lib9c.Tests/Action/Coupons/RedeemCouponTest.cs
+++ b/.Lib9c.Tests/Action/Coupons/RedeemCouponTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action.Coupons
using System.Linq;
using Libplanet.Action;
using Libplanet.Action.State;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Action.Coupons;
@@ -21,7 +22,7 @@ public void Execute()
{
IRandom random = new TestRandom();
var sheets = TableSheetsImporter.ImportSheets();
- IWorld state = new World(new MockWorldState())
+ IWorld state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
Addresses.GameConfig,
new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize()
@@ -42,7 +43,7 @@ public void Execute()
.Derive(SerializeKeys.AvatarAddressKey)
.Derive("avatar-states-0");
- var agent1Avatar0State = CreateAvatar0.CreateAvatarState(
+ var agent1Avatar0State = CreateAvatar.CreateAvatarState(
"agent1avatar0",
agent1Avatar0Address,
new ActionContext
@@ -53,7 +54,7 @@ public void Execute()
},
state.GetSheet(),
default);
- var agent1Avatar1State = CreateAvatar0.CreateAvatarState(
+ var agent1Avatar1State = CreateAvatar.CreateAvatarState(
"agent1avatar1",
agent1Avatar1Address,
new ActionContext
@@ -64,7 +65,7 @@ public void Execute()
},
state.GetSheet(),
default);
- var agent2Avatar0State = CreateAvatar0.CreateAvatarState(
+ var agent2Avatar0State = CreateAvatar.CreateAvatarState(
"agent2avatar0",
agent2Avatar0Address,
new ActionContext
diff --git a/.Lib9c.Tests/Action/Coupons/TransferCouponsTest.cs b/.Lib9c.Tests/Action/Coupons/TransferCouponsTest.cs
index 4b8fae9ae8..7986ce2f52 100644
--- a/.Lib9c.Tests/Action/Coupons/TransferCouponsTest.cs
+++ b/.Lib9c.Tests/Action/Coupons/TransferCouponsTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action.Coupons
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Action.Coupons;
using Nekoyume.Model.Coupons;
@@ -18,7 +19,7 @@ public class TransferCouponsTest
[Fact]
public void Execute()
{
- IWorld state = new World(new MockWorldState());
+ IWorld state = new World(MockUtil.MockModernWorldState);
IRandom random = new TestRandom();
var coupon1 = new Coupon(CouponsFixture.Guid1, CouponsFixture.RewardSet1);
diff --git a/.Lib9c.Tests/Action/CreateAvatarTest.cs b/.Lib9c.Tests/Action/CreateAvatarTest.cs
new file mode 100644
index 0000000000..b6e4b39ae4
--- /dev/null
+++ b/.Lib9c.Tests/Action/CreateAvatarTest.cs
@@ -0,0 +1,281 @@
+namespace Lib9c.Tests.Action
+{
+ using System.Collections.Generic;
+ using System.Collections.Immutable;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Runtime.Serialization.Formatters.Binary;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Helper;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Nekoyume.TableData;
+ using Xunit;
+ using static Lib9c.SerializeKeys;
+
+ public class CreateAvatarTest
+ {
+ private readonly Address _agentAddress;
+ private readonly TableSheets _tableSheets;
+
+ public CreateAvatarTest()
+ {
+ _agentAddress = default;
+ _tableSheets = new TableSheets(TableSheetsImporter.ImportSheets());
+ }
+
+ [Theory]
+ [InlineData(0L)]
+ [InlineData(7_210_000L)]
+ [InlineData(7_210_001L)]
+ public void Execute(long blockIndex)
+ {
+ var action = new CreateAvatar()
+ {
+ index = 0,
+ hair = 0,
+ ear = 0,
+ lens = 0,
+ tail = 0,
+ name = "test",
+ };
+
+ var sheets = TableSheetsImporter.ImportSheets();
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(
+ Addresses.GameConfig,
+ new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize()
+ );
+
+ foreach (var (key, value) in sheets)
+ {
+ state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ Assert.Equal(0 * CrystalCalculator.CRYSTAL, state.GetBalance(_agentAddress, CrystalCalculator.CRYSTAL));
+
+ var nextState = action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ BlockIndex = blockIndex,
+ RandomSeed = 0,
+ });
+
+ var avatarAddress = _agentAddress.Derive(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ CreateAvatar.DeriveFormat,
+ 0
+ )
+ );
+ Assert.True(nextState.TryGetAvatarState(
+ default,
+ avatarAddress,
+ out var nextAvatarState)
+ );
+ var agentState = nextState.GetAgentState(default);
+ Assert.NotNull(agentState);
+ Assert.True(agentState.avatarAddresses.Any());
+ Assert.Equal("test", nextAvatarState.name);
+ Assert.Equal(200_000 * CrystalCalculator.CRYSTAL, nextState.GetBalance(_agentAddress, CrystalCalculator.CRYSTAL));
+ var avatarItemSheet = nextState.GetSheet();
+ foreach (var row in avatarItemSheet.Values)
+ {
+ Assert.True(nextAvatarState.inventory.HasItem(row.ItemId, row.Count));
+ }
+
+ var avatarFavSheet = nextState.GetSheet();
+ foreach (var row in avatarFavSheet.Values)
+ {
+ var targetAddress = row.Target == CreateAvatarFavSheet.Target.Agent
+ ? _agentAddress
+ : avatarAddress;
+ Assert.Equal(row.Currency * row.Quantity, nextState.GetBalance(targetAddress, row.Currency));
+ }
+ }
+
+ [Theory]
+ [InlineData("홍길동")]
+ [InlineData("山田太郎")]
+ public void ExecuteThrowInvalidNamePatterException(string nickName)
+ {
+ var agentAddress = default(Address);
+
+ var action = new CreateAvatar()
+ {
+ index = 0,
+ hair = 0,
+ ear = 0,
+ lens = 0,
+ tail = 0,
+ name = nickName,
+ };
+
+ var state = new World(MockUtil.MockModernWorldState);
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = agentAddress,
+ BlockIndex = 0,
+ })
+ );
+ }
+
+ [Fact]
+ public void ExecuteThrowInvalidAddressException()
+ {
+ var avatarAddress = _agentAddress.Derive(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ CreateAvatar.DeriveFormat,
+ 0
+ )
+ );
+
+ var avatarState = new AvatarState(
+ avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ new GameConfigState(),
+ default
+ );
+
+ var action = new CreateAvatar()
+ {
+ index = 0,
+ hair = 0,
+ ear = 0,
+ lens = 0,
+ tail = 0,
+ name = "test",
+ };
+
+ var state = new World(MockUtil.MockModernWorldState).SetAvatarState(avatarAddress, avatarState);
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ BlockIndex = 0,
+ })
+ );
+ }
+
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(3)]
+ public void ExecuteThrowAvatarIndexOutOfRangeException(int index)
+ {
+ var agentState = new AgentState(_agentAddress);
+ var state = new World(MockUtil.MockModernWorldState).SetAgentState(_agentAddress, agentState);
+ var action = new CreateAvatar()
+ {
+ index = index,
+ hair = 0,
+ ear = 0,
+ lens = 0,
+ tail = 0,
+ name = "test",
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ BlockIndex = 0,
+ })
+ );
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(2)]
+ public void ExecuteThrowAvatarIndexAlreadyUsedException(int index)
+ {
+ var agentState = new AgentState(_agentAddress);
+ var avatarAddress = _agentAddress.Derive(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ CreateAvatar.DeriveFormat,
+ 0
+ )
+ );
+ agentState.avatarAddresses[index] = avatarAddress;
+ var state = new World(MockUtil.MockModernWorldState).SetAgentState(_agentAddress, agentState);
+
+ var action = new CreateAvatar()
+ {
+ index = index,
+ hair = 0,
+ ear = 0,
+ lens = 0,
+ tail = 0,
+ name = "test",
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ BlockIndex = 0,
+ })
+ );
+ }
+
+ [Fact]
+ public void AddItem()
+ {
+ var itemSheet = _tableSheets.ItemSheet;
+ var createAvatarItemSheet = new CreateAvatarItemSheet();
+ createAvatarItemSheet.Set(@"item_id,count
+10112000,2
+10512000,2
+600201,2
+");
+ var avatarState = new AvatarState(default, default, 0L, _tableSheets.GetAvatarSheets(), new GameConfigState(), default, "test");
+ CreateAvatar.AddItem(itemSheet, createAvatarItemSheet, avatarState, new TestRandom());
+ foreach (var row in createAvatarItemSheet.Values)
+ {
+ Assert.True(avatarState.inventory.HasItem(row.ItemId, row.Count));
+ }
+
+ Assert.Equal(4, avatarState.inventory.Equipments.Count());
+ foreach (var equipment in avatarState.inventory.Equipments)
+ {
+ var equipmentRow = _tableSheets.EquipmentItemSheet[equipment.Id];
+ Assert.Equal(equipmentRow.Stat, equipment.Stat);
+ }
+ }
+
+ [Fact]
+ public void MintAsset()
+ {
+ var createAvatarFavSheet = new CreateAvatarFavSheet();
+ createAvatarFavSheet.Set(@"currency,quantity,target
+CRYSTAL,200000,Agent
+RUNE_GOLDENLEAF,200000,Avatar
+");
+ var avatarAddress = new PrivateKey().Address;
+ var agentAddress = new PrivateKey().Address;
+ var avatarState = new AvatarState(avatarAddress, agentAddress, 0L, _tableSheets.GetAvatarSheets(), new GameConfigState(), default, "test");
+ var nextState = CreateAvatar.MintAsset(createAvatarFavSheet, avatarState, new World(MockUtil.MockModernWorldState), new ActionContext());
+ foreach (var row in createAvatarFavSheet.Values)
+ {
+ var targetAddress = row.Target == CreateAvatarFavSheet.Target.Agent
+ ? agentAddress
+ : avatarAddress;
+ Assert.Equal(row.Currency * row.Quantity, nextState.GetBalance(targetAddress, row.Currency));
+ }
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/CreatePendingActivationTest.cs b/.Lib9c.Tests/Action/CreatePendingActivationTest.cs
index c2bc9dff45..9478aa2f28 100644
--- a/.Lib9c.Tests/Action/CreatePendingActivationTest.cs
+++ b/.Lib9c.Tests/Action/CreatePendingActivationTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model.State;
using Nekoyume.Module;
@@ -21,9 +22,8 @@ public void Execute()
var action = new CreatePendingActivation(pendingActivation);
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var state = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize()));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
var actionContext = new ActionContext()
{
BlockIndex = 1,
@@ -49,9 +49,8 @@ public void CheckPermission()
var action = new CreatePendingActivation(pendingActivation);
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var state = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize()));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
Assert.Throws(
() => action.Execute(new ActionContext()
diff --git a/.Lib9c.Tests/Action/CreatePendingActivationsTest.cs b/.Lib9c.Tests/Action/CreatePendingActivationsTest.cs
index 5367bfa212..efd37f9663 100644
--- a/.Lib9c.Tests/Action/CreatePendingActivationsTest.cs
+++ b/.Lib9c.Tests/Action/CreatePendingActivationsTest.cs
@@ -4,8 +4,9 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
- using Nekoyume.Model.State;
+ using Nekoyume.Model.State;
using Nekoyume.Module;
using Xunit;
@@ -28,9 +29,8 @@ PendingActivationState CreatePendingActivation()
var action = new CreatePendingActivations(activations);
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var state = new World(
- new MockWorldState().SetState(
- ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize()));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
var actionContext = new ActionContext()
{
BlockIndex = 1,
@@ -79,9 +79,8 @@ public void CheckPermission()
var action = new CreatePendingActivations();
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var state = new World(
- new MockWorldState().SetState(
- ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize()));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
Assert.Throws(
() => action.Execute(new ActionContext()
diff --git a/.Lib9c.Tests/Action/CreatePledgeTest.cs b/.Lib9c.Tests/Action/CreatePledgeTest.cs
index 8a5fb64501..9799227cf9 100644
--- a/.Lib9c.Tests/Action/CreatePledgeTest.cs
+++ b/.Lib9c.Tests/Action/CreatePledgeTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using System.Collections.Generic;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -35,7 +36,7 @@ public void Execute(bool admin, Type exc)
var agentAddress = new PrivateKey().Address;
var pledgeAddress = agentAddress.GetPledgeAddress();
var context = new ActionContext();
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.Admin, adminState.Serialize())
.MintAsset(context, patronAddress, 4 * 500 * mead);
diff --git a/.Lib9c.Tests/Action/DailyRewardTest.cs b/.Lib9c.Tests/Action/DailyRewardTest.cs
index dd24648622..c8fc505a1b 100644
--- a/.Lib9c.Tests/Action/DailyRewardTest.cs
+++ b/.Lib9c.Tests/Action/DailyRewardTest.cs
@@ -2,6 +2,7 @@ namespace Lib9c.Tests.Action
{
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Helper;
@@ -26,7 +27,7 @@ public DailyRewardTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -92,7 +93,7 @@ public void Execute(bool legacy)
[Fact]
public void Execute_Throw_FailedLoadStateException() =>
- Assert.Throws(() => ExecuteInternal(new World(new MockWorldState())));
+ Assert.Throws(() => ExecuteInternal(new World(MockUtil.MockModernWorldState)));
[Theory]
[InlineData(0, 0, true)]
diff --git a/.Lib9c.Tests/Action/EndPledgeTest.cs b/.Lib9c.Tests/Action/EndPledgeTest.cs
index 82b7c2e589..6f72fa720d 100644
--- a/.Lib9c.Tests/Action/EndPledgeTest.cs
+++ b/.Lib9c.Tests/Action/EndPledgeTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model.State;
using Nekoyume.Module;
@@ -19,7 +20,7 @@ public void Execute(int balance)
var patron = new PrivateKey().Address;
var agent = new PrivateKey().Address;
var context = new ActionContext();
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(agent.GetPledgeAddress(), List.Empty.Add(patron.Serialize()).Add(true.Serialize()));
var mead = Currencies.Mead;
if (balance > 0)
@@ -52,7 +53,7 @@ public void Execute_Throw_Exception(bool invalidSigner, bool invalidAgent, Type
Address patron = new PrivateKey().Address;
Address agent = new PrivateKey().Address;
List contract = List.Empty.Add(patron.Serialize()).Add(true.Serialize());
- IWorld states = new World(new MockWorldState()).SetLegacyState(agent.GetPledgeAddress(), contract);
+ IWorld states = new World(MockUtil.MockModernWorldState).SetLegacyState(agent.GetPledgeAddress(), contract);
var action = new EndPledge
{
diff --git a/.Lib9c.Tests/Action/EventConsumableItemCraftsTest.cs b/.Lib9c.Tests/Action/EventConsumableItemCraftsTest.cs
index dcf9a59df5..72fddc9d3d 100644
--- a/.Lib9c.Tests/Action/EventConsumableItemCraftsTest.cs
+++ b/.Lib9c.Tests/Action/EventConsumableItemCraftsTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model;
@@ -24,7 +25,7 @@ public class EventConsumableItemCraftsTest
public EventConsumableItemCraftsTest()
{
- _initialStates = new World(new MockWorldState());
+ _initialStates = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/EventDungeonBattleTest.cs b/.Lib9c.Tests/Action/EventDungeonBattleTest.cs
new file mode 100644
index 0000000000..65113fb626
--- /dev/null
+++ b/.Lib9c.Tests/Action/EventDungeonBattleTest.cs
@@ -0,0 +1,493 @@
+namespace Lib9c.Tests.Action
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Exceptions;
+ using Nekoyume.Extensions;
+ using Nekoyume.Model.Event;
+ using Nekoyume.Model.Rune;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Nekoyume.TableData;
+ using Nekoyume.TableData.Event;
+ using Xunit;
+
+ public class EventDungeonBattleTest
+ {
+ private readonly Currency _ncgCurrency;
+ private readonly TableSheets _tableSheets;
+
+ private readonly Address _agentAddress;
+ private readonly Address _avatarAddress;
+ private IWorld _initialStates;
+
+ public EventDungeonBattleTest()
+ {
+ _initialStates = new World(MockUtil.MockModernWorldState);
+
+#pragma warning disable CS0618
+ // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
+ _ncgCurrency = Currency.Legacy("NCG", 2, null);
+#pragma warning restore CS0618
+ _initialStates = _initialStates.SetLegacyState(
+ GoldCurrencyState.Address,
+ new GoldCurrencyState(_ncgCurrency).Serialize());
+ var sheets = TableSheetsImporter.ImportSheets();
+ foreach (var (key, value) in sheets)
+ {
+ _initialStates = _initialStates
+ .SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ _tableSheets = new TableSheets(sheets);
+
+ _agentAddress = new PrivateKey().Address;
+ _avatarAddress = _agentAddress.Derive("avatar");
+
+ var agentState = new AgentState(_agentAddress);
+ agentState.avatarAddresses.Add(0, _avatarAddress);
+
+ var gameConfigState = new GameConfigState(sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ new PrivateKey().Address
+ )
+ {
+ level = 100,
+ };
+
+ _initialStates = _initialStates
+ .SetAgentState(_agentAddress, agentState)
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010001)]
+ public void Execute_Success_Within_Event_Period(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ var contextBlockIndex = scheduleRow.StartBlockIndex;
+ var nextStates = Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex);
+ var eventDungeonInfoAddr =
+ EventDungeonInfo.DeriveAddress(_avatarAddress, eventDungeonId);
+ var eventDungeonInfo =
+ new EventDungeonInfo(nextStates.GetLegacyState(eventDungeonInfoAddr));
+ Assert.Equal(
+ scheduleRow.DungeonTicketsMax - 1,
+ eventDungeonInfo.RemainingTickets);
+
+ contextBlockIndex = scheduleRow.DungeonEndBlockIndex;
+ nextStates = Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex);
+ eventDungeonInfo =
+ new EventDungeonInfo(nextStates.GetLegacyState(eventDungeonInfoAddr));
+ Assert.Equal(
+ scheduleRow.DungeonTicketsMax - 1,
+ eventDungeonInfo.RemainingTickets);
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010001, 0, 0, 0)]
+ [InlineData(1001, 10010001, 10010001, 1, 1, 1)]
+ [InlineData(1001, 10010001, 10010001, int.MaxValue, int.MaxValue, int.MaxValue - 1)]
+ public void Execute_Success_With_Ticket_Purchase(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId,
+ int dungeonTicketPrice,
+ int dungeonTicketAdditionalPrice,
+ int numberOfTicketPurchases)
+ {
+ var context = new ActionContext();
+ var previousStates = _initialStates;
+ var scheduleSheet = _tableSheets.EventScheduleSheet;
+ Assert.True(scheduleSheet.TryGetValue(eventScheduleId, out var scheduleRow));
+ var sb = new StringBuilder();
+ sb.AppendLine(
+ "id,_name,start_block_index,dungeon_end_block_index,dungeon_tickets_max,dungeon_tickets_reset_interval_block_range,dungeon_exp_seed_value,recipe_end_block_index,dungeon_ticket_price,dungeon_ticket_additional_price");
+ sb.AppendLine(
+ $"{eventScheduleId}" +
+ $",\"2022 Summer Event\"" +
+ $",{scheduleRow.StartBlockIndex}" +
+ $",{scheduleRow.DungeonEndBlockIndex}" +
+ $",{scheduleRow.DungeonTicketsMax}" +
+ $",{scheduleRow.DungeonTicketsResetIntervalBlockRange}" +
+ $",{dungeonTicketPrice}" +
+ $",{dungeonTicketAdditionalPrice}" +
+ $",{scheduleRow.DungeonExpSeedValue}" +
+ $",{scheduleRow.RecipeEndBlockIndex}");
+ previousStates = previousStates.SetLegacyState(
+ Addresses.GetSheetAddress(),
+ sb.ToString().Serialize());
+
+ var eventDungeonInfoAddr =
+ EventDungeonInfo.DeriveAddress(_avatarAddress, eventDungeonId);
+ var eventDungeonInfo = new EventDungeonInfo(
+ remainingTickets: 0,
+ numberOfTicketPurchases: numberOfTicketPurchases);
+ previousStates = previousStates.SetLegacyState(
+ eventDungeonInfoAddr,
+ eventDungeonInfo.Serialize());
+
+ Assert.True(previousStates.GetSheet()
+ .TryGetValue(eventScheduleId, out var newScheduleRow));
+ var ncgHas = newScheduleRow.GetDungeonTicketCost(
+ numberOfTicketPurchases,
+ _ncgCurrency);
+ if (ncgHas.Sign > 0)
+ {
+ previousStates = previousStates.MintAsset(context, _agentAddress, ncgHas);
+ }
+
+ var nextStates = Execute(
+ previousStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ buyTicketIfNeeded: true,
+ blockIndex: scheduleRow.StartBlockIndex);
+ var nextEventDungeonInfoList =
+ (Bencodex.Types.List)nextStates.GetLegacyState(eventDungeonInfoAddr)!;
+ Assert.Equal(
+ numberOfTicketPurchases + 1,
+ nextEventDungeonInfoList[2].ToInteger());
+ Assert.True(
+ nextStates.TryGetGoldBalance(
+ _agentAddress,
+ _ncgCurrency,
+ out FungibleAssetValue balance
+ )
+ );
+ Assert.Equal(0 * _ncgCurrency, balance);
+ }
+
+ [Theory]
+ [InlineData(10000001, 10010001, 10010001)]
+ [InlineData(10010001, 10010001, 10010001)]
+ public void Execute_Throw_InvalidActionFieldException_By_EventScheduleId(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId) =>
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId));
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010001)]
+ public void Execute_Throw_InvalidActionFieldException_By_ContextBlockIndex(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ var contextBlockIndex = scheduleRow.StartBlockIndex - 1;
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex));
+ contextBlockIndex = scheduleRow.DungeonEndBlockIndex + 1;
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(1001, 10020001, 10010001)]
+ [InlineData(1001, 1001, 10010001)]
+ public void Execute_Throw_InvalidActionFieldException_By_EventDungeonId(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: scheduleRow.StartBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10020001)]
+ [InlineData(1001, 10010001, 1001)]
+ public void Execute_Throw_InvalidActionFieldException_By_EventDungeonStageId(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: scheduleRow.StartBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010001)]
+ public void Execute_Throw_NotEnoughEventDungeonTicketsException(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ var previousStates = _initialStates;
+ var eventDungeonInfoAddr =
+ EventDungeonInfo.DeriveAddress(_avatarAddress, eventDungeonId);
+ var eventDungeonInfo = new EventDungeonInfo();
+ previousStates = previousStates
+ .SetLegacyState(eventDungeonInfoAddr, eventDungeonInfo.Serialize());
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ Assert.Throws(() =>
+ Execute(
+ previousStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: scheduleRow.StartBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010001, 0)]
+ [InlineData(1001, 10010001, 10010001, int.MaxValue - 1)]
+ public void Execute_Throw_InsufficientBalanceException(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId,
+ int numberOfTicketPurchases)
+ {
+ var context = new ActionContext();
+ var previousStates = _initialStates;
+ var eventDungeonInfoAddr =
+ EventDungeonInfo.DeriveAddress(_avatarAddress, eventDungeonId);
+ var eventDungeonInfo = new EventDungeonInfo(
+ remainingTickets: 0,
+ numberOfTicketPurchases: numberOfTicketPurchases);
+ previousStates = previousStates
+ .SetLegacyState(eventDungeonInfoAddr, eventDungeonInfo.Serialize());
+
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ var ncgHas = scheduleRow.GetDungeonTicketCost(
+ numberOfTicketPurchases,
+ _ncgCurrency) - 1 * _ncgCurrency;
+ if (ncgHas.Sign > 0)
+ {
+ previousStates = previousStates.MintAsset(context, _agentAddress, ncgHas);
+ }
+
+ Assert.Throws(() =>
+ Execute(
+ previousStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ buyTicketIfNeeded: true,
+ blockIndex: scheduleRow.StartBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(1001, 10010001, 10010002)]
+ public void Execute_Throw_StageNotClearedException(
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(eventScheduleId, out var scheduleRow));
+ Assert.Throws(() =>
+ Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: scheduleRow.StartBlockIndex));
+ }
+
+ [Theory]
+ [InlineData(0, 30001, 1, 30001, typeof(DuplicatedRuneIdException))]
+ [InlineData(1, 10002, 1, 30001, typeof(DuplicatedRuneSlotIndexException))]
+ public void Execute_DuplicatedException(int slotIndex, int runeId, int slotIndex2, int runeId2, Type exception)
+ {
+ Assert.True(_tableSheets.EventScheduleSheet
+ .TryGetValue(1001, out var scheduleRow));
+
+ var context = new ActionContext();
+ _initialStates = _initialStates.MintAsset(context, _agentAddress, 99999 * _ncgCurrency);
+
+ var unlockRuneSlot = new UnlockRuneSlot()
+ {
+ AvatarAddress = _avatarAddress,
+ SlotIndex = 1,
+ };
+
+ _initialStates = unlockRuneSlot.Execute(new ActionContext
+ {
+ BlockIndex = 1,
+ PreviousState = _initialStates,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ });
+
+ Assert.Throws(exception, () =>
+ Execute(
+ _initialStates,
+ 1001,
+ 10010001,
+ 10010001,
+ false,
+ scheduleRow.StartBlockIndex,
+ slotIndex,
+ runeId,
+ slotIndex2,
+ runeId2));
+ }
+
+ [Fact]
+ public void Execute_V100301()
+ {
+ int eventScheduleId = 1001;
+ int eventDungeonId = 10010001;
+ int eventDungeonStageId = 10010001;
+ var csv = $@"id,_name,start_block_index,dungeon_end_block_index,dungeon_tickets_max,dungeon_tickets_reset_interval_block_range,dungeon_ticket_price,dungeon_ticket_additional_price,dungeon_exp_seed_value,recipe_end_block_index
+ 1001,2022 Summer Event,{ActionObsoleteConfig.V100301ExecutedBlockIndex},{ActionObsoleteConfig.V100301ExecutedBlockIndex + 100},5,7200,5,2,1,5018000";
+ _initialStates =
+ _initialStates.SetLegacyState(
+ Addresses.GetSheetAddress(),
+ csv.Serialize());
+ var sheet = new EventScheduleSheet();
+ sheet.Set(csv);
+ Assert.True(sheet.TryGetValue(eventScheduleId, out var scheduleRow));
+ var contextBlockIndex = scheduleRow.StartBlockIndex;
+ var nextStates = Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex);
+ var eventDungeonInfoAddr =
+ EventDungeonInfo.DeriveAddress(_avatarAddress, eventDungeonId);
+ var eventDungeonInfo =
+ new EventDungeonInfo(nextStates.GetLegacyState(eventDungeonInfoAddr));
+ Assert.Equal(
+ scheduleRow.DungeonTicketsMax - 1,
+ eventDungeonInfo.RemainingTickets);
+
+ contextBlockIndex = scheduleRow.DungeonEndBlockIndex;
+ nextStates = Execute(
+ _initialStates,
+ eventScheduleId,
+ eventDungeonId,
+ eventDungeonStageId,
+ blockIndex: contextBlockIndex);
+ eventDungeonInfo =
+ new EventDungeonInfo(nextStates.GetLegacyState(eventDungeonInfoAddr));
+ Assert.Equal(
+ scheduleRow.DungeonTicketsMax - 1,
+ eventDungeonInfo.RemainingTickets);
+ }
+
+ private IWorld Execute(
+ IWorld previousStates,
+ int eventScheduleId,
+ int eventDungeonId,
+ int eventDungeonStageId,
+ bool buyTicketIfNeeded = false,
+ long blockIndex = 0,
+ int slotIndex = 0,
+ int runeId = 10002,
+ int slotIndex2 = 1,
+ int runeId2 = 30001)
+ {
+ var previousAvatarState = previousStates.GetAvatarState(_avatarAddress);
+ var equipments =
+ Doomfist.GetAllParts(_tableSheets, previousAvatarState.level);
+ foreach (var equipment in equipments)
+ {
+ previousAvatarState.inventory.AddItem(equipment, iLock: null);
+ }
+
+ var action = new EventDungeonBattle
+ {
+ AvatarAddress = _avatarAddress,
+ EventScheduleId = eventScheduleId,
+ EventDungeonId = eventDungeonId,
+ EventDungeonStageId = eventDungeonStageId,
+ Equipments = equipments
+ .Select(e => e.NonFungibleId)
+ .ToList(),
+ Costumes = new List(),
+ Foods = new List(),
+ RuneInfos = new List()
+ {
+ new RuneSlotInfo(slotIndex, runeId),
+ new RuneSlotInfo(slotIndex2, runeId2),
+ },
+ BuyTicketIfNeeded = buyTicketIfNeeded,
+ };
+
+ var nextStates = action.Execute(new ActionContext
+ {
+ PreviousState = previousStates,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ BlockIndex = blockIndex,
+ });
+
+ Assert.True(nextStates.GetSheet().TryGetValue(
+ eventScheduleId,
+ out var scheduleRow));
+ var nextAvatarState = nextStates.GetAvatarState(_avatarAddress);
+ var expectExp = scheduleRow.GetStageExp(
+ eventDungeonStageId.ToEventDungeonStageNumber());
+ Assert.Equal(
+ previousAvatarState.exp + expectExp,
+ nextAvatarState.exp);
+
+ return nextStates;
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/EventMaterialItemCraftsTest.cs b/.Lib9c.Tests/Action/EventMaterialItemCraftsTest.cs
index e29c0b5779..82a9cc4169 100644
--- a/.Lib9c.Tests/Action/EventMaterialItemCraftsTest.cs
+++ b/.Lib9c.Tests/Action/EventMaterialItemCraftsTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Exceptions;
@@ -27,7 +28,7 @@ public class EventMaterialItemCraftsTest
public EventMaterialItemCraftsTest()
{
- _initialStates = new World(new MockWorldState());
+ _initialStates = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/Grinding0Test.cs b/.Lib9c.Tests/Action/Grinding0Test.cs
deleted file mode 100644
index 47b983cc6a..0000000000
--- a/.Lib9c.Tests/Action/Grinding0Test.cs
+++ /dev/null
@@ -1,254 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Libplanet.Action;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Libplanet.Types.Assets;
- using Nekoyume;
- using Nekoyume.Action;
- using Nekoyume.Model.Item;
- using Nekoyume.Model.Mail;
- using Nekoyume.Model.State;
- using Nekoyume.Module;
- using Nekoyume.TableData;
- using Nekoyume.TableData.Crystal;
- using Xunit;
- using static Lib9c.SerializeKeys;
-
- public class Grinding0Test
- {
- private readonly IRandom _random;
- private readonly TableSheets _tableSheets;
- private readonly Address _agentAddress;
- private readonly Address _avatarAddress;
- private readonly AgentState _agentState;
- private readonly AvatarState _avatarState;
- private readonly Currency _crystalCurrency;
- private readonly Currency _ncgCurrency;
- private readonly IWorld _initialState;
-
- public Grinding0Test()
- {
- _random = new TestRandom();
- var sheets = TableSheetsImporter.ImportSheets();
- _tableSheets = new TableSheets(sheets);
- _agentAddress = new PrivateKey().Address;
- _avatarAddress = new PrivateKey().Address;
-#pragma warning disable CS0618
- // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
- _crystalCurrency = Currency.Legacy("CRYSTAL", 18, null);
-#pragma warning restore CS0618
- var gameConfigState = new GameConfigState(sheets[nameof(GameConfigSheet)]);
-
- _agentState = new AgentState(_agentAddress);
- _avatarState = new AvatarState(
- _avatarAddress,
- _agentAddress,
- 0,
- _tableSheets.GetAvatarSheets(),
- gameConfigState,
- default
- );
-
- _agentState.avatarAddresses.Add(0, _avatarAddress);
-
-#pragma warning disable CS0618
- // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
- _ncgCurrency = Currency.Legacy("NCG", 2, null);
-#pragma warning restore CS0618
- var goldCurrencyState = new GoldCurrencyState(_ncgCurrency);
-
- _initialState = new World(new MockWorldState())
- .SetLegacyState(
- Addresses.GetSheetAddress(),
- _tableSheets.CrystalMonsterCollectionMultiplierSheet.Serialize())
- .SetLegacyState(
- Addresses.GetSheetAddress(),
- _tableSheets.CrystalEquipmentGrindingSheet.Serialize())
- .SetLegacyState(
- Addresses.GetSheetAddress(),
- _tableSheets.MaterialItemSheet.Serialize())
- .SetLegacyState(
- Addresses.GetSheetAddress(),
- _tableSheets.StakeRegularRewardSheet.Serialize())
- .SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize())
- .SetLegacyState(Addresses.GameConfig, gameConfigState.Serialize());
- }
-
- [Theory]
- [InlineData(true, true, 120, false, false, true, 1, 0, false, false, false, 0, 10, 1, null)]
- [InlineData(true, true, 120, false, false, true, 1, 2, false, false, false, 0, 40, 1, null)]
- // Multiply by StakeState.
- [InlineData(true, true, 120, false, false, true, 1, 2, false, true, false, 0, 40, 1, null)]
- [InlineData(true, true, 120, false, false, true, 1, 0, false, true, false, 2, 15, 1, null)]
- // Multiply by legacy MonsterCollectionState.
- [InlineData(true, true, 120, false, false, true, 1, 2, false, false, true, 0, 40, 1, null)]
- [InlineData(true, true, 120, false, false, true, 1, 0, false, false, true, 2, 15, 1, null)]
- // Charge AP.
- [InlineData(true, true, 0, true, true, true, 1, 0, false, false, false, 0, 10, 1, null)]
- // Invalid equipment count.
- [InlineData(true, true, 120, false, false, true, 1, 2, false, false, true, 0, 200, 0, typeof(InvalidItemCountException))]
- [InlineData(true, true, 120, false, false, true, 1, 2, false, false, true, 0, 200, 11, typeof(InvalidItemCountException))]
- // AgentState not exist.
- [InlineData(false, true, 120, false, false, false, 1, 0, false, false, false, 0, 0, 1, typeof(FailedLoadStateException))]
- // AvatarState not exist.
- [InlineData(true, false, 120, false, false, false, 1, 0, false, false, false, 0, 0, 1, typeof(FailedLoadStateException))]
- // Required more ActionPoint.
- [InlineData(true, true, 0, false, false, false, 1, 0, false, false, false, 0, 0, 1, typeof(NotEnoughActionPointException))]
- // Failed Charge AP.
- [InlineData(true, true, 0, true, false, false, 1, 0, false, false, false, 0, 100, 1, typeof(NotEnoughMaterialException))]
- // Equipment not exist.
- [InlineData(true, true, 120, false, false, false, 1, 0, false, false, false, 0, 0, 1, typeof(ItemDoesNotExistException))]
- // Locked equipment.
- [InlineData(true, true, 120, false, false, true, 100, 0, false, false, false, 0, 0, 1, typeof(RequiredBlockIndexException))]
- public void Execute(
- bool agentExist,
- bool avatarExist,
- int ap,
- bool chargeAp,
- bool apStoneExist,
- bool equipmentExist,
- long requiredBlockIndex,
- int itemLevel,
- bool equipped,
- bool stake,
- bool monsterCollect,
- int monsterCollectLevel,
- int totalAsset,
- int equipmentCount,
- Type exc
- )
- {
- var context = new ActionContext();
- var state = _initialState;
- if (agentExist)
- {
- state = state.SetAgentState(_agentAddress, _agentState);
- }
-
- if (avatarExist)
- {
- _avatarState.actionPoint = ap;
-
- if (equipmentExist)
- {
- var row = _tableSheets.EquipmentItemSheet.Values.First(r => r.Grade == 1);
- var equipment = (Equipment)ItemFactory.CreateItemUsable(row, default, requiredBlockIndex, itemLevel);
- equipment.equipped = equipped;
- _avatarState.inventory.AddItem(equipment, count: 1);
- }
- else
- {
- var row = _tableSheets.ConsumableItemSheet.Values.First(r => r.Grade == 1);
- var consumable = (Consumable)ItemFactory.CreateItemUsable(row, default, requiredBlockIndex, itemLevel);
- _avatarState.inventory.AddItem(consumable, count: 1);
- }
-
- if (chargeAp && apStoneExist)
- {
- var row = _tableSheets.MaterialItemSheet.Values.First(r =>
- r.ItemSubType == ItemSubType.ApStone);
- var apStone = ItemFactory.CreateMaterial(row);
- _avatarState.inventory.AddItem(apStone);
- }
-
- state = state
- .SetAvatarState(_avatarAddress, _avatarState);
-
- Assert.Equal(0 * _crystalCurrency, state.GetBalance(_avatarAddress, _crystalCurrency));
- }
-
- if (stake || monsterCollect)
- {
- // StakeState;
- var stakeStateAddress = StakeState.DeriveAddress(_agentAddress);
- var stakeState = new StakeState(stakeStateAddress, 1);
- var requiredGold = _tableSheets.StakeRegularRewardSheet.OrderedRows
- .FirstOrDefault(r => r.Level == monsterCollectLevel)?.RequiredGold ?? 0;
-
- if (stake)
- {
- state = state.SetLegacyState(stakeStateAddress, stakeState.SerializeV2());
-
- if (requiredGold > 0)
- {
- state = state.MintAsset(
- context,
- stakeStateAddress,
- requiredGold * _ncgCurrency
- );
- }
- }
-
- if (monsterCollect)
- {
- var mcAddress = MonsterCollectionState.DeriveAddress(_agentAddress, 0);
- state = state.SetLegacyState(
- mcAddress,
- new MonsterCollectionState(mcAddress, monsterCollectLevel, 1).Serialize()
- );
-
- if (requiredGold > 0)
- {
- state = state.MintAsset(context, mcAddress, requiredGold * _ncgCurrency);
- }
- }
- }
-
- var equipmentIds = new List();
- for (int i = 0; i < equipmentCount; i++)
- {
- equipmentIds.Add(default);
- }
-
- Assert.Equal(equipmentCount, equipmentIds.Count);
-
- var action = new Grinding0
- {
- AvatarAddress = _avatarAddress,
- EquipmentIds = equipmentIds,
- ChargeAp = chargeAp,
- };
-
- if (exc is null)
- {
- var nextState = action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- });
-
- var nextAvatarState = nextState.GetAvatarState(_avatarAddress);
- FungibleAssetValue asset = totalAsset * _crystalCurrency;
-
- Assert.Equal(asset, nextState.GetBalance(_agentAddress, _crystalCurrency));
- Assert.False(nextAvatarState.inventory.HasNonFungibleItem(default));
- Assert.Equal(115, nextAvatarState.actionPoint);
-
- var mail = nextAvatarState.mailBox.OfType().First(i => i.id.Equals(action.Id));
-
- Assert.Equal(1, mail.ItemCount);
- Assert.Equal(asset, mail.Asset);
-
- var row = _tableSheets.MaterialItemSheet.Values.First(r =>
- r.ItemSubType == ItemSubType.ApStone);
- Assert.False(nextAvatarState.inventory.HasItem(row.Id));
- }
- else
- {
- Assert.Throws(exc, () => action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- }));
- }
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/GrindingTest.cs b/.Lib9c.Tests/Action/GrindingTest.cs
index 9a8004fa4f..892e1c71c3 100644
--- a/.Lib9c.Tests/Action/GrindingTest.cs
+++ b/.Lib9c.Tests/Action/GrindingTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -61,7 +62,7 @@ public GrindingTest()
#pragma warning restore CS0618
var goldCurrencyState = new GoldCurrencyState(_ncgCurrency);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(
Addresses.GetSheetAddress(),
_tableSheets.CrystalMonsterCollectionMultiplierSheet.Serialize())
diff --git a/.Lib9c.Tests/Action/HackAndSlashRandomBuffTest.cs b/.Lib9c.Tests/Action/HackAndSlashRandomBuffTest.cs
index d1d8d3b39d..69894b45dd 100644
--- a/.Lib9c.Tests/Action/HackAndSlashRandomBuffTest.cs
+++ b/.Lib9c.Tests/Action/HackAndSlashRandomBuffTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -64,7 +65,7 @@ public HackAndSlashRandomBuffTest()
_weeklyArenaState = new WeeklyArenaState(0);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(_weeklyArenaState.address, _weeklyArenaState.Serialize())
.SetAgentState(_agentAddress, agentState)
.SetAvatarState(_avatarAddress, _avatarState)
diff --git a/.Lib9c.Tests/Action/HackAndSlashSweepTest.cs b/.Lib9c.Tests/Action/HackAndSlashSweepTest.cs
new file mode 100644
index 0000000000..154542a581
--- /dev/null
+++ b/.Lib9c.Tests/Action/HackAndSlashSweepTest.cs
@@ -0,0 +1,713 @@
+namespace Lib9c.Tests.Action
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Bencodex.Types;
+ using Libplanet.Action;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Extensions;
+ using Nekoyume.Helper;
+ using Nekoyume.Model;
+ using Nekoyume.Model.Item;
+ using Nekoyume.Model.Rune;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Nekoyume.TableData;
+ using Xunit;
+
+ public class HackAndSlashSweepTest
+ {
+ private readonly Dictionary _sheets;
+ private readonly TableSheets _tableSheets;
+
+ private readonly Address _agentAddress;
+
+ private readonly Address _avatarAddress;
+ private readonly AvatarState _avatarState;
+
+ private readonly Address _rankingMapAddress;
+
+ private readonly WeeklyArenaState _weeklyArenaState;
+ private readonly IWorld _initialState;
+ private readonly IRandom _random;
+
+ public HackAndSlashSweepTest()
+ {
+ _random = new TestRandom();
+ _sheets = TableSheetsImporter.ImportSheets();
+ _tableSheets = new TableSheets(_sheets);
+
+ var privateKey = new PrivateKey();
+ _agentAddress = privateKey.PublicKey.Address;
+ var agentState = new AgentState(_agentAddress);
+
+ _avatarAddress = _agentAddress.Derive("avatar");
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ _rankingMapAddress = _avatarAddress.Derive("ranking_map");
+ _avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress
+ )
+ {
+ level = 100,
+ };
+ agentState.avatarAddresses.Add(0, _avatarAddress);
+
+#pragma warning disable CS0618
+ // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
+ var currency = Currency.Legacy("NCG", 2, null);
+#pragma warning restore CS0618
+ var goldCurrencyState = new GoldCurrencyState(currency);
+ _weeklyArenaState = new WeeklyArenaState(0);
+ _initialState = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(_weeklyArenaState.address, _weeklyArenaState.Serialize())
+ .SetAgentState(_agentAddress, agentState)
+ .SetAvatarState(_avatarAddress, _avatarState)
+ .SetLegacyState(gameConfigState.address, gameConfigState.Serialize())
+ .SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize());
+
+ foreach (var (key, value) in _sheets)
+ {
+ _initialState = _initialState
+ .SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ foreach (var address in _avatarState.combinationSlotAddresses)
+ {
+ var slotState = new CombinationSlotState(
+ address,
+ GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
+ _initialState = _initialState.SetLegacyState(address, slotState.Serialize());
+ }
+ }
+
+ public (List Equipments, List Costumes) GetDummyItems(AvatarState avatarState)
+ {
+ var equipments = Doomfist.GetAllParts(_tableSheets, avatarState.level)
+ .Select(e => e.NonFungibleId).ToList();
+ var random = new TestRandom();
+ var costumes = new List();
+ if (avatarState.level >= GameConfig.RequireCharacterLevel.CharacterFullCostumeSlot)
+ {
+ var costumeId = _tableSheets
+ .CostumeItemSheet
+ .Values
+ .First(r => r.ItemSubType == ItemSubType.FullCostume)
+ .Id;
+
+ var costume = (Costume)ItemFactory.CreateItem(
+ _tableSheets.ItemSheet[costumeId], random);
+ avatarState.inventory.AddItem(costume);
+ costumes.Add(costume.ItemId);
+ }
+
+ return (equipments, costumes);
+ }
+
+ [Fact]
+ public void Execute_FailedLoadStateException()
+ {
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 1,
+ avatarAddress = _avatarAddress,
+ worldId = 1,
+ stageId = 1,
+ };
+
+ IWorld state = new World(MockUtil.MockModernWorldState);
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Theory]
+ [InlineData(100, 1)]
+ public void Execute_SheetRowNotFoundException(int worldId, int stageId)
+ {
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 1,
+ avatarAddress = _avatarAddress,
+ worldId = worldId,
+ stageId = stageId,
+ };
+
+ var state = _initialState.SetLegacyState(
+ _avatarAddress.Derive("world_ids"),
+ List.Empty.Add(worldId.Serialize())
+ );
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Theory]
+ [InlineData(1, 999)]
+ [InlineData(2, 50)]
+ public void Execute_SheetRowColumnException(int worldId, int stageId)
+ {
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 1,
+ avatarAddress = _avatarAddress,
+ worldId = worldId,
+ stageId = stageId,
+ };
+
+ var state = _initialState.SetLegacyState(
+ _avatarAddress.Derive("world_ids"),
+ List.Empty.Add(worldId.Serialize())
+ );
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Theory]
+ [InlineData(1, 48, 1, 50)]
+ [InlineData(1, 49, 2, 51)]
+ public void Execute_InvalidStageException(int clearedWorldId, int clearedStageId, int worldId, int stageId)
+ {
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 1,
+ avatarAddress = _avatarAddress,
+ worldId = worldId,
+ stageId = stageId,
+ };
+ var worldSheet = _initialState.GetSheet();
+ var worldUnlockSheet = _initialState.GetSheet();
+
+ _avatarState.worldInformation.ClearStage(clearedWorldId, clearedStageId, 1, worldSheet, worldUnlockSheet);
+
+ var state = _initialState
+ .SetLegacyState(
+ _avatarAddress.Derive("world_ids"),
+ List.Empty.Add(worldId.Serialize())
+ )
+ .SetAvatarState(_avatarAddress, _avatarState);
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Theory]
+ [InlineData(GameConfig.MimisbrunnrWorldId, 10000001, false)]
+ [InlineData(GameConfig.MimisbrunnrWorldId, 10000001, true)]
+ // Unlock CRYSTAL first.
+ [InlineData(2, 51, false)]
+ public void Execute_InvalidWorldException(int worldId, int stageId, bool unlockedIdsExist)
+ {
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 10000001),
+ };
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ if (unlockedIdsExist)
+ {
+ state = state.SetLegacyState(
+ _avatarAddress.Derive("world_ids"),
+ List.Empty.Add(worldId.Serialize())
+ );
+ }
+
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 1,
+ avatarAddress = _avatarAddress,
+ worldId = worldId,
+ stageId = stageId,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Fact]
+ public void Execute_UsageLimitExceedException()
+ {
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ };
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ apStoneCount = 99,
+ avatarAddress = _avatarAddress,
+ worldId = 1,
+ stageId = 2,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+
+ [Theory]
+ [InlineData(3, 2)]
+ [InlineData(7, 5)]
+ public void Execute_NotEnoughMaterialException(int useApStoneCount, int holdingApStoneCount)
+ {
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ level = 400,
+ };
+
+ var row = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.ApStone);
+ var apStone = ItemFactory.CreateTradableMaterial(row);
+ avatarState.inventory.AddItem(apStone, holdingApStoneCount);
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var stageSheet = _initialState.GetSheet();
+ var (expectedLevel, expectedExp) = (0, 0L);
+ if (stageSheet.TryGetValue(2, out var stageRow))
+ {
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / stageRow.CostAP * useApStoneCount;
+ var apPlayCount = avatarState.actionPoint / stageRow.CostAP;
+ var playCount = apPlayCount + itemPlayCount;
+ (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _tableSheets.CharacterLevelSheet,
+ 2,
+ playCount);
+
+ var (equipments, costumes) = GetDummyItems(avatarState);
+
+ var action = new HackAndSlashSweep
+ {
+ equipments = equipments,
+ costumes = costumes,
+ runeInfos = new List(),
+ avatarAddress = _avatarAddress,
+ actionPoint = avatarState.actionPoint,
+ apStoneCount = useApStoneCount,
+ worldId = 1,
+ stageId = 2,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+ }
+
+ [Fact]
+ public void Execute_NotEnoughActionPointException()
+ {
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ level = 400,
+ actionPoint = 0,
+ };
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var stageSheet = _initialState.GetSheet();
+ var (expectedLevel, expectedExp) = (0, 0L);
+ if (stageSheet.TryGetValue(2, out var stageRow))
+ {
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / stageRow.CostAP * 1;
+ var apPlayCount = avatarState.actionPoint / stageRow.CostAP;
+ var playCount = apPlayCount + itemPlayCount;
+ (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _tableSheets.CharacterLevelSheet,
+ 2,
+ playCount);
+
+ var (equipments, costumes) = GetDummyItems(avatarState);
+ var action = new HackAndSlashSweep
+ {
+ runeInfos = new List(),
+ costumes = costumes,
+ equipments = equipments,
+ avatarAddress = _avatarAddress,
+ actionPoint = 999999,
+ apStoneCount = 0,
+ worldId = 1,
+ stageId = 2,
+ };
+
+ Assert.Throws(() =>
+ action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+ }
+
+ [Fact]
+ public void Execute_PlayCountIsZeroException()
+ {
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ level = 400,
+ actionPoint = 0,
+ };
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var stageSheet = _initialState.GetSheet();
+ var (expectedLevel, expectedExp) = (0, 0L);
+ if (stageSheet.TryGetValue(2, out var stageRow))
+ {
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / stageRow.CostAP * 1;
+ var apPlayCount = avatarState.actionPoint / stageRow.CostAP;
+ var playCount = apPlayCount + itemPlayCount;
+ (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _tableSheets.CharacterLevelSheet,
+ 2,
+ playCount);
+
+ var (equipments, costumes) = GetDummyItems(avatarState);
+ var action = new HackAndSlashSweep
+ {
+ costumes = costumes,
+ equipments = equipments,
+ runeInfos = new List(),
+ avatarAddress = _avatarAddress,
+ actionPoint = 0,
+ apStoneCount = 0,
+ worldId = 1,
+ stageId = 2,
+ };
+
+ Assert.Throws(() =>
+ action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+ }
+
+ [Fact]
+ public void Execute_NotEnoughCombatPointException()
+ {
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ actionPoint = 0,
+ level = 1,
+ };
+
+ IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState);
+
+ var stageSheet = _initialState.GetSheet();
+ var (expectedLevel, expectedExp) = (0, 0L);
+ int stageId = 24;
+ if (stageSheet.TryGetValue(stageId, out var stageRow))
+ {
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / stageRow.CostAP * 1;
+ var apPlayCount = avatarState.actionPoint / stageRow.CostAP;
+ var playCount = apPlayCount + itemPlayCount;
+ (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _tableSheets.CharacterLevelSheet,
+ stageId,
+ playCount);
+
+ var action = new HackAndSlashSweep
+ {
+ costumes = new List(),
+ equipments = new List(),
+ runeInfos = new List(),
+ avatarAddress = _avatarAddress,
+ actionPoint = avatarState.actionPoint,
+ apStoneCount = 1,
+ worldId = 1,
+ stageId = stageId,
+ };
+
+ Assert.Throws(() =>
+ action.Execute(new ActionContext()
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(2)]
+ [InlineData(3)]
+ [InlineData(4)]
+ [InlineData(5)]
+ public void ExecuteWithStake(int stakingLevel)
+ {
+ const int worldId = 1;
+ const int stageId = 1;
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ actionPoint = 120,
+ level = 3,
+ };
+ var itemRow = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.ApStone);
+ var apStone = ItemFactory.CreateTradableMaterial(itemRow);
+ avatarState.inventory.AddItem(apStone);
+
+ var stakeStateAddress = StakeState.DeriveAddress(_agentAddress);
+ var stakeState = new StakeState(stakeStateAddress, 1);
+ var requiredGold = _tableSheets.StakeRegularRewardSheet.OrderedRows
+ .FirstOrDefault(r => r.Level == stakingLevel)?.RequiredGold ?? 0;
+ var context = new ActionContext();
+ var state = _initialState
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(stakeStateAddress, stakeState.Serialize())
+ .MintAsset(context, stakeStateAddress, requiredGold * _initialState.GetGoldCurrency());
+ var stageSheet = _initialState.GetSheet();
+ if (stageSheet.TryGetValue(stageId, out var stageRow))
+ {
+ var apSheet = _initialState.GetSheet();
+ var costAp = apSheet.GetActionPointByStaking(stageRow.CostAP, 1, stakingLevel);
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / costAp * 1;
+ var apPlayCount = avatarState.actionPoint / costAp;
+ var playCount = apPlayCount + itemPlayCount;
+ var (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _initialState.GetSheet(),
+ stageId,
+ playCount);
+
+ var action = new HackAndSlashSweep
+ {
+ costumes = new List(),
+ equipments = new List(),
+ runeInfos = new List(),
+ avatarAddress = _avatarAddress,
+ actionPoint = avatarState.actionPoint,
+ apStoneCount = 1,
+ worldId = worldId,
+ stageId = stageId,
+ };
+
+ var nextState = action.Execute(new ActionContext
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ });
+ var nextAvatar = nextState.GetAvatarState(_avatarAddress);
+ Assert.Equal(expectedLevel, nextAvatar.level);
+ Assert.Equal(expectedExp, nextAvatar.exp);
+ }
+ else
+ {
+ throw new SheetRowNotFoundException(nameof(StageSheet), stageId);
+ }
+ }
+
+ [Theory]
+ [InlineData(0, 30001, 1, 30001, typeof(DuplicatedRuneIdException))]
+ [InlineData(1, 10002, 1, 30001, typeof(DuplicatedRuneSlotIndexException))]
+ public void ExecuteDuplicatedException(int slotIndex, int runeId, int slotIndex2, int runeId2, Type exception)
+ {
+ var stakingLevel = 1;
+ const int worldId = 1;
+ const int stageId = 1;
+ var gameConfigState = _initialState.GetGameConfigState();
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _initialState.GetAvatarSheets(),
+ gameConfigState,
+ _rankingMapAddress)
+ {
+ worldInformation =
+ new WorldInformation(0, _initialState.GetSheet(), 25),
+ actionPoint = 120,
+ level = 3,
+ };
+ var itemRow = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.ApStone);
+ var apStone = ItemFactory.CreateTradableMaterial(itemRow);
+ avatarState.inventory.AddItem(apStone);
+
+ var stakeStateAddress = StakeState.DeriveAddress(_agentAddress);
+ var stakeState = new StakeState(stakeStateAddress, 1);
+ var requiredGold = _tableSheets.StakeRegularRewardSheet.OrderedRows
+ .FirstOrDefault(r => r.Level == stakingLevel)?.RequiredGold ?? 0;
+ var context = new ActionContext();
+ var state = _initialState
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(stakeStateAddress, stakeState.Serialize())
+ .MintAsset(context, stakeStateAddress, requiredGold * _initialState.GetGoldCurrency());
+ var stageSheet = _initialState.GetSheet();
+ if (stageSheet.TryGetValue(stageId, out var stageRow))
+ {
+ var apSheet = _initialState.GetSheet();
+ var costAp = apSheet.GetActionPointByStaking(stageRow.CostAP, 1, stakingLevel);
+ var itemPlayCount =
+ gameConfigState.ActionPointMax / costAp * 1;
+ var apPlayCount = avatarState.actionPoint / costAp;
+ var playCount = apPlayCount + itemPlayCount;
+ var (expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
+ _initialState.GetSheet(),
+ stageId,
+ playCount);
+
+ var ncgCurrency = state.GetGoldCurrency();
+ state = state.MintAsset(context, _agentAddress, 99999 * ncgCurrency);
+
+ var unlockRuneSlot = new UnlockRuneSlot()
+ {
+ AvatarAddress = _avatarAddress,
+ SlotIndex = 1,
+ };
+
+ state = unlockRuneSlot.Execute(new ActionContext
+ {
+ BlockIndex = 1,
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ });
+
+ var action = new HackAndSlashSweep
+ {
+ costumes = new List(),
+ equipments = new List(),
+ runeInfos = new List()
+ {
+ new RuneSlotInfo(slotIndex, runeId),
+ new RuneSlotInfo(slotIndex2, runeId2),
+ },
+ avatarAddress = _avatarAddress,
+ actionPoint = avatarState.actionPoint,
+ apStoneCount = 1,
+ worldId = worldId,
+ stageId = stageId,
+ };
+
+ Assert.Throws(exception, () => action.Execute(new ActionContext
+ {
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ }));
+ }
+ else
+ {
+ throw new SheetRowNotFoundException(nameof(StageSheet), stageId);
+ }
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/HackAndSlashTest.cs b/.Lib9c.Tests/Action/HackAndSlashTest.cs
index b99f062702..291a3f853c 100644
--- a/.Lib9c.Tests/Action/HackAndSlashTest.cs
+++ b/.Lib9c.Tests/Action/HackAndSlashTest.cs
@@ -9,6 +9,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -79,7 +80,7 @@ public HackAndSlashTest()
var currency = Currency.Legacy("NCG", 2, null);
#pragma warning restore CS0618
var goldCurrencyState = new GoldCurrencyState(currency);
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
_initialState = _initialState
.SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize())
.SetLegacyState(_weeklyArenaState.address, _weeklyArenaState.Serialize())
@@ -411,10 +412,10 @@ public void Execute_Throw_FailedLoadStateException(bool empty)
};
IWorld state = empty
- ? new World(new MockWorldState())
+ ? new World(MockUtil.MockModernWorldState)
: _initialState
.SetAvatarState(_avatarAddress, _avatarState)
- .SetAccount(Addresses.Inventory, new Account(new MockAccountState()));
+ .SetAccount(Addresses.Inventory, new Account(MockUtil.MockAccountState));
var exec = Assert.Throws(() => action.Execute(new ActionContext
{
diff --git a/.Lib9c.Tests/Action/InitializeStatesTest.cs b/.Lib9c.Tests/Action/InitializeStatesTest.cs
index 07d776ef0f..7af13e7d5f 100644
--- a/.Lib9c.Tests/Action/InitializeStatesTest.cs
+++ b/.Lib9c.Tests/Action/InitializeStatesTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -64,7 +65,7 @@ public void Execute()
BlockIndex = 0,
Signer = minterKey.Address,
Miner = default,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var addresses = new List()
@@ -131,7 +132,7 @@ public void ExecuteWithAuthorizedMinersState()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var fetchedState = new AuthorizedMinersState(
@@ -180,7 +181,7 @@ public void ExecuteWithActivateAdminKey()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var fetchedState = new ActivatedAccountsState(
@@ -232,7 +233,7 @@ public void ExecuteWithCredits()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var fetchedState = new CreditsState(
@@ -278,7 +279,7 @@ public void ExecuteWithoutAdminState()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var fetchedState = new ActivatedAccountsState(
@@ -321,7 +322,7 @@ public void ExecuteWithoutInitialSupply()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
Assert.Equal(0 * ncg, genesisState.GetBalance(GoldCurrencyState.Address, ncg));
@@ -362,7 +363,7 @@ public void ExecuteWithAssetMinters()
BlockIndex = 0,
Miner = default,
Signer = minterKey.Address,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
});
var assetMinters = Assert.IsType(genesisState.GetLegacyState(Addresses.AssetMinters));
diff --git a/.Lib9c.Tests/Action/IssueTokensFromGarageTest.cs b/.Lib9c.Tests/Action/IssueTokensFromGarageTest.cs
index 7ec5e15d7d..ef79bed692 100644
--- a/.Lib9c.Tests/Action/IssueTokensFromGarageTest.cs
+++ b/.Lib9c.Tests/Action/IssueTokensFromGarageTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -36,9 +37,8 @@ public IssueTokensFromGarageTest()
var garageBalanceAddr = Addresses.GetGarageBalanceAddress(_signer);
_prevState = new World(
- new MockWorldState()
- .SetBalance(garageBalanceAddr, Currencies.Crystal * 1000)
- );
+ MockWorldState.CreateModern()
+ .SetBalance(garageBalanceAddr, Currencies.Crystal * 1000));
IEnumerable materials = _tableSheets.MaterialItemSheet.OrderedList!
.Take(3)
diff --git a/.Lib9c.Tests/Action/ItemEnhancementTest.cs b/.Lib9c.Tests/Action/ItemEnhancementTest.cs
new file mode 100644
index 0000000000..82a2f2468b
--- /dev/null
+++ b/.Lib9c.Tests/Action/ItemEnhancementTest.cs
@@ -0,0 +1,367 @@
+namespace Lib9c.Tests.Action
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Linq;
+ using Bencodex.Types;
+ using Lib9c.Tests.Fixtures.TableCSV.Cost;
+ using Lib9c.Tests.Util;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Extensions;
+ using Nekoyume.Model.Item;
+ using Nekoyume.Model.Mail;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Xunit;
+
+ public class ItemEnhancementTest
+ {
+ private readonly TableSheets _tableSheets;
+ private readonly Address _agentAddress;
+ private readonly Address _avatarAddress;
+ private readonly AvatarState _avatarState;
+ private readonly Currency _currency;
+ private IWorld _initialState;
+
+ public ItemEnhancementTest()
+ {
+ _initialState = new World(MockUtil.MockModernWorldState);
+ Dictionary sheets;
+ (_initialState, sheets) = InitializeUtil.InitializeTableSheets(
+ _initialState,
+ sheetsOverride: new Dictionary
+ {
+ {
+ "EnhancementCostSheetV3",
+ EnhancementCostSheetFixtures.V3
+ },
+ });
+ _tableSheets = new TableSheets(sheets);
+ foreach (var (key, value) in sheets)
+ {
+ _initialState =
+ _initialState.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ var privateKey = new PrivateKey();
+ _agentAddress = privateKey.PublicKey.Address;
+ 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 = _initialState
+ .SetAgentState(_agentAddress, agentState)
+ .SetAvatarState(_avatarAddress, _avatarState)
+ .SetLegacyState(slotAddress, new CombinationSlotState(slotAddress, 0).Serialize())
+ .SetLegacyState(GoldCurrencyState.Address, gold.Serialize())
+ .MintAsset(context, GoldCurrencyState.Address, gold.Currency * 100_000_000_000)
+ .TransferAsset(
+ context,
+ Addresses.GoldCurrency,
+ _agentAddress,
+ gold.Currency * 3_000_000
+ );
+
+ Assert.Equal(
+ gold.Currency * 99_997_000_000,
+ _initialState.GetBalance(Addresses.GoldCurrency, gold.Currency)
+ );
+ Assert.Equal(
+ gold.Currency * 3_000_000,
+ _initialState.GetBalance(_agentAddress, gold.Currency)
+ );
+ }
+
+ [Theory]
+ // from 0 to 0 using one level 0 material
+ [InlineData(0, false, 0, false, 1)]
+ [InlineData(0, false, 0, true, 1)]
+ [InlineData(0, true, 0, false, 1)]
+ [InlineData(0, true, 0, true, 1)]
+ // from 0 to 1 using two level 0 material
+ [InlineData(0, false, 0, false, 3)]
+ [InlineData(0, false, 0, true, 3)]
+ [InlineData(0, true, 0, false, 3)]
+ [InlineData(0, true, 0, true, 3)]
+ // // Duplicated > from 0 to 0
+ [InlineData(0, false, 0, false, 3, true)]
+ [InlineData(0, false, 0, true, 3, true)]
+ [InlineData(0, true, 0, false, 3, true)]
+ [InlineData(0, true, 0, true, 3, true)]
+ // from 0 to N using multiple level 0 materials
+ [InlineData(0, false, 0, false, 7)]
+ [InlineData(0, false, 0, false, 31)]
+ [InlineData(0, false, 0, true, 7)]
+ [InlineData(0, false, 0, true, 31)]
+ [InlineData(0, true, 0, false, 7)]
+ [InlineData(0, true, 0, false, 31)]
+ [InlineData(0, true, 0, true, 7)]
+ [InlineData(0, true, 0, true, 31)]
+ // // Duplicated > from 0 to 0
+ [InlineData(0, false, 0, false, 7, true)]
+ [InlineData(0, false, 0, false, 31, true)]
+ [InlineData(0, false, 0, true, 7, true)]
+ [InlineData(0, false, 0, true, 31, true)]
+ [InlineData(0, true, 0, false, 7, true)]
+ [InlineData(0, true, 0, false, 31, true)]
+ [InlineData(0, true, 0, true, 7, true)]
+ [InlineData(0, true, 0, true, 31, true)]
+ // from K to K with material(s). Check requiredBlock == 0
+ [InlineData(10, false, 0, false, 1)]
+ [InlineData(10, false, 0, true, 1)]
+ [InlineData(10, true, 0, false, 1)]
+ [InlineData(10, true, 0, true, 1)]
+ // from K to N using one level X material
+ [InlineData(5, false, 6, false, 1)]
+ [InlineData(5, false, 6, true, 1)]
+ [InlineData(5, true, 6, false, 1)]
+ [InlineData(5, true, 6, true, 1)]
+ // from K to N using multiple materials
+ [InlineData(5, false, 4, false, 6)]
+ [InlineData(5, false, 7, false, 5)]
+ [InlineData(5, false, 4, true, 6)]
+ [InlineData(5, false, 7, true, 5)]
+ [InlineData(5, true, 4, false, 6)]
+ [InlineData(5, true, 7, false, 5)]
+ [InlineData(5, true, 4, true, 6)]
+ [InlineData(5, true, 7, true, 5)]
+ // // Duplicated: from K to K
+ [InlineData(5, true, 4, true, 6, true)]
+ [InlineData(5, true, 7, true, 5, true)]
+ [InlineData(5, true, 4, false, 6, true)]
+ [InlineData(5, true, 7, false, 5, true)]
+ [InlineData(5, false, 4, true, 6, true)]
+ [InlineData(5, false, 7, true, 5, true)]
+ [InlineData(5, false, 4, false, 6, true)]
+ [InlineData(5, false, 7, false, 5, true)]
+ // from 20 to 21 (just to reach level 21 exp)
+ [InlineData(20, false, 20, false, 1)]
+ [InlineData(20, false, 20, true, 1)]
+ [InlineData(20, true, 20, false, 1)]
+ [InlineData(20, true, 20, true, 1)]
+ // from 20 to 21 (over level 21)
+ [InlineData(20, false, 20, false, 2)]
+ [InlineData(20, false, 20, true, 2)]
+ [InlineData(20, true, 20, false, 2)]
+ [InlineData(20, true, 20, true, 2)]
+ // from 21 to 21 (no level up)
+ [InlineData(21, false, 1, false, 1)]
+ [InlineData(21, false, 21, false, 1)]
+ [InlineData(21, false, 1, true, 1)]
+ [InlineData(21, false, 21, true, 1)]
+ [InlineData(21, true, 1, false, 1)]
+ [InlineData(21, true, 21, false, 1)]
+ [InlineData(21, true, 1, true, 1)]
+ [InlineData(21, true, 21, true, 1)]
+ public void Execute(
+ int startLevel,
+ bool oldStart,
+ int materialLevel,
+ bool oldMaterial,
+ int materialCount,
+ bool duplicated = false
+ )
+ {
+ var row = _tableSheets.EquipmentItemSheet.Values.First(r => r.Id == 10110000);
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(row, default, 0, startLevel);
+ if (startLevel == 0)
+ {
+ equipment.Exp = (long)row.Exp!;
+ }
+ else
+ {
+ equipment.Exp = _tableSheets.EnhancementCostSheetV3.OrderedList.First(r =>
+ r.ItemSubType == equipment.ItemSubType && r.Grade == equipment.Grade &&
+ r.Level == equipment.level).Exp;
+ }
+
+ var startExp = equipment.Exp;
+ if (oldStart)
+ {
+ equipment.Exp = 0L;
+ }
+
+ _avatarState.inventory.AddItem(equipment, count: 1);
+
+ var startRow = _tableSheets.EnhancementCostSheetV3.OrderedList.FirstOrDefault(r =>
+ r.Grade == equipment.Grade && r.ItemSubType == equipment.ItemSubType &&
+ r.Level == startLevel);
+ var expectedExpIncrement = 0L;
+ var materialIds = new List();
+ var duplicatedGuid = Guid.NewGuid();
+ for (var i = 0; i < materialCount; i++)
+ {
+ var materialId = duplicated ? duplicatedGuid : Guid.NewGuid();
+ materialIds.Add(materialId);
+ var material =
+ (Equipment)ItemFactory.CreateItemUsable(row, materialId, 0, materialLevel);
+ if (materialLevel == 0)
+ {
+ material.Exp = (long)row.Exp!;
+ }
+ else
+ {
+ material.Exp = _tableSheets.EnhancementCostSheetV3.OrderedList.First(r =>
+ r.ItemSubType == material.ItemSubType && r.Grade == material.Grade &&
+ r.Level == material.level).Exp;
+ }
+
+ if (!(duplicated && i > 0))
+ {
+ expectedExpIncrement += material.Exp;
+ }
+
+ if (oldMaterial)
+ {
+ material.Exp = 0L;
+ }
+
+ _avatarState.inventory.AddItem(material, count: 1);
+ }
+
+ var result = new CombinationConsumable5.ResultModel()
+ {
+ id = default,
+ gold = 0,
+ actionPoint = 0,
+ recipeId = 1,
+ materials = new Dictionary(),
+ 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(startLevel, equipment.level);
+
+ _initialState = _initialState.SetAvatarState(_avatarAddress, _avatarState);
+
+ var action = new ItemEnhancement
+ {
+ itemId = default,
+ materialIds = materialIds,
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ var nextState = action.Execute(new ActionContext()
+ {
+ PreviousState = _initialState,
+ Signer = _agentAddress,
+ BlockIndex = 1,
+ RandomSeed = 0,
+ });
+
+ var slotState = nextState.GetCombinationSlotState(_avatarAddress, 0);
+ var resultEquipment = (Equipment)slotState.Result.itemUsable;
+ var level = resultEquipment.level;
+ var nextAvatarState = nextState.GetAvatarState(_avatarAddress);
+ var expectedTargetRow = _tableSheets.EnhancementCostSheetV3.OrderedList.FirstOrDefault(
+ r => r.Grade == equipment.Grade && r.ItemSubType == equipment.ItemSubType &&
+ r.Level == level);
+ var expectedCost = (expectedTargetRow?.Cost ?? 0) - (startRow?.Cost ?? 0);
+ var expectedBlockIndex =
+ (expectedTargetRow?.RequiredBlockIndex ?? 0) - (startRow?.RequiredBlockIndex ?? 0);
+ Assert.Equal(default, resultEquipment.ItemId);
+ Assert.Equal(startExp + expectedExpIncrement, resultEquipment.Exp);
+ Assert.Equal(
+ (3_000_000 - expectedCost) * _currency,
+ nextState.GetBalance(_agentAddress, _currency)
+ );
+
+ var arenaSheet = _tableSheets.ArenaSheet;
+ var arenaData = arenaSheet.GetRoundByBlockIndex(1);
+ var feeStoreAddress =
+ Addresses.GetBlacksmithFeeAddress(arenaData.ChampionshipId, arenaData.Round);
+ Assert.Equal(
+ expectedCost * _currency,
+ nextState.GetBalance(feeStoreAddress, _currency)
+ );
+ Assert.Equal(30, nextAvatarState.mailBox.Count);
+
+ var stateDict = (Dictionary)nextState.GetLegacyState(slotAddress);
+ var slot = new CombinationSlotState(stateDict);
+ var slotResult = (ItemEnhancement13.ResultModel)slot.Result;
+ if (startLevel != level)
+ {
+ var baseMinAtk = (decimal)preItemUsable.StatsMap.BaseATK;
+ var baseMaxAtk = (decimal)preItemUsable.StatsMap.BaseATK;
+ var extraMinAtk = (decimal)preItemUsable.StatsMap.AdditionalATK;
+ var extraMaxAtk = (decimal)preItemUsable.StatsMap.AdditionalATK;
+
+ for (var i = startLevel + 1; i <= level; i++)
+ {
+ var currentRow = _tableSheets.EnhancementCostSheetV3.OrderedList
+ .First(x =>
+ x.Grade == 1 && x.ItemSubType == equipment.ItemSubType && x.Level == i);
+
+ baseMinAtk *= currentRow.BaseStatGrowthMin.NormalizeFromTenThousandths() + 1;
+ baseMaxAtk *= currentRow.BaseStatGrowthMax.NormalizeFromTenThousandths() + 1;
+ extraMinAtk *= currentRow.ExtraStatGrowthMin.NormalizeFromTenThousandths() + 1;
+ extraMaxAtk *= currentRow.ExtraStatGrowthMax.NormalizeFromTenThousandths() + 1;
+ }
+
+ Assert.InRange(
+ resultEquipment.StatsMap.ATK,
+ baseMinAtk + extraMinAtk,
+ baseMaxAtk + extraMaxAtk + 1
+ );
+ }
+
+ Assert.Equal(
+ expectedBlockIndex + 1, // +1 for execution
+ resultEquipment.RequiredBlockIndex
+ );
+ Assert.Equal(preItemUsable.ItemId, slotResult.preItemUsable.ItemId);
+ Assert.Equal(preItemUsable.ItemId, resultEquipment.ItemId);
+ Assert.Equal(expectedCost, slotResult.gold);
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/JoinArena1Test.cs b/.Lib9c.Tests/Action/JoinArena1Test.cs
index 199df55e88..3ef350f8fc 100644
--- a/.Lib9c.Tests/Action/JoinArena1Test.cs
+++ b/.Lib9c.Tests/Action/JoinArena1Test.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -46,7 +47,7 @@ public JoinArena1Test(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
_signer = new PrivateKey().Address;
_avatarAddress = _signer.Derive("avatar");
diff --git a/.Lib9c.Tests/Action/JoinArena3Test.cs b/.Lib9c.Tests/Action/JoinArena3Test.cs
index 9a4ee71222..e5231ea72e 100644
--- a/.Lib9c.Tests/Action/JoinArena3Test.cs
+++ b/.Lib9c.Tests/Action/JoinArena3Test.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -47,7 +48,7 @@ public JoinArena3Test(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
_signer = new PrivateKey().Address;
_avatarAddress = _signer.Derive("avatar");
diff --git a/.Lib9c.Tests/Action/MarketValidationTest.cs b/.Lib9c.Tests/Action/MarketValidationTest.cs
index 4889ee45cf..2c367db871 100644
--- a/.Lib9c.Tests/Action/MarketValidationTest.cs
+++ b/.Lib9c.Tests/Action/MarketValidationTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using System.Collections.Generic;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume.Action;
using Nekoyume.Battle;
@@ -23,7 +24,7 @@ public class MarketValidationTest
public MarketValidationTest()
{
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(Gold).Serialize());
}
@@ -245,7 +246,7 @@ public void Validate_ProductInfo(params ProductInfosMember[] validateMembers)
Assert.Throws(validateMember.Exc, () => buyProduct.Execute(actionContext));
- var cancelRegister = new CancelProductRegistration0
+ var cancelRegister = new CancelProductRegistration
{
AvatarAddress = AvatarAddress,
ProductInfos = new List() { productInfo },
diff --git a/.Lib9c.Tests/Action/MigrateAgentAvatarTest.cs b/.Lib9c.Tests/Action/MigrateAgentAvatarTest.cs
index befb0fe72d..956b5b3574 100644
--- a/.Lib9c.Tests/Action/MigrateAgentAvatarTest.cs
+++ b/.Lib9c.Tests/Action/MigrateAgentAvatarTest.cs
@@ -8,6 +8,7 @@
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -62,21 +63,17 @@ public void MigrateAgentAvatar(int legacyAvatarVersion, bool alreadyMigrated)
gameConfigState,
default);
- MockWorldState mock = new MockWorldState()
- .SetState(
- ReservedAddresses.LegacyAccount,
+ IWorld mock = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(
GoldCurrencyState.Address,
new GoldCurrencyState(currency, 0).Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
weekly.address,
weekly.Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
Addresses.GoldDistribution,
new List())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
gameConfigState.address,
gameConfigState.Serialize());
@@ -84,35 +81,28 @@ public void MigrateAgentAvatar(int legacyAvatarVersion, bool alreadyMigrated)
{
case 1:
mock = mock
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
agentAddress,
SerializeLegacyAgent(agentState))
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
avatarAddress,
MigrationAvatarState.LegacySerializeV1(avatarState));
break;
case 2:
mock = mock
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
agentAddress,
SerializeLegacyAgent(agentState))
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
avatarAddress,
MigrationAvatarState.LegacySerializeV2(avatarState))
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
inventoryAddress,
avatarState.inventory.Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
worldInformationAddress,
avatarState.questList.Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ .SetLegacyState(
questListAddress,
avatarState.questList.Serialize());
break;
@@ -122,27 +112,26 @@ public void MigrateAgentAvatar(int legacyAvatarVersion, bool alreadyMigrated)
if (alreadyMigrated)
{
- mock = mock
- .SetState(
- Addresses.Agent,
- agentAddress,
- agentState.SerializeList())
- .SetState(
- Addresses.Avatar,
- avatarAddress,
- avatarState.SerializeList())
- .SetState(
- Addresses.Inventory,
- avatarAddress,
- avatarState.inventory.Serialize())
- .SetState(
- Addresses.WorldInformation,
- avatarAddress,
- avatarState.worldInformation.Serialize())
- .SetState(
- Addresses.QuestList,
- avatarAddress,
- avatarState.questList.Serialize());
+ mock = mock.SetAccount(
+ Addresses.Agent,
+ mock.GetAccount(Addresses.Agent)
+ .SetState(agentAddress, agentState.SerializeList()));
+ mock = mock.SetAccount(
+ Addresses.Avatar,
+ mock.GetAccount(Addresses.Avatar)
+ .SetState(avatarAddress, avatarState.SerializeList()));
+ mock = mock.SetAccount(
+ Addresses.Inventory,
+ mock.GetAccount(Addresses.Inventory)
+ .SetState(avatarAddress, avatarState.inventory.Serialize()));
+ mock = mock.SetAccount(
+ Addresses.WorldInformation,
+ mock.GetAccount(Addresses.WorldInformation)
+ .SetState(avatarAddress, avatarState.worldInformation.Serialize()));
+ mock = mock.SetAccount(
+ Addresses.QuestList,
+ mock.GetAccount(Addresses.QuestList)
+ .SetState(avatarAddress, avatarState.questList.Serialize()));
}
IAction action = new MigrateAgentAvatar
@@ -154,11 +143,10 @@ public void MigrateAgentAvatar(int legacyAvatarVersion, bool alreadyMigrated)
var actionLoader = new NCActionLoader();
action = actionLoader.LoadAction(123, plainValue);
- var states = new World(mock);
IWorld nextState = action.Execute(
new ActionContext()
{
- PreviousState = states,
+ PreviousState = mock,
Miner = default,
Signer = new Address("e2D18a50472e93d3165c478DefA69fa149214E72"),
}
diff --git a/.Lib9c.Tests/Action/MigrateMonsterCollectionTest.cs b/.Lib9c.Tests/Action/MigrateMonsterCollectionTest.cs
index 4a0fc6c454..257d9c5fa3 100644
--- a/.Lib9c.Tests/Action/MigrateMonsterCollectionTest.cs
+++ b/.Lib9c.Tests/Action/MigrateMonsterCollectionTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -31,7 +32,7 @@ public MigrateMonsterCollectionTest(ITestOutputHelper outputHelper)
_signer = default;
_avatarAddress = _signer.Derive("avatar");
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
Dictionary sheets = TableSheetsImporter.ImportSheets();
var tableSheets = new TableSheets(sheets);
var rankingMapAddress = new PrivateKey().Address;
diff --git a/.Lib9c.Tests/Action/MigrationActivatedAccountsStateTest.cs b/.Lib9c.Tests/Action/MigrationActivatedAccountsStateTest.cs
index 63fc3b4328..f131917863 100644
--- a/.Lib9c.Tests/Action/MigrationActivatedAccountsStateTest.cs
+++ b/.Lib9c.Tests/Action/MigrationActivatedAccountsStateTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model;
using Nekoyume.Model.State;
@@ -17,10 +18,9 @@ public void Execute()
{
var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
var admin = new Address("8d9f76aF8Dc5A812aCeA15d8bf56E2F790F47fd7");
- var state = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, new AdminState(admin, 100).Serialize())
- .SetState(ReservedAddresses.LegacyAccount, ActivatedAccountsState.Address, new ActivatedAccountsState().AddAccount(default).Serialize()));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, new AdminState(admin, 100).Serialize())
+ .SetLegacyState(ActivatedAccountsState.Address, new ActivatedAccountsState().AddAccount(default).Serialize());
var action = new MigrationActivatedAccountsState();
diff --git a/.Lib9c.Tests/Action/MigrationAvatarStateTest.cs b/.Lib9c.Tests/Action/MigrationAvatarStateTest.cs
index 3b2e115951..fa11a13926 100644
--- a/.Lib9c.Tests/Action/MigrationAvatarStateTest.cs
+++ b/.Lib9c.Tests/Action/MigrationAvatarStateTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model.State;
using Nekoyume.Module;
@@ -33,10 +34,9 @@ public void Execute()
);
var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
var admin = new Address("8d9f76aF8Dc5A812aCeA15d8bf56E2F790F47fd7");
- var state = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, new AdminState(admin, 100).Serialize())
- .SetState(ReservedAddresses.LegacyAccount, avatarAddress, MigrationAvatarState.LegacySerializeV2(avatarState)));
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, new AdminState(admin, 100).Serialize())
+ .SetLegacyState(avatarAddress, MigrationAvatarState.LegacySerializeV2(avatarState));
var action = new MigrationAvatarState
{
diff --git a/.Lib9c.Tests/Action/MintAssetsTest.cs b/.Lib9c.Tests/Action/MintAssetsTest.cs
index 981ebb1913..23523f397e 100644
--- a/.Lib9c.Tests/Action/MintAssetsTest.cs
+++ b/.Lib9c.Tests/Action/MintAssetsTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Libplanet.Types.Tx;
using Nekoyume;
@@ -38,11 +39,9 @@ public MintAssetsTest()
new PrivateKey().Address,
new PrivateKey().Address,
};
- _prevState = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, new AdminState(_adminAddress, 100).Serialize())
- .SetState(ReservedAddresses.LegacyAccount, Addresses.AssetMinters, new List(_minters.Select(m => m.Serialize())))
- );
+ _prevState = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, new AdminState(_adminAddress, 100).Serialize())
+ .SetLegacyState(Addresses.AssetMinters, new List(_minters.Select(m => m.Serialize())));
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
diff --git a/.Lib9c.Tests/Action/PatchTableSheetTest.cs b/.Lib9c.Tests/Action/PatchTableSheetTest.cs
index ef629fc041..28f8a63912 100644
--- a/.Lib9c.Tests/Action/PatchTableSheetTest.cs
+++ b/.Lib9c.Tests/Action/PatchTableSheetTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -24,7 +25,7 @@ public PatchTableSheetTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -114,13 +115,11 @@ public void CheckPermission()
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
const string tableName = "TestTable";
- var initStates = new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize())
+ .SetLegacyState(
Addresses.TableSheet.Derive(tableName),
Dictionary.Empty.Add(tableName, "Initial"));
- var state = new World(initStates);
var action = new PatchTableSheet()
{
TableName = tableName,
@@ -160,13 +159,11 @@ public void ExecuteNewTable()
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
const string tableName = "TestTable";
- var initStates = new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize())
- .SetState(
- ReservedAddresses.LegacyAccount,
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize())
+ .SetLegacyState(
Addresses.TableSheet.Derive(tableName),
Dictionary.Empty.Add(tableName, "Initial"));
- var state = new World(initStates);
var action = new PatchTableSheet()
{
TableName = nameof(CostumeStatSheet),
diff --git a/.Lib9c.Tests/Action/PrepareRewardAssetsTest.cs b/.Lib9c.Tests/Action/PrepareRewardAssetsTest.cs
index bf7189ee75..ce2b205f36 100644
--- a/.Lib9c.Tests/Action/PrepareRewardAssetsTest.cs
+++ b/.Lib9c.Tests/Action/PrepareRewardAssetsTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using System.Collections.Immutable;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -37,7 +38,7 @@ public void Execute(bool admin, bool includeNcg, Type exc)
#pragma warning restore CS0618
}
- IWorld state = new World(new MockWorldState())
+ IWorld state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.Admin, adminState.Serialize());
var action = new PrepareRewardAssets(poolAddress, assets);
diff --git a/.Lib9c.Tests/Action/RaidTest.cs b/.Lib9c.Tests/Action/RaidTest.cs
new file mode 100644
index 0000000000..c46af29cdd
--- /dev/null
+++ b/.Lib9c.Tests/Action/RaidTest.cs
@@ -0,0 +1,627 @@
+namespace Lib9c.Tests.Action
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Bencodex.Types;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Libplanet.Types.Assets;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Battle;
+ using Nekoyume.Extensions;
+ using Nekoyume.Helper;
+ using Nekoyume.Model.Arena;
+ using Nekoyume.Model.Rune;
+ using Nekoyume.Model.Stat;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Nekoyume.TableData;
+ using Xunit;
+ using static SerializeKeys;
+
+ public class RaidTest
+ {
+ private readonly Dictionary _sheets;
+ private readonly Address _agentAddress;
+ private readonly Address _avatarAddress;
+ private readonly TableSheets _tableSheets;
+ private readonly Currency _goldCurrency;
+
+ public RaidTest()
+ {
+ _sheets = TableSheetsImporter.ImportSheets();
+ _tableSheets = new TableSheets(_sheets);
+ _agentAddress = new PrivateKey().Address;
+ _avatarAddress = new PrivateKey().Address;
+#pragma warning disable CS0618
+ // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
+ _goldCurrency = Currency.Legacy("NCG", 2, null);
+#pragma warning restore CS0618
+ }
+
+ [Theory]
+ // Join new raid.
+ [InlineData(null, true, true, true, false, 0, 0L, false, false, 0, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ [InlineData(null, true, true, true, false, 0, 0L, false, false, 0, false, false, false, 5, true, 0, 10002, 1, 30001)]
+ // Refill by interval.
+ [InlineData(null, true, true, false, true, 0, -10368, false, false, 0, false, false, false, 5, true, 0, 10002, 1, 30001)]
+ // Refill by NCG.
+ [InlineData(null, true, true, false, true, 0, 200L, true, true, 0, false, false, false, 5, true, 0, 10002, 1, 30001)]
+ [InlineData(null, true, true, false, true, 0, 200L, true, true, 1, false, false, false, 5, true, 0, 10002, 1, 30001)]
+ // Boss level up.
+ [InlineData(null, true, true, false, true, 3, 100L, false, false, 0, true, true, false, 5, true, 0, 10002, 1, 30001)]
+ // Update RaidRewardInfo.
+ [InlineData(null, true, true, false, true, 3, 100L, false, false, 0, true, true, true, 5, true, 0, 10002, 1, 30001)]
+ // Boss skip level up.
+ [InlineData(null, true, true, false, true, 3, 100L, false, false, 0, true, false, false, 5, true, 0, 10002, 1, 30001)]
+ // AvatarState null.
+ [InlineData(typeof(FailedLoadStateException), false, false, false, false, 0, 0L, false, false, 0, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ // Insufficient CRYSTAL.
+ [InlineData(typeof(InsufficientBalanceException), true, true, false, false, 0, 0L, false, false, 0, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ // Insufficient NCG.
+ [InlineData(typeof(InsufficientBalanceException), true, true, false, true, 0, 0L, true, false, 0, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ // Wait interval.
+ [InlineData(typeof(RequiredBlockIntervalException), true, true, false, true, 3, 10L, false, false, 0, false, false, false, 1, false, 0, 10002, 1, 30001)]
+ // Exceed purchase limit.
+ [InlineData(typeof(ExceedTicketPurchaseLimitException), true, true, false, true, 0, 100L, true, false, 1_000, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ // Exceed challenge count.
+ [InlineData(typeof(ExceedPlayCountException), true, true, false, true, 0, 100L, false, false, 0, false, false, false, 5, false, 0, 10002, 1, 30001)]
+ [InlineData(typeof(DuplicatedRuneIdException), true, true, false, true, 3, 100L, true, false, 0, false, false, false, 5, false, 0, 30001, 1, 30001)]
+ [InlineData(typeof(DuplicatedRuneSlotIndexException), true, true, false, true, 3, 100L, true, false, 0, false, false, false, 5, false, 1, 10002, 1, 30001)]
+ public void Execute(
+ Type exc,
+ bool avatarExist,
+ bool stageCleared,
+ bool crystalExist,
+ bool raiderStateExist,
+ int remainChallengeCount,
+ long refillBlockIndexOffset,
+ bool payNcg,
+ bool ncgExist,
+ int purchaseCount,
+ bool kill,
+ bool levelUp,
+ bool rewardRecordExist,
+ long executeOffset,
+ bool raiderListExist,
+ int slotIndex,
+ int runeId,
+ int slotIndex2,
+ int runeId2
+ )
+ {
+ var blockIndex = _tableSheets.WorldBossListSheet.Values
+ .OrderBy(x => x.StartedBlockIndex)
+ .First(x =>
+ {
+ if (exc == typeof(InsufficientBalanceException))
+ {
+ return ncgExist ? x.TicketPrice > 0 : x.EntranceFee > 0;
+ }
+
+ return true;
+ })
+ .StartedBlockIndex;
+
+ var action = new Raid
+ {
+ AvatarAddress = _avatarAddress,
+ EquipmentIds = new List(),
+ CostumeIds = new List(),
+ FoodIds = new List(),
+ RuneInfos = new List()
+ {
+ new RuneSlotInfo(slotIndex, runeId),
+ new RuneSlotInfo(slotIndex2, runeId2),
+ },
+ PayNcg = payNcg,
+ };
+ Currency crystal = CrystalCalculator.CRYSTAL;
+ int raidId = _tableSheets.WorldBossListSheet.FindRaidIdByBlockIndex(blockIndex);
+ Address raiderAddress = Addresses.GetRaiderAddress(_avatarAddress, raidId);
+ var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
+ WorldBossListSheet.Row worldBossRow = _tableSheets.WorldBossListSheet.FindRowByBlockIndex(blockIndex);
+ var hpSheet = _tableSheets.WorldBossGlobalHpSheet;
+ Address bossAddress = Addresses.GetWorldBossAddress(raidId);
+ Address worldBossKillRewardRecordAddress = Addresses.GetWorldBossKillRewardRecordAddress(_avatarAddress, raidId);
+ Address raiderListAddress = Addresses.GetRaiderListAddress(raidId);
+ int level = 1;
+ if (kill & !levelUp)
+ {
+ level = hpSheet.OrderedList.Last().Level;
+ }
+
+ var fee = _tableSheets.WorldBossListSheet[raidId].EntranceFee;
+
+ var context = new ActionContext();
+ IWorld state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
+ .SetAgentState(_agentAddress, new AgentState(_agentAddress));
+
+ foreach (var (key, value) in _sheets)
+ {
+ state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ default
+ );
+
+ if (avatarExist)
+ {
+ var equipments = Doomfist.GetAllParts(_tableSheets, avatarState.level);
+ foreach (var equipment in equipments)
+ {
+ avatarState.inventory.AddItem(equipment);
+ }
+
+ if (stageCleared)
+ {
+ for (int i = 0; i < 50; i++)
+ {
+ avatarState.worldInformation.ClearStage(1, i + 1, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
+ }
+ }
+
+ if (crystalExist)
+ {
+ var price = _tableSheets.WorldBossListSheet[raidId].EntranceFee;
+ state = state.MintAsset(context, _agentAddress, price * crystal);
+ }
+
+ if (raiderStateExist)
+ {
+ var raiderState = new RaiderState();
+ raiderState.RefillBlockIndex = blockIndex + refillBlockIndexOffset;
+ raiderState.RemainChallengeCount = remainChallengeCount;
+ raiderState.TotalScore = 1_000;
+ raiderState.HighScore = 0;
+ raiderState.TotalChallengeCount = 1;
+ raiderState.PurchaseCount = purchaseCount;
+ raiderState.Cp = 0;
+ raiderState.Level = 0;
+ raiderState.IconId = 0;
+ raiderState.AvatarName = "hash";
+ raiderState.AvatarAddress = _avatarAddress;
+ raiderState.UpdatedBlockIndex = blockIndex;
+
+ state = state.SetLegacyState(raiderAddress, raiderState.Serialize());
+
+ var raiderList = new List().Add(raiderAddress.Serialize());
+
+ if (raiderListExist)
+ {
+ raiderList = raiderList.Add(new PrivateKey().Address.Serialize());
+ }
+
+ state = state.SetLegacyState(raiderListAddress, raiderList);
+ }
+
+ if (rewardRecordExist)
+ {
+ var rewardRecord = new WorldBossKillRewardRecord
+ {
+ [0] = false,
+ };
+ state = state.SetLegacyState(worldBossKillRewardRecordAddress, rewardRecord.Serialize());
+ }
+
+ if (ncgExist)
+ {
+ var row = _tableSheets.WorldBossListSheet.FindRowByBlockIndex(blockIndex);
+ state = state.MintAsset(context, _agentAddress, (row.TicketPrice + row.AdditionalTicketPrice * purchaseCount) * _goldCurrency);
+ }
+
+ state = state
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
+ }
+
+ if (kill)
+ {
+ var bossState =
+ new WorldBossState(worldBossRow, _tableSheets.WorldBossGlobalHpSheet[level])
+ {
+ CurrentHp = 0,
+ Level = level,
+ };
+ state = state.SetLegacyState(bossAddress, bossState.Serialize());
+ }
+
+ if (exc is null)
+ {
+ var randomSeed = 0;
+ var ctx = new ActionContext
+ {
+ BlockIndex = blockIndex + executeOffset,
+ PreviousState = state,
+ RandomSeed = randomSeed,
+ Signer = _agentAddress,
+ };
+
+ var nextState = action.Execute(ctx);
+
+ var random = new TestRandom(randomSeed);
+ var bossListRow = _tableSheets.WorldBossListSheet.FindRowByBlockIndex(ctx.BlockIndex);
+ var raidSimulatorSheets = _tableSheets.GetRaidSimulatorSheets();
+ var simulator = new RaidSimulator(
+ bossListRow.BossId,
+ random,
+ avatarState,
+ action.FoodIds,
+ null,
+ raidSimulatorSheets,
+ _tableSheets.CostumeStatSheet,
+ new List());
+ simulator.Simulate();
+ var score = simulator.DamageDealt;
+
+ Dictionary rewardMap
+ = new Dictionary();
+ foreach (var reward in simulator.AssetReward)
+ {
+ rewardMap[reward.Currency] = reward;
+ }
+
+ if (rewardRecordExist)
+ {
+ var bossRow = raidSimulatorSheets.WorldBossCharacterSheet[bossListRow.BossId];
+ Assert.True(state.TryGetLegacyState(bossAddress, out List prevRawBoss));
+ var prevBossState = new WorldBossState(prevRawBoss);
+ int rank = WorldBossHelper.CalculateRank(bossRow, raiderStateExist ? 1_000 : 0);
+ var rewards = RuneHelper.CalculateReward(
+ rank,
+ prevBossState.Id,
+ _tableSheets.RuneWeightSheet,
+ _tableSheets.WorldBossKillRewardSheet,
+ _tableSheets.RuneSheet,
+ random
+ );
+
+ foreach (var reward in rewards)
+ {
+ if (!rewardMap.ContainsKey(reward.Currency))
+ {
+ rewardMap[reward.Currency] = reward;
+ }
+ else
+ {
+ rewardMap[reward.Currency] += reward;
+ }
+ }
+
+ foreach (var reward in rewardMap)
+ {
+ if (reward.Key.Equals(CrystalCalculator.CRYSTAL))
+ {
+ Assert.Equal(reward.Value, nextState.GetBalance(_agentAddress, reward.Key));
+ }
+ else
+ {
+ Assert.Equal(reward.Value, nextState.GetBalance(_avatarAddress, reward.Key));
+ }
+ }
+ }
+
+ if (rewardMap.ContainsKey(crystal))
+ {
+ Assert.Equal(rewardMap[crystal], nextState.GetBalance(_agentAddress, crystal));
+ }
+
+ if (crystalExist)
+ {
+ Assert.Equal(fee * crystal, nextState.GetBalance(bossAddress, crystal));
+ }
+
+ Assert.True(nextState.TryGetLegacyState(raiderAddress, out List rawRaider));
+ var raiderState = new RaiderState(rawRaider);
+ long expectedTotalScore = raiderStateExist ? 1_000 + score : score;
+ int expectedRemainChallenge = payNcg ? 0 : 2;
+ int expectedTotalChallenge = raiderStateExist ? 2 : 1;
+
+ Assert.Equal(score, raiderState.HighScore);
+ Assert.Equal(expectedTotalScore, raiderState.TotalScore);
+ Assert.Equal(expectedRemainChallenge, raiderState.RemainChallengeCount);
+ Assert.Equal(expectedTotalChallenge, raiderState.TotalChallengeCount);
+ Assert.Equal(1, raiderState.Level);
+ Assert.Equal(GameConfig.DefaultAvatarArmorId, raiderState.IconId);
+ Assert.True(raiderState.Cp > 0);
+
+ Assert.True(nextState.TryGetLegacyState(bossAddress, out List rawBoss));
+ var bossState = new WorldBossState(rawBoss);
+ int expectedLevel = level;
+ if (kill & levelUp)
+ {
+ expectedLevel++;
+ }
+
+ Assert.Equal(expectedLevel, bossState.Level);
+ Assert.Equal(expectedLevel, raiderState.LatestBossLevel);
+ if (kill)
+ {
+ Assert.Equal(hpSheet[expectedLevel].Hp, bossState.CurrentHp);
+ }
+
+ if (payNcg)
+ {
+ Assert.Equal(0 * _goldCurrency, nextState.GetBalance(_agentAddress, _goldCurrency));
+ Assert.Equal(purchaseCount + 1, nextState.GetRaiderState(raiderAddress).PurchaseCount);
+ }
+
+ Assert.True(nextState.TryGetLegacyState(worldBossKillRewardRecordAddress, out List rawRewardInfo));
+ var rewardRecord = new WorldBossKillRewardRecord(rawRewardInfo);
+ Assert.Contains(expectedLevel, rewardRecord.Keys);
+ if (rewardRecordExist)
+ {
+ Assert.True(rewardRecord[0]);
+ }
+ else
+ {
+ if (expectedLevel == 1)
+ {
+ Assert.False(rewardRecord[1]);
+ }
+ else
+ {
+ Assert.DoesNotContain(1, rewardRecord.Keys);
+ }
+ }
+
+ Assert.True(nextState.TryGetLegacyState(raiderListAddress, out List rawRaiderList));
+ List raiderList = rawRaiderList.ToList(StateExtensions.ToAddress);
+
+ Assert.Contains(raiderAddress, raiderList);
+ }
+ else
+ {
+ if (exc == typeof(DuplicatedRuneIdException) || exc == typeof(DuplicatedRuneSlotIndexException))
+ {
+ var ncgCurrency = state.GetGoldCurrency();
+ state = state.MintAsset(context, _agentAddress, 99999 * ncgCurrency);
+
+ var unlockRuneSlot = new UnlockRuneSlot()
+ {
+ AvatarAddress = _avatarAddress,
+ SlotIndex = 1,
+ };
+
+ state = unlockRuneSlot.Execute(new ActionContext
+ {
+ BlockIndex = 1,
+ PreviousState = state,
+ Signer = _agentAddress,
+ RandomSeed = 0,
+ });
+ }
+
+ Assert.Throws(exc, () => action.Execute(new ActionContext
+ {
+ BlockIndex = blockIndex + executeOffset,
+ PreviousState = state,
+ RandomSeed = 0,
+ Signer = _agentAddress,
+ }));
+ }
+ }
+
+ [Fact]
+ public void Execute_With_Reward()
+ {
+ var action = new Raid
+ {
+ AvatarAddress = _avatarAddress,
+ EquipmentIds = new List(),
+ CostumeIds = new List(),
+ FoodIds = new List(),
+ RuneInfos = new List(),
+ PayNcg = false,
+ };
+
+ var worldBossRow = _tableSheets.WorldBossListSheet.First().Value;
+ int raidId = worldBossRow.Id;
+ Address raiderAddress = Addresses.GetRaiderAddress(_avatarAddress, raidId);
+ var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
+ Address bossAddress = Addresses.GetWorldBossAddress(raidId);
+ Address worldBossKillRewardRecordAddress = Addresses.GetWorldBossKillRewardRecordAddress(_avatarAddress, raidId);
+
+ IWorld state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
+ .SetAgentState(_agentAddress, new AgentState(_agentAddress));
+
+ foreach (var (key, value) in _sheets)
+ {
+ state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ default
+ );
+
+ for (int i = 0; i < 50; i++)
+ {
+ avatarState.worldInformation.ClearStage(1, i + 1, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
+ }
+
+ var raiderState = new RaiderState();
+ raiderState.RefillBlockIndex = 0;
+ raiderState.RemainChallengeCount = WorldBossHelper.MaxChallengeCount;
+ raiderState.TotalScore = 1_000;
+ raiderState.TotalChallengeCount = 1;
+ raiderState.PurchaseCount = 0;
+ raiderState.Cp = 0;
+ raiderState.Level = 0;
+ raiderState.IconId = 0;
+ raiderState.AvatarName = "hash";
+ raiderState.AvatarAddress = _avatarAddress;
+ state = state.SetLegacyState(raiderAddress, raiderState.Serialize());
+
+ var rewardRecord = new WorldBossKillRewardRecord
+ {
+ [1] = false,
+ };
+ state = state.SetLegacyState(worldBossKillRewardRecordAddress, rewardRecord.Serialize());
+
+ state = state
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
+
+ var bossState =
+ new WorldBossState(worldBossRow, _tableSheets.WorldBossGlobalHpSheet[2])
+ {
+ CurrentHp = 0,
+ Level = 2,
+ };
+ state = state.SetLegacyState(bossAddress, bossState.Serialize());
+ var randomSeed = 0;
+ var random = new TestRandom(randomSeed);
+
+ var simulator = new RaidSimulator(
+ worldBossRow.BossId,
+ random,
+ avatarState,
+ action.FoodIds,
+ null,
+ _tableSheets.GetRaidSimulatorSheets(),
+ _tableSheets.CostumeStatSheet,
+ new List());
+ simulator.Simulate();
+
+ Dictionary rewardMap
+ = new Dictionary();
+ foreach (var reward in simulator.AssetReward)
+ {
+ rewardMap[reward.Currency] = reward;
+ }
+
+ List killRewards = RuneHelper.CalculateReward(
+ 0,
+ bossState.Id,
+ _tableSheets.RuneWeightSheet,
+ _tableSheets.WorldBossKillRewardSheet,
+ _tableSheets.RuneSheet,
+ random
+ );
+
+ var nextState = action.Execute(new ActionContext
+ {
+ BlockIndex = worldBossRow.StartedBlockIndex + gameConfigState.WorldBossRequiredInterval,
+ PreviousState = state,
+ RandomSeed = randomSeed,
+ Signer = _agentAddress,
+ });
+
+ Assert.True(nextState.TryGetLegacyState(raiderAddress, out List rawRaider));
+ var nextRaiderState = new RaiderState(rawRaider);
+ Assert.Equal(simulator.DamageDealt, nextRaiderState.HighScore);
+
+ foreach (var reward in killRewards)
+ {
+ if (!rewardMap.ContainsKey(reward.Currency))
+ {
+ rewardMap[reward.Currency] = reward;
+ }
+ else
+ {
+ rewardMap[reward.Currency] += reward;
+ }
+ }
+
+ foreach (var reward in rewardMap)
+ {
+ if (reward.Key.Equals(CrystalCalculator.CRYSTAL))
+ {
+ Assert.Equal(reward.Value, nextState.GetBalance(_agentAddress, reward.Key));
+ }
+ else
+ {
+ Assert.Equal(reward.Value, nextState.GetBalance(_avatarAddress, reward.Key));
+ }
+ }
+
+ Assert.Equal(1, nextRaiderState.Level);
+ Assert.Equal(GameConfig.DefaultAvatarArmorId, nextRaiderState.IconId);
+ Assert.True(nextRaiderState.Cp > 0);
+ Assert.Equal(3, nextRaiderState.LatestBossLevel);
+ Assert.True(nextState.TryGetLegacyState(bossAddress, out List rawBoss));
+ var nextBossState = new WorldBossState(rawBoss);
+ Assert.Equal(3, nextBossState.Level);
+ Assert.True(nextState.TryGetLegacyState(worldBossKillRewardRecordAddress, out List rawRewardInfo));
+ var nextRewardInfo = new WorldBossKillRewardRecord(rawRewardInfo);
+ Assert.True(nextRewardInfo[1]);
+ }
+
+ [Fact]
+ public void Execute_With_Free_Crystal_Fee()
+ {
+ var action = new Raid
+ {
+ AvatarAddress = _avatarAddress,
+ EquipmentIds = new List(),
+ CostumeIds = new List(),
+ FoodIds = new List(),
+ RuneInfos = new List(),
+ PayNcg = false,
+ };
+ Currency crystal = CrystalCalculator.CRYSTAL;
+
+ _sheets[nameof(WorldBossListSheet)] =
+ "id,boss_id,started_block_index,ended_block_index,fee,ticket_price,additional_ticket_price,max_purchase_count\r\n" +
+ "1,900002,0,100,0,1,1,40";
+
+ var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
+ IWorld state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
+ .SetAgentState(_agentAddress, new AgentState(_agentAddress));
+
+ foreach (var (key, value) in _sheets)
+ {
+ state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ gameConfigState,
+ default
+ );
+
+ for (int i = 0; i < 50; i++)
+ {
+ avatarState.worldInformation.ClearStage(1, i + 1, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
+ }
+
+ state = state
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
+
+ var blockIndex = gameConfigState.WorldBossRequiredInterval;
+ var randomSeed = 0;
+ var ctx = new ActionContext
+ {
+ BlockIndex = blockIndex,
+ PreviousState = state,
+ RandomSeed = randomSeed,
+ Signer = _agentAddress,
+ };
+ action.Execute(ctx);
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/RankingBattleTest.cs b/.Lib9c.Tests/Action/RankingBattleTest.cs
index 2bff5d2cfc..e16518da31 100644
--- a/.Lib9c.Tests/Action/RankingBattleTest.cs
+++ b/.Lib9c.Tests/Action/RankingBattleTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model;
@@ -29,7 +30,7 @@ public class RankingBattleTest
public RankingBattleTest(ITestOutputHelper outputHelper)
{
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var keys = new List
{
diff --git a/.Lib9c.Tests/Action/RapidCombinationTest.cs b/.Lib9c.Tests/Action/RapidCombinationTest.cs
new file mode 100644
index 0000000000..a81c03df5b
--- /dev/null
+++ b/.Lib9c.Tests/Action/RapidCombinationTest.cs
@@ -0,0 +1,616 @@
+namespace Lib9c.Tests.Action
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Immutable;
+ using System.Globalization;
+ using System.Linq;
+ using Bencodex.Types;
+ using Lib9c.Tests.Fixtures.TableCSV;
+ using Lib9c.Tests.Fixtures.TableCSV.Item;
+ using Lib9c.Tests.Util;
+ using Libplanet.Action;
+ using Libplanet.Action.State;
+ using Libplanet.Crypto;
+ using Libplanet.Mocks;
+ using Nekoyume;
+ using Nekoyume.Action;
+ using Nekoyume.Helper;
+ using Nekoyume.Model;
+ using Nekoyume.Model.Item;
+ using Nekoyume.Model.Mail;
+ using Nekoyume.Model.State;
+ using Nekoyume.Module;
+ using Nekoyume.TableData;
+ using Xunit;
+ using static Lib9c.SerializeKeys;
+
+ public class RapidCombinationTest
+ {
+ private readonly IWorld _initialState;
+
+ private readonly TableSheets _tableSheets;
+
+ private readonly Address _agentAddress;
+ private readonly Address _avatarAddress;
+
+ public RapidCombinationTest()
+ {
+ _initialState = new World(MockUtil.MockModernWorldState);
+ Dictionary sheets;
+ (_initialState, sheets) = InitializeUtil.InitializeTableSheets(
+ _initialState,
+ sheetsOverride: new Dictionary
+ {
+ {
+ "EquipmentItemRecipeSheet",
+ EquipmentItemRecipeSheetFixtures.Default
+ },
+ {
+ "EquipmentItemSubRecipeSheet",
+ EquipmentItemSubRecipeSheetFixtures.V1
+ },
+ {
+ "GameConfigSheet",
+ GameConfigSheetFixtures.Default
+ },
+ });
+ _tableSheets = new TableSheets(sheets);
+ foreach (var (key, value) in sheets)
+ {
+ _initialState =
+ _initialState.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
+ }
+
+ _agentAddress = new PrivateKey().Address;
+ var agentState = new AgentState(_agentAddress);
+
+ _avatarAddress = new PrivateKey().Address;
+ var avatarState = new AvatarState(
+ _avatarAddress,
+ _agentAddress,
+ 0,
+ _tableSheets.GetAvatarSheets(),
+ new GameConfigState(),
+ default
+ );
+
+ agentState.avatarAddresses[0] = _avatarAddress;
+
+ _initialState = _initialState
+ .SetLegacyState(Addresses.GameConfig, new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize())
+ .SetAgentState(_agentAddress, agentState)
+ .SetAvatarState(_avatarAddress, avatarState);
+ }
+
+ [Fact]
+ public void Execute()
+ {
+ const int slotStateUnlockStage = 1;
+
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _initialState.GetSheet(),
+ slotStateUnlockStage);
+
+ var row = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.Hourglass);
+ avatarState.inventory.AddItem(ItemFactory.CreateMaterial(row), 83);
+ avatarState.inventory.AddItem(ItemFactory.CreateTradableMaterial(row), 100);
+ Assert.True(avatarState.inventory.HasFungibleItem(row.ItemId, 0, 183));
+
+ var firstEquipmentRow = _tableSheets.EquipmentItemSheet.First;
+ Assert.NotNull(firstEquipmentRow);
+
+ var gameConfigState = _initialState.GetGameConfigState();
+ var requiredBlockIndex = gameConfigState.HourglassPerBlock * 200;
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ requiredBlockIndex);
+ avatarState.inventory.AddItem(equipment);
+
+ var result = new CombinationConsumable5.ResultModel
+ {
+ actionPoint = 0,
+ gold = 0,
+ materials = new Dictionary(),
+ itemUsable = equipment,
+ recipeId = 0,
+ itemType = ItemType.Equipment,
+ };
+
+ var mail = new CombinationMail(result, 0, default, requiredBlockIndex);
+ result.id = mail.id;
+ avatarState.Update2(mail);
+
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, slotStateUnlockStage);
+ slotState.Update(result, 0, requiredBlockIndex);
+
+ var tempState = _initialState
+ .SetLegacyState(slotAddress, slotState.Serialize())
+ .SetAvatarState(_avatarAddress, avatarState);
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ var nextState = action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = 51,
+ });
+
+ var nextAvatarState = nextState.GetAvatarState(_avatarAddress);
+ var item = nextAvatarState.inventory.Equipments.First();
+
+ Assert.Empty(nextAvatarState.inventory.Materials.Select(r => r.ItemSubType == ItemSubType.Hourglass));
+ Assert.Equal(equipment.ItemId, item.ItemId);
+ Assert.Equal(51, item.RequiredBlockIndex);
+ }
+
+ [Fact]
+ public void Execute_Throw_CombinationSlotResultNullException()
+ {
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, 0);
+ slotState.Update(null, 0, 0);
+
+ var tempState = _initialState
+ .SetLegacyState(slotAddress, slotState.Serialize());
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = 1,
+ }));
+ }
+
+ [Theory]
+ [InlineData(0, 0)]
+ [InlineData(10, 100)]
+ public void Execute_Throw_RequiredBlockIndexException(int itemRequiredBlockIndex, int contextBlockIndex)
+ {
+ const int avatarClearedStage = 1;
+
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _initialState.GetSheet(),
+ avatarClearedStage);
+
+ var firstEquipmentRow = _tableSheets.EquipmentItemSheet.First;
+ Assert.NotNull(firstEquipmentRow);
+
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ itemRequiredBlockIndex);
+
+ var result = new CombinationConsumable5.ResultModel
+ {
+ actionPoint = 0,
+ gold = 0,
+ materials = new Dictionary(),
+ itemUsable = equipment,
+ recipeId = 0,
+ itemType = ItemType.Equipment,
+ };
+
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, avatarClearedStage);
+ slotState.Update(result, 0, 0);
+
+ var tempState = _initialState
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(slotAddress, slotState.Serialize());
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = contextBlockIndex,
+ }));
+ }
+
+ [Theory]
+ [InlineData(0, 0, 0, 40)]
+ [InlineData(0, 1, 2, 40)]
+ [InlineData(22, 0, 0, 40)]
+ [InlineData(0, 22, 0, 40)]
+ [InlineData(0, 22, 2, 40)]
+ [InlineData(2, 10, 2, 40)]
+ public void Execute_Throw_NotEnoughMaterialException(int materialCount, int tradableCount, long blockIndex, int requiredCount)
+ {
+ const int slotStateUnlockStage = 1;
+
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _initialState.GetSheet(),
+ slotStateUnlockStage);
+
+ var row = _tableSheets.MaterialItemSheet.Values.First(r => r.ItemSubType == ItemSubType.Hourglass);
+ avatarState.inventory.AddItem(ItemFactory.CreateMaterial(row), count: materialCount);
+ if (tradableCount > 0)
+ {
+ var material = ItemFactory.CreateTradableMaterial(row);
+ material.RequiredBlockIndex = blockIndex;
+ avatarState.inventory.AddItem(material, count: tradableCount);
+ }
+
+ var firstEquipmentRow = _tableSheets.EquipmentItemSheet.First;
+ Assert.NotNull(firstEquipmentRow);
+
+ var gameConfigState = _initialState.GetGameConfigState();
+ var requiredBlockIndex = gameConfigState.HourglassPerBlock * requiredCount;
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ requiredBlockIndex);
+ avatarState.inventory.AddItem(equipment);
+
+ var result = new CombinationConsumable5.ResultModel
+ {
+ actionPoint = 0,
+ gold = 0,
+ materials = new Dictionary(),
+ itemUsable = equipment,
+ recipeId = 0,
+ itemType = ItemType.Equipment,
+ };
+
+ var mail = new CombinationMail(result, 0, default, requiredBlockIndex);
+ result.id = mail.id;
+ avatarState.Update2(mail);
+
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, slotStateUnlockStage);
+ slotState.Update(result, 0, 0);
+
+ var tempState = _initialState
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(slotAddress, slotState.Serialize());
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = 51,
+ }));
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData(1)]
+ public void ResultModelDeterministic(int? subRecipeId)
+ {
+ var row = _tableSheets.MaterialItemSheet.Values.First();
+ var row2 = _tableSheets.MaterialItemSheet.Values.Last();
+
+ Assert.True(row.Id < row2.Id);
+
+ var material = ItemFactory.CreateMaterial(row);
+ var material2 = ItemFactory.CreateMaterial(row2);
+
+ var itemUsable = ItemFactory.CreateItemUsable(_tableSheets.EquipmentItemSheet.Values.First(), default, 0);
+ var r = new CombinationConsumable5.ResultModel
+ {
+ id = default,
+ gold = 0,
+ actionPoint = 0,
+ recipeId = 1,
+ subRecipeId = subRecipeId,
+ materials = new Dictionary
+ {
+ [material] = 1,
+ [material2] = 1,
+ },
+ itemUsable = itemUsable,
+ };
+ var result = new RapidCombination0.ResultModel((Dictionary)r.Serialize())
+ {
+ cost = new Dictionary
+ {
+ [material] = 1,
+ [material2] = 1,
+ },
+ };
+
+ var r2 = new CombinationConsumable5.ResultModel
+ {
+ id = default,
+ gold = 0,
+ actionPoint = 0,
+ recipeId = 1,
+ subRecipeId = subRecipeId,
+ materials = new Dictionary
+ {
+ [material2] = 1,
+ [material] = 1,
+ },
+ itemUsable = itemUsable,
+ };
+
+ var result2 = new RapidCombination0.ResultModel((Dictionary)r2.Serialize())
+ {
+ cost = new Dictionary
+ {
+ [material2] = 1,
+ [material] = 1,
+ },
+ };
+
+ Assert.Equal(result.Serialize(), result2.Serialize());
+ }
+
+ [Fact]
+ public void Execute_Throw_RequiredAppraiseBlockException()
+ {
+ const int slotStateUnlockStage = 1;
+
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _initialState.GetSheet(),
+ slotStateUnlockStage);
+
+ var row = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.Hourglass);
+ avatarState.inventory.AddItem(ItemFactory.CreateMaterial(row), count: 22);
+
+ var firstEquipmentRow = _tableSheets.EquipmentItemSheet.First;
+ Assert.NotNull(firstEquipmentRow);
+
+ var gameConfigState = _initialState.GetGameConfigState();
+ var requiredBlockIndex = gameConfigState.HourglassPerBlock * 40;
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ requiredBlockIndex);
+ avatarState.inventory.AddItem(equipment);
+
+ var result = new CombinationConsumable5.ResultModel
+ {
+ actionPoint = 0,
+ gold = 0,
+ materials = new Dictionary(),
+ itemUsable = equipment,
+ recipeId = 0,
+ itemType = ItemType.Equipment,
+ };
+
+ var mail = new CombinationMail(result, 0, default, requiredBlockIndex);
+ result.id = mail.id;
+ avatarState.Update(mail);
+
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, slotStateUnlockStage);
+ slotState.Update(result, 0, 0);
+
+ var tempState = _initialState
+ .SetAvatarState(_avatarAddress, avatarState)
+ .SetLegacyState(slotAddress, slotState.Serialize());
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ Assert.Throws(() => action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = 1,
+ }));
+ }
+
+ [Theory]
+ [InlineData(7)]
+ [InlineData(9)]
+ [InlineData(10)]
+ [InlineData(11)]
+ public void Execute_NotThrow_InvalidOperationException_When_TargetSlotCreatedBy(
+ int itemEnhancementResultModelNumber)
+ {
+ const int slotStateUnlockStage = 1;
+
+ var avatarState = _initialState.GetAvatarState(_avatarAddress);
+ avatarState.worldInformation = new WorldInformation(
+ 0,
+ _initialState.GetSheet(),
+ slotStateUnlockStage);
+
+ var row = _tableSheets.MaterialItemSheet.Values.First(r =>
+ r.ItemSubType == ItemSubType.Hourglass);
+ avatarState.inventory.AddItem(ItemFactory.CreateMaterial(row), 83);
+ avatarState.inventory.AddItem(ItemFactory.CreateTradableMaterial(row), 100);
+ Assert.True(avatarState.inventory.HasFungibleItem(row.ItemId, 0, 183));
+
+ var firstEquipmentRow = _tableSheets.EquipmentItemSheet
+ .OrderedList.First(e => e.Grade >= 1);
+ Assert.NotNull(firstEquipmentRow);
+
+ var gameConfigState = _initialState.GetGameConfigState();
+ var requiredBlockIndex = gameConfigState.HourglassPerBlock * 200;
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ requiredBlockIndex);
+ var materialEquipment = (Equipment)ItemFactory.CreateItemUsable(
+ firstEquipmentRow,
+ Guid.NewGuid(),
+ requiredBlockIndex);
+ avatarState.inventory.AddItem(equipment);
+ avatarState.inventory.AddItem(materialEquipment);
+
+ AttachmentActionResult resultModel = null;
+ var random = new TestRandom();
+ var mailId = random.GenerateRandomGuid();
+ var preItemUsable = new Equipment((Dictionary)equipment.Serialize());
+ switch (itemEnhancementResultModelNumber)
+ {
+ case 7:
+ {
+ equipment = ItemEnhancement7.UpgradeEquipment(equipment);
+ resultModel = new ItemEnhancement7.ResultModel
+ {
+ id = mailId,
+ itemUsable = equipment,
+ materialItemIdList = new[] { materialEquipment.NonFungibleId },
+ };
+
+ break;
+ }
+
+ case 9:
+ {
+ Assert.True(ItemEnhancement9.TryGetRow(
+ equipment,
+ _tableSheets.EnhancementCostSheetV2,
+ out var costRow));
+ var equipmentResult = ItemEnhancement9.GetEnhancementResult(costRow, random);
+ equipment.LevelUp(
+ random,
+ costRow,
+ equipmentResult == ItemEnhancement9.EnhancementResult.GreatSuccess);
+ resultModel = new ItemEnhancement9.ResultModel
+ {
+ id = mailId,
+ preItemUsable = preItemUsable,
+ itemUsable = equipment,
+ materialItemIdList = new[] { materialEquipment.NonFungibleId },
+ gold = 0,
+ actionPoint = 0,
+ enhancementResult = ItemEnhancement9.EnhancementResult.GreatSuccess,
+ };
+
+ break;
+ }
+
+ case 10:
+ {
+ Assert.True(ItemEnhancement10.TryGetRow(
+ equipment,
+ _tableSheets.EnhancementCostSheetV2,
+ out var costRow));
+ var equipmentResult = ItemEnhancement10.GetEnhancementResult(costRow, random);
+ equipment.LevelUp(
+ random,
+ costRow,
+ equipmentResult == ItemEnhancement10.EnhancementResult.GreatSuccess);
+ resultModel = new ItemEnhancement10.ResultModel
+ {
+ id = mailId,
+ preItemUsable = preItemUsable,
+ itemUsable = equipment,
+ materialItemIdList = new[] { materialEquipment.NonFungibleId },
+ gold = 0,
+ actionPoint = 0,
+ enhancementResult = ItemEnhancement10.EnhancementResult.GreatSuccess,
+ };
+
+ break;
+ }
+
+ case 11:
+ {
+ Assert.True(ItemEnhancement11.TryGetRow(
+ equipment,
+ _tableSheets.EnhancementCostSheetV2,
+ out var costRow));
+ var equipmentResult = ItemEnhancement11.GetEnhancementResult(costRow, random);
+ equipment.LevelUp(
+ random,
+ costRow,
+ equipmentResult == ItemEnhancement11.EnhancementResult.GreatSuccess);
+ resultModel = new ItemEnhancement11.ResultModel
+ {
+ id = mailId,
+ preItemUsable = preItemUsable,
+ itemUsable = equipment,
+ materialItemIdList = new[] { materialEquipment.NonFungibleId },
+ gold = 0,
+ actionPoint = 0,
+ enhancementResult = ItemEnhancement11.EnhancementResult.GreatSuccess,
+ CRYSTAL = 0 * CrystalCalculator.CRYSTAL,
+ };
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // NOTE: Do not update `mail`, because this test assumes that the `mail` was removed.
+ {
+ // var mail = new ItemEnhanceMail(resultModel, 0, random.GenerateRandomGuid(), requiredBlockIndex);
+ // avatarState.Update(mail);
+ }
+
+ var slotAddress = _avatarAddress.Derive(string.Format(
+ CultureInfo.InvariantCulture,
+ CombinationSlotState.DeriveFormat,
+ 0));
+ var slotState = new CombinationSlotState(slotAddress, slotStateUnlockStage);
+ slotState.Update(resultModel, 0, requiredBlockIndex);
+
+ var tempState = _initialState.SetLegacyState(slotAddress, slotState.Serialize())
+ .SetAvatarState(_avatarAddress, avatarState);
+
+ var action = new RapidCombination
+ {
+ avatarAddress = _avatarAddress,
+ slotIndex = 0,
+ };
+
+ action.Execute(new ActionContext
+ {
+ PreviousState = tempState,
+ Signer = _agentAddress,
+ BlockIndex = 51,
+ });
+ }
+ }
+}
diff --git a/.Lib9c.Tests/Action/ReRegisterProduct0Test.cs b/.Lib9c.Tests/Action/ReRegisterProduct0Test.cs
index 6b1d315fea..c200602f7e 100644
--- a/.Lib9c.Tests/Action/ReRegisterProduct0Test.cs
+++ b/.Lib9c.Tests/Action/ReRegisterProduct0Test.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Model.Order;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -40,7 +41,7 @@ public ReRegisterProduct0Test(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/ReRegisterProductTest.cs b/.Lib9c.Tests/Action/ReRegisterProductTest.cs
index b0c1ecabc4..9b74188d4e 100644
--- a/.Lib9c.Tests/Action/ReRegisterProductTest.cs
+++ b/.Lib9c.Tests/Action/ReRegisterProductTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Model.Order;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -40,7 +41,7 @@ public ReRegisterProductTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
diff --git a/.Lib9c.Tests/Action/RedeemCodeTest.cs b/.Lib9c.Tests/Action/RedeemCodeTest.cs
index e491e300f3..dcc2266601 100644
--- a/.Lib9c.Tests/Action/RedeemCodeTest.cs
+++ b/.Lib9c.Tests/Action/RedeemCodeTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -71,7 +72,7 @@ public void Execute(bool backward)
#pragma warning restore CS0618
var context = new ActionContext();
- var initialState = new World(new MockWorldState())
+ var initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(_agentAddress, agentState)
.SetLegacyState(RedeemCodeState.Address, prevRedeemCodesState.Serialize())
.SetLegacyState(GoldCurrencyState.Address, goldState.Serialize())
diff --git a/.Lib9c.Tests/Action/RegisterProduct0Test.cs b/.Lib9c.Tests/Action/RegisterProduct0Test.cs
index 3acb53a28f..72b261530f 100644
--- a/.Lib9c.Tests/Action/RegisterProduct0Test.cs
+++ b/.Lib9c.Tests/Action/RegisterProduct0Test.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -55,7 +56,7 @@ public RegisterProduct0Test()
};
agentState.avatarAddresses[0] = AvatarAddress;
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(Gold).Serialize())
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.MaterialItemSheet.Serialize())
.SetLegacyState(Addresses.GameConfig, _gameConfigState.Serialize())
diff --git a/.Lib9c.Tests/Action/RegisterProductTest.cs b/.Lib9c.Tests/Action/RegisterProductTest.cs
index d9c92299dd..9ee04961cf 100644
--- a/.Lib9c.Tests/Action/RegisterProductTest.cs
+++ b/.Lib9c.Tests/Action/RegisterProductTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -55,7 +56,7 @@ public RegisterProductTest()
};
agentState.avatarAddresses[0] = AvatarAddress;
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(Gold).Serialize())
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.MaterialItemSheet.Serialize())
.SetLegacyState(Addresses.GameConfig, _gameConfigState.Serialize())
diff --git a/.Lib9c.Tests/Action/RenewAdminStateTest.cs b/.Lib9c.Tests/Action/RenewAdminStateTest.cs
index a43b873bcc..b41e36146f 100644
--- a/.Lib9c.Tests/Action/RenewAdminStateTest.cs
+++ b/.Lib9c.Tests/Action/RenewAdminStateTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using System;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -21,9 +22,8 @@ public RenewAdminStateTest()
_adminPrivateKey = new PrivateKey();
_validUntil = 1_500_000L;
_adminState = new AdminState(_adminPrivateKey.Address, _validUntil);
- _stateDelta = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, Addresses.Admin, _adminState.Serialize()));
+ _stateDelta = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(Addresses.Admin, _adminState.Serialize());
}
[Fact]
diff --git a/.Lib9c.Tests/Action/RequestPledgeTest.cs b/.Lib9c.Tests/Action/RequestPledgeTest.cs
index 71486ac433..77b25fcdb6 100644
--- a/.Lib9c.Tests/Action/RequestPledgeTest.cs
+++ b/.Lib9c.Tests/Action/RequestPledgeTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -19,7 +20,7 @@ public void Execute(int contractedMead)
Currency mead = Currencies.Mead;
Address patron = new PrivateKey().Address;
var context = new ActionContext();
- IWorld states = new World(new MockWorldState()).MintAsset(context, patron, 2 * mead);
+ IWorld states = new World(MockUtil.MockModernWorldState).MintAsset(context, patron, 2 * mead);
var address = new PrivateKey().Address;
var action = new RequestPledge
{
@@ -50,7 +51,7 @@ public void Execute_Throw_AlreadyContractedException()
Address patron = new PrivateKey().Address;
var address = new PrivateKey().Address;
Address contractAddress = address.GetPledgeAddress();
- IWorld states = new World(new MockWorldState()).SetLegacyState(contractAddress, List.Empty);
+ IWorld states = new World(MockUtil.MockModernWorldState).SetLegacyState(contractAddress, List.Empty);
var action = new RequestPledge
{
AgentAddress = address,
diff --git a/.Lib9c.Tests/Action/RewardGoldTest.cs b/.Lib9c.Tests/Action/RewardGoldTest.cs
index 08096bcc43..d97f34d4bf 100644
--- a/.Lib9c.Tests/Action/RewardGoldTest.cs
+++ b/.Lib9c.Tests/Action/RewardGoldTest.cs
@@ -15,6 +15,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Blockchain.Policies;
using Libplanet.Blockchain.Renderers;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Assets;
@@ -77,7 +78,7 @@ public RewardGoldTest()
var gold = new GoldCurrencyState(Currency.Legacy("NCG", 2, null));
#pragma warning restore CS0618
IActionContext context = new ActionContext();
- _baseState = new World(new MockWorldState())
+ _baseState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, gold.Serialize())
.SetLegacyState(Addresses.GoldDistribution, GoldDistributionTest.Fixture.Select(v => v.Serialize()).Serialize())
.MintAsset(context, GoldCurrencyState.Address, gold.Currency * 100000000000);
@@ -585,7 +586,7 @@ public void TransferMead(int patronMead, int balance)
var patronAddress = new PrivateKey().Address;
var contractAddress = agentAddress.GetPledgeAddress();
IActionContext context = new ActionContext();
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.MintAsset(context, patronAddress, patronMead * Currencies.Mead)
.TransferAsset(context, patronAddress, agentAddress, 1 * Currencies.Mead)
.SetLegacyState(contractAddress, List.Empty.Add(patronAddress.Serialize()).Add(true.Serialize()).Add(balance.Serialize()))
@@ -607,7 +608,7 @@ public void NoRewardWhenEmptySupply()
gameConfigState.Set(_tableSheets.GameConfigSheet);
var currency = Currency.Legacy("NCG", 2, null);
- IWorld states = new World(new MockWorldState())
+ IWorld states = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(currency, 0).Serialize())
.SetLegacyState(weekly.address, weekly.Serialize())
.SetLegacyState(Addresses.GoldDistribution, new List())
diff --git a/.Lib9c.Tests/Action/RuneEnhancement0Test.cs b/.Lib9c.Tests/Action/RuneEnhancement0Test.cs
deleted file mode 100644
index c80199ccb6..0000000000
--- a/.Lib9c.Tests/Action/RuneEnhancement0Test.cs
+++ /dev/null
@@ -1,469 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System;
- using System.Linq;
- using Bencodex.Types;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Libplanet.Types.Assets;
- using Nekoyume;
- using Nekoyume.Action;
- using Nekoyume.Helper;
- using Nekoyume.Model.Rune;
- using Nekoyume.Model.State;
- using Nekoyume.Module;
- using Nekoyume.TableData;
- using Xunit;
-
- public class RuneEnhancement0Test
- {
- private readonly Currency _goldCurrency;
-
- public RuneEnhancement0Test()
- {
- _goldCurrency = Currency.Legacy("NCG", 2, null);
- }
-
- [Theory]
- [InlineData(10000)]
- [InlineData(1)]
- public void Execute(int seed)
- {
- var agentAddress = new PrivateKey().Address;
- var avatarAddress = new PrivateKey().Address;
- var sheets = TableSheetsImporter.ImportSheets();
- var tableSheets = new TableSheets(sheets);
- var blockIndex = tableSheets.WorldBossListSheet.Values
- .OrderBy(x => x.StartedBlockIndex)
- .First()
- .StartedBlockIndex;
-
- var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var context = new ActionContext();
- var state = new World(new MockWorldState())
- .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
- .SetAgentState(agentAddress, new AgentState(agentAddress));
-
- foreach (var (key, value) in sheets)
- {
- state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
- }
-
- var avatarState = new AvatarState(
- avatarAddress,
- agentAddress,
- 0,
- tableSheets.GetAvatarSheets(),
- new GameConfigState(),
- default
- );
-
- var runeListSheet = state.GetSheet();
- var runeId = runeListSheet.First().Value.Id;
- var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
- var runeState = new RuneState(runeId);
- state = state.SetLegacyState(runeStateAddress, runeState.Serialize());
-
- var costSheet = state.GetSheet();
- if (!costSheet.TryGetValue(runeId, out var costRow))
- {
- throw new RuneCostNotFoundException($"[{nameof(Execute)}] ");
- }
-
- if (!costRow.TryGetCost(runeState.Level + 1, out var cost))
- {
- throw new RuneCostDataNotFoundException($"[{nameof(Execute)}] ");
- }
-
- var runeSheet = state.GetSheet();
- if (!runeSheet.TryGetValue(runeId, out var runeRow))
- {
- throw new RuneNotFoundException($"[{nameof(Execute)}] ");
- }
-
- var ncgCurrency = state.GetGoldCurrency();
- var crystalCurrency = CrystalCalculator.CRYSTAL;
- var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null);
-
- var ncgBal = cost.NcgQuantity * ncgCurrency * 10000;
- var crystalBal = cost.CrystalQuantity * crystalCurrency * 10000;
- var runeBal = cost.RuneStoneQuantity * runeCurrency * 10000;
-
- var rand = new TestRandom(seed);
- if (!RuneHelper.TryEnhancement(ncgBal, crystalBal, runeBal, ncgCurrency, crystalCurrency, runeCurrency, cost, rand, 99, out var tryCount))
- {
- throw new RuneNotFoundException($"[{nameof(Execute)}] ");
- }
-
- if (ncgBal.Sign > 0)
- {
- state = state.MintAsset(context, agentAddress, ncgBal);
- }
-
- if (crystalBal.Sign > 0)
- {
- state = state.MintAsset(context, agentAddress, crystalBal);
- }
-
- if (runeBal.Sign > 0)
- {
- state = state.MintAsset(context, avatarState.address, runeBal);
- }
-
- var action = new RuneEnhancement0()
- {
- AvatarAddress = avatarState.address,
- RuneId = runeId,
- TryCount = tryCount,
- };
- var ctx = new ActionContext
- {
- BlockIndex = blockIndex,
- PreviousState = state,
- RandomSeed = rand.Seed,
- Signer = agentAddress,
- };
-
- var nextState = action.Execute(ctx);
- if (!nextState.TryGetLegacyState(runeStateAddress, out List nextRuneRawState))
- {
- throw new Exception();
- }
-
- var nextRunState = new RuneState(nextRuneRawState);
- var nextNcgBal = nextState.GetBalance(agentAddress, ncgCurrency);
- var nextCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency);
- var nextRuneBal = nextState.GetBalance(agentAddress, runeCurrency);
-
- if (cost.NcgQuantity != 0)
- {
- Assert.NotEqual(ncgBal, nextNcgBal);
- }
-
- if (cost.CrystalQuantity != 0)
- {
- Assert.NotEqual(crystalBal, nextCrystalBal);
- }
-
- if (cost.RuneStoneQuantity != 0)
- {
- Assert.NotEqual(runeBal, nextRuneBal);
- }
-
- var costNcg = tryCount * cost.NcgQuantity * ncgCurrency;
- var costCrystal = tryCount * cost.CrystalQuantity * crystalCurrency;
- var costRune = tryCount * cost.RuneStoneQuantity * runeCurrency;
-
- if (costNcg.Sign > 0)
- {
- nextState = nextState.MintAsset(context, agentAddress, costNcg);
- }
-
- if (costCrystal.Sign > 0)
- {
- nextState = nextState.MintAsset(context, agentAddress, costCrystal);
- }
-
- if (costRune.Sign > 0)
- {
- nextState = nextState.MintAsset(context, avatarState.address, costRune);
- }
-
- var finalNcgBal = nextState.GetBalance(agentAddress, ncgCurrency);
- var finalCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency);
- var finalRuneBal = nextState.GetBalance(avatarState.address, runeCurrency);
- Assert.Equal(ncgBal, finalNcgBal);
- Assert.Equal(crystalBal, finalCrystalBal);
- Assert.Equal(runeBal, finalRuneBal);
- Assert.Equal(runeState.Level + 1, nextRunState.Level);
- }
-
- [Fact]
- public void Execute_RuneCostNotFoundException()
- {
- var agentAddress = new PrivateKey().Address;
- var avatarAddress = new PrivateKey().Address;
- var sheets = TableSheetsImporter.ImportSheets();
- var tableSheets = new TableSheets(sheets);
- var blockIndex = tableSheets.WorldBossListSheet.Values
- .OrderBy(x => x.StartedBlockIndex)
- .First()
- .StartedBlockIndex;
-
- var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var state = new World(new MockWorldState())
- .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
- .SetAgentState(agentAddress, new AgentState(agentAddress));
-
- foreach (var (key, value) in sheets)
- {
- state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
- }
-
- var avatarState = new AvatarState(
- avatarAddress,
- agentAddress,
- 0,
- tableSheets.GetAvatarSheets(),
- new GameConfigState(),
- default
- );
-
- var runeListSheet = state.GetSheet();
- var runeId = runeListSheet.First().Value.Id;
- var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
- var runeState = new RuneState(128381293);
- state = state.SetLegacyState(runeStateAddress, runeState.Serialize());
- var action = new RuneEnhancement0()
- {
- AvatarAddress = avatarState.address,
- RuneId = runeId,
- TryCount = 1,
- };
-
- Assert.Throws(() =>
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = agentAddress,
- RandomSeed = 0,
- BlockIndex = blockIndex,
- }));
- }
-
- [Fact]
- public void Execute_RuneCostDataNotFoundException()
- {
- var agentAddress = new PrivateKey().Address;
- var avatarAddress = new PrivateKey().Address;
- var sheets = TableSheetsImporter.ImportSheets();
- var tableSheets = new TableSheets(sheets);
- var blockIndex = tableSheets.WorldBossListSheet.Values
- .OrderBy(x => x.StartedBlockIndex)
- .First()
- .StartedBlockIndex;
-
- var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var state = new World(new MockWorldState())
- .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
- .SetAgentState(agentAddress, new AgentState(agentAddress));
-
- foreach (var (key, value) in sheets)
- {
- state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
- }
-
- var avatarState = new AvatarState(
- avatarAddress,
- agentAddress,
- 0,
- tableSheets.GetAvatarSheets(),
- new GameConfigState(),
- default
- );
-
- var runeListSheet = state.GetSheet();
- var runeId = runeListSheet.First().Value.Id;
- var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
- var runeState = new RuneState(runeId);
- var costSheet = state.GetSheet();
- if (!costSheet.TryGetValue(runeId, out var costRow))
- {
- throw new RuneCostNotFoundException($"[{nameof(Execute)}] ");
- }
-
- for (var i = 0; i < costRow.Cost.Count + 1; i++)
- {
- runeState.LevelUp();
- }
-
- state = state.SetLegacyState(runeStateAddress, runeState.Serialize());
-
- var action = new RuneEnhancement0()
- {
- AvatarAddress = avatarState.address,
- RuneId = runeId,
- TryCount = 1,
- };
-
- Assert.Throws(() =>
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = agentAddress,
- RandomSeed = 0,
- BlockIndex = blockIndex,
- }));
- }
-
- [Theory]
- [InlineData(false, true, true)]
- [InlineData(true, true, false)]
- [InlineData(true, false, true)]
- public void Execute_NotEnoughFungibleAssetValueException(bool ncg, bool crystal, bool rune)
- {
- var agentAddress = new PrivateKey().Address;
- var avatarAddress = new PrivateKey().Address;
- var sheets = TableSheetsImporter.ImportSheets();
- var tableSheets = new TableSheets(sheets);
- var blockIndex = tableSheets.WorldBossListSheet.Values
- .OrderBy(x => x.StartedBlockIndex)
- .First()
- .StartedBlockIndex;
-
- var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var context = new ActionContext();
- var state = new World(new MockWorldState())
- .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
- .SetAgentState(agentAddress, new AgentState(agentAddress));
-
- foreach (var (key, value) in sheets)
- {
- state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
- }
-
- var avatarState = new AvatarState(
- avatarAddress,
- agentAddress,
- 0,
- tableSheets.GetAvatarSheets(),
- new GameConfigState(),
- default
- );
-
- var runeListSheet = state.GetSheet();
- var runeId = runeListSheet.First().Value.Id;
- var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
- var runeState = new RuneState(runeId);
- state = state.SetLegacyState(runeStateAddress, runeState.Serialize());
-
- var costSheet = state.GetSheet();
- if (!costSheet.TryGetValue(runeId, out var costRow))
- {
- throw new RuneCostNotFoundException($"[{nameof(Execute)}] ");
- }
-
- if (!costRow.TryGetCost(runeState.Level + 1, out var cost))
- {
- throw new RuneCostDataNotFoundException($"[{nameof(Execute)}] ");
- }
-
- var runeSheet = state.GetSheet();
- if (!runeSheet.TryGetValue(runeId, out var runeRow))
- {
- throw new RuneNotFoundException($"[{nameof(Execute)}] ");
- }
-
- var ncgCurrency = state.GetGoldCurrency();
- var crystalCurrency = CrystalCalculator.CRYSTAL;
- var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null);
-
- if (ncg && cost.NcgQuantity > 0)
- {
- state = state.MintAsset(context, agentAddress, cost.NcgQuantity * ncgCurrency);
- }
-
- if (crystal && cost.CrystalQuantity > 0)
- {
- state = state.MintAsset(context, agentAddress, cost.CrystalQuantity * crystalCurrency);
- }
-
- if (rune)
- {
- state = state.MintAsset(context, avatarState.address, cost.RuneStoneQuantity * runeCurrency);
- }
-
- var action = new RuneEnhancement0()
- {
- AvatarAddress = avatarState.address,
- RuneId = runeId,
- TryCount = 1,
- };
- var ctx = new ActionContext
- {
- BlockIndex = blockIndex,
- PreviousState = state,
- RandomSeed = 0,
- Signer = agentAddress,
- };
-
- if (!ncg && cost.NcgQuantity == 0)
- {
- return;
- }
-
- if (!crystal && cost.CrystalQuantity == 0)
- {
- return;
- }
-
- if (!rune && cost.RuneStoneQuantity == 0)
- {
- return;
- }
-
- Assert.Throws(() =>
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = agentAddress,
- RandomSeed = 0,
- BlockIndex = blockIndex,
- }));
- }
-
- [Fact]
- public void Execute_TryCountIsZeroException()
- {
- var agentAddress = new PrivateKey().Address;
- var avatarAddress = new PrivateKey().Address;
- var sheets = TableSheetsImporter.ImportSheets();
- var tableSheets = new TableSheets(sheets);
- var blockIndex = tableSheets.WorldBossListSheet.Values
- .OrderBy(x => x.StartedBlockIndex)
- .First()
- .StartedBlockIndex;
-
- var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var state = new World(new MockWorldState())
- .SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
- .SetAgentState(agentAddress, new AgentState(agentAddress));
-
- foreach (var (key, value) in sheets)
- {
- state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
- }
-
- var avatarState = new AvatarState(
- avatarAddress,
- agentAddress,
- 0,
- tableSheets.GetAvatarSheets(),
- new GameConfigState(),
- default
- );
-
- var runeListSheet = state.GetSheet();
- var runeId = runeListSheet.First().Value.Id;
- var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
- var runeState = new RuneState(runeId);
- state = state.SetLegacyState(runeStateAddress, runeState.Serialize());
-
- var action = new RuneEnhancement0()
- {
- AvatarAddress = avatarState.address,
- RuneId = runeId,
- TryCount = 0,
- };
-
- Assert.Throws(() =>
- action.Execute(new ActionContext()
- {
- PreviousState = state,
- Signer = agentAddress,
- RandomSeed = 0,
- BlockIndex = blockIndex,
- }));
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/RuneEnhancementTest.cs b/.Lib9c.Tests/Action/RuneEnhancementTest.cs
index 16b398d0a4..ec108d4b75 100644
--- a/.Lib9c.Tests/Action/RuneEnhancementTest.cs
+++ b/.Lib9c.Tests/Action/RuneEnhancementTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -51,7 +52,7 @@ public void Execute(int seed)
);
agentState.avatarAddresses.Add(0, avatarAddress);
var context = new ActionContext();
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState);
@@ -205,7 +206,7 @@ public void Execute_RuneCostNotFoundException()
rankingMapAddress
);
agentState.avatarAddresses.Add(0, avatarAddress);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState);
@@ -261,7 +262,7 @@ public void Execute_RuneCostDataNotFoundException()
rankingMapAddress
);
agentState.avatarAddresses.Add(0, avatarAddress);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState);
@@ -333,7 +334,7 @@ public void Execute_NotEnoughFungibleAssetValueException(bool ncg, bool crystal,
);
agentState.avatarAddresses.Add(0, avatarAddress);
var context = new ActionContext();
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState);
@@ -448,7 +449,7 @@ public void Execute_TryCountIsZeroException()
rankingMapAddress
);
agentState.avatarAddresses.Add(0, avatarAddress);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState);
@@ -494,7 +495,7 @@ public void Execute_FailedLoadStateException()
.StartedBlockIndex;
var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, new AgentState(agentAddress));
diff --git a/.Lib9c.Tests/Action/Scenario/ArenaScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/ArenaScenarioTest.cs
index 5b6262816e..4818449363 100644
--- a/.Lib9c.Tests/Action/Scenario/ArenaScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/ArenaScenarioTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action.Scenario
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -36,7 +37,7 @@ public ArenaScenarioTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _state = new World(new MockWorldState());
+ _state = new World(MockUtil.MockModernWorldState);
_sheets = TableSheetsImporter.ImportSheets();
var tableSheets = new TableSheets(_sheets);
diff --git a/.Lib9c.Tests/Action/Scenario/AuraScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/AuraScenarioTest.cs
index 49382047cb..2fa35fe85d 100644
--- a/.Lib9c.Tests/Action/Scenario/AuraScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/AuraScenarioTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action.Scenario
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -50,7 +51,7 @@ public AuraScenarioTest()
var skill = SkillFactory.Get(skillRow, 0, 100, 0, StatType.NONE);
_aura.Skills.Add(skill);
var addresses = new[] { _avatarAddress, _enemyAvatarAddress };
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
for (int i = 0; i < addresses.Length; i++)
{
var avatarAddress = addresses[i];
diff --git a/.Lib9c.Tests/Action/Scenario/CollectionScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/CollectionScenarioTest.cs
index 720f58cc4a..745a8415c4 100644
--- a/.Lib9c.Tests/Action/Scenario/CollectionScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/CollectionScenarioTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action.Scenario
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -35,7 +36,7 @@ public CollectionScenarioTest()
_tableSheets = new TableSheets(_sheets);
var gameConfigState = new GameConfigState(_sheets[nameof(GameConfigSheet)]);
var addresses = new[] { _avatarAddress, _enemyAvatarAddress };
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
for (int i = 0; i < addresses.Length; i++)
{
var avatarAddress = addresses[i];
diff --git a/.Lib9c.Tests/Action/Scenario/MarketScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/MarketScenarioTest.cs
index c89b190833..ac9bb76e65 100644
--- a/.Lib9c.Tests/Action/Scenario/MarketScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/MarketScenarioTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests.Action.Scenario
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -103,7 +104,7 @@ public MarketScenarioTest(ITestOutputHelper outputHelper)
agentState3.avatarAddresses[0] = _buyerAvatarAddress;
_currency = Currency.Legacy("NCG", 2, minters: null);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(_currency).Serialize())
.SetLegacyState(Addresses.GameConfig, _gameConfigState.Serialize())
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.MaterialItemSheet.Serialize())
@@ -446,7 +447,7 @@ public void Register_And_Cancel()
}
Assert.All(new[] { nonFungibleProductId, fungibleProductId, assetProductId }, productId => Assert.NotEqual(default, productId));
- var action2 = new CancelProductRegistration0
+ var action2 = new CancelProductRegistration
{
AvatarAddress = _sellerAvatarAddress,
ProductInfos = new List
@@ -498,7 +499,9 @@ public void Register_And_Cancel()
);
}
- Assert.Equal(_gameConfigState.ActionPointMax - RegisterProduct.CostAp - CancelProductRegistration0.CostAp, latestAvatarState.actionPoint);
+ Assert.Equal(
+ _gameConfigState.ActionPointMax - RegisterProduct.CostAp - CancelProductRegistration.CostAp,
+ latestAvatarState.actionPoint);
var sellProductList = new ProductsState((List)latestState.GetLegacyState(productsStateAddress));
Assert.Empty(sellProductList.ProductIds);
@@ -965,7 +968,7 @@ public void HardFork()
},
};
//Cancel
- var cancelAction = new CancelProductRegistration0
+ var cancelAction = new CancelProductRegistration
{
AvatarAddress = _sellerAvatarAddress,
ProductInfos = productInfos,
diff --git a/.Lib9c.Tests/Action/Scenario/MeadScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/MeadScenarioTest.cs
index de83be4c2c..ac56297807 100644
--- a/.Lib9c.Tests/Action/Scenario/MeadScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/MeadScenarioTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action.Scenario
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -20,7 +21,7 @@ public void Contract()
Currency mead = Currencies.Mead;
var patron = new PrivateKey().Address;
IActionContext context = new ActionContext();
- IWorld states = new World(new MockWorldState()).MintAsset(context, patron, 10 * mead);
+ IWorld states = new World(MockUtil.MockModernWorldState).MintAsset(context, patron, 10 * mead);
var agentAddress = new PrivateKey().Address;
var requestPledge = new RequestPledge
@@ -85,7 +86,7 @@ bool IsTarget(Type type)
var action = (IAction)Activator.CreateInstance(typeId)!;
var actionContext = new ActionContext
{
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
};
try
{
diff --git a/.Lib9c.Tests/Action/Scenario/RuneScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/RuneScenarioTest.cs
index d6f786bbbe..48cb43d1bb 100644
--- a/.Lib9c.Tests/Action/Scenario/RuneScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/RuneScenarioTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action.Scenario
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -40,7 +41,7 @@ public void Craft_And_Unlock_And_Equip()
);
var context = new ActionContext();
- IWorld initialState = new World(new MockWorldState())
+ IWorld initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(agentAddress, agentState)
.SetAvatarState(avatarAddress, avatarState)
.SetLegacyState(
diff --git a/.Lib9c.Tests/Action/Scenario/SellAndCancellationAndSellTest.cs b/.Lib9c.Tests/Action/Scenario/SellAndCancellationAndSellTest.cs
index 5aa2457b93..63186f8a01 100644
--- a/.Lib9c.Tests/Action/Scenario/SellAndCancellationAndSellTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/SellAndCancellationAndSellTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action.Scenario
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -60,7 +61,7 @@ public SellAndCancellationAndSellTest(ITestOutputHelper outputHelper)
GameConfig.RequireClearedStageLevel.ActionsInShop),
};
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, gold.Serialize())
.SetLegacyState(gameConfigState.address, gameConfigState.Serialize())
.SetAgentState(_agentAddress, agentState)
diff --git a/.Lib9c.Tests/Action/Scenario/WorldUnlockScenarioTest.cs b/.Lib9c.Tests/Action/Scenario/WorldUnlockScenarioTest.cs
index c158ccce4c..fbe0dc1065 100644
--- a/.Lib9c.Tests/Action/Scenario/WorldUnlockScenarioTest.cs
+++ b/.Lib9c.Tests/Action/Scenario/WorldUnlockScenarioTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action.Scenario
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -56,7 +57,7 @@ public WorldUnlockScenarioTest()
var currency = Currency.Legacy("NCG", 2, null);
#pragma warning restore CS0618
var goldCurrencyState = new GoldCurrencyState(currency);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize())
.SetLegacyState(_weeklyArenaState.address, _weeklyArenaState.Serialize())
.SetAgentState(_agentAddress, agentState)
diff --git a/.Lib9c.Tests/Action/SecureMiningRewardTest.cs b/.Lib9c.Tests/Action/SecureMiningRewardTest.cs
index 1d84b24da6..4ba4db9052 100644
--- a/.Lib9c.Tests/Action/SecureMiningRewardTest.cs
+++ b/.Lib9c.Tests/Action/SecureMiningRewardTest.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using System.Collections.Immutable;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume.Action;
using Nekoyume.Model.State;
@@ -35,13 +36,13 @@ public class SecureMiningRewardTest
}.ToImmutableList();
private static readonly IWorld _previousState = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, new AdminState(_admin, 100).Serialize())
- .SetState(ReservedAddresses.LegacyAccount, GoldCurrencyState.Address, new GoldCurrencyState(NCG).Serialize())
+ MockWorldState.CreateModern()
.SetBalance(_authMiners[0], NCG * 1000)
.SetBalance(_authMiners[1], NCG * 2000)
.SetBalance(_authMiners[2], NCG * 3000)
- .SetBalance(_authMiners[3], NCG * 4000));
+ .SetBalance(_authMiners[3], NCG * 4000))
+ .SetLegacyState(AdminState.Address, new AdminState(_admin, 100).Serialize())
+ .SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(NCG).Serialize());
[Fact]
public void Execute()
diff --git a/.Lib9c.Tests/Action/SellCancellationTest.cs b/.Lib9c.Tests/Action/SellCancellationTest.cs
index 5feb2f10a2..59f84113d7 100644
--- a/.Lib9c.Tests/Action/SellCancellationTest.cs
+++ b/.Lib9c.Tests/Action/SellCancellationTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Model.Order;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -38,7 +39,7 @@ public SellCancellationTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -233,7 +234,7 @@ bool fromPreviousAction
Signer = _agentAddress,
});
- var cancelProductRegistration = new CancelProductRegistration0
+ var cancelProductRegistration = new CancelProductRegistration
{
AvatarAddress = _avatarAddress,
ProductInfos = new List
diff --git a/.Lib9c.Tests/Action/SellTest.cs b/.Lib9c.Tests/Action/SellTest.cs
index d791456cc4..474cbc890c 100644
--- a/.Lib9c.Tests/Action/SellTest.cs
+++ b/.Lib9c.Tests/Action/SellTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Model.Order;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -35,7 +36,7 @@ public SellTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -297,7 +298,7 @@ public void Execute_Throw_InvalidOperationException_DueTo_EmptyState()
Assert.Throws(() => action.Execute(new ActionContext
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
Signer = _agentAddress,
}));
}
diff --git a/.Lib9c.Tests/Action/Stake0Test.cs b/.Lib9c.Tests/Action/Stake0Test.cs
index dddc15b24a..d47d89be41 100644
--- a/.Lib9c.Tests/Action/Stake0Test.cs
+++ b/.Lib9c.Tests/Action/Stake0Test.cs
@@ -3,6 +3,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -28,7 +29,7 @@ public Stake0Test(ITestOutputHelper outputHelper)
.CreateLogger();
var context = new ActionContext();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
diff --git a/.Lib9c.Tests/Action/Stake2Test.cs b/.Lib9c.Tests/Action/Stake2Test.cs
index 7fc03212dc..22816c8886 100644
--- a/.Lib9c.Tests/Action/Stake2Test.cs
+++ b/.Lib9c.Tests/Action/Stake2Test.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -29,7 +30,7 @@ public Stake2Test(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
diff --git a/.Lib9c.Tests/Action/Summon/AuraSummonTest.cs b/.Lib9c.Tests/Action/Summon/AuraSummonTest.cs
index d8a70fd4ec..3b331002dd 100644
--- a/.Lib9c.Tests/Action/Summon/AuraSummonTest.cs
+++ b/.Lib9c.Tests/Action/Summon/AuraSummonTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action.Summon
using Lib9c.Tests.Fixtures.TableCSV.Summon;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -55,7 +56,7 @@ public AuraSummonTest()
var gold = new GoldCurrencyState(_currency);
var context = new ActionContext();
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(_agentAddress, agentState)
.SetAvatarState(_avatarAddress, _avatarState)
.SetLegacyState(GoldCurrencyState.Address, gold.Serialize())
diff --git a/.Lib9c.Tests/Action/Summon/RuneSummonTest.cs b/.Lib9c.Tests/Action/Summon/RuneSummonTest.cs
index 8dc111a3cd..7cf03d4e9d 100644
--- a/.Lib9c.Tests/Action/Summon/RuneSummonTest.cs
+++ b/.Lib9c.Tests/Action/Summon/RuneSummonTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action.Summon
using System.Linq;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -55,7 +56,7 @@ public RuneSummonTest()
var gold = new GoldCurrencyState(_currency);
var context = new ActionContext();
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(_agentAddress, agentState)
.SetAvatarState(_avatarAddress, _avatarState)
.SetLegacyState(GoldCurrencyState.Address, gold.Serialize())
diff --git a/.Lib9c.Tests/Action/TransferAssetTest.cs b/.Lib9c.Tests/Action/TransferAssetTest.cs
index 7c5e8fae63..4ec020e08e 100644
--- a/.Lib9c.Tests/Action/TransferAssetTest.cs
+++ b/.Lib9c.Tests/Action/TransferAssetTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -54,7 +55,7 @@ public void Execute()
var contractAddress = _sender.Derive(nameof(RequestPledge));
var patronAddress = new PrivateKey().Address;
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10));
var action = new TransferAsset(
@@ -77,7 +78,7 @@ public void Execute()
public void Execute_Throw_InvalidTransferSignerException()
{
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10)
.SetBalance(_sender, Currencies.Mead * 1));
@@ -107,7 +108,7 @@ public void Execute_Throw_InvalidTransferSignerException()
public void Execute_Throw_InvalidTransferRecipientException()
{
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_sender, Currencies.Mead * 1));
// Should not allow TransferAsset with same sender and recipient.
@@ -135,7 +136,7 @@ public void Execute_Throw_InvalidTransferRecipientException()
public void Execute_Throw_InsufficientBalanceException()
{
IWorld prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10));
prevState = prevState.SetAgentState(_recipient, new AgentState(_recipient));
@@ -170,7 +171,7 @@ public void Execute_Throw_InvalidTransferMinterException(bool minterAsSender)
var currencyBySender = Currency.Legacy("NCG", 2, minter);
#pragma warning restore CS0618
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, currencyBySender * 1000)
.SetBalance(_recipient, currencyBySender * 10)
.SetBalance(_sender, Currencies.Mead * 1))
@@ -247,10 +248,10 @@ public void Execute_Throw_InvalidTransferCurrencyException()
{
var crystal = CrystalCalculator.CRYSTAL;
var prevState = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, _recipient.Derive(ActivationKey.DeriveKey), true.Serialize())
+ MockWorldState.CreateModern()
.SetBalance(_sender, crystal * 1000)
- .SetBalance(_sender, Currencies.Mead * 1));
+ .SetBalance(_sender, Currencies.Mead * 1))
+ .SetLegacyState(_recipient.Derive(ActivationKey.DeriveKey), true.Serialize());
var action = new TransferAsset(
sender: _sender,
recipient: _recipient,
@@ -285,7 +286,7 @@ public void LoadPlainValue_ThrowsMemoLengthOverflowException()
public void Execute_Throw_ArgumentException()
{
var baseState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000));
var action = new TransferAsset(
sender: _sender,
diff --git a/.Lib9c.Tests/Action/TransferAssetsTest.cs b/.Lib9c.Tests/Action/TransferAssetsTest.cs
index 45c828e486..70a3169f44 100644
--- a/.Lib9c.Tests/Action/TransferAssetsTest.cs
+++ b/.Lib9c.Tests/Action/TransferAssetsTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -69,7 +70,7 @@ public void Execute()
var contractAddress = _sender.Derive(nameof(RequestPledge));
var patronAddress = new PrivateKey().Address;
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10));
var action = new TransferAssets(
@@ -98,7 +99,7 @@ public void Execute()
public void Execute_Throw_InvalidTransferSignerException()
{
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10));
var action = new TransferAssets(
@@ -129,7 +130,7 @@ public void Execute_Throw_InvalidTransferSignerException()
public void Execute_Throw_InvalidTransferRecipientException()
{
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000));
// Should not allow TransferAsset with same sender and recipient.
var action = new TransferAssets(
@@ -158,7 +159,7 @@ public void Execute_Throw_InvalidTransferRecipientException()
public void Execute_Throw_InsufficientBalanceException()
{
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, _currency * 1000)
.SetBalance(_recipient, _currency * 10))
.SetAgentState(_recipient, new AgentState(_recipient));
@@ -192,7 +193,7 @@ public void Execute_Throw_InvalidTransferMinterException()
var currencyBySender = Currency.Legacy("NCG", 2, _sender);
#pragma warning restore CS0618
var prevState = new World(
- new MockWorldState()
+ MockWorldState.CreateModern()
.SetBalance(_sender, currencyBySender * 1000)
.SetBalance(_recipient, currencyBySender * 10))
.SetAgentState(_recipient, new AgentState(_recipient));
@@ -332,7 +333,7 @@ public void Execute_Throw_ArgumentOutOfRangeException()
{
action.Execute(new ActionContext()
{
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
Signer = _sender,
BlockIndex = 1,
});
@@ -344,9 +345,9 @@ public void Execute_Throw_InvalidTransferCurrencyException()
{
var crystal = CrystalCalculator.CRYSTAL;
var prevState = new World(
- new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, _recipient.Derive(ActivationKey.DeriveKey), true.Serialize())
- .SetBalance(_sender, crystal * 1000));
+ MockWorldState.CreateModern()
+ .SetBalance(_sender, crystal * 1000))
+ .SetLegacyState(_recipient.Derive(ActivationKey.DeriveKey), true.Serialize());
var action = new TransferAssets(
sender: _sender,
recipients: new List<(Address, FungibleAssetValue)>
@@ -366,9 +367,7 @@ public void Execute_Throw_InvalidTransferCurrencyException()
[Fact]
public void Execute_Throw_ArgumentException()
{
- var baseState = new World(
- new MockWorldState()
- .SetBalance(_sender, _currency * 1000));
+ var baseState = new World(MockWorldState.CreateModern().SetBalance(_sender, _currency * 1000));
var action = new TransferAssets(
sender: _sender,
new List<(Address, FungibleAssetValue)>
diff --git a/.Lib9c.Tests/Action/UnlockEquipmentRecipe1Test.cs b/.Lib9c.Tests/Action/UnlockEquipmentRecipe1Test.cs
deleted file mode 100644
index ab9c910537..0000000000
--- a/.Lib9c.Tests/Action/UnlockEquipmentRecipe1Test.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Bencodex.Types;
- using Libplanet.Action;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Libplanet.Types.Assets;
- using Nekoyume;
- using Nekoyume.Action;
- using Nekoyume.Model.Item;
- using Nekoyume.Model.State;
- using Nekoyume.Module;
- using Nekoyume.TableData;
- using Xunit;
- using static Lib9c.SerializeKeys;
-
- public class UnlockEquipmentRecipe1Test
- {
- private readonly IRandom _random;
- private readonly TableSheets _tableSheets;
- private readonly Address _agentAddress;
- private readonly Address _avatarAddress;
- private readonly AvatarState _avatarState;
- private readonly Currency _currency;
- private readonly IWorld _initialState;
-
- public UnlockEquipmentRecipe1Test()
- {
- _random = new TestRandom();
- var sheets = TableSheetsImporter.ImportSheets();
- _tableSheets = new TableSheets(sheets);
- _agentAddress = new PrivateKey().Address;
- _avatarAddress = new PrivateKey().Address;
-#pragma warning disable CS0618
- // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319
- _currency = Currency.Legacy("CRYSTAL", 18, null);
-#pragma warning restore CS0618
- var gameConfigState = new GameConfigState(sheets[nameof(GameConfigSheet)]);
-
- var agentState = new AgentState(_agentAddress);
- _avatarState = new AvatarState(
- _avatarAddress,
- _agentAddress,
- 0,
- _tableSheets.GetAvatarSheets(),
- gameConfigState,
- default
- );
-
- agentState.avatarAddresses.Add(0, _avatarAddress);
-
- _initialState = new World(new MockWorldState())
- .SetAgentState(_agentAddress, agentState)
- .SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.EquipmentItemSheet.Serialize())
- .SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.EquipmentItemRecipeSheet.Serialize())
- .SetLegacyState(Addresses.GameConfig, gameConfigState.Serialize());
- }
-
- [Theory]
- [InlineData(new[] { 6, 5 }, true, false, true, true, null)]
- [InlineData(new[] { 6 }, true, false, true, true, null)]
- // Unlock Belt without Armor unlock.
- [InlineData(new[] { 94 }, true, false, true, true, null)]
- // Unlock Weapon & Ring
- [InlineData(new[] { 6, 133 }, true, false, true, true, null)]
- // Invalid recipe id.
- [InlineData(new[] { -1 }, true, false, false, false, typeof(InvalidRecipeIdException))]
- [InlineData(new[] { 1 }, true, false, true, false, typeof(InvalidRecipeIdException))]
- [InlineData(new int[] { }, true, false, false, false, typeof(InvalidRecipeIdException))]
- // AvatarState is null.
- [InlineData(new[] { 6 }, false, false, true, true, typeof(FailedLoadStateException))]
- // Already unlocked recipe.
- [InlineData(new[] { 6 }, true, true, true, true, typeof(AlreadyRecipeUnlockedException))]
- // Skip prev recipe.
- [InlineData(new[] { 5 }, true, false, true, false, typeof(InvalidRecipeIdException))]
- // Stage not cleared.
- [InlineData(new[] { 6 }, true, false, false, true, typeof(NotEnoughClearedStageLevelException))]
- // Insufficient CRYSTAL.
- [InlineData(new[] { 6 }, true, false, true, false, typeof(NotEnoughFungibleAssetValueException))]
- public void Execute(
- IEnumerable ids,
- bool stateExist,
- bool alreadyUnlocked,
- bool stageCleared,
- bool balanceEnough,
- Type exc
- )
- {
- var context = new ActionContext();
- List recipeIds = ids.ToList();
- var rows = _tableSheets.EquipmentItemRecipeSheet.Values
- .Where(r => recipeIds.Contains(r.Id)).ToList();
- var balance = balanceEnough ? rows.Sum(r => r.CRYSTAL) : 1;
- var state = _initialState.MintAsset(context, _agentAddress, balance * _currency);
- Address unlockedRecipeIdsAddress = _avatarAddress.Derive("recipe_ids");
- if (stateExist)
- {
- var stage = rows.Any() ? rows.Max(r => r.UnlockStage) : 1;
- var worldSheet = _tableSheets.WorldSheet;
- var worldId = worldSheet.OrderedList
- .Last(r => r.StageBegin <= stage && stage <= r.StageEnd).Id;
- var worldInformation = _avatarState.worldInformation;
- if (stageCleared)
- {
- for (int j = 1; j < worldId + 1; j++)
- {
- for (var i = 1; i < stage + 1; i++)
- {
- _avatarState.worldInformation.ClearStage(
- j,
- i,
- 0,
- _tableSheets.WorldSheet,
- _tableSheets.WorldUnlockSheet
- );
- }
- }
- }
- else
- {
- Assert.All(recipeIds, recipeId => worldInformation.IsStageCleared(recipeId));
- }
-
- if (alreadyUnlocked)
- {
- var serializedIds = new List(recipeIds.Select(i => i.Serialize()));
- state = state.SetLegacyState(unlockedRecipeIdsAddress, serializedIds);
- }
-
- state = state.SetAvatarState(_avatarAddress, _avatarState);
- }
-
- var action = new UnlockEquipmentRecipe1
- {
- RecipeIds = recipeIds.ToList(),
- AvatarAddress = _avatarAddress,
- };
-
- if (exc is null)
- {
- IWorld nextState = action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- });
-
- Assert.True(nextState.TryGetLegacyState(unlockedRecipeIdsAddress, out List rawIds));
-
- var unlockedIds = rawIds.ToList(StateExtensions.ToInteger);
-
- Assert.All(recipeIds, recipeId => Assert.Contains(recipeId, unlockedIds));
- Assert.Equal(0 * _currency, nextState.GetBalance(_agentAddress, _currency));
- Assert.Equal(balance * _currency, nextState.GetBalance(Addresses.UnlockEquipmentRecipe, _currency));
- }
- else
- {
- Assert.Throws(exc, () => action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- }));
- }
- }
-
- [Theory]
- [InlineData(ItemSubType.Weapon)]
- [InlineData(ItemSubType.Armor)]
- [InlineData(ItemSubType.Belt)]
- [InlineData(ItemSubType.Necklace)]
- [InlineData(ItemSubType.Ring)]
- public void UnlockedIds(ItemSubType itemSubType)
- {
- var worldInformation = _avatarState.worldInformation;
- var rows = _tableSheets.EquipmentItemRecipeSheet.Values
- .Where(i => i.ItemSubType == itemSubType && i.Id != 1 && i.UnlockStage != 999);
-
- // Clear Stage
- for (int i = 0; i < _tableSheets.WorldSheet.Count; i++)
- {
- var worldRow = _tableSheets.WorldSheet.OrderedList[i];
- for (int v = worldRow.StageBegin; v < worldRow.StageEnd + 1; v++)
- {
- worldInformation.ClearStage(worldRow.Id, v, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
- }
- }
-
- // Unlock All recipe by ItemSubType
- UnlockEquipmentRecipe1.UnlockedIds(_initialState, new PrivateKey().Address, _tableSheets.EquipmentItemRecipeSheet, worldInformation, rows.Select(i => i.Id).ToList());
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/UnlockEquipmentRecipeTest.cs b/.Lib9c.Tests/Action/UnlockEquipmentRecipeTest.cs
index d45563ae92..69ab353f07 100644
--- a/.Lib9c.Tests/Action/UnlockEquipmentRecipeTest.cs
+++ b/.Lib9c.Tests/Action/UnlockEquipmentRecipeTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -52,7 +53,7 @@ public UnlockEquipmentRecipeTest()
agentState.avatarAddresses.Add(0, _avatarAddress);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetAgentState(_agentAddress, agentState)
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.EquipmentItemSheet.Serialize())
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.EquipmentItemRecipeSheet.Serialize())
diff --git a/.Lib9c.Tests/Action/UnlockRuneSlotTest.cs b/.Lib9c.Tests/Action/UnlockRuneSlotTest.cs
index 6491c72a19..215f08f96b 100644
--- a/.Lib9c.Tests/Action/UnlockRuneSlotTest.cs
+++ b/.Lib9c.Tests/Action/UnlockRuneSlotTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -35,7 +36,7 @@ public IWorld Init(out Address agentAddress, out Address avatarAddress, out long
.StartedBlockIndex;
var goldCurrencyState = new GoldCurrencyState(_goldCurrency);
- var state = new World(new MockWorldState())
+ var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(goldCurrencyState.address, goldCurrencyState.Serialize())
.SetAgentState(agentAddress, new AgentState(agentAddress));
diff --git a/.Lib9c.Tests/Action/UnlockWorld1Test.cs b/.Lib9c.Tests/Action/UnlockWorld1Test.cs
deleted file mode 100644
index 628bcc6bf0..0000000000
--- a/.Lib9c.Tests/Action/UnlockWorld1Test.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-namespace Lib9c.Tests.Action
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Bencodex.Types;
- using Libplanet.Action;
- using Libplanet.Action.State;
- using Libplanet.Crypto;
- using Libplanet.Types.Assets;
- using Nekoyume;
- using Nekoyume.Action;
- using Nekoyume.Helper;
- using Nekoyume.Model;
- using Nekoyume.Model.State;
- using Nekoyume.Module;
- using Nekoyume.TableData;
- using Xunit;
- using static Lib9c.SerializeKeys;
-
- public class UnlockWorld1Test
- {
- private readonly IRandom _random;
- private readonly TableSheets _tableSheets;
- private readonly Address _agentAddress;
- private readonly Address _avatarAddress;
- private readonly AvatarState _avatarState;
- private readonly Currency _currency;
- private readonly IWorld _initialState;
-
- public UnlockWorld1Test()
- {
- _random = new TestRandom();
- var sheets = TableSheetsImporter.ImportSheets();
- _tableSheets = new TableSheets(sheets);
- _agentAddress = new PrivateKey().Address;
- _avatarAddress = new PrivateKey().Address;
- _currency = CrystalCalculator.CRYSTAL;
- var gameConfigState = new GameConfigState(sheets[nameof(GameConfigSheet)]);
-
- var agentState = new AgentState(_agentAddress);
- _avatarState = new AvatarState(
- _avatarAddress,
- _agentAddress,
- 0,
- _tableSheets.GetAvatarSheets(),
- gameConfigState,
- default
- );
-
- agentState.avatarAddresses.Add(0, _avatarAddress);
-
- _initialState = new World(new MockWorldState())
- .SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.WorldUnlockSheet.Serialize())
- .SetLegacyState(Addresses.GameConfig, gameConfigState.Serialize());
- }
-
- [Theory]
- [InlineData(new[] { 2 }, true, false, true, 500, null)]
- // Migration AvatarState.
- [InlineData(new[] { 2, 3, 4, 5 }, true, false, true, 153000, null)]
- // Try open Yggdrasil.
- [InlineData(new[] { 1 }, false, false, true, 0, typeof(InvalidWorldException))]
- // Try open Mimisbrunnr.
- [InlineData(new[] { GameConfig.MimisbrunnrWorldId }, false, false, true, 0, typeof(InvalidWorldException))]
- // Empty WorldId.
- [InlineData(new int[] { }, false, false, true, 0, typeof(InvalidWorldException))]
- // AvatarState is null.
- [InlineData(new[] { 2 }, false, false, true, 0, typeof(FailedLoadStateException))]
- // Already unlocked world.
- [InlineData(new[] { 2 }, true, true, true, 0, typeof(AlreadyWorldUnlockedException))]
- // Skip previous world.
- [InlineData(new[] { 3 }, true, false, true, 0, typeof(FailedToUnlockWorldException))]
- // Stage not cleared.
- [InlineData(new[] { 2 }, true, false, false, 0, typeof(FailedToUnlockWorldException))]
- // Insufficient CRYSTAL.
- [InlineData(new[] { 2 }, true, false, true, 100, typeof(NotEnoughFungibleAssetValueException))]
- public void Execute(
- IEnumerable ids,
- bool stateExist,
- bool alreadyUnlocked,
- bool stageCleared,
- int balance,
- Type exc
- )
- {
- var context = new ActionContext();
- var state = (balance > 0)
- ? _initialState.MintAsset(context, _agentAddress, balance * _currency)
- : _initialState;
- var worldIds = ids.ToList();
-
- if (stateExist)
- {
- var worldInformation = _avatarState.worldInformation;
- if (stageCleared)
- {
- foreach (var wordId in worldIds)
- {
- var row = _tableSheets.WorldUnlockSheet.OrderedList.First(r =>
- r.WorldIdToUnlock == wordId);
- var worldRow = _tableSheets.WorldSheet[row.WorldId];
- var prevRow =
- _tableSheets.WorldUnlockSheet.OrderedList.FirstOrDefault(r =>
- r.WorldIdToUnlock == row.WorldId);
- // Clear prev world.
- if (!(prevRow is null))
- {
- var prevWorldRow = _tableSheets.WorldSheet[prevRow.WorldId];
- for (int i = prevWorldRow.StageBegin; i < prevWorldRow.StageEnd + 1; i++)
- {
- worldInformation.ClearStage(prevWorldRow.Id, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
- }
- }
-
- for (int i = worldRow.StageBegin; i < worldRow.StageEnd + 1; i++)
- {
- worldInformation.ClearStage(worldRow.Id, i, 0, _tableSheets.WorldSheet, _tableSheets.WorldUnlockSheet);
- }
- }
- }
-
- state = state.SetAvatarState(_avatarAddress, _avatarState);
- }
-
- var unlockedWorldIdsAddress = _avatarAddress.Derive("world_ids");
- if (alreadyUnlocked)
- {
- var unlockIds = List.Empty.Add(1.Serialize());
- foreach (var worldId in worldIds)
- {
- unlockIds = unlockIds.Add(worldId.Serialize());
- }
-
- state = state.SetLegacyState(unlockedWorldIdsAddress, unlockIds);
- }
-
- var action = new UnlockWorld1
- {
- WorldIds = worldIds,
- AvatarAddress = _avatarAddress,
- };
-
- if (exc is null)
- {
- IWorld nextState = action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- });
-
- Assert.True(nextState.TryGetLegacyState(unlockedWorldIdsAddress, out List rawIds));
-
- var unlockedIds = rawIds.ToList(StateExtensions.ToInteger);
-
- Assert.All(worldIds, worldId => Assert.Contains(worldId, unlockedIds));
- Assert.Equal(0 * _currency, nextState.GetBalance(_agentAddress, _currency));
- Assert.Equal(balance * _currency, nextState.GetBalance(Addresses.UnlockWorld, _currency));
- }
- else
- {
- Assert.Throws(exc, () => action.Execute(new ActionContext
- {
- PreviousState = state,
- Signer = _agentAddress,
- BlockIndex = 1,
- RandomSeed = _random.Seed,
- }));
- }
- }
- }
-}
diff --git a/.Lib9c.Tests/Action/UnlockWorldTest.cs b/.Lib9c.Tests/Action/UnlockWorldTest.cs
index 28d57e370a..04bbd92d77 100644
--- a/.Lib9c.Tests/Action/UnlockWorldTest.cs
+++ b/.Lib9c.Tests/Action/UnlockWorldTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -50,7 +51,7 @@ public UnlockWorldTest()
agentState.avatarAddresses.Add(0, _avatarAddress);
- _initialState = new World(new MockWorldState())
+ _initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(Addresses.GetSheetAddress(), _tableSheets.WorldUnlockSheet.Serialize())
.SetLegacyState(Addresses.GameConfig, gameConfigState.Serialize());
}
diff --git a/.Lib9c.Tests/Action/UpdateSellTest.cs b/.Lib9c.Tests/Action/UpdateSellTest.cs
index 3791cc5f1e..944b72a8da 100644
--- a/.Lib9c.Tests/Action/UpdateSellTest.cs
+++ b/.Lib9c.Tests/Action/UpdateSellTest.cs
@@ -7,6 +7,7 @@ namespace Lib9c.Tests.Action
using Lib9c.Model.Order;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -38,7 +39,7 @@ public UpdateSellTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
var sheets = TableSheetsImporter.ImportSheets();
foreach (var (key, value) in sheets)
{
@@ -254,7 +255,7 @@ public void Execute_Throw_ListEmptyException()
Assert.Throws(() => action.Execute(new ActionContext
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
Signer = _agentAddress,
}));
}
@@ -279,7 +280,7 @@ public void Execute_Throw_FailedLoadStateException()
Assert.Throws(() => action.Execute(new ActionContext
{
BlockIndex = 0,
- PreviousState = new World(new MockWorldState()),
+ PreviousState = new World(MockUtil.MockModernWorldState),
Signer = _agentAddress,
}));
}
diff --git a/.Lib9c.Tests/Action/ValidatorSetOperateTest.cs b/.Lib9c.Tests/Action/ValidatorSetOperateTest.cs
index 743242fcd3..73f0cf0a6a 100644
--- a/.Lib9c.Tests/Action/ValidatorSetOperateTest.cs
+++ b/.Lib9c.Tests/Action/ValidatorSetOperateTest.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Action
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Consensus;
using Nekoyume;
using Nekoyume.Action;
@@ -27,7 +28,7 @@ public ValidatorSetOperateTest(ITestOutputHelper outputHelper)
.WriteTo.TestOutput(outputHelper)
.CreateLogger();
- _initialState = new World(new MockWorldState());
+ _initialState = new World(MockUtil.MockModernWorldState);
_validator = new Validator(new PrivateKey().PublicKey, BigInteger.One);
var sheets = TableSheetsImporter.ImportSheets();
@@ -44,9 +45,8 @@ public void CheckPermission()
{
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var initStates = new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize());
- var state = new World(initStates);
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
var action = ValidatorSetOperate.Append(_validator);
var nextState = action.Execute(
new ActionContext()
@@ -65,9 +65,8 @@ public void CheckPermission_Throws_PermissionDenied()
{
var adminAddress = new Address("399bddF9F7B6d902ea27037B907B2486C9910730");
var adminState = new AdminState(adminAddress, 100);
- var initStates = new MockWorldState()
- .SetState(ReservedAddresses.LegacyAccount, AdminState.Address, adminState.Serialize());
- var state = new World(initStates);
+ var state = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(AdminState.Address, adminState.Serialize());
var action = ValidatorSetOperate.Append(_validator);
PermissionDeniedException exc1 = Assert.Throws(() =>
@@ -101,7 +100,7 @@ public void Append_Throws_WhenAlreadyExistValidator()
[Fact]
public void Update_Throws_WhenDoNotExistValidator()
{
- var state = new World(new MockWorldState());
+ var state = new World(MockUtil.MockModernWorldState);
var action = ValidatorSetOperate.Update(_validator);
InvalidOperationException exc = Assert.Throws(() =>
action.Execute(new ActionContext
@@ -116,7 +115,7 @@ public void Update_Throws_WhenDoNotExistValidator()
[Fact]
public void Remove_Throws_WhenDoNotExistValidator()
{
- var state = new World(new MockWorldState());
+ var state = new World(MockUtil.MockModernWorldState);
var action = ValidatorSetOperate.Remove(_validator);
InvalidOperationException exc = Assert.Throws(() =>
action.Execute(new ActionContext
diff --git a/.Lib9c.Tests/Extensions/SheetsExtensionsTest.cs b/.Lib9c.Tests/Extensions/SheetsExtensionsTest.cs
index 99e281627f..b556f78a6e 100644
--- a/.Lib9c.Tests/Extensions/SheetsExtensionsTest.cs
+++ b/.Lib9c.Tests/Extensions/SheetsExtensionsTest.cs
@@ -8,6 +8,7 @@ namespace Lib9c.Tests.Extensions
using Lib9c.Tests.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Extensions;
@@ -26,7 +27,7 @@ public class SheetsExtensionsTest
public SheetsExtensionsTest()
{
- _states = new World(new MockWorldState());
+ _states = new World(MockUtil.MockModernWorldState);
InitSheets(
_states,
out _sheetNameAndFiles,
diff --git a/.Lib9c.Tests/Lib9c.Tests.csproj b/.Lib9c.Tests/Lib9c.Tests.csproj
index fb877391a1..d6545f071e 100644
--- a/.Lib9c.Tests/Lib9c.Tests.csproj
+++ b/.Lib9c.Tests/Lib9c.Tests.csproj
@@ -50,6 +50,7 @@
+
diff --git a/.Lib9c.Tests/Model/Skill/Adventure/CombatTest.cs b/.Lib9c.Tests/Model/Skill/Adventure/CombatTest.cs
index aa9554b53a..06ed7a0c5d 100644
--- a/.Lib9c.Tests/Model/Skill/Adventure/CombatTest.cs
+++ b/.Lib9c.Tests/Model/Skill/Adventure/CombatTest.cs
@@ -181,11 +181,10 @@ public void DispelOnUse(int dispelId, int chance, int seed, int[] debuffIdList,
[Fact]
public void DispelOnDuration_Block()
{
- const int actionBuffId = 708000; // Dispel with duration
var actionBuffSheet = _tableSheets.ActionBuffSheet;
// Use Dispel first
- var dispel = actionBuffSheet.Values.First(bf => bf.Id == actionBuffId);
+ var dispel = actionBuffSheet.Values.First(bf => bf.ActionBuffType == ActionBuffType.Dispel);
_player.AddBuff(BuffFactory.GetActionBuff(_player.Stats, dispel));
Assert.Single(_player.Buffs);
@@ -216,11 +215,10 @@ public void DispelOnDuration_Block()
[Fact]
public void DispelOnDuration_Affect()
{
- const int actionBuffId = 708000; // Dispel with duration
var actionBuffSheet = _tableSheets.ActionBuffSheet;
// Use Dispel first
- var dispel = actionBuffSheet.Values.First(bf => bf.Id == actionBuffId);
+ var dispel = actionBuffSheet.Values.First(bf => bf.ActionBuffType == ActionBuffType.Dispel);
_player.AddBuff(BuffFactory.GetActionBuff(_player.Stats, dispel));
Assert.Single(_player.Buffs);
diff --git a/.Lib9c.Tests/Model/Skill/Adventure/ShatterStrikeTest.cs b/.Lib9c.Tests/Model/Skill/Adventure/ShatterStrikeTest.cs
index 29a80523ef..876eebde7a 100644
--- a/.Lib9c.Tests/Model/Skill/Adventure/ShatterStrikeTest.cs
+++ b/.Lib9c.Tests/Model/Skill/Adventure/ShatterStrikeTest.cs
@@ -35,7 +35,7 @@ public void Use(int enemyHp, int ratioBp, bool expectedEnemyDead, bool copyChara
var gameConfigState =
new GameConfigState((Text)_tableSheets.GameConfigSheet.Serialize());
Assert.True(
- _tableSheets.SkillSheet.TryGetValue(700011, out var skillRow)
+ _tableSheets.SkillSheet.TryGetValue(700010, out var skillRow)
); // 700011 is ShatterStrike
var shatterStrike = new ShatterStrike(skillRow, 0, 0, ratioBp, StatType.NONE);
diff --git a/.Lib9c.Tests/Model/Skill/Arena/ArenaCombatTest.cs b/.Lib9c.Tests/Model/Skill/Arena/ArenaCombatTest.cs
index 04e42a5aaf..3bd23d47a9 100644
--- a/.Lib9c.Tests/Model/Skill/Arena/ArenaCombatTest.cs
+++ b/.Lib9c.Tests/Model/Skill/Arena/ArenaCombatTest.cs
@@ -6,6 +6,7 @@ namespace Lib9c.Tests.Model.Skill.Arena
using Nekoyume.Arena;
using Nekoyume.Model;
using Nekoyume.Model.Buff;
+ using Nekoyume.Model.Skill;
using Nekoyume.Model.Skill.Arena;
using Nekoyume.Model.Stat;
using Nekoyume.Model.State;
@@ -13,8 +14,6 @@ namespace Lib9c.Tests.Model.Skill.Arena
public class ArenaCombatTest
{
- private const int ActionBuffId = 708000; // Dispel with duration
-
private readonly TableSheets _tableSheets;
private readonly AvatarState _avatar1;
private readonly AvatarState _avatar2;
@@ -48,7 +47,7 @@ public ArenaCombatTest()
[Theory]
[InlineData(700009, new[] { 600001 })]
- [InlineData(700010, new[] { 600001, 704000 })]
+ [InlineData(700009, new[] { 600001, 704000 })]
public void DispelOnUse(int dispelId, int[] debuffIdList)
{
var arenaSheets = _tableSheets.GetArenaSimulatorSheets();
@@ -122,7 +121,7 @@ public void DispelOnDuration_Block()
);
// Use Dispel first
- var dispel = _tableSheets.ActionBuffSheet.Values.First(bf => bf.Id == ActionBuffId);
+ var dispel = _tableSheets.ActionBuffSheet.Values.First(bf => bf.ActionBuffType == ActionBuffType.Dispel);
challenger.AddBuff(BuffFactory.GetActionBuff(challenger.Stats, dispel));
Assert.Single(challenger.Buffs);
@@ -170,7 +169,7 @@ public void DispelOnDuration_Affect()
);
// Use Dispel first
- var dispel = _tableSheets.ActionBuffSheet.Values.First(bf => bf.Id == ActionBuffId);
+ var dispel = _tableSheets.ActionBuffSheet.Values.First(bf => bf.ActionBuffType == ActionBuffType.Dispel);
challenger.AddBuff(BuffFactory.GetActionBuff(challenger.Stats, dispel));
Assert.Single(challenger.Buffs);
diff --git a/.Lib9c.Tests/Model/Skill/Arena/ArenaShatterStrikeTest.cs b/.Lib9c.Tests/Model/Skill/Arena/ArenaShatterStrikeTest.cs
index 545852abc8..d3e8109ad5 100644
--- a/.Lib9c.Tests/Model/Skill/Arena/ArenaShatterStrikeTest.cs
+++ b/.Lib9c.Tests/Model/Skill/Arena/ArenaShatterStrikeTest.cs
@@ -81,7 +81,7 @@ public void Use(int hpModifier, int ratioBp, bool expectedEnemyDead)
new List()
);
- var skillRow = _tableSheets.SkillSheet.OrderedList.First(s => s.Id == 700011);
+ var skillRow = _tableSheets.SkillSheet.OrderedList.First(s => s.Id == 700010);
var shatterStrike = new ArenaShatterStrike(skillRow, 0, 0, ratioBp, StatType.NONE);
var used = shatterStrike.Use(challenger, enemy, simulator.Turn, new List());
Assert.Single(used.SkillInfos);
diff --git a/.Lib9c.Tests/Model/Stake/StakeStateUtilsTest.cs b/.Lib9c.Tests/Model/Stake/StakeStateUtilsTest.cs
index 8c3b103ca5..37626bee61 100644
--- a/.Lib9c.Tests/Model/Stake/StakeStateUtilsTest.cs
+++ b/.Lib9c.Tests/Model/Stake/StakeStateUtilsTest.cs
@@ -2,11 +2,11 @@ namespace Lib9c.Tests.Model.Stake
{
using System;
using Bencodex.Types;
- using Lib9c.Tests.Action;
using Lib9c.Tests.Fixtures.TableCSV;
using Lib9c.Tests.Fixtures.TableCSV.Stake;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume;
using Nekoyume.Model.Stake;
using Nekoyume.Model.State;
@@ -32,7 +32,7 @@ public void TryMigrate_Return_False_When_IValue_Null()
[Fact]
public void TryMigrate_Return_False_When_Staking_State_Null()
{
- var state = new World(new MockWorldState());
+ var state = new World(MockUtil.MockModernWorldState);
Assert.False(StakeStateUtils.TryMigrate(state, new PrivateKey().Address, out _));
}
@@ -108,7 +108,7 @@ public void TryMigrate_Return_True_With_StakeState(
string stakeRegularFixedRewardSheetTableName,
string stakeRegularRewardSheetTableName)
{
- IWorld state = new World(new MockWorldState());
+ IWorld state = new World(MockUtil.MockModernWorldState);
state = state.SetLegacyState(
Addresses.GameConfig,
new GameConfigState(GameConfigSheetFixtures.Default).Serialize());
@@ -140,7 +140,7 @@ public void TryMigrate_Return_True_With_StakeStateV2(
long startedBlockIndex,
long? receivedBlockIndex)
{
- IWorld state = new World(new MockWorldState());
+ IWorld state = new World(MockUtil.MockModernWorldState);
state = state.SetLegacyState(
Addresses.GameConfig,
new GameConfigState(GameConfigSheetFixtures.Default).Serialize());
diff --git a/.Lib9c.Tests/Module/CollectionModuleTest.cs b/.Lib9c.Tests/Module/CollectionModuleTest.cs
index b3ea162800..a996886239 100644
--- a/.Lib9c.Tests/Module/CollectionModuleTest.cs
+++ b/.Lib9c.Tests/Module/CollectionModuleTest.cs
@@ -4,6 +4,7 @@ namespace Lib9c.Tests.Module
using Lib9c.Tests.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Nekoyume.Action;
using Nekoyume.Model.State;
using Nekoyume.Module;
@@ -14,7 +15,7 @@ public class CollectionModuleTest
[Fact]
public void CollectionState()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var address = new PrivateKey().Address;
Assert.Throws(() => states.GetCollectionState(address));
Assert.False(states.TryGetCollectionState(address, out _));
@@ -37,7 +38,7 @@ public void CollectionState()
[Fact]
public void CollectionStates()
{
- IWorld states = new World(new MockWorldState());
+ IWorld states = new World(MockUtil.MockModernWorldState);
var address = new PrivateKey().Address;
var address2 = new PrivateKey().Address;
var addresses = new[] { address, address2 };
diff --git a/.Lib9c.Tests/Policy/BlockPolicyTest.cs b/.Lib9c.Tests/Policy/BlockPolicyTest.cs
index f5591b66cb..f420bec26e 100644
--- a/.Lib9c.Tests/Policy/BlockPolicyTest.cs
+++ b/.Lib9c.Tests/Policy/BlockPolicyTest.cs
@@ -396,7 +396,6 @@ public void EarnMiningGoldWhenSuccessMining()
blockChain.Append(block, GenerateBlockCommit(block, adminPrivateKey));
FungibleAssetValue actualBalance = blockChain
.GetWorldState()
- .GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(adminAddress, _currency);
FungibleAssetValue expectedBalance = new FungibleAssetValue(_currency, 10, 0);
Assert.True(expectedBalance.Equals(actualBalance));
diff --git a/.Lib9c.Tests/TestHelper/BlockChainHelper.cs b/.Lib9c.Tests/TestHelper/BlockChainHelper.cs
index 42a9b17e2f..6383494f65 100644
--- a/.Lib9c.Tests/TestHelper/BlockChainHelper.cs
+++ b/.Lib9c.Tests/TestHelper/BlockChainHelper.cs
@@ -12,6 +12,7 @@ namespace Lib9c.Tests.TestHelper
using Libplanet.Blockchain;
using Libplanet.Blockchain.Policies;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Assets;
@@ -99,16 +100,14 @@ public static MakeInitialStateResult MakeInitialState()
var sheets = TableSheetsImporter.ImportSheets();
var weeklyArenaAddress = WeeklyArenaState.DeriveAddress(0);
var context = new ActionContext();
- var initialState = new World(new MockWorldState())
+ var initialState = new World(MockUtil.MockModernWorldState)
.SetLegacyState(GoldCurrencyState.Address, goldCurrencyState.Serialize())
.SetLegacyState(
Addresses.GoldDistribution,
- GoldDistributionTest.Fixture.Select(v => v.Serialize()).Serialize()
- )
+ GoldDistributionTest.Fixture.Select(v => v.Serialize()).Serialize())
.SetLegacyState(
Addresses.GameConfig,
- new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize()
- )
+ new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize())
.SetLegacyState(Addresses.Ranking, ranking.Serialize())
.SetLegacyState(weeklyArenaAddress, new WeeklyArenaState(0).Serialize());
diff --git a/.Lib9c.Tests/Util/InitializeUtil.cs b/.Lib9c.Tests/Util/InitializeUtil.cs
index 8d3490af88..4bc3089055 100644
--- a/.Lib9c.Tests/Util/InitializeUtil.cs
+++ b/.Lib9c.Tests/Util/InitializeUtil.cs
@@ -5,6 +5,7 @@ namespace Lib9c.Tests.Util
using Lib9c.Tests.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
+ using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume;
using Nekoyume.Action;
@@ -29,9 +30,10 @@ IWorld initialStatesWithAvatarStateV2
{
adminAddr ??= new PrivateKey().Address;
var context = new ActionContext();
- var states = new World(new MockWorldState()).SetLegacyState(
- Addresses.Admin,
- new AdminState(adminAddr.Value, long.MaxValue).Serialize());
+ var states = new World(MockUtil.MockModernWorldState)
+ .SetLegacyState(
+ Addresses.Admin,
+ new AdminState(adminAddr.Value, long.MaxValue).Serialize());
var goldCurrency = Currency.Legacy(
"NCG",
diff --git a/.Lib9c.Tools/SubCommand/Account.cs b/.Lib9c.Tools/SubCommand/Account.cs
index 7eee98c734..ca4ec8408c 100644
--- a/.Lib9c.Tools/SubCommand/Account.cs
+++ b/.Lib9c.Tools/SubCommand/Account.cs
@@ -62,7 +62,6 @@ public void Balance(
FungibleAssetValue balance =
chain
.GetWorldState(offset.Hash)
- .GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(addr, gold);
Console.WriteLine("{0}\t{1}", addr, balance);
return;
@@ -94,7 +93,6 @@ i.GoldDistributions is Bencodex.Types.List l
FungibleAssetValue balance =
chain
.GetWorldState(offset.Hash)
- .GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(addr, gold);
Console.WriteLine("{0}\t{1}", addr, balance);
printed.Add(addr);
diff --git a/.Libplanet b/.Libplanet
index 1016fbce88..81ddb0a52b 160000
--- a/.Libplanet
+++ b/.Libplanet
@@ -1 +1 @@
-Subproject commit 1016fbce882309452a45eda1a19c9a8b213801a5
+Subproject commit 81ddb0a52b2ea66034848270f3d8a6630432585b
diff --git a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccount.cs b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccount.cs
index 69e7860b71..c9471db66b 100644
--- a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccount.cs
+++ b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccount.cs
@@ -22,21 +22,12 @@ public RemoteAccount(IAccountState baseState)
public ITrie Trie => _baseState.Trie;
- public FungibleAssetValue GetBalance(Address address, Currency currency)
- => _baseState.GetBalance(address, currency);
-
public IValue? GetState(Address address)
=> _baseState.GetState(address);
public IReadOnlyList GetStates(IReadOnlyList addresses)
=> _baseState.GetStates(addresses);
- public FungibleAssetValue GetTotalSupply(Currency currency)
- => _baseState.GetTotalSupply(currency);
-
- public ValidatorSet GetValidatorSet()
- => _baseState.GetValidatorSet();
-
public IAccount MintAsset(IActionContext context, Address recipient, FungibleAssetValue value)
{
throw new NotSupportedException();
diff --git a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccountState.cs b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccountState.cs
index c9ac2bb574..dd4aef008f 100644
--- a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccountState.cs
+++ b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteAccountState.cs
@@ -8,9 +8,7 @@
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Store.Trie;
-using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
-using Libplanet.Types.Consensus;
namespace Libplanet.Extensions.RemoteBlockChainStates;
@@ -121,131 +119,6 @@ public RemoteAccountState(
return response.Data.StateQuery.States is { } state ? codec.Decode(state) : null;
}
- public FungibleAssetValue GetBalance(Address address, Currency currency)
- {
- object? currencyInput = currency.TotalSupplyTrackable ? new
- {
- ticker = currency.Ticker,
- decimalPlaces = currency.DecimalPlaces,
- minters = currency.Minters?.Select(addr => addr.ToString()).ToArray(),
- totalSupplyTrackable = currency.TotalSupplyTrackable,
- maximumSupplyMajorUnit = currency.MaximumSupply.Value.MajorUnit,
- maximumSupplyMinorUnit = currency.MaximumSupply.Value.MinorUnit,
- } : new
- {
- ticker = currency.Ticker,
- decimalPlaces = currency.DecimalPlaces,
- minters = currency.Minters?.Select(addr => addr.ToString()).ToArray(),
- totalSupplyTrackable = currency.TotalSupplyTrackable,
- };
- var response = _graphQlHttpClient.SendQueryAsync(
- new GraphQLRequest(
- @"query GetBalance(
- $owner: Address!,
- $currency: CurrencyInput!,
- $accountStateRootHash: HashDigest_SHA256!)
- {
- stateQuery
- {
- balance(
- owner: $owner,
- currency: $currency,
- accountStateRootHash: $accountStateRootHash)
- {
- string
- }
- }
- }",
- operationName: "GetBalance",
- variables: new
- {
- owner = address.ToString(),
- currency = currencyInput,
- accountStateRootHash = Trie.Hash is { } accountSrh
- ? ByteUtil.Hex(accountSrh.ByteArray)
- : null,
- })).Result;
-
- return FungibleAssetValue.Parse(currency, response.Data.StateQuery.Balance.String.Split()[0]);
- }
-
- public FungibleAssetValue GetTotalSupply(Currency currency)
- {
- object? currencyInput = currency.TotalSupplyTrackable ? new
- {
- ticker = currency.Ticker,
- decimalPlaces = currency.DecimalPlaces,
- minters = currency.Minters.Select(addr => addr.ToString()).ToArray(),
- totalSupplyTrackable = currency.TotalSupplyTrackable,
- maximumSupplyMajorUnit = currency.MaximumSupply.Value.MajorUnit,
- maximumSupplyMinorUnit = currency.MaximumSupply.Value.MinorUnit,
- } : new
- {
- ticker = currency.Ticker,
- decimalPlaces = currency.DecimalPlaces,
- minters = currency.Minters.Select(addr => addr.ToString()).ToArray(),
- totalSupplyTrackable = currency.TotalSupplyTrackable,
- };
- var response = _graphQlHttpClient.SendQueryAsync(
- new GraphQLRequest(
- @"query GetTotalSupply(
- $currency: CurrencyInput!,
- $accountStateRootHash: HashDigest_SHA256!)
- {
- stateQuery
- {
- totalSupply(
- currency: $currency,
- offsetBlockHash: $offsetBlockHash
- accountStateRootHash: $accountStateRootHash)
- {
- string
- }
- }
- }",
- operationName: "GetTotalSupply",
- variables: new
- {
- currency = currencyInput,
- accountStateRootHash = Trie.Hash is { } accountSrh
- ? ByteUtil.Hex(accountSrh.ByteArray)
- : null,
- })).Result;
-
- return FungibleAssetValue.Parse(currency, response.Data.StateQuery.TotalSupply.String.Split()[0]);
- }
-
- public ValidatorSet GetValidatorSet()
- {
- var response = _graphQlHttpClient.SendQueryAsync(
- new GraphQLRequest(
- @"query GetValidators(
- $accountStateRootHash: HashDigest_SHA256!)
- {
- stateQuery
- {
- validators(
- accountStateRootHash: $accountStateRootHash)
- {
- publicKey
- power
- }
- }
- }",
- operationName: "GetValidators",
- variables: new
- {
- accountStateRootHash = Trie.Hash is { } accountSrh
- ? ByteUtil.Hex(accountSrh.ByteArray)
- : null,
- })).Result;
-
- return new ValidatorSet(response.Data.StateQuery.Validators
- .Select(x =>
- new Validator(new PublicKey(ByteUtil.ParseHex(x.PublicKey)), x.Power))
- .ToList());
- }
-
private class GetAccountStateResponseType
{
public StateQueryWithAccountStateType StateQuery { get; set; }
@@ -270,46 +143,4 @@ private class StateQueryWithStatesType
{
public byte[] States { get; set; }
}
-
- private class GetBalanceResponseType
- {
- public StateQueryWithBalanceType StateQuery { get; set; }
- }
-
- private class StateQueryWithBalanceType
- {
- public FungibleAssetValueWithStringType Balance { get; set; }
- }
-
- private class FungibleAssetValueWithStringType
- {
- public string String { get; set; }
- }
-
- private class GetTotalSupplyResponseType
- {
- public StateQueryWithTotalSupplyType StateQuery { get; set; }
- }
-
- private class StateQueryWithTotalSupplyType
- {
- public FungibleAssetValueWithStringType TotalSupply { get; set; }
- }
-
- private class GetValidatorsResponseType
- {
- public StateQueryWithValidatorsType StateQuery { get; set; }
- }
-
- private class StateQueryWithValidatorsType
- {
- public ValidatorType[] Validators { get; set; }
- }
-
- private class ValidatorType
- {
- public string PublicKey { get; set; }
-
- public long Power { get; set; }
- }
}
diff --git a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteWorldState.cs b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteWorldState.cs
index 4ccffd1619..6d2977b219 100644
--- a/.Libplanet.Extensions.RemoteBlockChainStates/RemoteWorldState.cs
+++ b/.Libplanet.Extensions.RemoteBlockChainStates/RemoteWorldState.cs
@@ -6,7 +6,9 @@
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Store.Trie;
+using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
+using Libplanet.Types.Consensus;
namespace Libplanet.Extensions.RemoteBlockChainStates;
@@ -77,6 +79,131 @@ public RemoteWorldState(Uri explorerEndpoint, HashDigest? offsetStateRoo
public IAccountState GetAccountState(Address address) =>
new RemoteAccountState(_explorerEndpoint, address, Trie.Hash);
+ public FungibleAssetValue GetBalance(Address address, Currency currency)
+ {
+ object? currencyInput = currency.TotalSupplyTrackable ? new
+ {
+ ticker = currency.Ticker,
+ decimalPlaces = currency.DecimalPlaces,
+ minters = currency.Minters?.Select(addr => addr.ToString()).ToArray(),
+ totalSupplyTrackable = currency.TotalSupplyTrackable,
+ maximumSupplyMajorUnit = currency.MaximumSupply.Value.MajorUnit,
+ maximumSupplyMinorUnit = currency.MaximumSupply.Value.MinorUnit,
+ } : new
+ {
+ ticker = currency.Ticker,
+ decimalPlaces = currency.DecimalPlaces,
+ minters = currency.Minters?.Select(addr => addr.ToString()).ToArray(),
+ totalSupplyTrackable = currency.TotalSupplyTrackable,
+ };
+ var response = _graphQlHttpClient.SendQueryAsync(
+ new GraphQLRequest(
+ @"query GetBalance(
+ $owner: Address!,
+ $currency: CurrencyInput!,
+ $accountStateRootHash: HashDigest_SHA256!)
+ {
+ stateQuery
+ {
+ balance(
+ owner: $owner,
+ currency: $currency,
+ accountStateRootHash: $accountStateRootHash)
+ {
+ string
+ }
+ }
+ }",
+ operationName: "GetBalance",
+ variables: new
+ {
+ owner = address.ToString(),
+ currency = currencyInput,
+ accountStateRootHash = Trie.Hash is { } accountSrh
+ ? ByteUtil.Hex(accountSrh.ByteArray)
+ : null,
+ })).Result;
+
+ return FungibleAssetValue.Parse(currency, response.Data.StateQuery.Balance.String.Split()[0]);
+ }
+
+ public FungibleAssetValue GetTotalSupply(Currency currency)
+ {
+ object? currencyInput = currency.TotalSupplyTrackable ? new
+ {
+ ticker = currency.Ticker,
+ decimalPlaces = currency.DecimalPlaces,
+ minters = currency.Minters.Select(addr => addr.ToString()).ToArray(),
+ totalSupplyTrackable = currency.TotalSupplyTrackable,
+ maximumSupplyMajorUnit = currency.MaximumSupply.Value.MajorUnit,
+ maximumSupplyMinorUnit = currency.MaximumSupply.Value.MinorUnit,
+ } : new
+ {
+ ticker = currency.Ticker,
+ decimalPlaces = currency.DecimalPlaces,
+ minters = currency.Minters.Select(addr => addr.ToString()).ToArray(),
+ totalSupplyTrackable = currency.TotalSupplyTrackable,
+ };
+ var response = _graphQlHttpClient.SendQueryAsync(
+ new GraphQLRequest(
+ @"query GetTotalSupply(
+ $currency: CurrencyInput!,
+ $accountStateRootHash: HashDigest_SHA256!)
+ {
+ stateQuery
+ {
+ totalSupply(
+ currency: $currency,
+ offsetBlockHash: $offsetBlockHash
+ accountStateRootHash: $accountStateRootHash)
+ {
+ string
+ }
+ }
+ }",
+ operationName: "GetTotalSupply",
+ variables: new
+ {
+ currency = currencyInput,
+ accountStateRootHash = Trie.Hash is { } accountSrh
+ ? ByteUtil.Hex(accountSrh.ByteArray)
+ : null,
+ })).Result;
+
+ return FungibleAssetValue.Parse(currency, response.Data.StateQuery.TotalSupply.String.Split()[0]);
+ }
+
+ public ValidatorSet GetValidatorSet()
+ {
+ var response = _graphQlHttpClient.SendQueryAsync(
+ new GraphQLRequest(
+ @"query GetValidators(
+ $accountStateRootHash: HashDigest_SHA256!)
+ {
+ stateQuery
+ {
+ validators(
+ accountStateRootHash: $accountStateRootHash)
+ {
+ publicKey
+ power
+ }
+ }
+ }",
+ operationName: "GetValidators",
+ variables: new
+ {
+ accountStateRootHash = Trie.Hash is { } accountSrh
+ ? ByteUtil.Hex(accountSrh.ByteArray)
+ : null,
+ })).Result;
+
+ return new ValidatorSet(response.Data.StateQuery.Validators
+ .Select(x =>
+ new Validator(new PublicKey(ByteUtil.ParseHex(x.PublicKey)), x.Power))
+ .ToList());
+ }
+
public class GetWorldStateResponseType
{
public StateQueryWithWorldStateType StateQuery { get; set; }
@@ -93,4 +220,46 @@ public class WorldStateType
public bool Legacy { get; set; }
}
+
+ private class GetBalanceResponseType
+ {
+ public StateQueryWithBalanceType StateQuery { get; set; }
+ }
+
+ private class StateQueryWithBalanceType
+ {
+ public FungibleAssetValueWithStringType Balance { get; set; }
+ }
+
+ private class FungibleAssetValueWithStringType
+ {
+ public string String { get; set; }
+ }
+
+ private class GetTotalSupplyResponseType
+ {
+ public StateQueryWithTotalSupplyType StateQuery { get; set; }
+ }
+
+ private class StateQueryWithTotalSupplyType
+ {
+ public FungibleAssetValueWithStringType TotalSupply { get; set; }
+ }
+
+ private class GetValidatorsResponseType
+ {
+ public StateQueryWithValidatorsType StateQuery { get; set; }
+ }
+
+ private class StateQueryWithValidatorsType
+ {
+ public ValidatorType[] Validators { get; set; }
+ }
+
+ private class ValidatorType
+ {
+ public string PublicKey { get; set; }
+
+ public long Power { get; set; }
+ }
}
diff --git a/Lib9c.Policy/Policy/BlockPolicySource.cs b/Lib9c.Policy/Policy/BlockPolicySource.cs
index 5d31b60a2d..946749aa62 100644
--- a/Lib9c.Policy/Policy/BlockPolicySource.cs
+++ b/Lib9c.Policy/Policy/BlockPolicySource.cs
@@ -174,7 +174,6 @@ internal IBlockPolicy GetPolicy(
{
if (blockChain
.GetWorldState()
- .GetAccountState(ReservedAddresses.LegacyAccount)
.GetBalance(MeadConfig.PatronAddress, Currencies.Mead) < 1 * Currencies.Mead)
{
// Check Activation
diff --git a/Lib9c/Action/ActivateAccount0.cs b/Lib9c/Action/ActivateAccount0.cs
deleted file mode 100644
index 53090ca922..0000000000
--- a/Lib9c/Action/ActivateAccount0.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Bencodex.Types;
-using Lib9c.Abstractions;
-using Libplanet.Action;
-using Libplanet.Action.State;
-using Libplanet.Crypto;
-using Nekoyume.Model.State;
-using Nekoyume.Module;
-using Serilog;
-
-namespace Nekoyume.Action
-{
- [Serializable]
- [ActionObsolete(ActionObsoleteConfig.V200020AccidentObsoleteIndex)]
- [ActionType("activate_account")]
- public class ActivateAccount0 : ActionBase, IActivateAccount
- {
- public Address PendingAddress { get; private set; }
-
- public byte[] Signature { get; private set; }
-
- Address IActivateAccount.PendingAddress => PendingAddress;
- byte[] IActivateAccount.Signature => Signature;
-
- public override IValue PlainValue => Dictionary.Empty
- .Add("type_id", "activate_account")
- .Add("values", new Dictionary(
- new[]
- {
- new KeyValuePair((Text)"pending_address", PendingAddress.Serialize()),
- new KeyValuePair((Text)"signature", (Binary) Signature),
- }
- ));
-
- public ActivateAccount0()
- {
- }
-
- public ActivateAccount0(Address pendingAddress, byte[] signature)
- {
- PendingAddress = pendingAddress;
- Signature = signature;
- }
-
- public override IWorld Execute(IActionContext context)
- {
- context.UseGas(1);
- IWorld state = context.PreviousState;
-
- CheckObsolete(ActionObsoleteConfig.V100080ObsoleteIndex, context);
-
- if (!state.TryGetLegacyState(ActivatedAccountsState.Address, out Dictionary accountsAsDict))
- {
- throw new ActivatedAccountsDoesNotExistsException();
- }
- if (!state.TryGetLegacyState(PendingAddress, out Dictionary pendingAsDict))
- {
- throw new PendingActivationDoesNotExistsException(PendingAddress);
- }
-
- var accounts = new ActivatedAccountsState(accountsAsDict);
- var pending = new PendingActivationState(pendingAsDict);
-
- if (pending.Verify(Signature))
- {
- // We left this log message to track activation history.
- // Please delete it if we have an API for evaluation results on the Libplanet side.
- Log.Information("{pendingAddress} is activated by {signer} now.", pending.address, context.Signer);
- return state.SetLegacyState(
- ActivatedAccountsState.Address,
- accounts.AddAccount(context.Signer).Serialize()
- ).SetLegacyState(
- pending.address,
- new Bencodex.Types.Null()
- );
- }
- else
- {
- throw new InvalidSignatureException(pending, Signature);
- }
- }
-
- public override void LoadPlainValue(IValue plainValue)
- {
- var asDict = (Dictionary)((Dictionary)plainValue)["values"];
- PendingAddress = asDict["pending_address"].ToAddress();
- Signature = ((Binary)asDict["signature"]).ToByteArray();
- }
-
- public Address GetPendingAddress() => PendingAddress;
-
- public byte[] GetSignature() => Signature;
- }
-}
diff --git a/Lib9c/Action/CancelProductRegistration0.cs b/Lib9c/Action/CancelProductRegistration0.cs
deleted file mode 100644
index a7472bdbb8..0000000000
--- a/Lib9c/Action/CancelProductRegistration0.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using Bencodex.Types;
-using Lib9c.Model.Order;
-using Libplanet.Action;
-using Libplanet.Action.State;
-using Libplanet.Crypto;
-using Nekoyume.Battle;
-using Nekoyume.Model.Item;
-using Nekoyume.Model.Mail;
-using Nekoyume.Model.Market;
-using Nekoyume.Model.State;
-using Nekoyume.Module;
-using Nekoyume.TableData;
-using static Lib9c.SerializeKeys;
-
-namespace Nekoyume.Action
-{
- [ActionObsolete(ActionObsoleteConfig.V200092ObsoleteIndex)]
- [ActionType("cancel_product_registration")]
- public class CancelProductRegistration0 : GameAction
- {
- public const int CostAp = 5;
- public const int Capacity = 100;
- public Address AvatarAddress;
- public List ProductInfos;
- public bool ChargeAp;
- public override IWorld Execute(IActionContext context)
- {
- context.UseGas(1);
- IWorld states = context.PreviousState;
-
- if (!ProductInfos.Any())
- {
- throw new ListEmptyException("ProductInfos was empty.");
- }
-
- if (ProductInfos.Count > Capacity)
- {
- throw new ArgumentOutOfRangeException($"{nameof(ProductInfos)} must be less than or equal {Capacity}.");
- }
-
- foreach (var productInfo in ProductInfos)
- {
- productInfo.ValidateType();
- if (productInfo.AvatarAddress != AvatarAddress ||
- productInfo.AgentAddress != context.Signer)
- {
- throw new InvalidAddressException();
- }
- }
-
- if (!states.TryGetAvatarState(context.Signer, AvatarAddress, out var avatarState))
- {
- throw new FailedLoadStateException("failed to load avatar state");
- }
-
- if (!avatarState.worldInformation.IsStageCleared(GameConfig.RequireClearedStageLevel.ActionsInShop))
- {
- avatarState.worldInformation.TryGetLastClearedStageId(out var current);
- throw new NotEnoughClearedStageLevelException(AvatarAddress.ToHex(),
- GameConfig.RequireClearedStageLevel.ActionsInShop, current);
- }
-
- avatarState.UseAp(CostAp, ChargeAp, states.GetSheet(), context.BlockIndex, states.GetGameConfigState());
- var productsStateAddress = ProductsState.DeriveAddress(AvatarAddress);
- ProductsState productsState;
- if (states.TryGetLegacyState(productsStateAddress, out List rawProductList))
- {
- productsState = new ProductsState(rawProductList);
- }
- else
- {
- // cancel order before product registered case.
- var marketState = states.TryGetLegacyState(Addresses.Market, out List rawMarketList)
- ? rawMarketList
- : List.Empty;
- productsState = new ProductsState();
- marketState = marketState.Add(AvatarAddress.Serialize());
- states = states.SetLegacyState(Addresses.Market, marketState);
- }
- var addressesHex = GetSignerAndOtherAddressesHex(context, AvatarAddress);
- foreach (var productInfo in ProductInfos)
- {
- if (productInfo is ItemProductInfo {Legacy: true})
- {
- var productType = productInfo.Type;
- var orderAddress = Order.DeriveAddress(productInfo.ProductId);
- if (!states.TryGetLegacyState(orderAddress, out Dictionary rawOrder))
- {
- throw new FailedLoadStateException(
- $"{addressesHex} failed to load {nameof(Order)}({orderAddress}).");
- }
-
- var order = OrderFactory.Deserialize(rawOrder);
- switch (order)
- {
- case FungibleOrder _:
- if (productInfo.Type == ProductType.NonFungible)
- {
- throw new InvalidProductTypeException($"FungibleOrder not support {productType}");
- }
-
- break;
- case NonFungibleOrder _:
- if (productInfo.Type == ProductType.Fungible)
- {
- throw new InvalidProductTypeException($"NoneFungibleOrder not support {productType}");
- }
-
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(order));
- }
-
- states = SellCancellation.Cancel(context, states, avatarState, addressesHex,
- order);
- }
- else
- {
- states = Cancel(productsState, productInfo, states, avatarState, context);
- }
- }
-
- states = states
- .SetAvatarState(AvatarAddress, avatarState)
- .SetLegacyState(productsStateAddress, productsState.Serialize());
-
- return states;
- }
-
- public static IWorld Cancel(ProductsState productsState, IProductInfo productInfo, IWorld states,
- AvatarState avatarState, IActionContext context)
- {
- var productId = productInfo.ProductId;
- if (!productsState.ProductIds.Contains(productId))
- {
- throw new ProductNotFoundException($"can't find product {productId}");
- }
-
- productsState.ProductIds.Remove(productId);
-
- var productAddress = Product.DeriveAddress(productId);
- var product = ProductFactory.DeserializeProduct((List) states.GetLegacyState(productAddress));
- product.Validate(productInfo);
-
- switch (product)
- {
- case FavProduct favProduct:
- states = states.TransferAsset(context, productAddress, avatarState.address,
- favProduct.Asset);
- break;
- case ItemProduct itemProduct:
- switch (itemProduct.TradableItem)
- {
- case Costume costume:
- avatarState.UpdateFromAddCostume(costume, true);
- break;
- case ItemUsable itemUsable:
- avatarState.UpdateFromAddItem(itemUsable, true);
- break;
- case TradableMaterial tradableMaterial:
- {
- avatarState.UpdateFromAddItem(tradableMaterial, itemProduct.ItemCount, true);
- break;
- }
- }
-
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(product));
- }
-
- var mail = new ProductCancelMail(context.BlockIndex, productId, context.BlockIndex, productId);
- avatarState.Update(mail);
- states = states.SetLegacyState(productAddress, Null.Value);
- return states;
- }
-
-
- protected override IImmutableDictionary PlainValueInternal =>
- new Dictionary
- {
- ["a"] = AvatarAddress.Serialize(),
- ["p"] = new List(ProductInfos.Select(p => p.Serialize())),
- ["c"] = ChargeAp.Serialize(),
- }.ToImmutableDictionary();
-
- protected override void LoadPlainValueInternal(IImmutableDictionary plainValue)
- {
- AvatarAddress = plainValue["a"].ToAddress();
- ProductInfos = plainValue["p"].ToList(s => ProductFactory.DeserializeProductInfo((List) s));
- ChargeAp = plainValue["c"].ToBoolean();
- }
- }
-}
diff --git a/Lib9c/Action/CreateAvatar.cs b/Lib9c/Action/CreateAvatar.cs
index be34d1f3f2..293eb72828 100644
--- a/Lib9c/Action/CreateAvatar.cs
+++ b/Lib9c/Action/CreateAvatar.cs
@@ -3,13 +3,16 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
+using System.Linq;
using System.Text.RegularExpressions;
using Bencodex.Types;
using Lib9c.Abstractions;
using Libplanet.Action;
using Libplanet.Action.State;
+using Libplanet.Crypto;
using Nekoyume.Extensions;
using Nekoyume.Model.Item;
+using Nekoyume.Model.Stat;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Nekoyume.TableData;
@@ -126,7 +129,7 @@ public override IWorld Execute(IActionContext context)
// Avoid NullReferenceException in test
var materialItemSheet = ctx.PreviousState.GetSheet();
- avatarState = CreateAvatar0.CreateAvatarState(name, avatarAddress, ctx, materialItemSheet, default);
+ avatarState = CreateAvatarState(name, avatarAddress, ctx, materialItemSheet, default);
if (hair < 0) hair = 0;
if (lens < 0) lens = 0;
@@ -148,11 +151,11 @@ public override IWorld Execute(IActionContext context)
// prepare for test when executing on editor mode.
var data = TestbedHelper.LoadData("TestbedCreateAvatar");
- states = CreateAvatar0.AddRunesForTest(ctx, avatarAddress, states, data.RuneStoneCount);
- states = CreateAvatar0.AddSoulStoneForTest(ctx, avatarAddress, states, data.SoulStoneCount);
+ states = AddRunesForTest(ctx, avatarAddress, states, data.RuneStoneCount);
+ states = AddSoulStoneForTest(ctx, avatarAddress, states, data.SoulStoneCount);
if (data.AddPet)
{
- states = CreateAvatar0.AddPetsForTest(avatarAddress, states);
+ states = AddPetsForTest(avatarAddress, states);
}
var equipmentSheet = states.GetSheet();
@@ -279,5 +282,174 @@ public static IWorld MintAsset(CreateAvatarFavSheet favSheet,
return states;
}
+
+ public static AvatarState CreateAvatarState(string name,
+ Address avatarAddress,
+ IActionContext ctx,
+ MaterialItemSheet materialItemSheet,
+ Address rankingMapAddress)
+ {
+ var state = ctx.PreviousState;
+ var random = ctx.GetRandom();
+ var gameConfigState = state.GetGameConfigState();
+ var avatarState = new AvatarState(
+ avatarAddress,
+ ctx.Signer,
+ ctx.BlockIndex,
+ state.GetAvatarSheets(),
+ gameConfigState,
+ rankingMapAddress,
+ name
+ );
+
+#if LIB9C_DEV_EXTENSIONS || UNITY_EDITOR
+ var data = TestbedHelper.LoadData("TestbedCreateAvatar");
+ var costumeItemSheet = ctx.PreviousState.GetSheet();
+ var equipmentItemSheet = ctx.PreviousState.GetSheet();
+ var consumableItemSheet = ctx.PreviousState.GetSheet();
+
+ AddItemsForTest(
+ avatarState: avatarState,
+ random: random,
+ costumeItemSheet: costumeItemSheet,
+ materialItemSheet: materialItemSheet,
+ equipmentItemSheet: equipmentItemSheet,
+ consumableItemSheet: consumableItemSheet,
+ data.MaterialCount,
+ data.TradableMaterialCount,
+ data.FoodCount);
+
+ var skillSheet = ctx.PreviousState.GetSheet();
+ var optionSheet = ctx.PreviousState.GetSheet();
+
+ var items = data.CustomEquipmentItems;
+ foreach (var item in items)
+ {
+ AddCustomEquipment(
+ avatarState: avatarState,
+ random: random,
+ skillSheet: skillSheet,
+ equipmentItemSheet: equipmentItemSheet,
+ equipmentItemOptionSheet: optionSheet,
+ // Set level of equipment here.
+ level: item.Level,
+ // Set recipeId of target equipment here.
+ recipeId: item.ID,
+ // Add optionIds here.
+ item.OptionIds);
+ }
+#endif
+
+ return avatarState;
+ }
+
+ private static void AddItemsForTest(
+ AvatarState avatarState,
+ IRandom random,
+ CostumeItemSheet costumeItemSheet,
+ MaterialItemSheet materialItemSheet,
+ EquipmentItemSheet equipmentItemSheet,
+ ConsumableItemSheet consumableItemSheet,
+ int materialCount,
+ int tradableMaterialCount,
+ int foodCount)
+ {
+ foreach (var row in costumeItemSheet.OrderedList)
+ {
+ avatarState.inventory.AddItem2(ItemFactory.CreateCostume(row, random.GenerateRandomGuid()));
+ }
+
+ foreach (var row in materialItemSheet.OrderedList)
+ {
+ avatarState.inventory.AddItem2(ItemFactory.CreateMaterial(row), materialCount);
+
+ if (row.ItemSubType == ItemSubType.Hourglass ||
+ row.ItemSubType == ItemSubType.ApStone)
+ {
+ avatarState.inventory.AddItem2(ItemFactory.CreateTradableMaterial(row), tradableMaterialCount);
+ }
+ }
+
+ foreach (var row in equipmentItemSheet.OrderedList.Where(row =>
+ row.Id > GameConfig.DefaultAvatarWeaponId))
+ {
+ var itemId = random.GenerateRandomGuid();
+ avatarState.inventory.AddItem2(ItemFactory.CreateItemUsable(row, itemId, default));
+ }
+
+ foreach (var row in consumableItemSheet.OrderedList)
+ {
+ for (var i = 0; i < foodCount; i++)
+ {
+ var itemId = random.GenerateRandomGuid();
+ var consumable = (Consumable)ItemFactory.CreateItemUsable(row, itemId,
+ 0, 0);
+ avatarState.inventory.AddItem2(consumable);
+ }
+ }
+ }
+
+ private static void AddCustomEquipment(
+ AvatarState avatarState,
+ IRandom random,
+ SkillSheet skillSheet,
+ EquipmentItemSheet equipmentItemSheet,
+ EquipmentItemOptionSheet equipmentItemOptionSheet,
+ int level,
+ int recipeId,
+ params int[] optionIds
+ )
+ {
+ if (!equipmentItemSheet.TryGetValue(recipeId, out var equipmentRow))
+ {
+ return;
+ }
+
+ var itemId = random.GenerateRandomGuid();
+ var equipment = (Equipment)ItemFactory.CreateItemUsable(equipmentRow, itemId, 0, level);
+ var optionRows = new List();
+ foreach (var optionId in optionIds)
+ {
+ if (!equipmentItemOptionSheet.TryGetValue(optionId, out var optionRow))
+ {
+ continue;
+ }
+ optionRows.Add(optionRow);
+ }
+
+ AddOption(skillSheet, equipment, optionRows, random);
+
+ avatarState.inventory.AddItem2(equipment);
+ }
+
+ private static HashSet AddOption(
+ SkillSheet skillSheet,
+ Equipment equipment,
+ IEnumerable optionRows,
+ IRandom random)
+ {
+ var optionIds = new HashSet();
+
+ foreach (var optionRow in optionRows.OrderBy(r => r.Id))
+ {
+ if (optionRow.StatType != StatType.NONE)
+ {
+ var stat = CombinationEquipment5.GetStat(optionRow, random);
+ equipment.StatsMap.AddStatAdditionalValue(stat.StatType, stat.BaseValue);
+ }
+ else
+ {
+ var skill = CombinationEquipment5.GetSkill(optionRow, skillSheet, random);
+ if (!(skill is null))
+ {
+ equipment.Skills.Add(skill);
+ }
+ }
+
+ optionIds.Add(optionRow.Id);
+ }
+
+ return optionIds;
+ }
}
}
diff --git a/Lib9c/Action/CreateAvatar0.cs b/Lib9c/Action/CreateAvatar0.cs
deleted file mode 100644
index 8b84c3c25d..0000000000
--- a/Lib9c/Action/CreateAvatar0.cs
+++ /dev/null
@@ -1,372 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Diagnostics;
-using System.Linq;
-using System.Text.RegularExpressions;
-using Bencodex.Types;
-using Lib9c;
-using Lib9c.Abstractions;
-using Libplanet.Action;
-using Libplanet.Action.State;
-using Libplanet.Crypto;
-using Nekoyume.Model.Item;
-using Nekoyume.Model.Stat;
-using Nekoyume.Model.State;
-using Nekoyume.Module;
-using Nekoyume.TableData;
-using Serilog;
-using Nekoyume.Helper;
-
-#if LIB9C_DEV_EXTENSIONS || UNITY_EDITOR
-using Lib9c.DevExtensions;
-using Lib9c.DevExtensions.Model;
-#endif
-
-namespace Nekoyume.Action
-{
- [Serializable]
- [ActionObsolete(ActionObsoleteConfig.V200020AccidentObsoleteIndex)]
- [ActionType("create_avatar")]
- public class CreateAvatar0 : GameAction, ICreateAvatarV1
- {
- public Address avatarAddress;
- public int index;
- public int hair;
- public int lens;
- public int ear;
- public int tail;
- public string name;
-
- Address ICreateAvatarV1.AvatarAddress => avatarAddress;
- int ICreateAvatarV1.Index => index;
- int ICreateAvatarV1.Hair => hair;
- int ICreateAvatarV1.Lens => lens;
- int ICreateAvatarV1.Ear => ear;
- int ICreateAvatarV1.Tail => tail;
- string ICreateAvatarV1.Name => name;
-
- protected override IImmutableDictionary PlainValueInternal => new Dictionary()
- {
- ["avatarAddress"] = avatarAddress.Serialize(),
- ["index"] = (Integer) index,
- ["hair"] = (Integer) hair,
- ["lens"] = (Integer) lens,
- ["ear"] = (Integer) ear,
- ["tail"] = (Integer) tail,
- ["name"] = (Text) name,
- }.ToImmutableDictionary();
-
- protected override void LoadPlainValueInternal(IImmutableDictionary plainValue)
- {
- avatarAddress = plainValue["avatarAddress"].ToAddress();
- index = (int) ((Integer) plainValue["index"]).Value;
- hair = (int) ((Integer) plainValue["hair"]).Value;
- lens = (int) ((Integer) plainValue["lens"]).Value;
- ear = (int) ((Integer) plainValue["ear"]).Value;
- tail = (int) ((Integer) plainValue["tail"]).Value;
- name = (Text) plainValue["name"];
- }
-
- public override IWorld Execute(IActionContext context)
- {
- context.UseGas(1);
- IActionContext ctx = context;
- var random = ctx.GetRandom();
- var states = ctx.PreviousState;
-
- CheckObsolete(ActionObsoleteConfig.V100080ObsoleteIndex, context);
-
- var addressesHex = GetSignerAndOtherAddressesHex(context, avatarAddress);
-
- Log.Warning("{AddressesHex}create_avatar is deprecated. Please use create_avatar2", addressesHex);
-
- if (!Regex.IsMatch(name, GameConfig.AvatarNickNamePattern))
- {
- throw new InvalidNamePatternException(
- $"{addressesHex}Aborted as the input name {name} does not follow the allowed name pattern.");
- }
-
- var sw = new Stopwatch();
- sw.Start();
- var started = DateTimeOffset.UtcNow;
- Log.Verbose("{AddressesHex}CreateAvatar exec started", addressesHex);
- AgentState existingAgentState = states.GetAgentState(ctx.Signer);
- var agentState = existingAgentState ?? new AgentState(ctx.Signer);
- var avatarState = states.GetAvatarState(avatarAddress);
- if (!(avatarState is null))
- {
- throw new InvalidAddressException(
- $"{addressesHex}Aborted as there is already an avatar at {avatarAddress}.");
- }
-
- if (!(0 <= index && index < GameConfig.SlotCount))
- {
- throw new AvatarIndexOutOfRangeException(
- $"{addressesHex}Aborted as the index is out of range #{index}.");
- }
-
- if (agentState.avatarAddresses.ContainsKey(index))
- {
- throw new AvatarIndexAlreadyUsedException(
- $"{addressesHex}Aborted as the signer already has an avatar at index #{index}.");
- }
- sw.Stop();
- Log.Verbose("{AddressesHex}CreateAvatar Get AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed);
- sw.Restart();
-
- Log.Verbose("{AddressesHex}Execute CreateAvatar; player: {AvatarAddress}", addressesHex, avatarAddress);
-
- agentState.avatarAddresses.Add(index, avatarAddress);
-
- // Avoid NullReferenceException in test
- var materialItemSheet = ctx.PreviousState.GetSheet();
-
- var rankingState = ctx.PreviousState.GetRankingState0();
-
- var rankingMapAddress = rankingState.UpdateRankingMap(avatarAddress);
-
- avatarState = CreateAvatarState(name, avatarAddress, ctx, materialItemSheet, rankingMapAddress);
-
- if (hair < 0) hair = 0;
- if (lens < 0) lens = 0;
- if (ear < 0) ear = 0;
- if (tail < 0) tail = 0;
-
- avatarState.Customize(hair, lens, ear, tail);
-
- foreach (var address in avatarState.combinationSlotAddresses)
- {
- var slotState =
- new CombinationSlotState(address, GameConfig.RequireClearedStageLevel.CombinationEquipmentAction);
- states = states.SetLegacyState(address, slotState.Serialize());
- }
-
- avatarState.UpdateQuestRewards2(materialItemSheet);
-
- sw.Stop();
- Log.Verbose("{AddressesHex}CreateAvatar CreateAvatarState: {Elapsed}", addressesHex, sw.Elapsed);
- var ended = DateTimeOffset.UtcNow;
- Log.Verbose("{AddressesHex}CreateAvatar Total Executed Time: {Elapsed}", addressesHex, ended - started);
- return states
- .SetAgentState(ctx.Signer, agentState)
- .SetLegacyState(Addresses.Ranking, rankingState.Serialize())
- .SetAvatarState(avatarAddress, avatarState);
- }
-
- public static AvatarState CreateAvatarState(string name,
- Address avatarAddress,
- IActionContext ctx,
- MaterialItemSheet materialItemSheet,
- Address rankingMapAddress)
- {
- var state = ctx.PreviousState;
- var random = ctx.GetRandom();
- var gameConfigState = state.GetGameConfigState();
- var avatarState = new AvatarState(
- avatarAddress,
- ctx.Signer,
- ctx.BlockIndex,
- state.GetAvatarSheets(),
- gameConfigState,
- rankingMapAddress,
- name
- );
-
-#if LIB9C_DEV_EXTENSIONS || UNITY_EDITOR
- var data = TestbedHelper.LoadData("TestbedCreateAvatar");
- var costumeItemSheet = ctx.PreviousState.GetSheet();
- var equipmentItemSheet = ctx.PreviousState.GetSheet();
- var consumableItemSheet = ctx.PreviousState.GetSheet();
-
- AddItemsForTest(
- avatarState: avatarState,
- random: random,
- costumeItemSheet: costumeItemSheet,
- materialItemSheet: materialItemSheet,
- equipmentItemSheet: equipmentItemSheet,
- consumableItemSheet: consumableItemSheet,
- data.MaterialCount,
- data.TradableMaterialCount,
- data.FoodCount);
-
- var skillSheet = ctx.PreviousState.GetSheet();
- var optionSheet = ctx.PreviousState.GetSheet();
-
- var items = data.CustomEquipmentItems;
- foreach (var item in items)
- {
- AddCustomEquipment(
- avatarState: avatarState,
- random: random,
- skillSheet: skillSheet,
- equipmentItemSheet: equipmentItemSheet,
- equipmentItemOptionSheet: optionSheet,
- // Set level of equipment here.
- level: item.Level,
- // Set recipeId of target equipment here.
- recipeId: item.ID,
- // Add optionIds here.
- item.OptionIds);
- }
-#endif
-
- return avatarState;
- }
-
- private static void AddItemsForTest(
- AvatarState avatarState,
- IRandom random,
- CostumeItemSheet costumeItemSheet,
- MaterialItemSheet materialItemSheet,
- EquipmentItemSheet equipmentItemSheet,
- ConsumableItemSheet consumableItemSheet,
- int materialCount,
- int tradableMaterialCount,
- int foodCount)
- {
- foreach (var row in costumeItemSheet.OrderedList)
- {
- avatarState.inventory.AddItem2(ItemFactory.CreateCostume(row, random.GenerateRandomGuid()));
- }
-
- foreach (var row in materialItemSheet.OrderedList)
- {
- avatarState.inventory.AddItem2(ItemFactory.CreateMaterial(row), materialCount);
-
- if (row.ItemSubType == ItemSubType.Hourglass ||
- row.ItemSubType == ItemSubType.ApStone)
- {
- avatarState.inventory.AddItem2(ItemFactory.CreateTradableMaterial(row), tradableMaterialCount);
- }
- }
-
- foreach (var row in equipmentItemSheet.OrderedList.Where(row =>
- row.Id > GameConfig.DefaultAvatarWeaponId))
- {
- var itemId = random.GenerateRandomGuid();
- avatarState.inventory.AddItem2(ItemFactory.CreateItemUsable(row, itemId, default));
- }
-
- foreach (var row in consumableItemSheet.OrderedList)
- {
- for (var i = 0; i < foodCount; i++)
- {
- var itemId = random.GenerateRandomGuid();
- var consumable = (Consumable)ItemFactory.CreateItemUsable(row, itemId,
- 0, 0);
- avatarState.inventory.AddItem2(consumable);
- }
- }
- }
-
- private static void AddCustomEquipment(
- AvatarState avatarState,
- IRandom random,
- SkillSheet skillSheet,
- EquipmentItemSheet equipmentItemSheet,
- EquipmentItemOptionSheet equipmentItemOptionSheet,
- int level,
- int recipeId,
- params int[] optionIds
- )
- {
- if (!equipmentItemSheet.TryGetValue(recipeId, out var equipmentRow))
- {
- return;
- }
-
- var itemId = random.GenerateRandomGuid();
- var equipment = (Equipment)ItemFactory.CreateItemUsable(equipmentRow, itemId, 0, level);
- var optionRows = new List();
- foreach (var optionId in optionIds)
- {
- if (!equipmentItemOptionSheet.TryGetValue(optionId, out var optionRow))
- {
- continue;
- }
- optionRows.Add(optionRow);
- }
-
- AddOption(skillSheet, equipment, optionRows, random);
-
- avatarState.inventory.AddItem2(equipment);
- }
-
- private static HashSet AddOption(
- SkillSheet skillSheet,
- Equipment equipment,
- IEnumerable optionRows,
- IRandom random)
- {
- var optionIds = new HashSet();
-
- foreach (var optionRow in optionRows.OrderBy(r => r.Id))
- {
- if (optionRow.StatType != StatType.NONE)
- {
- var stat = CombinationEquipment5.GetStat(optionRow, random);
- equipment.StatsMap.AddStatAdditionalValue(stat.StatType, stat.BaseValue);
- }
- else
- {
- var skill = CombinationEquipment5.GetSkill(optionRow, skillSheet, random);
- if (!(skill is null))
- {
- equipment.Skills.Add(skill);
- }
- }
-
- optionIds.Add(optionRow.Id);
- }
-
- return optionIds;
- }
-
- public static IWorld AddRunesForTest(
- IActionContext context,
- Address avatarAddress,
- IWorld states,
- int count = int.MaxValue)
- {
- var runeSheet = states.GetSheet();
- foreach (var row in runeSheet.Values)
- {
- var rune = RuneHelper.ToFungibleAssetValue(row, count);
- states = states.MintAsset(context, avatarAddress, rune);
- }
- return states;
- }
-
- public static IWorld AddSoulStoneForTest(
- IActionContext context,
- Address avatarAddress,
- IWorld states,
- int count = int.MaxValue)
- {
- var petSheet = states.GetSheet();
- foreach (var row in petSheet.Values)
- {
- var soulStone = Currencies.GetSoulStone(row.SoulStoneTicker) * count;
- states = states.MintAsset(context, avatarAddress, soulStone);
- }
- return states;
- }
-
- public static IWorld AddPetsForTest(
- Address avatarAddress,
- IWorld states)
- {
- var petSheet = states.GetSheet();
- foreach (var id in petSheet.Keys)
- {
- var petState = new PetState(id);
- petState.LevelUp();
- var petStateAddress = PetState.DeriveAddress(avatarAddress, id);
- states = states.SetLegacyState(petStateAddress, petState.Serialize());
- }
-
- return states;
- }
- }
-}
diff --git a/Lib9c/Action/Grinding0.cs b/Lib9c/Action/Grinding0.cs
deleted file mode 100644
index e048888820..0000000000
--- a/Lib9c/Action/Grinding0.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using Bencodex.Types;
-using Lib9c.Abstractions;
-using Libplanet.Action;
-using Libplanet.Action.State;
-using Libplanet.Crypto;
-using Libplanet.Types.Assets;
-using Nekoyume.Extensions;
-using Nekoyume.Helper;
-using Nekoyume.Model.Item;
-using Nekoyume.Model.Mail;
-using Nekoyume.Model.State;
-using Nekoyume.Module;
-using Nekoyume.TableData;
-using Nekoyume.TableData.Crystal;
-using Serilog;
-using static Lib9c.SerializeKeys;
-
-namespace Nekoyume.Action
-{
- [ActionType("grinding")]
- public class Grinding0 : GameAction, IGrindingV1
- {
- public const int CostAp = 5;
- public const int Limit = 10;
- public Address AvatarAddress;
- public List EquipmentIds;
- public bool ChargeAp;
-
- Address IGrindingV1.AvatarAddress => AvatarAddress;
- List IGrindingV1.EquipmentsIds => EquipmentIds;
- bool IGrindingV1.ChargeAp => ChargeAp;
-
- public override IWorld Execute(IActionContext context)
- {
- context.UseGas(1);
- IActionContext ctx = context;
- IWorld states = ctx.PreviousState;
- var addressesHex = GetSignerAndOtherAddressesHex(context, AvatarAddress);
- var started = DateTimeOffset.UtcNow;
- Log.Debug("{AddressesHex}Grinding exec started", addressesHex);
- if (!EquipmentIds.Any() || EquipmentIds.Count > Limit)
- {
- throw new InvalidItemCountException();
- }
-
- var agentState = states.GetAgentState(ctx.Signer);
- if (agentState is null)
- {
- throw new FailedLoadStateException("");
- }
-
- if (!states.TryGetAvatarState(ctx.Signer, AvatarAddress, out var avatarState))
- {
- throw new FailedLoadStateException("");
- }
-
- Address monsterCollectionAddress = MonsterCollectionState.DeriveAddress(
- context.Signer,
- agentState.MonsterCollectionRound
- );
-
- Dictionary sheets = states.GetSheets(sheetTypes: new[]
- {
- typeof(CrystalEquipmentGrindingSheet),
- typeof(CrystalMonsterCollectionMultiplierSheet),
- typeof(MaterialItemSheet),
- typeof(StakeRegularRewardSheet)
- });
-
- Currency currency = states.GetGoldCurrency();
- FungibleAssetValue stakedAmount = states.GetStakedAmount(context.Signer);
- if (stakedAmount == currency * 0 && states.TryGetLegacyState(monsterCollectionAddress, out Dictionary _))
- {
- stakedAmount = states.GetBalance(monsterCollectionAddress, currency);
- }
-
- if (avatarState.actionPoint < CostAp)
- {
- switch (ChargeAp)
- {
- case false:
- throw new NotEnoughActionPointException("");
- case true:
- {
- MaterialItemSheet.Row row = sheets.GetSheet()
- .OrderedList
- .First(r => r.ItemSubType == ItemSubType.ApStone);
- if (!avatarState.inventory.RemoveFungibleItem(row.ItemId, context.BlockIndex))
- {
- throw new NotEnoughMaterialException("not enough ap stone.");
- }
- GameConfigState gameConfigState = states.GetGameConfigState();
- avatarState.actionPoint = gameConfigState.ActionPointMax;
- break;
- }
- }
- }
-
- avatarState.actionPoint -= CostAp;
-
- List equipmentList = new List();
- foreach (var equipmentId in EquipmentIds)
- {
- if(avatarState.inventory.TryGetNonFungibleItem(equipmentId, out Equipment equipment))
- {
- if (equipment.RequiredBlockIndex > context.BlockIndex)
- {
- throw new RequiredBlockIndexException($"{equipment.ItemSubType} / unlock on {equipment.RequiredBlockIndex}");
- }
- }
- else
- {
- // Invalid Item Type.
- throw new ItemDoesNotExistException($"Can't find Equipment. {equipmentId}");
- }
-
- if (!avatarState.inventory.RemoveNonFungibleItem(equipmentId))
- {
- throw new ItemDoesNotExistException($"Can't find Equipment. {equipmentId}");
- }
- equipmentList.Add(equipment);
- }
-
- FungibleAssetValue crystal = CrystalCalculator.CalculateCrystal(
- context.Signer,
- equipmentList,
- stakedAmount,
- false,
- sheets.GetSheet(),
- sheets.GetSheet(),
- sheets.GetSheet()
- );
-
- var mail = new GrindingMail(
- ctx.BlockIndex,
- Id,
- ctx.BlockIndex,
- EquipmentIds.Count,
- crystal
- );
- avatarState.Update(mail);
-
- var ended = DateTimeOffset.UtcNow;
- Log.Debug("{AddressesHex}Grinding Total Executed Time: {Elapsed}", addressesHex, ended - started);
- return states
- .SetAvatarState(AvatarAddress, avatarState)
- .MintAsset(context, context.Signer, crystal);
- }
-
- protected override IImmutableDictionary PlainValueInternal =>
- new Dictionary
- {
- ["a"] = AvatarAddress.Serialize(),
- ["e"] = new List(EquipmentIds.OrderBy(i => i).Select(i => i.Serialize())),
- ["c"] = ChargeAp.Serialize(),
- }.ToImmutableDictionary();
- protected override void LoadPlainValueInternal(IImmutableDictionary plainValue)
- {
- AvatarAddress = plainValue["a"].ToAddress();
- EquipmentIds = plainValue["e"].ToList(StateExtensions.ToGuid);
- ChargeAp = plainValue["c"].ToBoolean();
- }
- }
-}
diff --git a/Lib9c/Action/ReRegisterProduct.cs b/Lib9c/Action/ReRegisterProduct.cs
index 7ed74ff2af..bf05bd2568 100644
--- a/Lib9c/Action/ReRegisterProduct.cs
+++ b/Lib9c/Action/ReRegisterProduct.cs
@@ -153,7 +153,7 @@ public override IWorld Execute(IActionContext context)
}
else
{
- states = CancelProductRegistration0.Cancel(productsState, productInfo,
+ states = CancelProductRegistration.Cancel(productsState, productInfo,
states, avatarState, context);
}
diff --git a/Lib9c/Action/ReRegisterProduct0.cs b/Lib9c/Action/ReRegisterProduct0.cs
index a7f3561b24..504f3f5767 100644
--- a/Lib9c/Action/ReRegisterProduct0.cs
+++ b/Lib9c/Action/ReRegisterProduct0.cs
@@ -153,7 +153,7 @@ public override IWorld Execute(IActionContext context)
}
else
{
- states = CancelProductRegistration0.Cancel(productsState, productInfo,
+ states = CancelProductRegistration.Cancel(productsState, productInfo,
states, avatarState, context);
}
diff --git a/Lib9c/Action/RewardGold.cs b/Lib9c/Action/RewardGold.cs
index 13a2e21265..a4fcebbb71 100644
--- a/Lib9c/Action/RewardGold.cs
+++ b/Lib9c/Action/RewardGold.cs
@@ -308,8 +308,7 @@ public IWorld MinerReward(IActionContext ctx, IWorld states)
public static IWorld TransferMead(IActionContext context, IWorld states)
{
#pragma warning disable LAA1002
- var targetAddresses = states.GetAccount(ReservedAddresses.LegacyAccount)
- .TotalUpdatedFungibleAssets
+ var targetAddresses = states.TotalUpdatedFungibleAssets
#pragma warning restore LAA1002
.Where(pair => pair.Item2.Equals(Currencies.Mead))
.Select(pair => pair.Item1)
diff --git a/Lib9c/Action/RuneEnhancement0.cs b/Lib9c/Action/RuneEnhancement0.cs
deleted file mode 100644
index 277eef7b05..0000000000
--- a/Lib9c/Action/RuneEnhancement0.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using Bencodex.Types;
-using Lib9c.Abstractions;
-using Libplanet.Action;
-using Libplanet.Action.State;
-using Libplanet.Crypto;
-using Libplanet.Types.Assets;
-using Nekoyume.Extensions;
-using Nekoyume.Helper;
-using Nekoyume.Model.Rune;
-using Nekoyume.Model.State;
-using Nekoyume.Module;
-using Nekoyume.TableData;
-
-namespace Nekoyume.Action
-{
- [Serializable]
- [ActionObsolete(ActionObsoleteConfig.V200020AccidentObsoleteIndex)]
- [ActionType("runeEnhancement")]
- public class RuneEnhancement0 : GameAction, IRuneEnhancementV1
- {
- public Address AvatarAddress;
- public int RuneId;
- public int TryCount = 1;
-
- Address IRuneEnhancementV1.AvatarAddress => AvatarAddress;
- int IRuneEnhancementV1.RuneId => RuneId;
- int IRuneEnhancementV1.TryCount => TryCount;
-
- protected override IImmutableDictionary PlainValueInternal =>
- new Dictionary
- {
- ["a"] = AvatarAddress.Serialize(),
- ["r"] = RuneId.Serialize(),
- ["t"] = TryCount.Serialize(),
- }.ToImmutableDictionary();
-
- protected override void LoadPlainValueInternal(
- IImmutableDictionary