Skip to content

Commit a5dd5bd

Browse files
author
ulismoon (hyeon)
authored
Merge pull request #2675 from planetarium/release/1.14.0
1.14.0
2 parents 315e97a + c3ac6ac commit a5dd5bd

File tree

99 files changed

+7345
-725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+7345
-725
lines changed

.Lib9c.Tests/Action/AdventureBoss/ClaimAdventureBossRewardTest.cs

Lines changed: 1054 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
namespace Lib9c.Tests.Action.AdventureBoss
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Numerics;
7+
using Bencodex.Types;
8+
using Libplanet.Action.State;
9+
using Libplanet.Crypto;
10+
using Libplanet.Mocks;
11+
using Libplanet.Types.Assets;
12+
using Nekoyume;
13+
using Nekoyume.Action;
14+
using Nekoyume.Action.AdventureBoss;
15+
using Nekoyume.Extensions;
16+
using Nekoyume.Model.AdventureBoss;
17+
using Nekoyume.Model.EnumType;
18+
using Nekoyume.Model.Item;
19+
using Nekoyume.Model.State;
20+
using Nekoyume.Module;
21+
using Nekoyume.TableData;
22+
using Xunit;
23+
24+
public class ExploreAdventureBossTest
25+
{
26+
private static readonly Dictionary<string, string> Sheets =
27+
TableSheetsImporter.ImportSheets();
28+
29+
private static readonly TableSheets TableSheets = new TableSheets(Sheets);
30+
#pragma warning disable CS0618
31+
// Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1419
32+
private static readonly Currency NCG = Currency.Legacy("NCG", 2, null);
33+
#pragma warning restore CS0618
34+
35+
// Wanted
36+
private static readonly Address WantedAddress = new PrivateKey().Address;
37+
38+
private static readonly Address WantedAvatarAddress =
39+
Addresses.GetAvatarAddress(WantedAddress, 0);
40+
41+
private static readonly AvatarState WantedAvatarState = new (
42+
WantedAvatarAddress, WantedAddress, 0L, TableSheets.GetAvatarSheets(),
43+
new PrivateKey().Address, name: "wanted"
44+
);
45+
46+
private static readonly AgentState WantedState = new (WantedAddress)
47+
{
48+
avatarAddresses = { [0] = WantedAvatarAddress, },
49+
};
50+
51+
// Test Account
52+
private static readonly Address TesterAddress =
53+
new ("2000000000000000000000000000000000000002");
54+
55+
private static readonly Address TesterAvatarAddress =
56+
Addresses.GetAvatarAddress(TesterAddress, 0);
57+
58+
private static readonly AvatarState TesterAvatarState = new (
59+
TesterAvatarAddress, TesterAddress, 0L, TableSheets.GetAvatarSheets(),
60+
new PrivateKey().Address, name: "Tester"
61+
) { level = 500 };
62+
63+
private static readonly AgentState TesterState = new (TesterAddress)
64+
{
65+
avatarAddresses =
66+
{
67+
[0] = TesterAvatarAddress,
68+
},
69+
};
70+
71+
private readonly IWorld _initialState = new World(MockUtil.MockModernWorldState)
72+
.SetLegacyState(Addresses.GoldCurrency, new GoldCurrencyState(NCG).Serialize())
73+
.SetLegacyState(
74+
GameConfigState.Address,
75+
new GameConfigState(Sheets["GameConfigSheet"]).Serialize()
76+
)
77+
.SetAvatarState(WantedAvatarAddress, WantedAvatarState)
78+
.SetAgentState(WantedAddress, WantedState)
79+
.SetAvatarState(TesterAvatarAddress, TesterAvatarState)
80+
.SetAgentState(TesterAddress, TesterState)
81+
.MintAsset(new ActionContext(), WantedAddress, 1_000_000 * NCG);
82+
83+
public ExploreAdventureBossTest()
84+
{
85+
var collectionSheet = TableSheets.CollectionSheet;
86+
var collectionState = new CollectionState();
87+
foreach (var row in collectionSheet.Values)
88+
{
89+
collectionState.Ids.Add(row.Id);
90+
}
91+
92+
_initialState = _initialState.SetCollectionState(TesterAvatarAddress, collectionState);
93+
}
94+
95+
// Member Data
96+
public static IEnumerable<object[]> GetExecuteMemberData()
97+
{
98+
// No AP potion at all
99+
yield return new object[]
100+
{
101+
0, 5, 0, 0, 0, null, new (int, int)[] { },
102+
};
103+
// Start from bottom, goes to 5
104+
yield return new object[]
105+
{
106+
0, 5, 5, 10, 5, null,
107+
new[]
108+
{
109+
(600301, 76), // 50 first Reward + 26 floor reward
110+
(600302, 50), // 50 first reward
111+
(600303, 0),
112+
(600304, 0),
113+
},
114+
};
115+
// Start from bottom, goes to 3 because of potion
116+
yield return new object[]
117+
{
118+
0, 5, 3, 3, 0, null, new[]
119+
{
120+
(600301, 47), // 30 first reward + 17 floor reward
121+
(600302, 30), // 30 first reward
122+
(600303, 0),
123+
(600304, 0),
124+
},
125+
};
126+
// Start from 3, goes to 5 because of locked floor
127+
yield return new object[]
128+
{
129+
2, 5, 5, 5, 2, null, new[]
130+
{
131+
(600301, 40), // 30 first reward + 10 floor reward
132+
(600302, 39), // 30 first reward + 9 floor reward
133+
(600303, 0),
134+
(600304, 0),
135+
},
136+
};
137+
// Start from 6, goes to 10
138+
yield return new object[]
139+
{
140+
5, 10, 10, 10, 5, null,
141+
new[]
142+
{
143+
(600301, 72), // 50 first reward + 22 floor reward
144+
(600302, 50), // 50 first reward
145+
(600303, 0),
146+
(600304, 0),
147+
},
148+
};
149+
// Start from 20, cannot enter
150+
yield return new object[]
151+
{
152+
20, 20, 20, 10, 10, typeof(InvalidOperationException), null,
153+
};
154+
}
155+
156+
[Theory]
157+
[MemberData(nameof(GetExecuteMemberData))]
158+
public void Execute(
159+
int floor,
160+
int maxFloor,
161+
int expectedFloor,
162+
int initialPotion,
163+
int expectedPotion,
164+
Type exc,
165+
(int, int)[] expectedRewards
166+
)
167+
{
168+
// Settings
169+
var state = _initialState;
170+
var gameConfigState = new GameConfigState(Sheets[nameof(GameConfigSheet)]);
171+
state = state.SetLegacyState(gameConfigState.address, gameConfigState.Serialize());
172+
173+
foreach (var (key, value) in Sheets)
174+
{
175+
state = state.SetLegacyState(Addresses.TableSheet.Derive(key), value.Serialize());
176+
}
177+
178+
state = Stake(state, WantedAddress);
179+
var sheets = state.GetSheets(sheetTypes: new[]
180+
{
181+
typeof(MaterialItemSheet),
182+
});
183+
var materialSheet = sheets.GetSheet<MaterialItemSheet>();
184+
var materialRow =
185+
materialSheet.OrderedList.First(row => row.ItemSubType == ItemSubType.ApStone);
186+
var apPotion = ItemFactory.CreateMaterial(materialRow);
187+
188+
if (initialPotion > 0)
189+
{
190+
var inventory = state.GetInventoryV2(TesterAvatarAddress);
191+
inventory.AddItem(apPotion, initialPotion);
192+
state = state.SetInventory(TesterAvatarAddress, inventory);
193+
}
194+
195+
// Open season
196+
state = new Wanted
197+
{
198+
Season = 1,
199+
AvatarAddress = WantedAvatarAddress,
200+
Bounty = gameConfigState.AdventureBossMinBounty * NCG,
201+
}.Execute(new ActionContext
202+
{
203+
PreviousState = state,
204+
Signer = WantedAddress,
205+
BlockIndex = 0L,
206+
RandomSeed = 1,
207+
});
208+
var exp = new Explorer(TesterAvatarAddress, TesterAvatarState.name)
209+
{
210+
MaxFloor = maxFloor,
211+
Floor = floor,
212+
};
213+
state = state.SetExplorer(1, exp);
214+
215+
// Explore and Test
216+
var itemSlotStateAddress =
217+
ItemSlotState.DeriveAddress(TesterAvatarAddress, BattleType.Adventure);
218+
var itemSlotState =
219+
state.TryGetLegacyState(itemSlotStateAddress, out List rawItemSlotState)
220+
? new ItemSlotState(rawItemSlotState)
221+
: new ItemSlotState(BattleType.Adventure);
222+
Assert.True(itemSlotState.Equipments.Count == 0);
223+
224+
var previousAvatarState = _initialState.GetAvatarState(TesterAvatarAddress);
225+
var equipments = Doomfist.GetAllParts(TableSheets, previousAvatarState.level);
226+
foreach (var equipment in equipments)
227+
{
228+
previousAvatarState.inventory.AddItem(equipment);
229+
}
230+
231+
var action = new ExploreAdventureBoss
232+
{
233+
Season = 1,
234+
AvatarAddress = TesterAvatarAddress,
235+
Costumes = new List<Guid>(),
236+
Equipments = equipments.Select(e => e.NonFungibleId).ToList(),
237+
Foods = new List<Guid>(),
238+
RuneInfos = new List<RuneSlotInfo>(),
239+
};
240+
241+
if (exc is not null)
242+
{
243+
Assert.Throws(exc, () => action.Execute(new ActionContext
244+
{
245+
PreviousState = state,
246+
Signer = TesterAddress,
247+
BlockIndex = 1L,
248+
}
249+
));
250+
}
251+
else
252+
{
253+
state = action.Execute(new ActionContext
254+
{
255+
PreviousState = state,
256+
Signer = TesterAddress,
257+
BlockIndex = 1L,
258+
});
259+
260+
var potion = state.GetInventoryV2(TesterAvatarAddress).Items
261+
.FirstOrDefault(i => i.item.ItemSubType == ItemSubType.ApStone);
262+
if (expectedPotion == 0)
263+
{
264+
Assert.Null(potion);
265+
}
266+
else
267+
{
268+
Assert.Equal(expectedPotion, potion!.count);
269+
}
270+
271+
var exploreBoard = state.GetExploreBoard(1);
272+
var explorer = state.GetExplorer(1, TesterAvatarAddress);
273+
274+
Assert.Equal(initialPotion - expectedPotion, exploreBoard.UsedApPotion);
275+
Assert.Equal(expectedFloor, explorer.Floor);
276+
277+
var inventory = state.GetInventoryV2(TesterAvatarAddress);
278+
foreach (var (id, amount) in expectedRewards)
279+
{
280+
if (amount == 0)
281+
{
282+
Assert.Null(inventory.Items.FirstOrDefault(i => i.item.Id == id));
283+
}
284+
else
285+
{
286+
Assert.Equal(amount, inventory.Items.First(i => i.item.Id == id).count);
287+
}
288+
}
289+
290+
itemSlotState =
291+
state.TryGetLegacyState(itemSlotStateAddress, out rawItemSlotState)
292+
? new ItemSlotState(rawItemSlotState)
293+
: new ItemSlotState(BattleType.Adventure);
294+
Assert.True(itemSlotState.Equipments.Count > 0);
295+
}
296+
}
297+
298+
private IWorld Stake(IWorld world, Address agentAddress)
299+
{
300+
var action = new Stake(new BigInteger(500_000));
301+
var state = action.Execute(new ActionContext
302+
{
303+
PreviousState = world,
304+
Signer = agentAddress,
305+
BlockIndex = 0L,
306+
});
307+
return state;
308+
}
309+
}
310+
}

0 commit comments

Comments
 (0)