adding an NBT GUI.
This commit is contained in:
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
158
src/main/java/me/trouper/sentinel/server/gui/PaginatedGUI.java
Normal file
158
src/main/java/me/trouper/sentinel/server/gui/PaginatedGUI.java
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
104
src/main/java/me/trouper/sentinel/server/gui/nbt/NBTGui.java
Normal file
104
src/main/java/me/trouper/sentinel/server/gui/nbt/NBTGui.java
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user