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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
package kubatech.api.eig;
import static kubatech.api.utils.ItemUtils.readItemStackFromNBT;
import static kubatech.api.utils.ItemUtils.writeItemStackToNBT;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
public class EIGDropTable {
private static final String NBT_DROP_TABLE_ITEM_KEY = "item";
private static final String NBT_DROP_TABLE_COUNT_KEY = "count";
private final ItemStackMap<Double> dropTable;
/**
* Initialises a new empty drop table.
*/
public EIGDropTable() {
this.dropTable = new ItemStackMap<>(true);
}
/**
* Loads a serialised drop table from nbt.
*
* @param nbt The nbt tag that contains the key for a drop table
* @param key The name of the key name for the drop table.
*/
public EIGDropTable(NBTTagCompound nbt, String key) {
// should create an empty table if no drops are found.
this(nbt.getTagList(key, 10));
}
/**
* Loads a serialised drop table from nbt.
*
* @param nbt The nbt tag that contains the key for a drop table
*/
public EIGDropTable(NBTTagList nbt) {
this();
for (int i = 0; i < nbt.tagCount(); i++) {
NBTTagCompound drop = nbt.getCompoundTagAt(i);
dropTable.merge(
readItemStackFromNBT(drop.getCompoundTag(NBT_DROP_TABLE_ITEM_KEY)),
drop.getDouble(NBT_DROP_TABLE_COUNT_KEY),
Double::sum);
}
}
/**
* Serialises the drop table to nbt
*
* @return The serialised drop table.
*/
public NBTTagList save() {
NBTTagList nbt = new NBTTagList();
for (Map.Entry<ItemStack, Double> entry : this.dropTable.entrySet()) {
NBTTagCompound entryNBT = new NBTTagCompound();
entryNBT.setTag(NBT_DROP_TABLE_ITEM_KEY, writeItemStackToNBT(entry.getKey()));
entryNBT.setDouble(NBT_DROP_TABLE_COUNT_KEY, entry.getValue());
nbt.appendTag(entryNBT);
}
return nbt;
}
/**
* Adds a drop to the drop table
*
* @param itemStack The item to add to the table.
* @param amount The amount to add to the table.
*/
public void addDrop(ItemStack itemStack, double amount) {
ItemStack key = itemStack.copy();
key.stackSize = 1;
this.dropTable.merge(key, amount, Double::sum);
}
/**
* Adds the values from this drop table to another, but multiplies the amount by a random amount bound by variance.
*
* @param target The drop table that you want to add the value to.
* @param variance How much to vary the amounts of this drop table to, 0 < x < 1 plz
* @param rand The random source for the variance.
*/
public void addTo(EIGDropTable target, double variance, Random rand) {
this.addTo(target, 1.0, variance, rand);
}
/**
* Adds the values from this drop table to another, but multiplies the amount by a multiplier and a random amount
* bound by variance.
*
* @param target The drop table that you want to add the value to.
* @param multiplier A multiplier to apply to all amounts from this drop table.
* @param variance How much to vary the amounts of this drop table to, 0 < x < 1 plz.
* @param rand The random source for the variance.
*/
public void addTo(EIGDropTable target, double multiplier, double variance, Random rand) {
this.addTo(target, variance * (rand.nextDouble() - 0.5) * multiplier);
}
/**
* Adds the values from this drop table to another.
*
* @param target The drop table that you want to add the value to.
*/
public void addTo(EIGDropTable target) {
this.addTo(target, 1.0);
}
/**
* Adds the values from this drop table to another but multiplies the values by a multiplier.
*
* @param target The drop table that you want to add the value to.
* @param multiplier A multiplier to apply to all amounts from this drop table.
*/
public void addTo(EIGDropTable target, double multiplier) {
for (Map.Entry<ItemStack, Double> entry : this.dropTable.entrySet()) {
target.dropTable.merge(entry.getKey(), entry.getValue() * multiplier, Double::sum);
}
}
/**
* Checks if the drop table is empty;
*
* @return true if empty.
*/
public boolean isEmpty() {
return this.dropTable.isEmpty();
}
/**
* Returns the entry set for this drop table.
*
* @return ItemStack -> amount
*/
public Set<Map.Entry<ItemStack, Double>> entrySet() {
return this.dropTable.entrySet();
}
/**
* Gets the amount for a specific item.
*
* @param item The item to look for.
* @return 0 if nothing is found else a positive value.
*/
public double getItemAmount(ItemStack item) {
if (this.dropTable.containsKey(item)) {
return this.dropTable.get(item);
}
return 0;
}
/**
* Sets the amount for a specific item.
*
* @param item The item to look for.
*/
public void setItemAmount(ItemStack item, double value) {
this.dropTable.put(item, value);
}
/**
* Removes an item from the drop table
*
* @param item The item to remove from the drop table.
*/
public void removeItem(ItemStack item) {
this.dropTable.remove(item);
}
/**
* Creates a new drop table that is the intersection of this drop table and another.
*
*
* @param with The drop table to intersect with.
* @return The result of the intersection.
*/
public EIGDropTable intersect(EIGDropTable with) {
EIGDropTable ret = new EIGDropTable();
for (ItemStack key : with.dropTable.keySet()) {
if (this.dropTable.containsKey(key)) {
ret.addDrop(key, this.dropTable.get(key));
}
}
return ret;
}
/**
* Consumes drops with drop counts above 1 and returns a list of the consumed item stacks.
*
* @return The list of consumed items;
*/
public ItemStack[] getDrops() {
// doesn't need to filter for less than 0 so that the EIG displays the progress of incomplete items.
return this.dropTable.entrySet()
.parallelStream()
.map(EIGDropTable::computeDrops)
.toArray(ItemStack[]::new);
}
/**
* Consumes the items in the entry and returns the consumed item without removing partial items.
*
* @param entry The entry to consume from
* @return The item tha twas removed.
*/
private static ItemStack computeDrops(Map.Entry<ItemStack, Double> entry) {
ItemStack copied = entry.getKey()
.copy();
copied.stackSize = (int) Math.floor(entry.getValue());
if (entry.getValue() >= 1.0d) {
entry.setValue(entry.getValue() % 1);
}
return copied;
}
}
|