-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy pathClaimPatrolReward.cs
120 lines (107 loc) · 4.37 KB
/
ClaimPatrolReward.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;
using Bencodex.Types;
using Lib9c;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Nekoyume.Extensions;
using Nekoyume.Helper;
using Nekoyume.Model.Mail;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Nekoyume.TableData.Event;
namespace Nekoyume.Action
{
/// <summary>
/// Claim patrol reward
/// </summary>
[Serializable]
[ActionType(TypeIdentifier)]
public class ClaimPatrolReward : ActionBase
{
public const string TypeIdentifier = "claim_patrol_reward";
/// <summary>
/// The address of the avatar to receive the patrol reward.
/// </summary>
public Address AvatarAddress;
public ClaimPatrolReward()
{
}
public ClaimPatrolReward(Address avatarAddress)
{
AvatarAddress = avatarAddress;
}
public override IWorld Execute(IActionContext context)
{
GasTracer.UseGas(1);
var signer = context.Signer;
var states = context.PreviousState;
// Validate that the avatar address belongs to the signer.
// This ensures that only the owner of the avatar can claim the patrol reward for it.
if (!Addresses.CheckAvatarAddrIsContainedInAgent(signer, AvatarAddress))
{
throw new InvalidAddressException();
}
// avatar
var avatarState = states.GetAvatarState(AvatarAddress, true, false, false);
var avatarLevel = avatarState.level;
var inventory = avatarState.inventory;
// sheets
var sheets = states.GetSheets(containItemSheet: true, sheetTypes: new[]
{
typeof(PatrolRewardSheet)
});
var patrolRewardSheet = sheets.GetSheet<PatrolRewardSheet>();
var itemSheet = sheets.GetItemSheet();
// validate
states.TryGetPatrolRewardClaimedBlockIndex(AvatarAddress, out var claimedBlockIndex);
var row = patrolRewardSheet.FindByLevel(avatarLevel, context.BlockIndex);
// Ensure rewards cannot be claimed too frequently.
// If the last claimed block index is set and the current block index is less than the allowed interval, throw an exception.
if (claimedBlockIndex > 0L && claimedBlockIndex + row.Interval > context.BlockIndex)
{
throw new RequiredBlockIndexException();
}
// mint rewards
var random = context.GetRandom();
var fav = new List<FungibleAssetValue>();
var items = new List<(int id, int count)>();
foreach (var reward in row.Rewards)
{
var ticker = reward.Ticker;
if (string.IsNullOrEmpty(ticker))
{
var itemRow = itemSheet[reward.ItemId];
inventory.MintItem(itemRow, reward.Count, false, random);
items.Add(new (reward.ItemId, reward.Count));
}
else
{
var currency = Currencies.GetMinterlessCurrency(ticker);
var recipient = Currencies.PickAddress(currency, signer, AvatarAddress);
var asset = currency * reward.Count;
states = states.MintAsset(context, recipient, asset);
fav.Add(asset);
}
}
var mailBox = avatarState.mailBox;
var mail = new PatrolRewardMail(context.BlockIndex, random.GenerateRandomGuid(), context.BlockIndex, fav, items);
mailBox.Add(mail);
mailBox.CleanUp();
avatarState.mailBox = mailBox;
// set states
return states
.SetAvatarState(AvatarAddress, avatarState, setAvatar: true, setInventory: true, setWorldInformation: false, setQuestList: false)
.SetPatrolRewardClaimedBlockIndex(AvatarAddress, context.BlockIndex);
}
public override IValue PlainValue => Dictionary.Empty
.Add("type_id", TypeIdentifier)
.Add("values", AvatarAddress.Serialize());
public override void LoadPlainValue(IValue plainValue)
{
AvatarAddress = ((Dictionary)plainValue)["values"].ToAddress();
}
}
}