Skip to content
Closed
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ View the Spigot page (with FAQ and install instructions) [here](https://www.spig
Check the [wiki](https://github.com/espidev/ProtectionStones/wiki) for plugin reference information.

### Dependencies
* ProtectionStones 2.10.5
* ProtectionStones 2.10.6
* Spigot 1.20.6+
* WorldGuard 7.0.9+
* WorldEdit 7.2.6+
Expand Down
38 changes: 34 additions & 4 deletions 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.5</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 Expand Up @@ -207,13 +207,13 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.6-R0.1-SNAPSHOT</version>
<version>1.21.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.9-SNAPSHOT</version>
<version>7.0.14-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
Expand All @@ -231,7 +231,7 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.6-SNAPSHOT</version>
<version>7.3.16-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
Expand All @@ -240,6 +240,36 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.17.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-plain</artifactId>
<version>4.17.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-bungeecord</artifactId>
<version>4.4.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.17.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
Expand Down
35 changes: 20 additions & 15 deletions src/main/java/dev/espi/protectionstones/BlockHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,15 @@
import dev.espi.protectionstones.utils.MiscUtil;
import dev.espi.protectionstones.utils.WGMerge;
import dev.espi.protectionstones.utils.WGUtils;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.chat.TextComponent;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.*;

public class BlockHandler {
private static HashMap<Player, Double> lastProtectStonePlaced = new HashMap<>();
Expand Down Expand Up @@ -140,7 +138,7 @@ public static boolean createPSRegion(Player p, Location l, PSProtectBlock blockO
if (ProtectionStones.getInstance().getConfigOptions().placingCooldown != -1) {
String time = checkCooldown(p);
if (time != null) {
PSL.msg(p, PSL.COOLDOWN.msg().replace("%time%", time));
PSL.msg(p, PSL.COOLDOWN.replace("%time%", time));
return false;
}
}
Expand Down Expand Up @@ -168,7 +166,7 @@ public static boolean createPSRegion(Player p, Location l, PSProtectBlock blockO

// check if player has enough money
if (ProtectionStones.getInstance().isVaultSupportEnabled() && blockOptions.costToPlace != 0 && !ProtectionStones.getInstance().getVaultEconomy().has(p, blockOptions.costToPlace)) {
PSL.msg(p, PSL.NOT_ENOUGH_MONEY.msg().replace("%price%", String.format("%.2f", blockOptions.costToPlace)));
PSL.msg(p, PSL.NOT_ENOUGH_MONEY.replace("%price%", String.format("%.2f", blockOptions.costToPlace)));
return false;
}

Expand All @@ -183,10 +181,10 @@ public static boolean createPSRegion(Player p, Location l, PSProtectBlock blockO
if (ProtectionStones.getInstance().isVaultSupportEnabled() && blockOptions.costToPlace != 0) {
EconomyResponse er = ProtectionStones.getInstance().getVaultEconomy().withdrawPlayer(p, blockOptions.costToPlace);
if (!er.transactionSuccess()) {
PSL.msg(p, er.errorMessage);
PSL.msg(p, Component.text(er.errorMessage));
return true;
}
PSL.msg(p, PSL.PAID_MONEY.msg().replace("%price%", String.format("%.2f", blockOptions.costToPlace)));
PSL.msg(p, PSL.PAID_MONEY.replace("%price%", String.format("%.2f", blockOptions.costToPlace)));
}

return true;
Expand Down Expand Up @@ -214,7 +212,7 @@ public static boolean createActualRegion(Player p, Location l, PSProtectBlock bl
// check for minimum distance between claims by using fake region
if (blockOptions.distanceBetweenClaims != -1 && !p.hasPermission("protectionstones.superowner")) {
if (!isFarEnoughFromOtherClaims(blockOptions, p.getWorld(), lp, bx, by, bz)) {
PSL.msg(p, PSL.REGION_TOO_CLOSE.msg().replace("%num%", "" + blockOptions.distanceBetweenClaims));
PSL.msg(p, PSL.REGION_TOO_CLOSE.replace("%num%", "" + blockOptions.distanceBetweenClaims));
return false;
}
}
Expand Down Expand Up @@ -315,7 +313,7 @@ private static void playerMergeTask(Player p, PSRegion r) {
Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> {
try {
WGMerge.mergeRealRegions(p.getWorld(), r.getWGRegionManager(), finalMergeTo, Arrays.asList(finalMergeTo, r));
PSL.msg(p, PSL.MERGE_AUTO_MERGED.msg().replace("%region%", finalMergeTo.getId()));
PSL.msg(p, PSL.MERGE_AUTO_MERGED.replace("%region%", finalMergeTo.getId()));
} catch (WGMerge.RegionHoleException e) {
PSL.msg(p, PSL.NO_REGION_HOLES.msg()); // TODO github issue #120, prevent holes even if showGUI is true
} catch (WGMerge.RegionCannotMergeWhileRentedException e) {
Expand All @@ -327,14 +325,21 @@ private static void playerMergeTask(Player p, PSRegion r) {

// show merge gui
if (showGUI) {
List<TextComponent> tc = ArgMerge.getGUI(p, r);
List<Component> tc = ArgMerge.getGUI(p, r);
if (!tc.isEmpty()) { // if there are regions you can merge into
p.sendMessage(ChatColor.WHITE + ""); // send empty line
PSL.msg(p, Component.empty());
PSL.msg(p, PSL.MERGE_INTO.msg());
PSL.msg(p, PSL.MERGE_HEADER.msg().replace("%region%", r.getId()));
for (TextComponent t : tc) p.spigot().sendMessage(t);
p.sendMessage(ChatColor.WHITE + ""); // send empty line
PSL.msg(p, PSL.MERGE_HEADER.replaceAll(Map.of("%region%", r.getId())));

// GUI entries
for (Component t : tc) {
PSL.msg(p, t);
}

// empty line again
PSL.msg(p, Component.empty());
}
}

}
}
55 changes: 43 additions & 12 deletions src/main/java/dev/espi/protectionstones/ListenerClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
import dev.espi.protectionstones.utils.RecipeUtil;
import dev.espi.protectionstones.utils.UUIDCache;
import dev.espi.protectionstones.utils.WGUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Furnace;
import org.bukkit.block.*;
import org.bukkit.block.data.type.Crafter;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
Expand All @@ -53,7 +53,7 @@
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.*;

import java.util.List;

Expand Down Expand Up @@ -92,7 +92,7 @@ public void onPlayerJoin(PlayerJoinEvent e) {
}

if (amount != 0) {
PSL.msg(psp, PSL.TAX_JOIN_MSG_PENDING_PAYMENTS.msg().replace("%money%", "" + amount));
PSL.msg(psp.getPlayer(), PSL.TAX_JOIN_MSG_PENDING_PAYMENTS.replace("%money%", "" + amount));
}
});
}
Expand Down Expand Up @@ -137,7 +137,7 @@ public void onBlockPlace(BlockPlaceEvent e) {

// returns the error message, or "" if the player has permission to break the region
// TODO: refactor and move this to PSRegion, so that /ps unclaim can use the same checks
private String checkPermissionToBreakProtection(Player p, PSRegion r) {
private Component checkPermissionToBreakProtection(Player p, PSRegion r) {
// check for destroy permission
if (!p.hasPermission("protectionstones.destroy")) {
return PSL.NO_PERMISSION_DESTROY.msg();
Expand All @@ -153,7 +153,7 @@ private String checkPermissionToBreakProtection(Player p, PSRegion r) {
return PSL.RENT_CANNOT_BREAK_WHILE_RENTING.msg();
}

return "";
return Component.empty();
}

// helper method for breaking protection blocks
Expand All @@ -162,8 +162,8 @@ private boolean playerBreakProtection(Player p, PSRegion r) {
PSProtectBlock blockOptions = r.getTypeOptions();

// check if player has permission to break the protection
String error = checkPermissionToBreakProtection(p, r);
if (!error.isEmpty()) {
Component error = checkPermissionToBreakProtection(p, r);
if (!error.contains(Component.empty())) {
PSL.msg(p, error);
return false;
}
Expand Down Expand Up @@ -220,6 +220,7 @@ public void onPlayerInteract(PlayerInteractEvent e) {
// thus we should cancel the event here if possible (so other plugins don't start acting upon it)
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockBreakLowPriority(BlockBreakEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onBlockBreakLowPriority");
Player p = e.getPlayer();
Block pb = e.getBlock();

Expand All @@ -228,8 +229,11 @@ public void onBlockBreakLowPriority(BlockBreakEvent e) {
// check if player has permission to break the protection
PSRegion r = PSRegion.fromLocation(pb.getLocation());
if (r != null) {
String error = checkPermissionToBreakProtection(p, r);
if (!error.isEmpty()) {
ProtectionStones.getInstance().debug("Player:"+ p.getName()+", Holding:"+ p.getPlayer().getInventory().getItemInMainHand().getType().name()+", Enchants:" +p.getPlayer().getInventory().getItemInMainHand().getEnchantments());


Component error = checkPermissionToBreakProtection(p, r);
if (!error.contains(Component.empty())) {
PSL.msg(p, error);
e.setCancelled(true);
}
Expand All @@ -238,6 +242,7 @@ public void onBlockBreakLowPriority(BlockBreakEvent e) {

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onBlockBreak");
Player p = e.getPlayer();
Block pb = e.getBlock();

Expand Down Expand Up @@ -275,6 +280,7 @@ public void onBlockBreak(BlockBreakEvent e) {

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onFurnaceSmelt(FurnaceSmeltEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onFurnaceSmelt");
// prevent protect block item to be smelt
PSProtectBlock options = ProtectionStones.getBlockOptions(e.getSource());
if (options != null && !options.allowSmeltItem) {
Expand All @@ -284,6 +290,7 @@ public void onFurnaceSmelt(FurnaceSmeltEvent e) {

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onFurnaceBurnItem(FurnaceBurnEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onFurnaceBurnItem");
// prevent protect block item to be smelt
Furnace f = (Furnace) e.getBlock().getState();
if (f.getInventory().getSmelting() != null) {
Expand All @@ -299,6 +306,7 @@ public void onFurnaceBurnItem(FurnaceBurnEvent e) {

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPrepareItemCraft(PrepareItemCraftEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onPrepareItemCraft");
for (ItemStack s : e.getInventory().getMatrix()) {
PSProtectBlock options = ProtectionStones.getBlockOptions(s);
if (options != null && !options.allowUseInCrafting) {
Expand All @@ -307,12 +315,30 @@ public void onPrepareItemCraft(PrepareItemCraftEvent e) {
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onCrafter(CrafterCraftEvent e) {
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));
}
}
}


// -=-=-=- disable grindstone inventory to prevent infinite exp exploit with enchanted_effect option -=-=-=-
// see https://github.com/espidev/ProtectionStones/issues/324

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryClickEvent(InventoryClickEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onInventoryClickEvent");
if (e.getInventory().getType() == InventoryType.GRINDSTONE) {
if (ProtectionStones.isProtectBlockItem(e.getCurrentItem())) {
e.setCancelled(true);
Expand All @@ -325,6 +351,7 @@ public void onInventoryClickEvent(InventoryClickEvent e) {

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerBucketFill(PlayerBucketEmptyEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onPlayerBucketFill");
Block clicked = e.getBlockClicked();
BlockFace bf = e.getBlockFace();
Block check = clicked.getWorld().getBlockAt(clicked.getX() + e.getBlockFace().getModX(), clicked.getY() + bf.getModY(), clicked.getZ() + e.getBlockFace().getModZ());
Expand All @@ -335,6 +362,7 @@ public void onPlayerBucketFill(PlayerBucketEmptyEvent e) {

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockIgnite(BlockIgniteEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onBlockIgnite");
if (ProtectionStones.isProtectBlock(e.getBlock())) {
e.setCancelled(true);
}
Expand Down Expand Up @@ -425,16 +453,19 @@ private void pistonUtil(List<Block> pushedBlocks, BlockPistonEvent e) {

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockExplode(BlockExplodeEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onBlockExplode");
explodeUtil(e.blockList(), e.getBlock().getLocation().getWorld());
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityExplode(EntityExplodeEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onEntityExplode");
explodeUtil(e.blockList(), e.getLocation().getWorld());
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent e) {
ProtectionStones.getInstance().debug("ListenerClass.java, onEntityChangeBlock");
if (!ProtectionStones.isProtectBlock(e.getBlock())) return;

// events like ender dragon block break, wither running into block break, etc.
Expand Down
Loading