forked from Slimefun/Slimefun4
-
-
Notifications
You must be signed in to change notification settings - Fork 61
/
DirtyChestMenu.java
231 lines (188 loc) · 7.58 KB
/
DirtyChestMenu.java
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
225
226
227
228
229
230
231
package me.mrCookieSlime.Slimefun.api.inventory;
import city.norain.slimefun4.utils.StringUtil;
import io.github.bakedlibs.dough.inventory.InvUtils;
import io.github.bakedlibs.dough.items.CustomItemStack;
import io.github.bakedlibs.dough.items.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.core.debug.Debug;
import io.github.thebusybiscuit.slimefun4.core.debug.TestCase;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
// This class will be deprecated, relocated and rewritten in a future version.
public class DirtyChestMenu extends ChestMenu {
protected final BlockMenuPreset preset;
protected int changes = 1;
public DirtyChestMenu(@Nonnull BlockMenuPreset preset) {
super(preset.getTitle());
this.preset = preset;
}
/**
* This method checks whether this {@link DirtyChestMenu} is currently viewed by a {@link Player}.
*
* @return Whether anyone is currently viewing this {@link Inventory}
*/
public boolean hasViewer() {
Inventory inv = toInventory();
return inv != null && !inv.getViewers().isEmpty();
}
public void markDirty() {
changes++;
}
public boolean isDirty() {
return changes > 0;
}
public int getUnsavedChanges() {
return changes;
}
@Nonnull
public BlockMenuPreset getPreset() {
return preset;
}
public boolean canOpen(Block b, Player p) {
return preset.canOpen(b, p);
}
@Override
public void open(Player... players) {
super.open(players);
// The Inventory will likely be modified soon
markDirty();
}
public void close() {
for (HumanEntity human : new ArrayList<>(toInventory().getViewers())) {
human.closeInventory();
}
}
public boolean fits(@Nonnull ItemStack item, int... slots) {
Debug.log(
TestCase.UTILS,
"DirtyChestMenu#fits - start check fits | item {} | slots {}",
StringUtil.itemStackToString(item),
Arrays.stream(slots).mapToObj(String::valueOf).collect(Collectors.joining(",")));
var isSfItem = SlimefunItem.getByItem(item) != null;
var wrapper = ItemStackWrapper.wrap(item);
var remain = item.getAmount();
for (int slot : slots) {
// A small optimization for empty slots
var slotItem = getItemInSlot(slot);
if (slotItem == null || slotItem.getType().isAir()) {
return true;
}
Debug.log(
TestCase.UTILS,
"DirtyChestMenu#fits - Now checking item | Slot {} | Item {}",
slot,
StringUtil.itemStackToString(slotItem));
if (isSfItem) {
Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - Check slimefun item fits");
if (!slotItem.hasItemMeta()
|| item.getType() != slotItem.getType()
|| !SlimefunUtils.isItemSimilar(slotItem, wrapper, true, false)) {
continue;
}
var slotRemain = slotItem.getMaxStackSize() - slotItem.getAmount();
Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - current slot remain: {}", slotRemain);
remain -= slotRemain;
Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - remaining amount: {}", remain);
if (remain <= 0) {
Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - check fits result (no remain): false");
return true;
}
}
}
boolean result = false;
if (!isSfItem) {
result = InvUtils.fits(toInventory(), wrapper, slots);
}
Debug.log(TestCase.UTILS, "DirtyChestMenu#fits - check fits result: {}", result);
return result;
}
/**
* Adds given {@link ItemStack} to any of the given inventory slots.
* Items will be added to the inventory slots based on their order in the function argument.
* Items will be added either to any empty inventory slots or any partially filled slots, in which case
* as many items as can fit will be added to that specific spot.
*
* @param item {@link ItemStack} to be added to the inventory
* @param slots Numbers of slots to add the {@link ItemStack} to
* @return {@link ItemStack} with any items that did not fit into the inventory
* or null when everything had fit
*/
@Nullable public ItemStack pushItem(ItemStack item, int... slots) {
if (item == null || item.getType() == Material.AIR) {
throw new IllegalArgumentException("Cannot push null or AIR");
}
ItemStackWrapper wrapper = null;
int amount = item.getAmount();
for (int slot : slots) {
if (amount <= 0) {
break;
}
ItemStack stack = getItemInSlot(slot);
if (stack == null) {
replaceExistingItem(slot, item);
return null;
} else {
int maxStackSize =
Math.min(stack.getMaxStackSize(), toInventory().getMaxStackSize());
if (stack.getAmount() < maxStackSize) {
if (wrapper == null) {
wrapper = ItemStackWrapper.wrap(item);
}
if (SlimefunItem.getByItem(item) != null) {
// Patch: use sf item check
if (!SlimefunUtils.isItemSimilar(stack, wrapper, true, false)) {
continue;
}
} else {
// Use original check
if (!ItemUtils.canStack(wrapper, stack)) {
continue;
}
}
amount -= (maxStackSize - stack.getAmount());
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), maxStackSize));
item.setAmount(amount);
}
}
}
if (amount > 0) {
return new CustomItemStack(item, amount);
} else {
return null;
}
}
public void consumeItem(int slot) {
consumeItem(slot, 1);
}
public void consumeItem(int slot, int amount) {
consumeItem(slot, amount, false);
}
public void consumeItem(int slot, int amount, boolean replaceConsumables) {
ItemUtils.consumeItem(getItemInSlot(slot), amount, replaceConsumables);
markDirty();
}
@Override
public void replaceExistingItem(int slot, ItemStack item) {
replaceExistingItem(slot, item, true);
}
public void replaceExistingItem(int slot, ItemStack item, boolean event) {
if (event) {
ItemStack previous = getItemInSlot(slot);
item = preset.onItemStackChange(this, slot, previous, item);
}
super.replaceExistingItem(slot, item);
markDirty();
}
}