adding an NBT GUI.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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