adding an NBT GUI.

This commit is contained in:
2025-03-17 16:44:24 -05:00
parent 2a27af00d1
commit e3fec82a4c
38 changed files with 685 additions and 103 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -6,6 +6,7 @@ import me.trouper.sentinel.data.config.*;
import me.trouper.sentinel.data.config.lang.LanguageFile;
import me.trouper.sentinel.data.storage.ExtraStorage;
import me.trouper.sentinel.data.storage.CommandBlockStorage;
import me.trouper.sentinel.data.storage.NBTStorage;
import java.io.File;
@@ -20,6 +21,7 @@ public class IO {
private final File advcfg = new File(dataFolder, "/advanced-config.json");
private final File cmdWhitelist = new File(dataFolder, "/storage/whitelist.json");
private final File extraFile = new File(dataFolder, "/storage/extra.json");
private final File nbtFile = new File(dataFolder,"/storage/nbt.json");
public LanguageFile lang;
public ViolationConfig violationConfig = JsonSerializable.load(violationcfg, ViolationConfig.class, new ViolationConfig());
@@ -31,6 +33,7 @@ public class IO {
public StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig());
public NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig());
public AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig());
public NBTStorage nbtStorage = JsonSerializable.load(nbtFile, NBTStorage.class, new NBTStorage());
public void loadConfig() {
// Init
@@ -41,6 +44,7 @@ public class IO {
swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig());
nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig());
violationConfig = JsonSerializable.load(violationcfg,ViolationConfig.class,new ViolationConfig());
// Save
mainConfig.save();
@@ -50,11 +54,17 @@ public class IO {
swearConfig.save();
nbtConfig.save();
violationConfig.save();
// Storage
commandBlocks = JsonSerializable.load(cmdWhitelist, CommandBlockStorage.class, new CommandBlockStorage());
extraStorage = JsonSerializable.load(extraFile, ExtraStorage.class, new ExtraStorage());
nbtStorage = JsonSerializable.load(nbtFile,NBTStorage.class,new NBTStorage());
commandBlocks.save();
extraStorage.save();
nbtStorage.save();
Sentinel.getInstance().getLogger().info("Loading Dictionary (%s)...".formatted(mainConfig.plugin.lang));

View File

@@ -0,0 +1,46 @@
package me.trouper.sentinel.data.storage;
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
import me.trouper.sentinel.Sentinel;
import org.bukkit.inventory.ItemStack;
import java.io.*;
import java.util.*;
public class NBTStorage implements JsonSerializable<NBTStorage> {
@Override
public File getFile() {
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/storage/nbt.json");
file.getParentFile().mkdirs();
return file;
}
public Map<String, String> caughtItems = new HashMap<>();
public static ItemStack toItem(String data) {
try {
byte[] bytes = Base64.getDecoder().decode(data);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
ItemStack item = (ItemStack) objectInputStream.readObject();
objectInputStream.close();
return item;
} catch (IOException | ClassNotFoundException e) {
Sentinel.getInstance().getLogger().warning("Could not deserialize ItemStack: " + e.getMessage());
return null;
}
}
public static String toB64(ItemStack item) {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(item);
objectOutputStream.close();
return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
Sentinel.getInstance().getLogger().warning("Could not serialize ItemStack: " + e.getMessage());
return null;
}
}
}

View File

@@ -8,10 +8,7 @@ import me.trouper.sentinel.utils.DisplayUtils;
import me.trouper.sentinel.utils.ServerUtils;
import me.trouper.sentinel.utils.Text;
import me.trouper.sentinel.utils.display.BlockDisplayRaytracer;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.CommandBlock;
@@ -288,8 +285,11 @@ public class CommandBlockHolder {
}
if (!preLoaded) where.getChunk().unload();
}
if (changesMade) updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
if (changesMade) {
updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
updater.playSound(updater.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING,1,1.5F);
}
return changesMade;
}
@@ -313,7 +313,10 @@ public class CommandBlockHolder {
}
if (changesMade) updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
if (changesMade) {
updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
updater.playSound(updater.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING,1,1.5F);
}
return changesMade;
}
@@ -360,7 +363,10 @@ public class CommandBlockHolder {
changesMade = true;
}
if (changesMade) updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
if (changesMade) {
updater.sendMessage(Text.prefix("Successfully updated a &b%s&7.".formatted(Text.cleanName(this.type()))));
updater.playSound(updater.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING,1,1.5F);
}
return changesMade;
}
}

View File

@@ -45,7 +45,7 @@ public class CommandBlockBreak extends AbstractViolation{
if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockBreak.enabled) {
ServerUtils.verbose("Not enabled, deletion allowed.");
holder.delete();
if (!holder.isWhitelisted()) holder.delete();
return;
}

View File

@@ -48,7 +48,7 @@ public class CommandMinecartBreak extends AbstractViolation {
if (!Sentinel.getInstance().getDirector().io.violationConfig.commandBlockMinecartBreak.enabled) {
ServerUtils.verbose("Not enabled, deletion allowed.");
holder.delete();
if (!holder.isWhitelisted()) holder.delete();
return;
}

View File

@@ -2,6 +2,7 @@ package me.trouper.sentinel.server.events.violations.players;
import io.github.itzispyder.pdk.plugin.gui.CustomGui;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.data.storage.NBTStorage;
import me.trouper.sentinel.server.events.violations.AbstractViolation;
import me.trouper.sentinel.server.functions.helpers.ActionConfiguration;
import me.trouper.sentinel.server.functions.itemchecks.ItemCheck;
@@ -42,6 +43,9 @@ public class CreativeHotbar extends AbstractViolation {
if (new ItemCheck().passes(i)) return;
ServerUtils.verbose("NBT: Item doesn't pass, performing action");
Sentinel.getInstance().getDirector().io.nbtStorage.caughtItems.put(NBTStorage.toB64(i),p.getUniqueId().toString());
Sentinel.getInstance().getDirector().io.nbtStorage.save();
ActionConfiguration.Builder config = new ActionConfiguration.Builder()
.setEvent(e)
.setPlayer(p)

View File

@@ -82,9 +82,16 @@ public class Items {
.enchant(Enchantment.PROTECTION, 64)
.flag(ItemFlag.HIDE_ENCHANTS)
.build();
public static final ItemStack NBT = ItemBuilder.create()
.material(Material.HONEY_BOTTLE)
.name(Text.color("&aNBT Honeypot"))
.lore(Text.color("&8&l➥&7 View caught NBT"))
.enchant(Enchantment.PROTECTION, 64)
.flag(ItemFlag.HIDE_ENCHANTS)
.build();
public static ItemStack configItem(String valueName, Material material, String description) {
ServerUtils.verbose("Items#configItem: Creating a config item:\n Value Name -> %s\nMaterial in use -> %s".formatted(valueName,material.toString()));
ServerUtils.verbose("Creating a config item:\n Value Name -> %s\nMaterial in use -> %s".formatted(valueName,material.toString()));
List<String> desc = Arrays.stream(description.split("\n")).toList();

View File

@@ -3,6 +3,8 @@ package me.trouper.sentinel.server.gui;
import io.github.itzispyder.pdk.plugin.gui.CustomGui;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.server.gui.config.ConfigGUI;
import me.trouper.sentinel.server.gui.nbt.NBTGui;
import me.trouper.sentinel.server.gui.whitelist.NewWhitelistGUI;
import me.trouper.sentinel.server.gui.whitelist.WhitelistGUI;
import me.trouper.sentinel.utils.PlayerUtils;
import me.trouper.sentinel.utils.Text;
@@ -23,13 +25,17 @@ public class MainGUI {
.size(27)
.onDefine(this::blankPage)
.defineMain(this::mainClick)
.define(11,Items.CREDITS)
.define(13,Items.WHITELIST,this::openWhitelist)
.define(15,Items.CONFIG,this::openConfig)
.define(10,Items.CREDITS)
.define(12,Items.WHITELIST,this::openWhitelist)
.define(14,Items.NBT,this::openNBT)
.define(16,Items.CONFIG,this::openConfig)
.build();
private void openWhitelist(InventoryClickEvent e) {
e.getWhoClicked().openInventory(new WhitelistGUI().createGUI((Player) e.getWhoClicked()).getInventory());
e.getWhoClicked().openInventory(new NewWhitelistGUI().createGUI((Player) e.getWhoClicked()).getInventory());
}
private void openNBT(InventoryClickEvent e) {
e.getWhoClicked().openInventory(new NBTGui().createGUI((Player) e.getWhoClicked()).getInventory());
}
private void openConfig(InventoryClickEvent e) {

View File

@@ -0,0 +1,158 @@
package me.trouper.sentinel.server.gui;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.plugin.gui.CustomGui;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.data.types.CommandBlockHolder;
import me.trouper.sentinel.utils.ServerUtils;
import me.trouper.sentinel.utils.Text;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.*;
public abstract class PaginatedGUI<T> {
protected static final int ITEMS_PER_PAGE = 45;
protected static final Map<UUID, Integer> currentPages = new HashMap<>();
protected static final Map<UUID, Set<String>> activeFilters = new HashMap<>();
protected static final Map<UUID, FilterOperator> chosenOperator = new HashMap<>();
public CustomGui createGUI(Player p) {
ServerUtils.verbose("Creating GUI for player: %s", p.getName());
int page = currentPages.compute(p.getUniqueId(), (k, v) -> realizePage(p, v == null ? 0 : v));
return CustomGui.create()
.title(getTitle(p))
.size(54)
.onDefine(inv -> setupPage(p, inv))
.defineMain(e -> handleMainClick(p, e))
.define(45, createNavigationItem("Previous", page - 1), e -> changePage(p, -1))
.define(49, createFilterItem(p), e -> openFilterMenu(p))
.define(53, createNavigationItem("Next", page + 1), e -> changePage(p, 1))
.build();
}
protected abstract String getTitle(Player p);
protected void setupPage(Player p, Inventory inv) {
ServerUtils.verbose("Setting up page for player: %s", p.getName());
int page = currentPages.compute(p.getUniqueId(), (k, v) -> realizePage(p, v == null ? 0 : v));
List<T> filtered = filterEntries(p, chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND));
ServerUtils.verbose("Current page: %d, Total entries: %d", page, filtered.size());
// Clear previous items
for (int i = 0; i < ITEMS_PER_PAGE; i++) {
inv.setItem(i, null);
}
// Add paginated items
for (int i = page * ITEMS_PER_PAGE; i < (page + 1) * ITEMS_PER_PAGE && i < filtered.size(); i++) {
T item = filtered.get(i);
inv.setItem(i % ITEMS_PER_PAGE, createDisplayItem(item));
}
// Add persistent bottom items
inv.setItem(45, createNavigationItem("Previous", realizePage(p, page - 1)));
inv.setItem(49, createFilterItem(p));
inv.setItem(53, createNavigationItem("Next", realizePage(p, page + 1)));
}
protected abstract void handleMainClick(Player p, InventoryClickEvent e);
protected abstract ItemStack createDisplayItem(T item);
protected void openFilterMenu(Player p) {
ServerUtils.verbose("Creating filter menu for %s", p);
Set<String> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
CustomGui.GuiBuilder filterGui = CustomGui.create()
.title(Text.color("&6&lFilters"))
.size(27)
.defineMain(e -> e.setCancelled(true))
.define(26, Items.BACK, e -> {
p.playSound(p.getLocation(), Sound.ITEM_BOOK_PAGE_TURN, 1, 0.8F);
p.openInventory(createGUI(p).getInventory());
});
addFilterItems(filterGui, p, filters);
p.openInventory(filterGui.build().getInventory());
}
protected abstract void addFilterItems(CustomGui.GuiBuilder filterGui, Player p, Set<String> filters);
protected void toggleFilter(Player p, String filter) {
Set<String> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
ServerUtils.verbose("%s is now toggling the %s filter. Current %s", p, filter, filters);
if (filters.contains(filter)) filters.remove(filter);
else filters.add(filter);
ServerUtils.verbose("Current filters for %s: %s", p, filters);
openFilterMenu(p);
}
protected int getFilterCount(Player p) {
return activeFilters.getOrDefault(p.getUniqueId(), new HashSet<>()).size();
}
protected void changePage(Player p, int direction) {
int current = currentPages.getOrDefault(p.getUniqueId(), 0);
int newPage = realizePage(p, current + direction);
currentPages.put(p.getUniqueId(), newPage);
p.openInventory(createGUI(p).getInventory());
}
protected int realizePage(Player p, int requested) {
int validRequested = Math.max(0, requested);
int totalEntries = filterEntries(p, chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND)).size();
int maxPages = Math.max(0, Math.ceilDiv(totalEntries, ITEMS_PER_PAGE) - 1);
return Math.min(validRequested, maxPages);
}
private ItemStack createNavigationItem(String direction, int pageTo) {
return new ItemBuilder()
.material(Material.ARROW)
.name(Text.color("&b" + direction + "&7 Page"))
.lore(Text.color("&7 > &b" + pageTo))
.build();
}
private ItemStack createFilterItem(Player p) {
List<String> operatorList = new ArrayList<>();
FilterOperator chosen = chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND);
for (FilterOperator value : FilterOperator.values()) {
if (value.equals(chosen)) operatorList.add(Text.color("&b&n" + value.name()));
else operatorList.add(Text.color("&b" + value.name()));
}
return new ItemBuilder()
.material(Material.HOPPER)
.name(Text.color("&6&lFilters"))
.lore(Text.color("&7Filters Selected: &e" + getFilterCount(p)))
.lore(Text.color("&7Shift-Click to cycle filter operator."))
.lore(Text.color("&7Operator: "))
.lore(operatorList)
.build();
}
protected abstract List<T> filterEntries(Player p, FilterOperator operator);
public enum FilterOperator {
AND, // All conditions must be met
OR, // At least one condition must be met
NAND, // At least one condition must NOT be met
XOR; // Exactly one condition must be met
public boolean apply(boolean currentValue, boolean newCondition) {
return switch (this) {
case AND -> currentValue & newCondition;
case OR -> currentValue | newCondition;
case NAND -> !(currentValue & newCondition);
case XOR -> currentValue ^ newCondition;
};
}
}
}

View File

@@ -0,0 +1,104 @@
package me.trouper.sentinel.server.gui.nbt;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.plugin.gui.CustomGui;
import io.github.itzispyder.pdk.utils.misc.Pair;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.data.storage.NBTStorage;
import me.trouper.sentinel.server.gui.PaginatedGUI;
import me.trouper.sentinel.utils.ServerUtils;
import me.trouper.sentinel.utils.Text;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.stream.Collectors;
public class NBTGui extends PaginatedGUI<Map.Entry<String,String>> {
private final NBTStorage nbtStorage;
public NBTGui() {
this.nbtStorage = Sentinel.getInstance().getDirector().io.nbtStorage;
}
@Override
protected String getTitle(Player p) {
return Text.color("&6&lItem Ownership &7(" + getFilterCount(p) + " items)");
}
@Override
protected void handleMainClick(Player p, InventoryClickEvent e) {
int slot = e.getSlot();
if (slot >= 45) return;
if (e.getInventory().getItem(slot) == null) return;
int page = currentPages.compute(p.getUniqueId(), (k, v) -> realizePage(p, v == null ? 0 : v));
List<Map.Entry<String, String>> filtered = filterEntries(p, chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND));
int index = page * ITEMS_PER_PAGE + slot;
if (index < filtered.size()) {
Map.Entry<String, String> entry = filtered.get(index);
ItemStack item = NBTStorage.toItem(entry.getKey());
if (item != null) {
if (e.isLeftClick()) {
p.getInventory().addItem(item);
p.playSound(p.getLocation(), Sound.ENTITY_ITEM_PICKUP, 1, 1F);
} else if (e.isRightClick()) {
nbtStorage.caughtItems.remove(entry.getKey());
p.playSound(p.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1, 2F);
p.openInventory(createGUI(p).getInventory());
}
}
}
}
@Override
protected ItemStack createDisplayItem(Map.Entry<String, String> entry) {
ItemStack item = NBTStorage.toItem(entry.getKey());
if (item == null) return null;
List<String> lore = new ArrayList<>();
lore.add(Text.color("&7Owner: " + Bukkit.getOfflinePlayer(UUID.fromString(entry.getValue())).getName()));
lore.add("");
lore.add(Text.color("&eLeft-Click to give item"));
lore.add(Text.color("&eRight-Click to delete item"));
return new ItemBuilder()
.material(item.getType())
.name(Text.color("&b" + item.getType().name()))
.lore(lore)
.build();
}
@Override
protected void addFilterItems(CustomGui.GuiBuilder filterGui, Player p, Set<String> filters) {
// Add any specific filter items here if needed
}
@Override
protected List<Map.Entry<String, String>> filterEntries(Player p, FilterOperator operator) {
Set<String> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
ServerUtils.verbose("Filtering entries for %s. Current: ", p, filters.toString());
return nbtStorage.caughtItems.entrySet().stream()
.filter(entry -> {
if (filters.isEmpty()) return true;
boolean result = (operator == FilterOperator.AND); // AND starts true, OR starts false
for (String filter : filters) {
boolean conditionMet = switch (filter) {
case "OWNER" -> entry.getValue().equals(p.getUniqueId().toString());
default -> false;
};
result = operator.apply(result, conditionMet);
// Early exit for AND (false means no need to check further)
if (operator == FilterOperator.AND && !result) return false;
// Early exit for OR (true means we already pass)
if (operator == FilterOperator.OR && result) return true;
}
return result;
})
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,219 @@
package me.trouper.sentinel.server.gui.whitelist;
import io.github.itzispyder.pdk.commands.Args;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.plugin.gui.CustomGui;
import io.github.itzispyder.pdk.utils.misc.config.ConfigUpdater;
import io.papermc.paper.event.player.AsyncChatEvent;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.data.config.ViolationConfig;
import me.trouper.sentinel.data.types.CommandBlockHolder;
import me.trouper.sentinel.server.gui.Items;
import me.trouper.sentinel.server.gui.MainGUI;
import me.trouper.sentinel.server.gui.PaginatedGUI;
import me.trouper.sentinel.utils.ServerUtils;
import me.trouper.sentinel.utils.Text;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
public class NewWhitelistGUI extends PaginatedGUI<CommandBlockHolder> {
@Override
protected String getTitle(Player p) {
return Text.color("&6&lCommand Blocks &7(" + getFilterCount(p) + " filters)");
}
@Override
protected void handleMainClick(Player p, InventoryClickEvent e) {
int slot = e.getSlot();
if (slot >= 45) return;
if (e.getInventory().getItem(slot) == null) return;
int page = currentPages.compute(p.getUniqueId(), (k, v) -> realizePage(p, v == null ? 0 : v));
List<CommandBlockHolder> filtered = filterEntries(p, chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND));
int index = page * ITEMS_PER_PAGE + slot;
if (index < filtered.size()) {
CommandBlockHolder holder = filtered.get(index);
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1, 0.8F);
openManagementMenu(p, holder);
}
}
@Override
protected ItemStack createDisplayItem(CommandBlockHolder holder) {
Material type = holder.getType();
String name = holder.isCart() ?
"Minecart: " + holder.loc().toUIID() :
String.format("X: %d, Y: %d, Z: %d",
(int) holder.loc().x(),
(int) holder.loc().y(),
(int) holder.loc().z());
List<String> lore = new ArrayList<>();
lore.add(Text.color("&7Owner: " + Bukkit.getOfflinePlayer(holder.owner()).getName()));
lore.add(Text.color("&7Command: &f" + holder.command()));
lore.add(Text.color("&7Type: &f" + holder.type()));
lore.add(Text.color("&7Whitelisted: " + (holder.isWhitelisted() ? "&aYes" : "&cNo")));
lore.add(Text.color("&7Present: " + (holder.present() ? "&aYes" : "&cNo")));
lore.add("");
lore.add(Text.color("&eClick to manage!"));
return new ItemBuilder()
.material(type)
.name(Text.color("&b" + name))
.lore(lore)
.build();
}
@Override
protected void addFilterItems(CustomGui.GuiBuilder filterGui, Player p, Set<String> filters) {
filterGui.define(0, createFilterToggleItem("Your Blocks", Material.PLAYER_HEAD, filters.contains("OWNER")), e -> toggleFilter(p, "OWNER"));
filterGui.define(1, createFilterToggleItem("Other Owners", Material.SPYGLASS, filters.contains("OTHER_OWNERS")), e -> toggleFilter(p, "OTHER_OWNERS"));
filterGui.define(2, createFilterToggleItem("Current World", Material.TARGET, filters.contains("CURRENT_WORLD")), e -> toggleFilter(p, "CURRENT_WORLD"));
filterGui.define(3, createFilterToggleItem("Whitelisted Blocks", Material.PAPER, filters.contains("WHITELISTED")), e -> toggleFilter(p, "WHITELISTED"));
filterGui.define(4, createFilterToggleItem("Not Whitelisted Only", Material.BARRIER, filters.contains("NOT_WHITELISTED")), e -> toggleFilter(p, "NOT_WHITELISTED"));
filterGui.define(5, createFilterToggleItem("Missing Command Blocks", Material.GLASS, filters.contains("NOT_PRESENT")), e -> toggleFilter(p, "NOT_PRESENT"));
filterGui.define(6, createFilterToggleItem("Repeating Command Blocks", Material.REPEATING_COMMAND_BLOCK, filters.contains("REPEAT")), e -> toggleFilter(p, "REPEAT"));
filterGui.define(7, createFilterToggleItem("Chain Command Blocks", Material.CHAIN_COMMAND_BLOCK, filters.contains("CHAIN")), e -> toggleFilter(p, "CHAIN"));
filterGui.define(8, createFilterToggleItem("Impulse Command Blocks", Material.COMMAND_BLOCK, filters.contains("IMPULSE")), e -> toggleFilter(p, "IMPULSE"));
filterGui.define(9, createFilterToggleItem("Minecart Commands", Material.COMMAND_BLOCK_MINECART, filters.contains("MINECART")), e -> toggleFilter(p, "MINECART"));
}
@Override
protected List<CommandBlockHolder> filterEntries(Player p, FilterOperator operator) {
Set<String> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
ServerUtils.verbose("Filtering entries for %s. Current: ", p, filters.toString());
return Sentinel.getInstance().getDirector().io.commandBlocks.holders.stream()
.filter(holder -> {
if (filters.isEmpty()) return true;
boolean result = (operator == FilterOperator.AND); // AND starts true, OR starts false
for (String filter : filters) {
boolean conditionMet = switch (filter) {
case "OWNER" -> holder.owner().equals(p.getUniqueId().toString());
case "CURRENT_WORLD" -> holder.loc().world().equals(p.getWorld().getName());
case "OTHER_OWNERS" -> !holder.owner().equals(p.getUniqueId().toString());
case "MINECART" -> holder.getType().equals(Material.COMMAND_BLOCK_MINECART);
case "REPEAT" -> holder.getType().equals(Material.REPEATING_COMMAND_BLOCK);
case "CHAIN" -> holder.getType().equals(Material.CHAIN_COMMAND_BLOCK);
case "IMPULSE" -> holder.getType().equals(Material.COMMAND_BLOCK);
case "WHITELISTED" -> holder.isWhitelisted();
case "NOT_WHITELISTED" -> !holder.isWhitelisted();
case "NOT_PRESENT" -> !holder.present();
default -> false;
};
result = operator.apply(result, conditionMet);
// Early exit for AND (false means no need to check further)
if (operator == FilterOperator.AND && !result) return false;
// Early exit for OR (true means we already pass)
if (operator == FilterOperator.OR && result) return true;
}
return result;
})
.collect(Collectors.toList());
}
private void openManagementMenu(Player p, CommandBlockHolder holder) {
ServerUtils.verbose("Opening management menu for %s", holder.owner());
boolean whitelisted = holder.isWhitelisted();
CustomGui menu = CustomGui.create()
.title(Text.color("&l ⬇ &6&lManaging Command Block"))
.size(9)
.defineMain(e -> e.setCancelled(true))
.define(0, createDisplayItem(holder))
.define(2, createActionItem(whitelisted ? "Un-Whitelist" : "Whitelist", whitelisted ? Material.BARRIER : Material.PAPER), e -> {
holder.setWhitelisted(!whitelisted);
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1, 1F);
openManagementMenu(p, holder);
})
.define(3, createActionItem("Teleport", Material.ENDER_PEARL), e -> {
if (holder.loc().isUUID()) {
// Handle minecart teleport
Entity entity = Bukkit.getEntity(holder.loc().toUIID());
if (entity == null) {
e.getInventory().setItem(e.getSlot(), new ItemBuilder()
.material(Material.BARRIER)
.name("&cTeleport Unavailable")
.lore("&7This entity is not loaded.")
.build());
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1, 1F);
return;
}
p.teleport(entity.getLocation());
} else {
p.teleport(holder.loc().translate());
}
p.playSound(p.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1, 0.5F);
p.closeInventory();
})
.define(4, createActionItem("Restore", Material.DISPENSER), e -> {
holder.restore();
p.openInventory(createGUI(p).getInventory());
p.playSound(p.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_RESONATE, 1, 1F);
})
.define(5, createActionItem("Destroy (Shift-Click)", Material.NETHERITE_PICKAXE), e -> {
if (!e.isShiftClick()) return;
holder.destroy();
p.playSound(p.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1, 2F);
p.openInventory(createGUI(p).getInventory());
})
.define(6, createActionItem("Take Ownership", Material.NAME_TAG), e -> {
holder.setOwner(p.getUniqueId().toString());
p.playSound(p.getLocation(), Sound.ENTITY_VILLAGER_TRADE, 1, 1F);
openManagementMenu(p, holder);
})
.define(8, Items.BACK, e -> {
p.playSound(p.getLocation(), Sound.ITEM_BOOK_PAGE_TURN, 1, 0.8F);
p.openInventory(createGUI(p).getInventory());
})
.build();
p.openInventory(menu.getInventory());
}
private ItemStack createActionItem(String name, Material mat) {
return new ItemBuilder()
.material(mat)
.name(Text.color("&b" + name))
.lore(Text.color("&7Click to " + name.toLowerCase()))
.build();
}
private ItemStack createFilterToggleItem(String name, Material mat, boolean active) {
return new ItemBuilder()
.material(mat)
.name(Text.color((active ? "&a" : "&c") + name))
.lore(Text.color("&7Click to " + (active ? "disable" : "enable")))
.build();
}
public static ConfigUpdater<AsyncChatEvent, ViolationConfig> updater = new ConfigUpdater<>(Sentinel.getInstance().getDirector().io.violationConfig);
protected void queuePlayer(Player player, BiConsumer<ViolationConfig, Args> action, String currentValue) {
MainGUI.awaitingCallback.add(player.getUniqueId());
player.closeInventory();
updater.queuePlayer(player, 20*60, (e)->{
e.setCancelled(true);
return LegacyComponentSerializer.legacySection().serialize(e.message());
}, (cfg, newValue) -> {
action.accept(cfg,new Args(newValue.split("\\s+")));
cfg.save();
player.sendMessage(Text.prefix("Value updated successfully"));
player.openInventory(getConfigGui().getInventory());
});
player.sendMessage(Component.text(Text.prefix("Enter the new value in chat. The value is currently set to &b%s&7. (Click to insert)".formatted(currentValue))).clickEvent(ClickEvent.suggestCommand(currentValue)));
}
}

View File

@@ -24,44 +24,45 @@ public class WhitelistGUI {
private static final Map<UUID, Integer> currentPages = new HashMap<>();
private static final Map<UUID, Set<Filter>> activeFilters = new HashMap<>();
private static final Map<UUID, FilterOperator> chosenOperator = new HashMap<>();
private static final Map<UUID, String> chosenPlayer = new HashMap<>();
public CustomGui createGUI(Player player) {
ServerUtils.verbose("Creating GUI for player: %s", player.getName());
int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v))));
public CustomGui createGUI(Player p) {
ServerUtils.verbose("Creating GUI for player: %s", p.getName());
int page = currentPages.compute(p.getUniqueId(), (k,v) -> realizePage(p,realizePage(p,(v == null ? 0 : v))));
return CustomGui.create()
.title(Text.color("&6&lCommand Blocks &7(" + getFilterCount(player) + " filters)"))
.title(Text.color("&6&lCommand Blocks &7(" + getFilterCount(p) + " filters)"))
.size(54)
.onDefine(inv -> setupPage(player, inv))
.onDefine(inv -> setupPage(p, inv))
.defineMain(e -> {
e.setCancelled(true);
handleMainClick(player, e);
handleMainClick(p, e);
})
.define(45, createNavigationItem("Previous",page - 1), e -> {
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,0.9F);
changePage(player, -1);
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,0.9F);
changePage(p, -1);
})
.define(49, createFilterItem(player), e -> {
.define(49, createFilterItem(p), e -> {
if (e.isShiftClick()) {
FilterOperator op = chosenOperator.computeIfAbsent(player.getUniqueId(),v-> FilterOperator.AND);
FilterOperator op = chosenOperator.computeIfAbsent(p.getUniqueId(),v-> FilterOperator.AND);
FilterOperator[] values = FilterOperator.values();
chosenOperator.put(player.getUniqueId(),values[(op.ordinal() + 1) % values.length]);
e.getClickedInventory().setItem(e.getSlot(),createFilterItem(player));
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.3F);
chosenOperator.put(p.getUniqueId(),values[(op.ordinal() + 1) % values.length]);
e.getClickedInventory().setItem(e.getSlot(),createFilterItem(p));
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.3F);
return;
}
openFilterMenu(player);
openFilterMenu(p);
})
.define(53, createNavigationItem("Next",page + 1), e -> {
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.1F);
changePage(player, 1);
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_HAT,1,1.1F);
changePage(p, 1);
})
.build();
}
private void setupPage(Player player, Inventory inv) {
ServerUtils.verbose("Setting up page for player: %s", player.getName());
int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v))));
List<CommandBlockHolder> filtered = filterEntries(player,chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND));
private void setupPage(Player p, Inventory inv) {
ServerUtils.verbose("Setting up page for player: %s", p.getName());
int page = currentPages.compute(p.getUniqueId(), (k,v) -> realizePage(p,realizePage(p,(v == null ? 0 : v))));
List<CommandBlockHolder> filtered = filterEntries(p,chosenOperator.computeIfAbsent(p.getUniqueId(),v->FilterOperator.AND));
ServerUtils.verbose("Current page: %d, Total entries: %d", page, filtered.size());
// Clear previous items
@@ -76,24 +77,24 @@ public class WhitelistGUI {
}
// Add persistent bottom items
inv.setItem(45, createNavigationItem("Previous",realizePage(player, page - 1)));
inv.setItem(49, createFilterItem(player));
inv.setItem(53, createNavigationItem("Next", realizePage(player,page + 1)));
inv.setItem(45, createNavigationItem("Previous",realizePage(p, page - 1)));
inv.setItem(49, createFilterItem(p));
inv.setItem(53, createNavigationItem("Next", realizePage(p,page + 1)));
}
private void handleMainClick(Player player, InventoryClickEvent e) {
private void handleMainClick(Player p, InventoryClickEvent e) {
int slot = e.getSlot();
if (slot >= 45) return;
if (e.getInventory().getItem(slot) == null) return;
int page = currentPages.compute(player.getUniqueId(), (k,v) -> realizePage(player,realizePage(player,(v == null ? 0 : v))));
List<CommandBlockHolder> filtered = filterEntries(player,chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND));
int page = currentPages.compute(p.getUniqueId(), (k,v) -> realizePage(p,realizePage(p,(v == null ? 0 : v))));
List<CommandBlockHolder> filtered = filterEntries(p,chosenOperator.computeIfAbsent(p.getUniqueId(),v->FilterOperator.AND));
int index = page * 45 + slot;
if (index < filtered.size()) {
CommandBlockHolder holder = filtered.get(index);
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_CHIME,1,0.8F);
openManagementMenu(player, holder);
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_CHIME,1,0.8F);
openManagementMenu(p, holder);
}
}
@@ -114,7 +115,7 @@ public class WhitelistGUI {
//ServerUtils.verbose("Name is %s", name);
List<String> lore = new ArrayList<>();
lore.add(Text.color("&7Owner: " + Bukkit.getOfflinePlayer(holder.owner()).getName()));
lore.add(Text.color("&7Owner: " + Bukkit.getOfflinePlayer(UUID.fromString(holder.owner())).getName()));
//ServerUtils.verbose("Got owner");
lore.add(Text.color("&7Command: &f" + holder.command()));
//ServerUtils.verbose("Got command");
@@ -136,7 +137,7 @@ public class WhitelistGUI {
.build();
}
private void openManagementMenu(Player player, CommandBlockHolder holder) {
private void openManagementMenu(Player p, CommandBlockHolder holder) {
ServerUtils.verbose("Opening management menu for %s", holder.owner());
boolean whitelisted = holder.isWhitelisted();
@@ -147,8 +148,8 @@ public class WhitelistGUI {
.define(0,createDisplayItem(holder))
.define(2, createActionItem(whitelisted ? "Un-Whitelist" : "Whitelist", whitelisted ? Material.BARRIER : Material.PAPER), e -> {
holder.setWhitelisted(!whitelisted);
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_PLING,1,1F);
openManagementMenu(player,holder);
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_PLING,1,1F);
openManagementMenu(p,holder);
})
.define(3, createActionItem("Teleport", Material.ENDER_PEARL), e -> {
if (holder.loc().isUUID()) {
@@ -160,39 +161,39 @@ public class WhitelistGUI {
.name("&cTeleport Unavailable")
.lore("&7This entity is not loaded.")
.build());
player.playSound(player.getLocation(),Sound.BLOCK_NOTE_BLOCK_BASS,1,1F);
p.playSound(p.getLocation(),Sound.BLOCK_NOTE_BLOCK_BASS,1,1F);
return;
}
player.teleport(entity.getLocation());
p.teleport(entity.getLocation());
} else {
player.teleport(holder.loc().translate());
p.teleport(holder.loc().translate());
}
player.playSound(player.getLocation(),Sound.ENTITY_ENDERMAN_TELEPORT,1,0.5F);
player.closeInventory();
p.playSound(p.getLocation(),Sound.ENTITY_ENDERMAN_TELEPORT,1,0.5F);
p.closeInventory();
})
.define(4, createActionItem("Restore", Material.DISPENSER), e -> {
holder.restore();
player.openInventory(createGUI(player).getInventory());
player.playSound(player.getLocation(),Sound.BLOCK_AMETHYST_BLOCK_RESONATE,1,1F);
p.openInventory(createGUI(p).getInventory());
p.playSound(p.getLocation(),Sound.BLOCK_AMETHYST_BLOCK_RESONATE,1,1F);
})
.define(5, createActionItem("Destroy (Shift-Click)", Material.NETHERITE_PICKAXE), e -> {
if (!e.isShiftClick()) return;
holder.destroy();
player.playSound(player.getLocation(),Sound.ENTITY_GENERIC_EXPLODE,1,2F);
player.openInventory(createGUI(player).getInventory());
p.playSound(p.getLocation(),Sound.ENTITY_GENERIC_EXPLODE,1,2F);
p.openInventory(createGUI(p).getInventory());
})
.define(6,createActionItem("Take Ownership",Material.NAME_TAG), e -> {
holder.setOwner(player.getUniqueId().toString());
player.playSound(player.getLocation(),Sound.ENTITY_VILLAGER_TRADE,1,1F);
openManagementMenu(player,holder);
holder.setOwner(p.getUniqueId().toString());
p.playSound(p.getLocation(),Sound.ENTITY_VILLAGER_TRADE,1,1F);
openManagementMenu(p,holder);
})
.define(8,Items.BACK,e->{
player.playSound(player.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F);
player.openInventory(createGUI(player).getInventory());
p.playSound(p.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F);
p.openInventory(createGUI(p).getInventory());
})
.build();
player.openInventory(menu.getInventory());
p.openInventory(menu.getInventory());
}
private ItemStack createActionItem(String name, Material mat) {
@@ -207,7 +208,8 @@ public class WhitelistGUI {
private enum Filter {
OWNER, CURRENT_WORLD, OTHER_OWNERS,
MINECART, REPEAT, CHAIN, IMPULSE,
WHITELISTED, NOT_WHITELISTED, NOT_PRESENT
WHITELISTED, NOT_WHITELISTED, NOT_PRESENT,
USER
}
public enum FilterOperator {
@@ -226,9 +228,9 @@ public class WhitelistGUI {
}
}
private List<CommandBlockHolder> filterEntries(Player player, FilterOperator operator) {
Set<Filter> filters = activeFilters.computeIfAbsent(player.getUniqueId(), v -> new HashSet<>());
ServerUtils.verbose("Filtering entries for %s. Current: ", player,filters.toString());
private List<CommandBlockHolder> filterEntries(Player p, FilterOperator operator) {
Set<Filter> filters = activeFilters.computeIfAbsent(p.getUniqueId(), v -> new HashSet<>());
ServerUtils.verbose("Filtering entries for %s. Current: ", p,filters.toString());
return Sentinel.getInstance().getDirector().io.commandBlocks.holders.stream()
.filter(holder -> {
if (filters.isEmpty()) return true;
@@ -237,9 +239,9 @@ public class WhitelistGUI {
for (Filter filter : filters) {
boolean conditionMet = switch (filter) {
case OWNER -> holder.owner().equals(player.getUniqueId().toString());
case CURRENT_WORLD -> holder.loc().world().equals(player.getWorld().getName());
case OTHER_OWNERS -> !holder.owner().equals(player.getUniqueId().toString());
case OWNER -> holder.owner().equals(p.getUniqueId().toString());
case CURRENT_WORLD -> holder.loc().world().equals(p.getWorld().getName());
case OTHER_OWNERS -> !holder.owner().equals(p.getUniqueId().toString());
case MINECART -> holder.getType().equals(Material.COMMAND_BLOCK_MINECART);
case REPEAT -> holder.getType().equals(Material.REPEATING_COMMAND_BLOCK);
case CHAIN -> holder.getType().equals(Material.CHAIN_COMMAND_BLOCK);
@@ -247,6 +249,7 @@ public class WhitelistGUI {
case WHITELISTED -> holder.isWhitelisted();
case NOT_WHITELISTED -> !holder.isWhitelisted();
case NOT_PRESENT -> !holder.present();
case USER -> holder.owner().equals(chosenPlayer.get(p.getUniqueId()));
};
result = operator.apply(result, conditionMet);
@@ -262,42 +265,49 @@ public class WhitelistGUI {
.collect(Collectors.toList());
}
private void openFilterMenu(Player player) {
ServerUtils.verbose("Creating filter menu for %s", player);
Set<Filter> filters = activeFilters.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>());
private void openFilterMenu(Player p) {
ServerUtils.verbose("Creating filter menu for %s", p);
Set<Filter> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
CustomGui filterGui = CustomGui.create()
.title(Text.color("&6&lFilters"))
.size(27)
.defineMain(e -> e.setCancelled(true))
.define(0, createFilterToggleItem("Your Blocks", Material.PLAYER_HEAD, filters.contains(Filter.OWNER)),
e -> toggleFilter(player, Filter.OWNER))
e -> toggleFilter(p, Filter.OWNER))
.define(1, createFilterToggleItem("Other Owners", Material.SPYGLASS, filters.contains(Filter.OTHER_OWNERS)),
e -> toggleFilter(player, Filter.OTHER_OWNERS))
e -> toggleFilter(p, Filter.OTHER_OWNERS))
.define(2, createFilterToggleItem("Current World", Material.TARGET, filters.contains(Filter.CURRENT_WORLD)),
e -> toggleFilter(player, Filter.CURRENT_WORLD))
e -> toggleFilter(p, Filter.CURRENT_WORLD))
.define(3, createFilterToggleItem("Whitelisted Blocks", Material.PAPER, filters.contains(Filter.WHITELISTED)),
e -> toggleFilter(player, Filter.WHITELISTED))
e -> toggleFilter(p, Filter.WHITELISTED))
.define(4, createFilterToggleItem("Not Whitelisted Only", Material.BARRIER, filters.contains(Filter.NOT_WHITELISTED)),
e -> toggleFilter(player, Filter.NOT_WHITELISTED))
e -> toggleFilter(p, Filter.NOT_WHITELISTED))
.define(5, createFilterToggleItem("Missing Command Blocks", Material.GLASS, filters.contains(Filter.NOT_PRESENT)),
e -> toggleFilter(player, Filter.NOT_PRESENT))
e -> toggleFilter(p, Filter.NOT_PRESENT))
.define(6, createFilterToggleItem("Repeating Command Blocks", Material.REPEATING_COMMAND_BLOCK, filters.contains(Filter.REPEAT)),
e -> toggleFilter(player, Filter.REPEAT))
e -> toggleFilter(p, Filter.REPEAT))
.define(7, createFilterToggleItem("Chain Command Blocks", Material.CHAIN_COMMAND_BLOCK, filters.contains(Filter.CHAIN)),
e -> toggleFilter(player, Filter.CHAIN))
e -> toggleFilter(p, Filter.CHAIN))
.define(8, createFilterToggleItem("Impulse Command Blocks", Material.COMMAND_BLOCK, filters.contains(Filter.IMPULSE)),
e -> toggleFilter(player, Filter.IMPULSE))
e -> toggleFilter(p, Filter.IMPULSE))
.define(9, createFilterToggleItem("Minecart Commands", Material.COMMAND_BLOCK_MINECART, filters.contains(Filter.MINECART)),
e -> toggleFilter(player, Filter.MINECART))
e -> toggleFilter(p, Filter.MINECART))
.define(10, createFilterToggleItemValue("Specific Player",Material.BOW,filters.contains(Filter.USER),chosenPlayer.getOrDefault(p.getUniqueId(),"null")),
e -> {
if (e.isLeftClick()) toggleFilter(p,Filter.USER);
else if (e.isRightClick()) {
Callback
}
})
.define(26, Items.BACK,
e-> {
player.playSound(player.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F);
player.openInventory(createGUI(player).getInventory());
p.playSound(p.getLocation(),Sound.ITEM_BOOK_PAGE_TURN,1,0.8F);
p.openInventory(createGUI(p).getInventory());
})
.build();
player.openInventory(filterGui.getInventory());
p.openInventory(filterGui.getInventory());
}
private ItemStack createFilterToggleItem(String name, Material mat, boolean active) {
@@ -308,30 +318,40 @@ public class WhitelistGUI {
.build();
}
private void toggleFilter(Player player, Filter filter) {
Set<Filter> filters = activeFilters.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>());
ServerUtils.verbose("%s is now toggling the %s filter. Current %s", player,filter,filters);
private ItemStack createFilterToggleItemValue(String name, Material mat, boolean active, String value) {
return new ItemBuilder()
.material(mat)
.name(Text.color((active ? "&a" : "&c") + name))
.lore(Text.color("&7Value&f: &b" + value))
.lore(Text.color("&7Left Click to " + (active ? "disable" : "enable")))
.lore(Text.color("&7Right Click to set value."))
.build();
}
private void toggleFilter(Player p, Filter filter) {
Set<Filter> filters = activeFilters.computeIfAbsent(p.getUniqueId(), k -> new HashSet<>());
ServerUtils.verbose("%s is now toggling the %s filter. Current %s", p,filter,filters);
if (filters.contains(filter)) filters.remove(filter);
else filters.add(filter);
ServerUtils.verbose("Current filters for %s: %s", player,filters);
openFilterMenu(player);
ServerUtils.verbose("Current filters for %s: %s", p,filters);
openFilterMenu(p);
}
private int getFilterCount(Player player) {
return activeFilters.getOrDefault(player.getUniqueId(), new HashSet<>()).size();
private int getFilterCount(Player p) {
return activeFilters.getOrDefault(p.getUniqueId(), new HashSet<>()).size();
}
private void changePage(Player player, int direction) {
int current = currentPages.getOrDefault(player.getUniqueId(), 0);
int newPage = realizePage(player, current + direction);
currentPages.put(player.getUniqueId(), newPage);
player.openInventory(createGUI(player).getInventory());
private void changePage(Player p, int direction) {
int current = currentPages.getOrDefault(p.getUniqueId(), 0);
int newPage = realizePage(p, current + direction);
currentPages.put(p.getUniqueId(), newPage);
p.openInventory(createGUI(p).getInventory());
}
private int realizePage(Player player, int requested) {
private int realizePage(Player p, int requested) {
int validRequested = Math.max(0, requested);
int totalEntries = filterEntries(player,
chosenOperator.computeIfAbsent(player.getUniqueId(), v -> FilterOperator.AND)).size();
int totalEntries = filterEntries(p,
chosenOperator.computeIfAbsent(p.getUniqueId(), v -> FilterOperator.AND)).size();
int maxPages = Math.max(0, Math.ceilDiv(totalEntries, 45) - 1);
return Math.min(validRequested, maxPages);
}
@@ -344,9 +364,9 @@ public class WhitelistGUI {
.build();
}
private ItemStack createFilterItem(Player player) {
private ItemStack createFilterItem(Player p) {
List<String> operatorList = new ArrayList<>();
FilterOperator chosen = chosenOperator.computeIfAbsent(player.getUniqueId(),v->FilterOperator.AND);
FilterOperator chosen = chosenOperator.computeIfAbsent(p.getUniqueId(),v->FilterOperator.AND);
for (FilterOperator value : FilterOperator.values()) {
if (value.equals(chosen)) operatorList.add(Text.color("&b&n" + value.name()));
else operatorList.add(Text.color("&b" + value.name()));
@@ -354,7 +374,7 @@ public class WhitelistGUI {
return new ItemBuilder()
.material(Material.HOPPER)
.name(Text.color("&6&lFilters"))
.lore(Text.color("&7Filters Selected: &e" + getFilterCount(player)))
.lore(Text.color("&7Filters Selected: &e" + getFilterCount(p)))
.lore(Text.color("&7Shift-Click to cycle filter operator."))
.lore(Text.color("&7Operator: "))
.lore(operatorList)

View File

@@ -19,6 +19,7 @@ import me.trouper.sentinel.server.events.violations.blocks.structure.StructureBl
import me.trouper.sentinel.server.events.violations.command.DangerousCommand;
import me.trouper.sentinel.server.events.violations.command.LoggedCommand;
import me.trouper.sentinel.server.events.violations.command.SpecificCommand;
import me.trouper.sentinel.server.events.violations.entities.CommandMinecartEdit;
import me.trouper.sentinel.server.events.violations.players.*;
import me.trouper.sentinel.server.events.violations.whitelist.CommandBlockExecute;
import me.trouper.sentinel.server.events.extras.ShadowRealmEvents;
@@ -150,6 +151,7 @@ public final class Loader {
PacketEvents.getAPI().getEventManager().registerListener(new PluginCloakingPacket(), PacketListenerPriority.NORMAL);
PacketEvents.getAPI().getEventManager().registerListener(new ShadowRealmEvents(), PacketListenerPriority.HIGHEST);
PacketEvents.getAPI().getEventManager().registerListener(new CommandBlockEdit(), PacketListenerPriority.NORMAL);
PacketEvents.getAPI().getEventManager().registerListener(new CommandMinecartEdit(), PacketListenerPriority.NORMAL);
// Events
new AntiBanEvents().register();