Skip to content

Commit 2dda881

Browse files
committed
refactor nbt container handling and improve item reversion
1 parent 02e7c89 commit 2dda881

File tree

6 files changed

+423
-51
lines changed

6 files changed

+423
-51
lines changed

src/main/java/org/zeroBzeroT/antiillegals/AntiIllegals.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,32 @@ public void onEnable() {
5353
log("unbreakables", "" + getConfig().getBoolean("unbreakables"));
5454
log("durability", "" + getConfig().getBoolean("durability"));
5555
log("illegalBlocks", "" + getConfig().getBoolean("illegalBlocks"));
56-
log("nbtContainers", "" + getConfig().getBoolean("nbtContainers"));
56+
log("nbtContainers.enabled", "" + getConfig().getBoolean("nbtContainers.enabled",
57+
getConfig().getBoolean("nbtContainers")));
58+
log("nbtContainers.armorStandItems", "" + getConfig().getBoolean("nbtContainers.armorStandItems", true));
59+
log("nbtContainers.itemFrameItems", "" + getConfig().getBoolean("nbtContainers.itemFrameItems", true));
60+
log("nbtContainers.bundleItems", "" + getConfig().getBoolean("nbtContainers.bundleItems", true));
61+
log("nbtContainers.stripOtherContainers", ""
62+
+ getConfig().getBoolean("nbtContainers.stripOtherContainers", true));
5763
log("blockStates.enabled", "" + getConfig().getBoolean("blockStates.enabled"));
5864
log("blockStates.keys", String.join(", ", getConfig().getStringList("blockStates.keys")));
5965
log("overstackedItems", "" + getConfig().getBoolean("overstackedItems"));
6066
log("allowCollectibles", "" + getConfig().getBoolean("allowCollectibles"));
6167
log("conflictingEnchantments", "" + getConfig().getBoolean("conflictingEnchantments"));
6268
log("maxEnchantments", "" + getConfig().getBoolean("maxEnchantments"));
63-
log("shulkerBoxes", "" + getConfig().getBoolean("shulkerBoxes"));
64-
log("maxBooksInShulker", "" + getConfig().getInt("maxBooksInShulker"));
65-
log("maxBooksShulkersInInventory", "" + getConfig().getInt("maxBooksShulkersInInventory"));
69+
log("interactItems", "" + getConfig().getBoolean("interactItems", true));
70+
log("books.lecternCheck", "" + getConfig().getBoolean("books.lecternCheck", true));
71+
log("books.shulkerBoxes.enabled", "" + getConfig().getBoolean("books.shulkerBoxes.enabled", true));
72+
log("books.shulkerBoxes.maxBooksInside", "" + getConfig().getInt("books.shulkerBoxes.maxBooksInside", 10));
73+
log("books.shulkerBoxes.maxContainersPerInventory",
74+
"" + getConfig().getInt("books.shulkerBoxes.maxContainersPerInventory", 3));
75+
log("books.bundles.enabled", "" + getConfig().getBoolean("books.bundles.enabled", true));
76+
log("books.bundles.maxBooksInside", "" + getConfig().getInt("books.bundles.maxBooksInside", 10));
77+
log("books.bundles.maxContainersPerInventory",
78+
"" + getConfig().getInt("books.bundles.maxContainersPerInventory", 1));
6679
log("attributeModifiers", "" + getConfig().getBoolean("attributeModifiers"));
6780
log("customPotionEffects", "" + getConfig().getBoolean("customPotionEffects"));
68-
log("crossbowProjectiles", "" + getConfig().getBoolean("crossbowProjectiles"));
81+
log("crossbowProjectiles", "" + getConfig().getBoolean("crossbowProjectiles"));
6982
log("suspiciousStewEffects", "" + getConfig().getBoolean("suspiciousStewEffects"));
7083
log("hideFlags", "" + getConfig().getBoolean("hideFlags"));
7184

src/main/java/org/zeroBzeroT/antiillegals/Events.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,44 @@ public void onBlockBreak(@NotNull final BlockBreakEvent event) {
6464
.ifPresent(inventory -> RevertHelper.checkInventory(inventory, location, true));
6565
}
6666

67+
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
68+
public void onPlayerInteractUseItem(@NotNull final PlayerInteractEvent event) {
69+
if (!AntiIllegals.config().getBoolean("interactItems"))
70+
return;
71+
72+
if (event.getAction() == Action.PHYSICAL)
73+
return;
74+
75+
final Player player = event.getPlayer();
76+
final PlayerInventory inventory = player.getInventory();
77+
final Location location = player.getLocation();
78+
79+
final ItemStack mainHandStack = inventory.getItemInMainHand();
80+
final ItemStack offhandHandStack = inventory.getItemInOffHand();
81+
82+
boolean removedIllegal = false;
83+
84+
final ItemState mainState = RevertHelper.checkItemStack(mainHandStack, location, true);
85+
if (mainState == ItemState.ILLEGAL && mainHandStack != null)
86+
mainHandStack.setAmount(0);
87+
88+
final ItemState offState = RevertHelper.checkItemStack(offhandHandStack, location, true);
89+
if (offState == ItemState.ILLEGAL && offhandHandStack != null)
90+
offhandHandStack.setAmount(0);
91+
92+
removedIllegal = mainState == ItemState.ILLEGAL || offState == ItemState.ILLEGAL;
93+
94+
inventory.setItemInMainHand(mainHandStack);
95+
inventory.setItemInOffHand(offhandHandStack);
96+
97+
if (!removedIllegal)
98+
return;
99+
100+
event.setCancelled(true);
101+
AntiIllegals.log(event.getEventName(), "Removed illegal items from " + player.getName()
102+
+ " during interaction.");
103+
}
104+
67105
@EventHandler(ignoreCancelled = true)
68106
public void onPlayerInteractBlock(@NotNull final PlayerInteractEvent event) {
69107
if (event.getAction() != Action.RIGHT_CLICK_BLOCK)
@@ -86,6 +124,21 @@ public void onPlayerInteractBlock(@NotNull final PlayerInteractEvent event) {
86124
});
87125
}
88126

127+
@EventHandler(ignoreCancelled = true)
128+
public void onPlayerTakeLecternBook(@NotNull final PlayerTakeLecternBookEvent event) {
129+
if (!BookHelper.shouldCheckLecternBooks())
130+
return;
131+
132+
final ItemStack book = event.getBook();
133+
final Location location = event.getLectern().getLocation();
134+
135+
if (!RevertHelper.revert(book, location, true, ItemState::wasReverted))
136+
return;
137+
138+
AntiIllegals.log(event.getEventName(), "Reverted lectern book taken by "
139+
+ event.getPlayer().getName() + ".");
140+
}
141+
89142
@EventHandler(ignoreCancelled = true)
90143
public void onInventoryOpen(@NotNull final InventoryOpenEvent event) {
91144
final Inventory inventory = event.getInventory();

src/main/java/org/zeroBzeroT/antiillegals/helpers/BookHelper.java

Lines changed: 181 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.zeroBzeroT.antiillegals.helpers;
22

3+
import de.tr7zw.changeme.nbtapi.NBT;
4+
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
5+
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
36
import org.bukkit.Bukkit;
47
import org.bukkit.Location;
58
import org.bukkit.Material;
@@ -10,9 +13,9 @@
1013
import org.jetbrains.annotations.Nullable;
1114
import org.zeroBzeroT.antiillegals.AntiIllegals;
1215

13-
import java.util.Arrays;
14-
import java.util.Collection;
15-
import java.util.Objects;
16+
import java.util.*;
17+
import java.util.concurrent.atomic.AtomicBoolean;
18+
import java.util.concurrent.atomic.AtomicInteger;
1619
import java.util.stream.Stream;
1720

1821
public class BookHelper {
@@ -21,32 +24,84 @@ private BookHelper() {
2124

2225
}
2326

24-
public static int maxBookShulkers() {
25-
return AntiIllegals.config().getInt("maxBooksShulkersInInventory");
27+
private static boolean hasConfigValue(@NotNull final String path) {
28+
return AntiIllegals.config().isSet(path);
2629
}
2730

28-
public static int maxBookItemsInShulker() {
29-
return AntiIllegals.config().getInt("maxBooksInShulker");
31+
private static boolean getBoolean(@NotNull final String newPath, @Nullable final String legacyPath,
32+
final boolean defaultValue) {
33+
if (hasConfigValue(newPath))
34+
return AntiIllegals.config().getBoolean(newPath);
35+
if (legacyPath != null && hasConfigValue(legacyPath))
36+
return AntiIllegals.config().getBoolean(legacyPath);
37+
return defaultValue;
38+
}
39+
40+
private static int getInt(@NotNull final String newPath, @Nullable final String legacyPath,
41+
final int defaultValue) {
42+
if (hasConfigValue(newPath))
43+
return AntiIllegals.config().getInt(newPath);
44+
if (legacyPath != null && hasConfigValue(legacyPath))
45+
return AntiIllegals.config().getInt(legacyPath);
46+
return defaultValue;
47+
}
48+
49+
public static boolean shouldCheckLecternBooks() {
50+
return getBoolean("books.lecternCheck", null, true);
3051
}
3152

3253
public static boolean shouldCleanBookShulkers() {
33-
return AntiIllegals.config().getBoolean("shulkerBoxes");
54+
return getBoolean("books.shulkerBoxes.enabled", "shulkerBoxes", true);
55+
}
56+
57+
public static int maxBookItemsInShulker() {
58+
return getInt("books.shulkerBoxes.maxBooksInside", "maxBooksInShulker", 10);
59+
}
60+
61+
public static int maxBookShulkers() {
62+
return getInt("books.shulkerBoxes.maxContainersPerInventory", "maxBooksShulkersInInventory", 3);
63+
}
64+
65+
public static boolean shouldCleanBundleBooks() {
66+
return getBoolean("books.bundles.enabled", null, true);
3467
}
3568

36-
public static void dropBookShulkerItem(@NotNull final Location location, @NotNull final ItemStack itemStack) {
69+
public static int maxBooksInBundle() {
70+
return getInt("books.bundles.maxBooksInside", null, 10);
71+
}
72+
73+
public static int maxBookBundlesInInventory() {
74+
return getInt("books.bundles.maxContainersPerInventory", null, 1);
75+
}
76+
77+
public static void dropBookContainerItem(@NotNull final Location location, @NotNull final ItemStack itemStack) {
3778
location.getWorld().dropItem(location, itemStack).setPickupDelay(100);
3879
}
3980

4081
public static int cleanBookItems(@NotNull final Inventory inventory, @Nullable final Location location,
41-
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack) {
82+
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack) {
83+
if (!shouldCleanBookShulkers())
84+
return 0;
85+
4286
return cleanOversizedItems(inventory, location, shulkerWithBooksItemStack, maxBookItemsInShulker());
4387
}
4488

4589
public static int cleanBookShulkers(@NotNull final Inventory inventory, @Nullable final Location location,
46-
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack) {
90+
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack) {
91+
if (!shouldCleanBookShulkers())
92+
return 0;
93+
4794
return cleanOversizedItems(inventory, location, shulkerWithBooksItemStack, maxBookShulkers());
4895
}
4996

97+
public static int cleanBookBundles(@NotNull final Inventory inventory, @Nullable final Location location,
98+
@NotNull final Collection<ItemStack> bundleItemStacks) {
99+
if (!shouldCleanBundleBooks())
100+
return 0;
101+
102+
return cleanOversizedItems(inventory, location, bundleItemStacks, maxBookBundlesInInventory());
103+
}
104+
50105
public static boolean isBookItem(@NotNull final ItemStack itemStack) {
51106
return isBookItem(itemStack.getType());
52107
}
@@ -85,12 +140,14 @@ public static boolean containsBooks(@NotNull final Inventory inventory) {
85140
* @return whether it contains books
86141
*/
87142
public static boolean containsBooks(@Nullable final ItemStack itemStack) {
88-
if (itemStack == null) return false;
143+
if (itemStack == null)
144+
return false;
89145
return InventoryHolderHelper.mapInventory(itemStack, BookHelper::containsBooks).orElse(false);
90146
}
91147

92148
public static int cleanBookShulkers(@NotNull final Inventory inventory, @Nullable final Location location) {
93-
if (!shouldCleanBookShulkers()) return 0;
149+
if (!shouldCleanBookShulkers())
150+
return 0;
94151

95152
final Collection<ItemStack> shulkersWithBooks = Arrays.stream(inventory.getContents())
96153
.filter(BookHelper::containsBooks)
@@ -99,32 +156,134 @@ public static int cleanBookShulkers(@NotNull final Inventory inventory, @Nullabl
99156
return BookHelper.cleanBookShulkers(inventory, location, shulkersWithBooks);
100157
}
101158

159+
public static boolean bundleContainsBooks(@NotNull final ItemStack itemStack) {
160+
if (!shouldCleanBundleBooks() || itemStack.getType() != Material.BUNDLE)
161+
return false;
162+
163+
final AtomicBoolean containsBooks = new AtomicBoolean(false);
164+
165+
NBT.modify(itemStack, nbtItem -> {
166+
final ReadWriteNBTCompoundList items = nbtItem.getCompoundList("Items");
167+
if (items == null)
168+
return;
169+
170+
for (final ReadWriteNBT entry : items) {
171+
if (entry == null)
172+
continue;
173+
174+
final ItemStack stored = NBT.itemStackFromNBT(entry);
175+
if (stored == null)
176+
continue;
177+
178+
if (!isBookItem(stored))
179+
continue;
180+
181+
containsBooks.set(true);
182+
break;
183+
}
184+
});
185+
186+
return containsBooks.get();
187+
}
188+
189+
public static int trimBundleBooks(@NotNull final Collection<ItemStack> bundleItemStacks,
190+
@Nullable final Location location) {
191+
if (!shouldCleanBundleBooks() || location == null || bundleItemStacks.isEmpty())
192+
return 0;
193+
194+
final int maxBooks = maxBooksInBundle();
195+
if (maxBooks < 0)
196+
return 0;
197+
198+
int removed = 0;
199+
for (final ItemStack bundle : bundleItemStacks) {
200+
removed += trimBooksFromBundle(bundle, location, maxBooks);
201+
}
202+
return removed;
203+
}
204+
205+
private static int trimBooksFromBundle(@NotNull final ItemStack bundle, @NotNull final Location location,
206+
final int maxBooks) {
207+
final AtomicInteger removed = new AtomicInteger(0);
208+
209+
NBT.modify(bundle, nbtItem -> {
210+
final ReadWriteNBTCompoundList items = nbtItem.getCompoundList("Items");
211+
if (items == null || items.isEmpty())
212+
return;
213+
214+
int seenBooks = 0;
215+
final List<Integer> removalIndexes = new ArrayList<>();
216+
final List<ItemStack> droppedBooks = new ArrayList<>();
217+
218+
for (int i = 0; i < items.size(); i++) {
219+
final ReadWriteNBT entry = items.get(i);
220+
if (entry == null)
221+
continue;
222+
223+
final ItemStack stored = NBT.itemStackFromNBT(entry);
224+
if (stored == null || !isBookItem(stored))
225+
continue;
226+
227+
if (seenBooks < maxBooks) {
228+
seenBooks++;
229+
continue;
230+
}
231+
232+
removalIndexes.add(i);
233+
droppedBooks.add(stored);
234+
}
235+
236+
if (removalIndexes.isEmpty())
237+
return;
238+
239+
removalIndexes.sort(Integer::compareTo);
240+
Collections.reverse(removalIndexes);
241+
removalIndexes.forEach(items::remove);
242+
243+
removed.addAndGet(droppedBooks.size());
244+
if (location.getWorld() != null)
245+
droppedBooks.forEach(stack -> dropBookContainerItem(location, stack));
246+
});
247+
248+
return removed.get();
249+
}
250+
102251
public static int cleanOversizedItems(@NotNull final Inventory inventory, @Nullable final Location location,
103-
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack,
104-
final int maxItems) {
105-
if (location == null || maxItems < 0 || shulkerWithBooksItemStack.size() <= maxItems) return 0;
252+
@NotNull final Collection<ItemStack> shulkerWithBooksItemStack,
253+
final int maxItems) {
254+
if (location == null || maxItems < 0 || shulkerWithBooksItemStack.size() <= maxItems)
255+
return 0;
106256

107257
int counter = 0;
108258

109259
for (final ItemStack shulkerItemStack : shulkerWithBooksItemStack) {
110260
inventory.remove(shulkerItemStack);
111-
Bukkit.getScheduler().runTask(AntiIllegals.INSTANCE, () -> dropBookShulkerItem(location, shulkerItemStack));
261+
Bukkit.getScheduler().runTask(AntiIllegals.INSTANCE,
262+
() -> dropBookContainerItem(location, shulkerItemStack));
112263
counter++;
113264
}
114265
return counter;
115266
}
116267

117268
public static void checkEnderChest(@NotNull final InventoryOpenEvent inventoryOpenEvent,
118-
@Nullable final Location location) {
269+
@Nullable final Location location) {
119270
final Inventory inventory = inventoryOpenEvent.getInventory();
120271
final ItemStack[] inventoryContents = inventory.getContents();
121272

122273
for (final ItemStack itemStack : inventoryContents) {
123-
if (itemStack == null) continue;
274+
if (itemStack == null)
275+
continue;
124276

125-
InventoryHolderHelper.iterateInventory(itemStack, inv ->
126-
BookHelper.cleanBookItems(inv, location, BookHelper.filterBooks(inv).toList())
127-
);
277+
InventoryHolderHelper.iterateInventory(itemStack,
278+
inv -> BookHelper.cleanBookItems(inv, location, BookHelper.filterBooks(inv).toList()));
128279
}
280+
281+
final List<ItemStack> bundlesWithBooks = Arrays.stream(inventoryContents)
282+
.filter(Objects::nonNull)
283+
.filter(BookHelper::bundleContainsBooks)
284+
.toList();
285+
286+
BookHelper.cleanBookBundles(inventory, location, bundlesWithBooks);
287+
BookHelper.trimBundleBooks(bundlesWithBooks, location);
129288
}
130289
}

0 commit comments

Comments
 (0)