-
-
Notifications
You must be signed in to change notification settings - Fork 434
Expand file tree
/
Copy pathTrackedItem.cs
More file actions
142 lines (114 loc) · 4.37 KB
/
Copy pathTrackedItem.cs
File metadata and controls
142 lines (114 loc) · 4.37 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.Diagnostics.CodeAnalysis;
using StardewValley;
namespace Pathoschild.Stardew.Automate;
/// <summary>An item stack which notifies callbacks when it's reduced.</summary>
public class TrackedItem : ITrackedStack
{
/*********
** Fields
*********/
/// <summary>The item stack.</summary>
private readonly Item Item;
/// <summary>The callback invoked when the stack size is reduced (including reduced to zero).</summary>
protected Action<TrackedItem, Item>? OnReducedImpl;
/// <summary>The callback invoked when the stack is empty.</summary>
protected Action<TrackedItem, Item>? OnEmptyImpl;
/*********
** Accessors
*********/
/// <inheritdoc />
public Item Sample { get; }
/// <inheritdoc />
public string Type { get; }
/// <inheritdoc />
public int Count { get; private set; }
/// <summary>The <see cref="Count"/> for which <see cref="OnReducedImpl"/> was last called (or the initial value if this is the first call).</summary>
public int LastCount { get; private set; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="item">The item stack.</param>
public TrackedItem(Item item)
{
this.Item = item ?? throw new InvalidOperationException("Can't track a null item stack.");
this.Type = item.TypeDefinitionId;
this.Sample = this.GetNewStack(item);
this.Count = item.Stack; // we can't trust Item.Stack to reduce correctly (e.g. Hat.Stack always return 1), so we need to track it ourselves
this.LastCount = this.Count;
}
/// <summary>Construct an instance.</summary>
/// <param name="item">The item stack.</param>
/// <param name="onReduced">The callback to raise when the stack size is reduced (including reduced to zero).</param>
/// <param name="onEmpty">The callback invoked when the stack is empty.</param>
[Obsolete($"Use {nameof(OnReduced)} or {nameof(OnEmpty)} instead of passing callbacks through the constructor.")]
public TrackedItem(Item item, Action<Item>? onReduced = null, Action<Item>? onEmpty = null)
: this(item)
{
if (onReduced != null)
this.OnReduced((_, reducedItem) => onReduced(reducedItem));
if (onEmpty != null)
this.OnEmpty((_, reducedItem) => onEmpty(reducedItem));
}
/// <summary>Register a callback to raise when the stack size is reduced (including reduced to zero).</summary>
/// <param name="onReduced">The callback to invoke.</param>
/// <returns>Returns the current instance for chaining.</returns>
public TrackedItem OnReduced(Action<TrackedItem, Item>? onReduced)
{
this.OnReducedImpl += onReduced;
return this;
}
/// <summary>Register a callback to raise when the stack size is reduced to zero.</summary>
/// <param name="onEmpty">The callback to invoke.</param>
/// <returns>Returns the current instance for chaining.</returns>
public TrackedItem OnEmpty(Action<TrackedItem, Item>? onEmpty)
{
this.OnEmptyImpl += onEmpty;
return this;
}
/// <inheritdoc />
public void Reduce(int count)
{
if (count <= 0)
return;
this.Item.Stack -= count;
this.Count -= count;
this.Delegate();
}
/// <inheritdoc />
public Item? Take(int count)
{
if (count <= 0)
return null;
this.Reduce(count);
return this.GetNewStack(this.Item, count);
}
/*********
** Private methods
*********/
/// <summary>Notify handlers.</summary>
private void Delegate()
{
// skip if not reduced
if (this.Count >= this.LastCount)
return;
// notify handlers
this.OnReducedImpl?.Invoke(this, this.Item);
if (this.Count <= 0)
this.OnEmptyImpl?.Invoke(this, this.Item);
this.LastCount = this.Count;
}
/// <summary>Create a new stack of the given item.</summary>
/// <param name="original">The item stack to clone.</param>
/// <param name="stackSize">The new stack size.</param>
[return: NotNullIfNotNull("original")]
private Item? GetNewStack(Item? original, int stackSize = 1)
{
if (original == null)
return null;
Item stack = original.getOne();
stack.Stack = stackSize;
return stack;
}
}