Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>dev.espi</groupId>
<artifactId>protectionstones</artifactId>
<version>2.10.6</version>
<version>2.10.7</version>
<name>ProtectionStones</name>
<description>A grief prevention plugin for Spigot Minecraft servers.</description>
<url>https://github.com/espidev/ProtectionStones</url>
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/dev/espi/protectionstones/ListenerClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -307,15 +307,17 @@ public void onPrepareItemCraft(PrepareItemCraftEvent e) {

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onCrafter(CrafterCraftEvent e) {
if (e.getBlock().getType() != Material.CRAFTER) return;
if (!(e.getBlock().getState() instanceof Container container)) return;
for (ItemStack item : container.getInventory().getContents()) {
Block block = e.getBlock();
BlockState state = block.getState();
if (block.getType() != Material.CRAFTER) return;
if (!(state instanceof Container container)) return;
Inventory inv = container.getInventory();
for (ItemStack item : inv.getContents()) {
if (item == null) continue;
PSProtectBlock options = ProtectionStones.getBlockOptions(item);
if (options != null && !options.allowUseInCrafting) {
e.setCancelled(true);
e.setResult(new ItemStack(Material.AIR));
return;
}
}
}
Expand Down
36 changes: 35 additions & 1 deletion src/main/java/dev/espi/protectionstones/PSConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,40 @@ public class PSConfig {
@Path("allow_home_teleport_for_members")
public Boolean allowHomeTeleportForMembers;

// ------------------------------------------------------------------
// Inventory GUI toggles
// If gui.enabled is false, all commands use legacy text-based output.
// If gui.enabled is true, individual commands can be enabled below.
@Path("gui.enabled")
public Boolean guiEnabled;
@Path("gui.commands.home")
public Boolean guiCommandHome;
@Path("gui.commands.flag")
public Boolean guiCommandFlag;
@Path("gui.commands.add")
public Boolean guiCommandAdd;
@Path("gui.commands.remove")
public Boolean guiCommandRemove;
@Path("gui.commands.addowner")
public Boolean guiCommandAddowner;
@Path("gui.commands.removeowner")
public Boolean guiCommandRemoveowner;

// Additional command GUIs
@Path("gui.commands.list")
public Boolean guiCommandList;
@Path("gui.commands.info")
public Boolean guiCommandInfo;
@Path("gui.commands.tp")
public Boolean guiCommandTp;
@Path("gui.commands.unclaim")
public Boolean guiCommandUnclaim;
@Path("gui.commands.priority")
public Boolean guiCommandPriority;

@Path("gui.commands.admin")
public Boolean guiCommandAdmin;

@Path("admin.cleanup_delete_regions_with_members_but_no_owners")
public Boolean cleanupDeleteRegionsWithMembersButNoOwners;

Expand Down Expand Up @@ -229,4 +263,4 @@ static void initConfig() {
RecipeUtil.setupPSRecipes();
}
}
}
}
22 changes: 21 additions & 1 deletion src/main/java/dev/espi/protectionstones/ProtectionStones.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import dev.espi.protectionstones.commands.ArgHelp;
import dev.espi.protectionstones.commands.PSCommandArg;
import dev.espi.protectionstones.gui.GuiManager;
import dev.espi.protectionstones.placeholders.PSPlaceholderExpansion;
import dev.espi.protectionstones.utils.BlockUtil;
import dev.espi.protectionstones.utils.RecipeUtil;
Expand Down Expand Up @@ -60,7 +61,7 @@

public class ProtectionStones extends JavaPlugin {
// change this when the config version goes up
public static final int CONFIG_VERSION = 16;
public static final int CONFIG_VERSION = 19;

private boolean debug = false;

Expand All @@ -72,6 +73,9 @@ public class ProtectionStones extends JavaPlugin {

private PSEconomy economy;

// Inventory GUI manager (used when gui.* config toggles are enabled)
private GuiManager guiManager;

// all configuration file options are stored in here
private PSConfig configOptions;
static HashMap<String, PSProtectBlock> protectionStonesOptions = new HashMap<>();
Expand Down Expand Up @@ -179,6 +183,10 @@ public PSConfig getConfigOptions() {
return configOptions;
}

public GuiManager getGuiManager() {
return guiManager;
}

/**
* @param conf config object to replace current config
*/
Expand Down Expand Up @@ -555,6 +563,11 @@ public void onEnable() {
Config.setInsertionOrderPreserved(true); // make sure that config upgrades aren't a complete mess

plugin = this;

// GUI manager (safe to register even if GUIs are disabled via config)
guiManager = new GuiManager(this);
guiManager.register();

configLocation = new File(this.getDataFolder() + "/config.toml");
blockDataFolder = new File(this.getDataFolder() + "/blocks");

Expand Down Expand Up @@ -661,4 +674,11 @@ public void onEnable() {
getLogger().info(ChatColor.WHITE + "ProtectionStones has successfully started!");
}

@Override
public void onDisable() {
if (guiManager != null) {
guiManager.unregister();
}
}

}
36 changes: 36 additions & 0 deletions src/main/java/dev/espi/protectionstones/commands/ArgAddRemove.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import dev.espi.protectionstones.*;
import dev.espi.protectionstones.utils.LimitUtil;
import dev.espi.protectionstones.gui.screens.members.RegionPlayerSelectGui;
import dev.espi.protectionstones.utils.UUIDCache;
import dev.espi.protectionstones.utils.WGUtils;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -66,6 +67,41 @@ public boolean executeArgument(CommandSender s, String[] args, HashMap<String, S
}

// determine player to be added or removed


// GUI toggle (inventory GUI vs legacy text-based output)
PSConfig conf = ProtectionStones.getInstance().getConfigOptions();
boolean guiGlobal = Boolean.TRUE.equals(conf.guiEnabled);
boolean guiThis = switch (operationType) {
case "add" -> Boolean.TRUE.equals(conf.guiCommandAdd);
case "remove" -> Boolean.TRUE.equals(conf.guiCommandRemove);
case "addowner" -> Boolean.TRUE.equals(conf.guiCommandAddowner);
case "removeowner" -> Boolean.TRUE.equals(conf.guiCommandRemoveowner);
default -> false;
};

// If GUI enabled for this command and no player argument provided (and not using -a), open selector GUI
if (guiGlobal && guiThis && args.length < 2 && !flags.containsKey("-a")) {
PSRegion r = PSRegion.fromLocationGroup(p.getLocation());
if (r == null) {
return PSL.msg(p, PSL.NOT_IN_REGION.msg());
} else if (WGUtils.hasNoAccess(r.getWGRegion(), p, WorldGuardPlugin.inst().wrapPlayer(p), false)) {
return PSL.msg(p, PSL.NO_ACCESS.msg());
}

RegionPlayerSelectGui.Mode mode = switch (operationType) {
case "add" -> RegionPlayerSelectGui.Mode.ADD_MEMBER;
case "remove" -> RegionPlayerSelectGui.Mode.REMOVE_MEMBER;
case "addowner" -> RegionPlayerSelectGui.Mode.ADD_OWNER;
case "removeowner" -> RegionPlayerSelectGui.Mode.REMOVE_OWNER;
default -> RegionPlayerSelectGui.Mode.ADD_MEMBER;
};

ProtectionStones.getInstance().getGuiManager().open(p,
new RegionPlayerSelectGui(ProtectionStones.getInstance().getGuiManager(), r, mode, 0));
return true;
}

if (args.length < 2) {
return PSL.msg(p, PSL.COMMAND_REQUIRES_PLAYER_NAME.msg());
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/dev/espi/protectionstones/commands/ArgAdmin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
import dev.espi.protectionstones.utils.upgrade.LegacyUpgrade;
import dev.espi.protectionstones.PSL;
import dev.espi.protectionstones.ProtectionStones;
import dev.espi.protectionstones.gui.screens.admin.AdminMenuGui;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;

import java.util.*;
Expand Down Expand Up @@ -86,6 +88,15 @@ public boolean executeArgument(CommandSender s, String[] args, HashMap<String, S
}

if (args.length < 2) {
// If enabled, show GUI menu for players; otherwise fall back to text help.
if (s instanceof Player p) {
var cfg = ProtectionStones.getInstance().getConfigOptions();
boolean guiMode = Boolean.TRUE.equals(cfg.guiEnabled) && Boolean.TRUE.equals(cfg.guiCommandAdmin);
if (guiMode) {
ProtectionStones.getInstance().getGuiManager().open(p, new AdminMenuGui(ProtectionStones.getInstance().getGuiManager()));
return true;
}
}
ArgAdminHelp.argumentAdminHelp(s, args);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ private static void send(CommandSender p, String text, String info, String click
}

static boolean argumentAdminHelp(CommandSender p, String[] args) {
String bc = "/" + ProtectionStones.getInstance().getConfigOptions().base_command;
String tx = ChatColor.AQUA + "> " + ChatColor.GRAY + bc;
String baseCommand = ProtectionStones.getInstance().getConfigOptions().base_command;
String bc = "/" + baseCommand;
String tx = ChatColor.AQUA + "> " + ChatColor.GRAY + "/" + bc;

p.sendMessage(ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "===============" +
ChatColor.RESET + " PS Admin Help " +
Expand All @@ -58,7 +59,7 @@ static boolean argumentAdminHelp(CommandSender p, String[] args) {
send(p,
tx + " admin version",
"Show the version number of the plugin.\n\n" + bc + " admin version",
bc + " admin version",
baseCommand + " admin version",
false);

send(p,
Expand Down
50 changes: 39 additions & 11 deletions src/main/java/dev/espi/protectionstones/commands/ArgFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.sk89q.worldguard.protection.flags.*;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import dev.espi.protectionstones.*;
import dev.espi.protectionstones.gui.screens.flags.FlagsGui;
import dev.espi.protectionstones.utils.MiscUtil;
import dev.espi.protectionstones.utils.WGUtils;
import net.md_5.bungee.api.chat.*;
Expand Down Expand Up @@ -118,7 +119,7 @@ private boolean openFlagGUI(Player p, PSRegion r, int page) {
}

// add line based on flag type
boolean isGroupValueAll = groupfValue.equalsIgnoreCase("all") || groupfValue.isEmpty();
boolean isGroupValueAll = groupfValue.equalsIgnoreCase("all") || groupfValue.isEmpty();;
if (f instanceof StateFlag) { // allow/deny

TextComponent allow = new TextComponent((fValue == StateFlag.State.ALLOW ? ChatColor.WHITE : ChatColor.DARK_GRAY) + "Allow"),
Expand Down Expand Up @@ -184,15 +185,25 @@ private boolean openFlagGUI(Player p, PSRegion r, int page) {
}

// set hover and click task for flag group
// HACK: Prevent pvp flag group from being changed when set to "all" to prevent exploit
boolean isPvpExploitCase = flag.equalsIgnoreCase("pvp") && isGroupValueAll;
if (isPvpExploitCase) {
BaseComponent[] hover = new ComponentBuilder(PSL.FLAG_PREVENT_EXPLOIT_HOVER.msg()).create();
BaseComponent[] hover;
// HACK: Prevent pvp flag value from being changed to none/null
// Special handling for "pvp" flag with "all" group, disabling interaction.
if (flag.equalsIgnoreCase("pvp") && isGroupValueAll) {
hover = new ComponentBuilder(PSL.FLAG_PREVENT_EXPLOIT_HOVER.msg()).create();
// Remove click action to fully disable changing this group.
groupChange.setClickEvent(null);
} else if (fValue == null) {
hover = new ComponentBuilder(PSL.FLAG_GUI_HOVER_CHANGE_GROUP_NULL.msg()).create();
} else {
hover = new ComponentBuilder(PSL.FLAG_GUI_HOVER_CHANGE_GROUP.msg().replace("%group%", nextGroup)).create();
}

// Always set hover if the flag is pvp and group is "all"
if (flag.equalsIgnoreCase("pvp") && groupfValue.equalsIgnoreCase("all")) {
hover = new ComponentBuilder(PSL.FLAG_PREVENT_EXPLOIT_HOVER.msg()).create();
groupChange.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover));
groupChange.setClickEvent(null); // Disable click event explicitly
} else if (!nextGroup.equals(groupfValue)) {
BaseComponent[] hover = fValue == null
? new ComponentBuilder(PSL.FLAG_GUI_HOVER_CHANGE_GROUP_NULL.msg()).create()
: new ComponentBuilder(PSL.FLAG_GUI_HOVER_CHANGE_GROUP.msg().replace("%group%", nextGroup)).create();
groupChange.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover));
groupChange.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, suggestedCommand + "-g " + nextGroup + " " + page + ":" + flag + " " + fValue));
}
Expand Down Expand Up @@ -230,6 +241,10 @@ public boolean executeArgument(CommandSender s, String[] args, HashMap<String, S
Player p = (Player) s;
PSRegion r = PSRegion.fromLocationGroup(p.getLocation());

// GUI toggle (inventory GUI vs legacy text-based output)
PSConfig conf = ProtectionStones.getInstance().getConfigOptions();
boolean useInvGui = Boolean.TRUE.equals(conf.guiEnabled) && Boolean.TRUE.equals(conf.guiCommandFlag);

if (!p.hasPermission("protectionstones.flags")) {
PSL.msg(p, PSL.NO_PERMISSION_FLAGS.msg());
return true;
Expand All @@ -244,12 +259,25 @@ public boolean executeArgument(CommandSender s, String[] args, HashMap<String, S
}

// /ps flag GUI
if (args.length == 1) return openFlagGUI(p, r, 0);
if (args.length == 1) {
if (useInvGui) {
ProtectionStones.getInstance().getGuiManager().open(p,
new FlagsGui(ProtectionStones.getInstance().getGuiManager(), p.getWorld().getUID(), r.getId(), 0));
return true;
}
return openFlagGUI(p, r, 0);
}

// go to GUI page
if (args.length == 2) {
if (MiscUtil.isValidInteger(args[1])) {
return openFlagGUI(p, r, Integer.parseInt(args[1]));
int page = Integer.parseInt(args[1]);
if (useInvGui) {
ProtectionStones.getInstance().getGuiManager().open(p,
new FlagsGui(ProtectionStones.getInstance().getGuiManager(), p.getWorld().getUID(), r.getId(), page));
return true;
}
return openFlagGUI(p, r, page);
}

PSL.msg(p, PSL.FLAG_HELP.msg());
Expand Down Expand Up @@ -349,7 +377,7 @@ public List<String> tabComplete(CommandSender sender, String alias, String[] arg
}

// /ps flag logic (utilizing WG internal /region flag logic)
static void setFlag(PSRegion r, CommandSender p, String flagName, String value, String groupValue) {
public static void setFlag(PSRegion r, CommandSender p, String flagName, String value, String groupValue) {
// correct the flag if gui flags are there
String[] flagSplit = flagName.split(":");
if (flagSplit.length == 2) flagName = flagSplit[1];
Expand Down
31 changes: 26 additions & 5 deletions src/main/java/dev/espi/protectionstones/commands/ArgHome.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package dev.espi.protectionstones.commands;

import dev.espi.protectionstones.*;
import dev.espi.protectionstones.gui.screens.home.HomeWorldsGui;
import dev.espi.protectionstones.utils.ChatUtil;
import dev.espi.protectionstones.utils.MiscUtil;
import dev.espi.protectionstones.utils.TextGUI;
Expand Down Expand Up @@ -121,6 +122,10 @@ private void openHomeGUI(PSPlayer psp, List<PSRegion> homes, int page) {
public boolean executeArgument(CommandSender s, String[] args, HashMap<String, String> flags) {
Player p = (Player) s;

// GUI toggle (inventory GUI vs legacy text-based output)
PSConfig conf = ProtectionStones.getInstance().getConfigOptions();
boolean useInvGui = Boolean.TRUE.equals(conf.guiEnabled) && Boolean.TRUE.equals(conf.guiCommandHome);

// prelim checks
if (!p.hasPermission("protectionstones.home"))
return PSL.msg(p, PSL.NO_PERMISSION_HOME.msg());
Expand All @@ -132,11 +137,27 @@ public boolean executeArgument(CommandSender s, String[] args, HashMap<String, S
PSPlayer psp = PSPlayer.fromPlayer(p);
if (args.length == 1) {
// just "/ps home"
List<PSRegion> regions = psp.getHomes(p.getWorld());
if (regions.size() == 1) { // teleport to home if there is only one home
ArgTp.teleportPlayer(p, regions.get(0));
} else { // otherwise, open the GUI
openHomeGUI(psp, regions, (flags.get("-p") == null || !MiscUtil.isValidInteger(flags.get("-p")) ? 0 : Integer.parseInt(flags.get("-p")) - 1));
if (useInvGui) {
// gather homes across all worlds; if only 1 total, teleport directly
List<PSRegion> allHomes = new ArrayList<>();
for (org.bukkit.World w : Bukkit.getWorlds()) {
allHomes.addAll(psp.getHomes(w));
}
if (allHomes.size() == 1) {
ArgTp.teleportPlayer(p, allHomes.get(0));
} else {
Bukkit.getScheduler().runTask(ProtectionStones.getInstance(), () ->
ProtectionStones.getInstance().getGuiManager().open(p, new HomeWorldsGui(ProtectionStones.getInstance().getGuiManager(), 0))
);
}
} else {
// legacy text-based GUI (current-world homes)
List<PSRegion> regions = psp.getHomes(p.getWorld());
if (regions.size() == 1) { // teleport to home if there is only one home
ArgTp.teleportPlayer(p, regions.get(0));
} else { // otherwise, open the text GUI
openHomeGUI(psp, regions, (flags.get("-p") == null || !MiscUtil.isValidInteger(flags.get("-p")) ? 0 : Integer.parseInt(flags.get("-p")) - 1));
}
}
} else {// /ps home [id]
// get regions from the query
Expand Down
Loading