diff --git a/README.md b/README.md
index c914c4a1..df541ba6 100644
--- a/README.md
+++ b/README.md
@@ -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.6
+* ProtectionStones 2.10.7
* Spigot 1.21.6+
* WorldGuard 7.0.9+
* WorldEdit 7.2.6+
diff --git a/pom.xml b/pom.xml
index 3c7a417c..d2dcbde8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0dev.espiprotectionstones
- 2.10.6
+ 2.10.7ProtectionStonesA grief prevention plugin for Spigot Minecraft servers.https://github.com/espidev/ProtectionStones
@@ -89,8 +89,8 @@
3.1
- 16
- 16
+ 21
+ 21${project.build.sourceEncoding}
@@ -107,13 +107,18 @@
org.apache.maven.pluginsmaven-shade-plugin
- 3.3.0
+ 3.5.0
- true
+ false
+ falseorg.bstats
- dev.espi.protectionstones
+ dev.espi.protectionstones.bstats
+
+
+ net.kyori
+ dev.espi.protectionstones.lib.kyori
@@ -201,7 +206,7 @@
org.bstatsbstats-bukkit
- 3.0.2
+ 3.1.0compile
@@ -272,5 +277,15 @@
json-simple1.1.1
+
+ net.kyori
+ adventure-text-minimessage
+ 4.17.0
+
+
+ net.kyori
+ adventure-platform-bukkit
+ 4.3.3
+
diff --git a/src/main/java/dev/espi/protectionstones/FlagHandler.java b/src/main/java/dev/espi/protectionstones/FlagHandler.java
index 28e46b20..12539779 100644
--- a/src/main/java/dev/espi/protectionstones/FlagHandler.java
+++ b/src/main/java/dev/espi/protectionstones/FlagHandler.java
@@ -44,12 +44,15 @@ public class FlagHandler {
// Custom WorldGuard Flags used by ProtectionStones
// Added to blocks on BlockPlaceEvent Listener
- // When adding flags, you may want to add them to the hidden_flags_from_info config option list
+ // When adding flags, you may want to add them to the hidden_flags_from_info
+ // config option list
public static final Flag PS_HOME = new StringFlag("ps-home");
public static final Flag PS_BLOCK_MATERIAL = new StringFlag("ps-block-material");
public static final Flag PS_NAME = new StringFlag("ps-name");
- public static final Flag> PS_MERGED_REGIONS = new SetFlag<>("ps-merged-regions", new StringFlag("ps-merged-region"));
- public static final Flag> PS_MERGED_REGIONS_TYPES = new SetFlag<>("ps-merged-regions-types", new StringFlag("ps-merged-region-type")); // each entry: "[psID] [type]"
+ public static final Flag> PS_MERGED_REGIONS = new SetFlag<>("ps-merged-regions",
+ new StringFlag("ps-merged-region"));
+ public static final Flag> PS_MERGED_REGIONS_TYPES = new SetFlag<>("ps-merged-regions-types",
+ new StringFlag("ps-merged-region-type")); // each entry: "[psID] [type]"
public static final Flag PS_LANDLORD = new StringFlag("ps-landlord");
public static final Flag PS_TENANT = new StringFlag("ps-tenant");
@@ -57,9 +60,12 @@ public class FlagHandler {
public static final Flag PS_PRICE = new DoubleFlag("ps-price");
public static final Flag PS_RENT_LAST_PAID = new DoubleFlag("ps-rent-last-paid");
public static final Flag PS_FOR_SALE = new BooleanFlag("ps-for-sale");
- public static final Flag> PS_RENT_SETTINGS = new SetFlag<>("ps-rent-settings", new StringFlag("ps-rent-setting")); // TODO
- public static final Flag> PS_TAX_PAYMENTS_DUE = new SetFlag<>("ps-tax-payments-due", new StringFlag("ps-tax-payment"));
- public static final Flag> PS_TAX_LAST_PAYMENT_ADDED = new SetFlag<>("ps-tax-last-payment-added", new StringFlag("ps-tax-last-payment-entry"));
+ public static final Flag> PS_RENT_SETTINGS = new SetFlag<>("ps-rent-settings",
+ new StringFlag("ps-rent-setting")); // TODO
+ public static final Flag> PS_TAX_PAYMENTS_DUE = new SetFlag<>("ps-tax-payments-due",
+ new StringFlag("ps-tax-payment"));
+ public static final Flag> PS_TAX_LAST_PAYMENT_ADDED = new SetFlag<>("ps-tax-last-payment-added",
+ new StringFlag("ps-tax-last-payment-entry"));
public static final Flag PS_TAX_AUTOPAYER = new StringFlag("ps-tax-autopayer");
// called on initial start
@@ -83,7 +89,8 @@ static void registerFlags() {
registry.register(PS_TAX_LAST_PAYMENT_ADDED);
registry.register(PS_TAX_AUTOPAYER);
} catch (FlagConflictException e) {
- Bukkit.getLogger().severe("Flag conflict found! The plugin will not work properly! Please contact the developers of the plugin.");
+ Bukkit.getLogger().severe(
+ "Flag conflict found! The plugin will not work properly! Please contact the developers of the plugin.");
e.printStackTrace();
}
@@ -100,6 +107,18 @@ static void registerHandlers() {
SessionManager sessionManager = WorldGuard.getInstance().getPlatform().getSessionManager();
sessionManager.registerHandler(GreetingFlagHandler.FACTORY, ExitFlag.FACTORY);
sessionManager.registerHandler(FarewellFlagHandler.FACTORY, ExitFlag.FACTORY);
+
+ // Register handlers for standard WorldGuard flags to support MiniMessage
+ try {
+ sessionManager.registerHandler(new dev.espi.protectionstones.flags.PSMessageFlagHandler.Factory(
+ (Flag) dev.espi.protectionstones.utils.WGUtils.getFlagRegistry().get("greeting"), false,
+ false), ExitFlag.FACTORY);
+ sessionManager.registerHandler(new dev.espi.protectionstones.flags.PSMessageFlagHandler.Factory(
+ (Flag) dev.espi.protectionstones.utils.WGUtils.getFlagRegistry().get("farewell"), true,
+ false), ExitFlag.FACTORY);
+ } catch (Exception ignored) {
+ }
+
}
// adds flag permissions for ALL registered WorldGuard flags
@@ -123,12 +142,14 @@ static void initCustomFlagsForPS(ProtectedRegion region, Location l, PSProtectBl
}
public static List getPlayerPlaceholderFlags() {
- return Arrays.asList("greeting", "greeting-title", "greeting-action", "farewell", "farewell-title", "farewell-action");
+ return Arrays.asList("greeting", "greeting-title", "greeting-action", "farewell", "farewell-title",
+ "farewell-action");
}
// Edit flags that require placeholders (variables)
public static void initDefaultFlagPlaceholders(HashMap, Object> flags, Player p) {
- for (Flag> f : getPlayerPlaceholderFlags().stream().map(WGUtils.getFlagRegistry()::get).collect(Collectors.toList())) {
+ for (Flag> f : getPlayerPlaceholderFlags().stream().map(WGUtils.getFlagRegistry()::get)
+ .collect(Collectors.toList())) {
if (flags.get(f) != null) {
String s = (String) flags.get(f);
@@ -153,7 +174,8 @@ static void initDefaultFlagsForBlock(PSProtectBlock b) {
String[] splGroups = spl[1].split(",");
List groups = new ArrayList<>();
for (String g : splGroups) {
- if (FLAG_GROUPS.contains(g)) groups.add(g);
+ if (FLAG_GROUPS.contains(g))
+ groups.add(g);
}
b.allowedFlags.put(spl[2], groups);
@@ -161,7 +183,8 @@ static void initDefaultFlagsForBlock(PSProtectBlock b) {
b.allowedFlags.put(f, FLAG_GROUPS);
}
} catch (Exception e) {
- ProtectionStones.getInstance().getLogger().warning("Skipping flag " + f + ". Did you configure the allowed_flags section correctly?");
+ ProtectionStones.getInstance().getLogger()
+ .warning("Skipping flag " + f + ". Did you configure the allowed_flags section correctly?");
e.printStackTrace();
}
}
@@ -190,7 +213,8 @@ static void initDefaultFlagsForBlock(PSProtectBlock b) {
}
// get settings (after flag name)
- for (int i = startInd; i < split.length; i++) settings += split[i] + " ";
+ for (int i = startInd; i < split.length; i++)
+ settings += split[i] + " ";
settings = settings.trim();
// if the setting is set to -e, change to empty flag
@@ -204,7 +228,9 @@ static void initDefaultFlagsForBlock(PSProtectBlock b) {
// warn if flag setting has already been set
if (b.regionFlags.containsKey(flag)) {
- ProtectionStones.getPluginLogger().warning(String.format("Duplicate default flags found (only one flag setting can be applied for each flag)! Overwriting the previous value set for %s with \"%s\" ...", flagName, flagraw));
+ ProtectionStones.getPluginLogger().warning(String.format(
+ "Duplicate default flags found (only one flag setting can be applied for each flag)! Overwriting the previous value set for %s with \"%s\" ...",
+ flagName, flagraw));
}
// apply flag
@@ -214,7 +240,8 @@ static void initDefaultFlagsForBlock(PSProtectBlock b) {
RegionGroup rGroup = flag.getRegionGroupFlag().detectValue(group);
if (rGroup == null) {
- ProtectionStones.getPluginLogger().severe(String.format("Error parsing flag \"%s\", the group value is invalid!", flagraw));
+ ProtectionStones.getPluginLogger().severe(
+ String.format("Error parsing flag \"%s\", the group value is invalid!", flagraw));
continue;
}
diff --git a/src/main/java/dev/espi/protectionstones/ListenerClass.java b/src/main/java/dev/espi/protectionstones/ListenerClass.java
index 87175a00..d4488d3d 100644
--- a/src/main/java/dev/espi/protectionstones/ListenerClass.java
+++ b/src/main/java/dev/espi/protectionstones/ListenerClass.java
@@ -44,6 +44,8 @@
import org.bukkit.event.block.*;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.event.entity.ProjectileHitEvent;
+import org.bukkit.entity.EntityType;
import org.bukkit.event.inventory.*;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@@ -67,7 +69,8 @@ public void onPlayerJoin(PlayerJoinEvent e) {
UUIDCache.storeUUIDNamePair(p.getUniqueId(), p.getName());
// allow worldguard to resolve all UUIDs to names
- Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> UUIDCache.storeWGProfile(p.getUniqueId(), p.getName()));
+ Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(),
+ () -> UUIDCache.storeWGProfile(p.getUniqueId(), p.getName()));
// add recipes to player's recipe book
p.discoverRecipes(RecipeUtil.getRecipeKeys());
@@ -80,7 +83,8 @@ public void onPlayerJoin(PlayerJoinEvent e) {
}
// tax join message
- if (ProtectionStones.getInstance().getConfigOptions().taxEnabled && ProtectionStones.getInstance().getConfigOptions().taxMessageOnJoin) {
+ if (ProtectionStones.getInstance().getConfigOptions().taxEnabled
+ && ProtectionStones.getInstance().getConfigOptions().taxMessageOnJoin) {
Bukkit.getScheduler().runTaskAsynchronously(ProtectionStones.getInstance(), () -> {
int amount = 0;
for (PSRegion psr : psp.getTaxEligibleRegions()) {
@@ -96,7 +100,8 @@ public void onPlayerJoin(PlayerJoinEvent e) {
}
}
- // specifically add WG passthrough bypass here, so other plugins can see the result
+ // specifically add WG passthrough bypass here, so other plugins can see the
+ // result
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockPlaceLowPriority(PlaceBlockEvent event) {
var cause = event.getCause().getRootCause();
@@ -111,17 +116,21 @@ public void onBlockPlaceLowPriority(PlaceBlockEvent event) {
if (options != null && options.placingBypassesWGPassthrough) {
// check if any regions here have the passthrough flag
- // we can't query unfortunately, since null flags seem to equate to ALLOW, when we want it to be DENY
- ApplicableRegionSet set = WGUtils.getRegionManagerWithWorld(event.getWorld()).getApplicableRegions(BukkitAdapter.asBlockVector(block.getLocation()));
+ // we can't query unfortunately, since null flags seem to equate to ALLOW, when
+ // we want it to be DENY
+ ApplicableRegionSet set = WGUtils.getRegionManagerWithWorld(event.getWorld())
+ .getApplicableRegions(BukkitAdapter.asBlockVector(block.getLocation()));
- // loop through regions, if any region does not have a passthrough value set, then don't allow
+ // loop through regions, if any region does not have a passthrough value set,
+ // then don't allow
for (var region : set.getRegions()) {
if (region.getFlag(Flags.PASSTHROUGH) == null) {
return;
}
}
- // if every region with an explicit passthrough value, then allow passthrough of protection block
+ // if every region with an explicit passthrough value, then allow passthrough of
+ // protection block
event.setResult(Event.Result.ALLOW);
}
}
@@ -133,8 +142,10 @@ public void onBlockPlace(BlockPlaceEvent e) {
BlockHandler.createPSRegion(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
+ // 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) {
// check for destroy permission
if (!p.hasPermission("protectionstones.destroy")) {
@@ -146,7 +157,8 @@ private String checkPermissionToBreakProtection(Player p, PSRegion r) {
return PSL.NO_REGION_PERMISSION.msg();
}
- // cannot break region being rented (prevents splitting merged regions, and breaking as tenant owner)
+ // cannot break region being rented (prevents splitting merged regions, and
+ // breaking as tenant owner)
if (r.getRentStage() == PSRegion.RentStage.RENTING && !p.hasPermission("protectionstones.superowner")) {
return PSL.RENT_CANNOT_BREAK_WHILE_RENTING.msg();
}
@@ -167,10 +179,11 @@ private boolean playerBreakProtection(Player p, PSRegion r) {
}
// Call PSBreakEvent
- PSBreakProtectBlockEvent event = new PSBreakProtectBlockEvent(r , p);
+ PSBreakProtectBlockEvent event = new PSBreakProtectBlockEvent(r, p);
Bukkit.getPluginManager().callEvent(event);
// don't give ps block to player if the event is cancelled
- if (event.isCancelled()) return false;
+ if (event.isCancelled())
+ return false;
// return protection stone if no drop option is off
if (blockOptions != null && !blockOptions.noDrop) {
@@ -188,7 +201,9 @@ private boolean playerBreakProtection(Player p, PSRegion r) {
// check if removing the region and firing region remove event blocked it
if (!r.deleteRegion(true, p)) {
- if (!ProtectionStones.getInstance().getConfigOptions().allowMergingHoles) { // side case if the removing creates a hole and those are prevented
+ if (!ProtectionStones.getInstance().getConfigOptions().allowMergingHoles) { // side case if the removing
+ // creates a hole and those are
+ // prevented
PSL.msg(p, PSL.DELETE_REGION_PREVENTED_NO_HOLES.msg());
}
return false;
@@ -215,13 +230,15 @@ public void onPlayerInteract(PlayerInteractEvent e) {
}
// this will be the first event handler called in the chain
- // thus we should cancel the event here if possible (so other plugins don't start acting upon it)
+ // 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) {
Player p = e.getPlayer();
Block pb = e.getBlock();
- if (!ProtectionStones.isProtectBlock(pb)) return;
+ if (!ProtectionStones.isProtectBlock(pb))
+ return;
// check if player has permission to break the protection
PSRegion r = PSRegion.fromLocation(pb.getLocation());
@@ -242,15 +259,18 @@ public void onBlockBreak(BlockBreakEvent e) {
PSProtectBlock blockOptions = ProtectionStones.getBlockOptions(pb);
// check if block broken is protection stone type
- if (blockOptions == null) return;
+ if (blockOptions == null)
+ return;
// check if that is actually a protection stone block (owns a region)
if (!ProtectionStones.isProtectBlock(pb)) {
- // prevent silk touching of protection stone blocks (that aren't holding a region)
+ // prevent silk touching of protection stone blocks (that aren't holding a
+ // region)
if (blockOptions.preventSilkTouch) {
ItemStack left = p.getInventory().getItemInMainHand();
ItemStack right = p.getInventory().getItemInOffHand();
- if (!left.containsEnchantment(Enchantment.SILK_TOUCH) && !right.containsEnchantment(Enchantment.SILK_TOUCH)) {
+ if (!left.containsEnchantment(Enchantment.SILK_TOUCH)
+ && !right.containsEnchantment(Enchantment.SILK_TOUCH)) {
return;
}
e.setDropItems(false);
@@ -307,10 +327,13 @@ 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;
+ if (e.getBlock().getType() != Material.CRAFTER)
+ return;
+ if (!(e.getBlock().getState() instanceof Container container))
+ return;
for (ItemStack item : container.getInventory().getContents()) {
- if (item == null) continue;
+ if (item == null)
+ continue;
PSProtectBlock options = ProtectionStones.getBlockOptions(item);
if (options != null && !options.allowUseInCrafting) {
e.setCancelled(true);
@@ -320,7 +343,8 @@ public void onCrafter(CrafterCraftEvent e) {
}
}
- // -=-=-=- disable grindstone inventory to prevent infinite exp exploit with enchanted_effect option -=-=-=-
+ // -=-=-=- 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)
@@ -332,14 +356,14 @@ public void onInventoryClickEvent(InventoryClickEvent e) {
}
}
-
// -=-=-=- block changes to protection block related events -=-=-=-
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerBucketFill(PlayerBucketEmptyEvent e) {
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());
+ Block check = clicked.getWorld().getBlockAt(clicked.getX() + e.getBlockFace().getModX(),
+ clicked.getY() + bf.getModY(), clicked.getZ() + e.getBlockFace().getModZ());
if (ProtectionStones.isProtectBlock(check)) {
e.setCancelled(true);
}
@@ -372,7 +396,7 @@ public void onSpongeAbsorb(SpongeAbsorbEvent event) {
event.setCancelled(true);
}
}
-
+
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockFade(BlockFadeEvent e) {
if (ProtectionStones.isProtectBlock(e.getBlock())) {
@@ -389,23 +413,31 @@ public void onBlockForm(BlockFormEvent e) {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockDropItem(BlockDropItemEvent e) {
- // unfortunately, the below fix does not really work because Spigot only triggers for the source block, despite
- // what the documentation says: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/block/BlockDropItemEvent.html
-
- // we want to replace protection blocks that have their protection block broken (ex. signs, banners)
- // the block may not exist anymore, and so we have to recreate the isProtectBlock method here
+ // unfortunately, the below fix does not really work because Spigot only
+ // triggers for the source block, despite
+ // what the documentation says:
+ // https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/block/BlockDropItemEvent.html
+
+ // we want to replace protection blocks that have their protection block broken
+ // (ex. signs, banners)
+ // the block may not exist anymore, and so we have to recreate the
+ // isProtectBlock method here
BlockState bs = e.getBlockState();
- if (!ProtectionStones.isProtectBlockType(bs.getType().toString())) return;
+ if (!ProtectionStones.isProtectBlockType(bs.getType().toString()))
+ return;
RegionManager rgm = WGUtils.getRegionManagerWithWorld(bs.getWorld());
- if (rgm == null) return;
+ if (rgm == null)
+ return;
// check if the block is a source block
ProtectedRegion br = rgm.getRegion(WGUtils.createPSID(bs.getLocation()));
- if (!ProtectionStones.isPSRegion(br) && PSMergedRegion.getMergedRegion(bs.getLocation()) == null) return;
+ if (!ProtectionStones.isPSRegion(br) && PSMergedRegion.getMergedRegion(bs.getLocation()) == null)
+ return;
PSRegion r = PSRegion.fromLocation(bs.getLocation());
- if (r == null) return;
+ if (r == null)
+ return;
// puts the block back
r.unhide();
@@ -447,7 +479,8 @@ public void onEntityExplode(EntityExplodeEvent e) {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent e) {
- if (!ProtectionStones.isProtectBlock(e.getBlock())) return;
+ if (!ProtectionStones.isProtectBlock(e.getBlock()))
+ return;
// events like ender dragon block break, wither running into block break, etc.
if (!blockExplodeUtil(e.getBlock().getWorld(), e.getBlock())) {
@@ -456,6 +489,17 @@ public void onEntityChangeBlock(EntityChangeBlockEvent e) {
}
}
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onProjectileHit(ProjectileHitEvent e) {
+ if (e.getHitBlock() != null && ProtectionStones.isProtectBlock(e.getHitBlock())) {
+ EntityType type = e.getEntity().getType();
+ if (type == EntityType.WIND_CHARGE || type == EntityType.BREEZE_WIND_CHARGE) {
+ e.setCancelled(true);
+ e.getEntity().remove();
+ }
+ }
+ }
+
private void explodeUtil(List blockList, World w) {
// loop through exploded blocks
for (int i = 0; i < blockList.size(); i++) {
@@ -501,24 +545,30 @@ private boolean blockExplodeUtil(World w, Block b) {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
// we only want plugin triggered teleports, ignore natural teleportation
- if (event.getCause() == TeleportCause.ENDER_PEARL || event.getCause() == TeleportCause.CHORUS_FRUIT) return;
+ if (event.getCause() == TeleportCause.ENDER_PEARL || event.getCause() == TeleportCause.CHORUS_FRUIT)
+ return;
- if (event.getPlayer().hasPermission("protectionstones.tp.bypassprevent")) return;
+ if (event.getPlayer().hasPermission("protectionstones.tp.bypassprevent"))
+ return;
WorldGuardPlugin wg = WorldGuardPlugin.inst();
RegionManager rgm = WGUtils.getRegionManagerWithWorld(event.getTo().getWorld());
BlockVector3 v = BlockVector3.at(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
if (rgm != null) {
- // check if player can teleport into region (no region with preventTeleportIn = true)
+ // check if player can teleport into region (no region with preventTeleportIn =
+ // true)
ApplicableRegionSet regions = rgm.getApplicableRegions(v);
- if (regions.getRegions().isEmpty()) return;
+ if (regions.getRegions().isEmpty())
+ return;
boolean foundNoTeleport = false;
for (ProtectedRegion r : regions) {
String f = r.getFlag(FlagHandler.PS_BLOCK_MATERIAL);
- if (f != null && ProtectionStones.getBlockOptions(f) != null && ProtectionStones.getBlockOptions(f).preventTeleportIn)
+ if (f != null && ProtectionStones.getBlockOptions(f) != null
+ && ProtectionStones.getBlockOptions(f).preventTeleportIn)
foundNoTeleport = true;
- if (r.getOwners().contains(wg.wrapPlayer(event.getPlayer()))) return;
+ if (r.getOwners().contains(wg.wrapPlayer(event.getPlayer())))
+ return;
}
if (foundNoTeleport) {
@@ -531,32 +581,38 @@ public void onPlayerTeleport(PlayerTeleportEvent event) {
// -=-=-=- player defined events -=-=-=-
private void execEvent(String action, CommandSender s, String player, PSRegion region) {
- if (player == null) player = "";
+ if (player == null)
+ player = "";
// split action_type: action
String[] sp = action.split(": ");
- if (sp.length == 0) return;
+ if (sp.length == 0)
+ return;
StringBuilder act = new StringBuilder(sp[1]);
- for (int i = 2; i < sp.length; i++) act.append(": ").append(sp[i]); // add anything extra that has a colon
+ for (int i = 2; i < sp.length; i++)
+ act.append(": ").append(sp[i]); // add anything extra that has a colon
act = new StringBuilder(act.toString()
.replace("%player%", player)
.replace("%world%", region.getWorld().getName())
- .replace("%region%", region.getName() == null ? region.getId() : region.getName() + " (" + region.getId() + ")")
+ .replace("%region%",
+ region.getName() == null ? region.getId() : region.getName() + " (" + region.getId() + ")")
.replace("%block_x%", region.getProtectBlock().getX() + "")
.replace("%block_y%", region.getProtectBlock().getY() + "")
.replace("%block_z%", region.getProtectBlock().getZ() + ""));
switch (sp[0]) {
case "player_command":
- if (s != null) Bukkit.getServer().dispatchCommand(s, act.toString());
+ if (s != null)
+ Bukkit.getServer().dispatchCommand(s, act.toString());
break;
case "console_command":
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), act.toString());
break;
case "message":
- if (s != null) s.sendMessage(ChatColor.translateAlternateColorCodes('&', act.toString()));
+ if (s != null)
+ s.sendMessage(ChatColor.translateAlternateColorCodes('&', act.toString()));
break;
case "global_message":
for (Player p : Bukkit.getOnlinePlayers()) {
@@ -572,10 +628,13 @@ private void execEvent(String action, CommandSender s, String player, PSRegion r
@EventHandler
public void onPSCreate(PSCreateEvent event) {
- if (event.isCancelled()) return;
- if (!event.getRegion().getTypeOptions().eventsEnabled) return;
+ if (event.isCancelled())
+ return;
+ if (!event.getRegion().getTypeOptions().eventsEnabled)
+ return;
- // run on next tick (after the region is created to allow for edits to the region)
+ // run on next tick (after the region is created to allow for edits to the
+ // region)
Bukkit.getServer().getScheduler().runTask(ProtectionStones.getInstance(), () -> {
// run custom commands (in config)
for (String action : event.getRegion().getTypeOptions().regionCreateCommands) {
@@ -586,9 +645,12 @@ public void onPSCreate(PSCreateEvent event) {
@EventHandler
public void onPSRemove(PSRemoveEvent event) {
- if (event.isCancelled()) return;
- if (event.getRegion().getTypeOptions() == null) return;
- if (!event.getRegion().getTypeOptions().eventsEnabled) return;
+ if (event.isCancelled())
+ return;
+ if (event.getRegion().getTypeOptions() == null)
+ return;
+ if (!event.getRegion().getTypeOptions().eventsEnabled)
+ return;
// run custom commands (in config)
for (String action : event.getRegion().getTypeOptions().regionDestroyCommands) {
diff --git a/src/main/java/dev/espi/protectionstones/PSGroupRegion.java b/src/main/java/dev/espi/protectionstones/PSGroupRegion.java
index 2d5bc3df..51f5e35b 100644
--- a/src/main/java/dev/espi/protectionstones/PSGroupRegion.java
+++ b/src/main/java/dev/espi/protectionstones/PSGroupRegion.java
@@ -19,6 +19,7 @@
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import dev.espi.protectionstones.utils.MiscUtil;
import dev.espi.protectionstones.utils.Objs;
+import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
@@ -28,8 +29,10 @@
import java.util.stream.Collectors;
/**
- * Represents a region that exists but is a group of merged {@link PSStandardRegion}s.
- * Contains multiple {@link PSMergedRegion} representing the individual merged regions (which don't technically exist in WorldGuard).
+ * Represents a region that exists but is a group of merged
+ * {@link PSStandardRegion}s.
+ * Contains multiple {@link PSMergedRegion} representing the individual merged
+ * regions (which don't technically exist in WorldGuard).
*/
public class PSGroupRegion extends PSStandardRegion {
@@ -66,12 +69,14 @@ public void updateTaxPayments() {
long currentTime = System.currentTimeMillis();
List payments = Objs.replaceNull(getTaxPaymentsDue(), new ArrayList<>());
- List lastAdded = Objs.replaceNull(getRegionLastTaxPaymentAddedEntries(), new ArrayList<>());
+ List lastAdded = Objs.replaceNull(getRegionLastTaxPaymentAddedEntries(),
+ new ArrayList<>());
// loop over merged regions
for (PSMergedRegion r : getMergedRegions()) {
// taxes disabled
- if (getTypeOptions().taxPeriod == -1) continue;
+ if (getTypeOptions().taxPeriod == -1)
+ continue;
boolean found = false;
for (LastRegionTaxPaymentEntry last : lastAdded) {
@@ -79,8 +84,11 @@ public void updateTaxPayments() {
if (last.getRegionId().equals(r.getId())) {
found = true;
// if it's time to pay
- if (last.getLastPaymentAdded() + Duration.ofSeconds(r.getTypeOptions().taxPeriod).toMillis() < currentTime) {
- payments.add(new TaxPayment(currentTime + Duration.ofSeconds(r.getTypeOptions().taxPaymentTime).toMillis(), r.getTaxRate(), r.getId()));
+ if (last.getLastPaymentAdded()
+ + Duration.ofSeconds(r.getTypeOptions().taxPeriod).toMillis() < currentTime) {
+ payments.add(new TaxPayment(
+ currentTime + Duration.ofSeconds(r.getTypeOptions().taxPaymentTime).toMillis(),
+ r.getTaxRate(), r.getId()));
last.setLastPaymentAdded(currentTime);
}
break;
@@ -88,7 +96,9 @@ public void updateTaxPayments() {
}
if (!found) {
- payments.add(new TaxPayment(currentTime + Duration.ofSeconds(r.getTypeOptions().taxPaymentTime).toMillis(), r.getTaxRate(), r.getId()));
+ payments.add(
+ new TaxPayment(currentTime + Duration.ofSeconds(r.getTypeOptions().taxPaymentTime).toMillis(),
+ r.getTaxRate(), r.getId()));
lastAdded.add(new LastRegionTaxPaymentEntry(r.getId(), currentTime));
}
}
@@ -98,13 +108,15 @@ public void updateTaxPayments() {
@Override
public boolean hide() {
- for (PSMergedRegion r : getMergedRegions()) r.hide();
+ for (PSMergedRegion r : getMergedRegions())
+ r.hide();
return true;
}
@Override
public boolean unhide() {
- for (PSMergedRegion r : getMergedRegions()) r.unhide();
+ for (PSMergedRegion r : getMergedRegions())
+ r.unhide();
return true;
}
@@ -125,18 +137,22 @@ public boolean deleteRegion(boolean deleteBlock, Player cause) {
/**
* Get the merged region whose ID is the same as the group region ID.
+ *
* @return the root region
*/
public PSMergedRegion getRootRegion() {
for (PSMergedRegion r : getMergedRegions()) {
- if (r.getId().equals(getId())) return r;
+ if (r.getId().equals(getId()))
+ return r;
}
return null;
}
/**
* Check if this region contains a specific merged region
- * @param id the psID that would've been generated if the merged region was a standard region
+ *
+ * @param id the psID that would've been generated if the merged region was a
+ * standard region
* @return whether or not the id is a merged region
*/
public boolean hasMergedRegion(String id) {
@@ -145,7 +161,9 @@ public boolean hasMergedRegion(String id) {
/**
* Removes the merged region's information from the object.
- * Note: This DOES NOT remove the actual PSMergedRegion object, you have to call deleteRegion() on that as well.
+ * Note: This DOES NOT remove the actual PSMergedRegion object, you have to call
+ * deleteRegion() on that as well.
+ *
* @param id the id of the merged region
*/
public void removeMergedRegionInfo(String id) {
@@ -166,14 +184,17 @@ public void removeMergedRegionInfo(String id) {
if (getWGRegion().getFlag(FlagHandler.PS_TAX_LAST_PAYMENT_ADDED) != null) {
String entry = "";
for (String e : getWGRegion().getFlag(FlagHandler.PS_TAX_LAST_PAYMENT_ADDED)) {
- if (e.startsWith(id)) entry = e;
+ if (e.startsWith(id))
+ entry = e;
}
getWGRegion().getFlag(FlagHandler.PS_TAX_LAST_PAYMENT_ADDED).remove(entry);
}
}
/**
- * Get the list of {@link PSMergedRegion} objects of the regions that were merged into this region.
+ * Get the list of {@link PSMergedRegion} objects of the regions that were
+ * merged into this region.
+ *
* @return the list of regions merged into this region
*/
public List getMergedRegions() {
@@ -183,8 +204,11 @@ public List getMergedRegions() {
}
/**
- * Get the list of {@link PSMergedRegion} objects of the regions that were merged into this region.
- * Note: This is unsafe as it includes {@link PSMergedRegion}s that are of types not configured in the config.
+ * Get the list of {@link PSMergedRegion} objects of the regions that were
+ * merged into this region.
+ * Note: This is unsafe as it includes {@link PSMergedRegion}s that are of types
+ * not configured in the config.
+ *
* @return the list of regions merged into this region
*/
public List getMergedRegionsUnsafe() {
@@ -196,4 +220,17 @@ public List getMergedRegionsUnsafe() {
}
return l;
}
+
+ public PSMergedRegion getMergedRegion(Location l) {
+ if (l == null)
+ return null;
+ com.sk89q.worldedit.math.BlockVector3 v = com.sk89q.worldedit.math.BlockVector3.at(l.getX(), l.getY(),
+ l.getZ());
+ for (PSMergedRegion r : getMergedRegions()) {
+ if (r.getWGRegion().contains(v)) {
+ return r;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/main/java/dev/espi/protectionstones/PSL.java b/src/main/java/dev/espi/protectionstones/PSL.java
index b64c3248..2f700a6c 100644
--- a/src/main/java/dev/espi/protectionstones/PSL.java
+++ b/src/main/java/dev/espi/protectionstones/PSL.java
@@ -22,515 +22,766 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public enum PSL {
- // messages.yml
-
- COOLDOWN("cooldown", ChatColor.GOLD + "Warning: " + ChatColor.GRAY + "Please wait for %time% seconds before placing again!"),
- NO_SUCH_COMMAND("no_such_command", ChatColor.RED + "No such command. please type /ps help for more info"),
- NO_ACCESS("no_access", ChatColor.RED + "You are not allowed to do that here."),
- NO_ROOM_IN_INVENTORY("no_room_in_inventory", ChatColor.RED + "You don't have enough room in your inventory."),
- NO_ROOM_DROPPING_ON_FLOOR("no_room_dropping_on_floor", ChatColor.RED + "You don't have enough room in your inventory. Dropping item on floor."),
- INVALID_BLOCK("invalid_block", ChatColor.RED + "Invalid protection block."),
- NOT_ENOUGH_MONEY("not_enough_money", ChatColor.RED + "You don't have enough money! The price is %price%."),
- PAID_MONEY("paid_money", ChatColor.AQUA + "You've paid $%price%."),
- INVALID_WORLD("invalid_world", ChatColor.RED + "Invalid world."),
- MUST_BE_PLAYER("must_be_player", ChatColor.RED + "You must be a player to execute this command."),
- GO_BACK_PAGE("go_back_page", "Go back a page."),
- GO_NEXT_PAGE("go_next_page", "Go to next page."),
- PAGE_DOES_NOT_EXIST("page_does_not_exist", ChatColor.RED + "Page does not exist."),
-
- HELP("help", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " PS Help " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "=====\n" + ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps help"),
- HELP_NEXT("help_next", ChatColor.GRAY + "Do /ps help %page% to go to the next page!"),
-
- COMMAND_REQUIRES_PLAYER_NAME("command_requires_player_name", ChatColor.RED + "This command requires a player name."),
-
- NO_PERMISSION_TOGGLE("no_permission_toggle", ChatColor.RED + "You don't have permission to use the toggle command."),
- NO_PERMISSION_CREATE("no_permission_create", ChatColor.RED + "You don't have permission to place a protection block."),
- NO_PERMISSION_CREATE_SPECIFIC("no_permission_create_specific", ChatColor.RED + "You don't have permission to place this protection block type."),
- NO_PERMISSION_DESTROY("no_permission_destroy", ChatColor.RED + "You don't have permission to destroy a protection block."),
- NO_PERMISSION_MEMBERS("no_permission_members", "&cYou don't have permission to use member commands."),
- NO_PERMISSION_OWNERS("no_permission_owners", "&cYou don't have permission to use owner commands."),
- NO_PERMISSION_ADMIN("no_permission_admin", ChatColor.RED + "You do not have permission to use that command."),
- NO_PERMISSION_COUNT("no_permission_count", ChatColor.RED + "You do not have permission to use that command."),
- NO_PERMISSION_COUNT_OTHERS("no_permission_count_others", ChatColor.RED + "You do not have permission to use that command."),
- NO_PERMISSION_FLAGS("no_permission_flags", "&cYou do not have permission to use flag commands."),
- NO_PERMISSION_PER_FLAG("no_permission_per_flag", ChatColor.RED + "You do not have permission to use that flag."),
- NO_PERMISSION_RENT("no_permission_rent", ChatColor.RED + "You do not have permission for renting."),
- NO_PERMISSION_TAX("no_permission_tax", ChatColor.RED + "You do not have permission to use the tax command."),
- NO_PERMISSION_BUYSELL("no_permission_buysell", ChatColor.RED + "You do not have permission to buy and sell regions."),
- NO_PERMISSION_UNHIDE("no_permission_unhide", ChatColor.RED + "You do not have permission to unhide protection blocks."),
- NO_PERMISSION_HIDE("no_permission_hide", ChatColor.RED + "You do not have permission to hide protection blocks."),
- NO_PERMISSION_INFO("no_permission_info", ChatColor.RED + "You do not have permission to use the region info command."),
- NO_PERMISSION_PRIORITY("no_permission_priority", ChatColor.RED + "You do not have permission to use the priority command."),
- NO_PERMISSION_REGION("no_permission_region", ChatColor.RED + "You do not have permission to use region commands."),
- NO_PERMISSION_TP("no_permission_tp", ChatColor.RED + "You do not have permission to teleport to other players' protection blocks."),
- NO_PERMISSION_HOME("no_permission_home", ChatColor.RED + "You do not have permission to teleport to your protection blocks."),
- NO_PERMISSION_UNCLAIM("no_permission_unclaim", ChatColor.RED + "You do not have permission to use the unclaim command."),
- NO_PERMISSION_UNCLAIM_REMOTE("no_permission_unclaim_remote", ChatColor.RED + "You do not have permission to use the unclaim remote command."),
- NO_PERMISSION_VIEW("no_permission_view", ChatColor.RED + "You do not have permission to use the view command."),
- NO_PERMISSION_GIVE("no_permission_give", ChatColor.RED + "You do not have permission to use the give command."),
- NO_PERMISSION_GET("no_permission_get", ChatColor.RED + "You do not have permission to use the get command."),
- NO_PERMISSION_SETHOME("no_permission_sethome", ChatColor.RED + "You do not have permission to use the sethome command."),
- NO_PERMISSION_LIST("no_permission_list", ChatColor.RED + "You do not have permission to use the list command."),
- NO_PERMISSION_LIST_OTHERS("no_permission_list_others", ChatColor.RED + "You do not have permission to use the list command for others."),
- NO_PERMISSION_NAME("no_permission_name", ChatColor.RED + "You do not have permission to use the name command."),
- NO_PERMISSION_SETPARENT("no_permission_setparent", ChatColor.RED + "You do not have permission to use the setparent command."),
- NO_PERMISSION_SETPARENT_OTHERS("no_permission_setparent_others", ChatColor.RED + "You do not have permission to inherit from regions you don't own."),
- NO_PERMISSION_MERGE("no_permission_merge", ChatColor.RED + "You do not have permission to use /ps merge."),
-
- ADDED_TO_REGION("psregion.added_to_region", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been added to this region."),
- ADDED_TO_REGION_SPECIFIC("psregion.added_to_region_specific", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been added to region %region%."),
- REMOVED_FROM_REGION("psregion.removed_from_region", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been removed from region."),
- REMOVED_FROM_REGION_SPECIFIC("psregion.removed_from_region_specific", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been removed from region %region%."),
- NOT_IN_REGION("psregion.not_in_region", ChatColor.RED + "You are not in a protection stones region!"),
- PLAYER_NOT_FOUND("psregion.player_not_found", ChatColor.RED + "Player not found."),
- NOT_PS_REGION("psregion.not_ps_region", ChatColor.RED + "Not a protection stones region."),
- REGION_DOES_NOT_EXIST("psregion.region_does_not_exist", ChatColor.RED + "Region does not exist."),
- NO_REGIONS_OWNED("psregion.no_regions_owned", ChatColor.RED + "You don't own any protected regions in this world!"),
- NO_REGION_PERMISSION("psregion.no_region_permission", ChatColor.RED + "You do not have permission to do this in this region."),
- PROTECTED("psregion.protected", ChatColor.AQUA + "This area is now protected."),
- NO_LONGER_PROTECTED("psregion.no_longer_protected", ChatColor.YELLOW + "This area is no longer protected."),
- CANT_PROTECT_THAT("psregion.cant_protect_that", ChatColor.RED + "You can't protect that area."),
- REACHED_REGION_LIMIT("psregion.reached_region_limit", ChatColor.RED + "You can not have any more protected regions (%limit%)."),
- REACHED_PER_BLOCK_REGION_LIMIT("psregion.reached_per_block_region_limit", ChatColor.RED + "You can not have any more regions of this type (%limit%)."),
- WORLD_DENIED_CREATE("psregion.world_denied_create", ChatColor.RED + "You can not create protections in this world."),
- REGION_OVERLAP("psregion.region_overlap", ChatColor.RED + "You can not place a protection block here as it overlaps another region."),
- REGION_TOO_CLOSE("psregion.region_too_close", ChatColor.RED + "Your protection block must be a minimum of %num% blocks from the edge of other regions!"),
- REGION_CANT_TELEPORT("psregion.cant_teleport", ChatColor.RED + "Your teleportation was blocked by a protection region!"),
- SPECIFY_ID_INSTEAD_OF_ALIAS("psregion.specify_id_instead_of_alias", ChatColor.GRAY + "There were multiple regions found with this name! Please use an ID instead.\n Regions with this name: " + ChatColor.AQUA + "%regions%"),
- REGION_NOT_ADJACENT("psregion.region_not_adjacent", ChatColor.RED + "You've passed the limit of non-adjacent regions! Try putting your protection block closer to other regions you already own."),
- REGION_NOT_OVERLAPPING("psregion.not_overlapping", ChatColor.RED + "These regions don't overlap each other!"),
- MULTI_REGION_DOES_NOT_EXIST("psregion.multi_region_does_not_exist", "One of these regions don't exist!"),
- NO_REGION_HOLES("psregion.no_region_holes", ChatColor.RED + "Unprotected area detected inside region! This is not allowed!"),
- DELETE_REGION_PREVENTED_NO_HOLES("psregion.delete_region_prevented", ChatColor.GRAY + "The region could not be removed, possibly because it creates a hole in the existing region."),
- NOT_OWNER("psregion.not_owner", ChatColor.RED + "You are not an owner of this region!"),
- CANNOT_MERGE_RENTED_REGION("psregion.cannot_merge_rented_region", ChatColor.RED + "Cannot merge regions because region %region% is in the process of being rented out!"),
- NO_PERMISSION_REGION_TYPE("psregion.no_permission_region_type", ChatColor.RED + "You do not have permission to have this region type."),
- REGION_HIDDEN("psregion.hidden", ChatColor.GRAY + "The protection block is now hidden."),
- MUST_BE_PLACED_IN_EXISTING_REGION("psregion.must_be_placed_in_existing_region", ChatColor.RED + "This must be placed inside of an existing region!"),
- REGION_ALREADY_IN_LOCATION_IS_HIDDEN("psregion.already_in_location_is_hidden", ChatColor.RED + "A region already exists in this location (is the protection block hidden?)"),
- CANNOT_REMOVE_YOURSELF_LAST_OWNER("psregion.cannot_remove_yourself_last_owner", ChatColor.RED + "You cannot remove yourself as you are the last owner."),
- CANNOT_REMOVE_YOURSELF_FROM_ALL_REGIONS("psregion.cannot_remove_yourself_all_regions", ChatColor.RED + "You cannot remove yourself from all of your regions at once, for safety reasons."),
-
- // ps toggle
- TOGGLE_HELP("toggle.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps toggle|on|off"),
- TOGGLE_HELP_DESC("toggle.help_desc", "Use this command to turn on or off placement of protection blocks."),
- TOGGLE_ON("toggle.toggle_on", ChatColor.AQUA + "Protection block placement turned on."),
- TOGGLE_OFF("toggle.toggle_off", ChatColor.AQUA + "Protection block placement turned off."),
-
- // ps count
- COUNT_HELP("count.count_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps count [player (optional)]"),
- COUNT_HELP_DESC("count.count_help_desc", "Count the number of regions you own or another player."),
- PERSONAL_REGION_COUNT("count.personal_region_count", ChatColor.GRAY + "Your region count in this world: " + ChatColor.AQUA + "%num%"),
- PERSONAL_REGION_COUNT_MERGED("count.personal_region_count_merged", ChatColor.GRAY + "- Including each merged region: " + ChatColor.AQUA + "%num%"),
- OTHER_REGION_COUNT("count.other_region_count", ChatColor.GRAY + "%player%'s region count in this world: " + ChatColor.AQUA + "%num%"),
- OTHER_REGION_COUNT_MERGED("count.other_region_count_merged", ChatColor.GRAY + "- Including each merged region: " + ChatColor.AQUA + "%num%"),
-
- // ps flag
- FLAG_HELP("flag.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps flag [flagname] [value|null|default]"),
- FLAG_HELP_DESC("flag.help_desc", "Use this command to set a flag in your protected region."),
- FLAG_SET("flag.flag_set", ChatColor.AQUA + "%flag%" + ChatColor.GRAY + " flag has been set."),
- FLAG_NOT_SET("flag.flag_not_set", ChatColor.AQUA + "%flag%" + ChatColor.GRAY + " flag has " + ChatColor.RED + "not" + ChatColor.GRAY + " been set. Check your values again."),
- FLAG_PREVENT_EXPLOIT("flag.flag_prevent_exploit", ChatColor.RED + "This has been disabled to prevent exploits."),
- FLAG_PREVENT_EXPLOIT_HOVER("flag.flag_prevent_exploit_hover", ChatColor.RED + "Disabled for security reasons."),
- FLAG_GUI_HEADER("flag.gui_header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Flags (click to change) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- FLAG_GUI_HOVER_SET("flag.gui_hover_set", ChatColor.AQUA + "Click to set."),
- FLAG_GUI_HOVER_SET_TEXT("flag.gui_hover_set_text", ChatColor.AQUA + "Click to change." + ChatColor.WHITE + "\nCurrent value:\n%value%"),
- FLAG_GUI_HOVER_CHANGE_GROUP("flag.hover_change_group", "Click to set this flag to apply to only %group%."),
- FLAG_GUI_HOVER_CHANGE_GROUP_NULL("flag.hover_change_group_null", ChatColor.RED + "You must set this flag to a value before changing the group."),
-
- // ps rent
- RENT_HELP("rent.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps rent"),
- RENT_HELP_DESC("rent.help_desc", "Use this command to manage rents (buying and selling)."),
- RENT_HELP_HEADER("rent.help_header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Rent Help " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- RENT_ALREADY_RENTING("rent.already_renting", ChatColor.RED + "The region is already being rented out! You must stop leasing the region first."),
- RENT_NOT_RENTED("rent.not_rented", ChatColor.RED + "This region is not being rented."),
- RENT_LEASE_SUCCESS("rent.lease_success", ChatColor.AQUA + "Region leasing terms set:\n" + ChatColor.AQUA + "Price: " + ChatColor.GRAY + "%price%\n" + ChatColor.AQUA + "Payment Term: " + ChatColor.GRAY + "%period%"),
- RENT_STOPPED("rent.stopped", ChatColor.AQUA + "Leasing stopped."),
- RENT_EVICTED("rent.evicted", ChatColor.GRAY + "Evicted tenant %tenant%."),
- RENT_NOT_RENTING("rent.not_renting", ChatColor.RED + "This region is not being rented out to tenants."),
- RENT_PAID_LANDLORD("rent.paid_landlord", ChatColor.AQUA + "%tenant%" + ChatColor.GRAY + " has paid " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + " for renting out " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
- RENT_PAID_TENANT("rent.paid_tenant", ChatColor.GRAY + "Paid " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + " to " + ChatColor.AQUA + "%landlord%" + ChatColor.GRAY + " for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
- RENT_RENTING_LANDLORD("rent.renting_landlord", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " is now renting out region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
- RENT_RENTING_TENANT("rent.renting_tenant", ChatColor.GRAY + "You are now renting out region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " for " + ChatColor.AQUA + "%price%" + ChatColor.GRAY + " per " + ChatColor.AQUA + "%period%" + ChatColor.GRAY + "."),
- RENT_NOT_TENANT("rent.not_tenant", ChatColor.RED + "You are not the tenant of this region!"),
- RENT_TENANT_STOPPED_LANDLORD("rent.tenant_stopped_landlord", ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has stopped renting out region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + ". It is now available for others to rent."),
- RENT_TENANT_STOPPED_TENANT("rent.tenant_stopped_tenant", ChatColor.AQUA + "You have stopped renting out region %region%."),
- RENT_BEING_SOLD("rent.being_sold", ChatColor.RED + "The region is being sold! Do /ps sell stop first."),
- RENT_EVICT_NO_MONEY_TENANT("rent.evict_no_money_tenant", ChatColor.GRAY + "You have been " + ChatColor.RED + "evicted" + ChatColor.GRAY + " from region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " because you do not have enough money (%price%) to pay for rent."),
- RENT_EVICT_NO_MONEY_LANDLORD("rent.evict_no_money_landlord", ChatColor.AQUA + "%tenant%" + ChatColor.GRAY + " has been " + ChatColor.RED + "evicted" + ChatColor.GRAY + " from region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " because they are unable to afford rent."),
- RENT_CANNOT_RENT_OWN_REGION("rent.cannot_rent_own_region", ChatColor.RED + "You cannot rent your own region!"),
- RENT_REACHED_LIMIT("rent.reached_limit", ChatColor.RED + "You've reached the limit of regions you are allowed to rent!"),
- RENT_PRICE_TOO_LOW("rent.price_too_low", ChatColor.RED + "The rent price is too low (must be larger than %price%)."),
- RENT_PRICE_TOO_HIGH("rent.price_too_high", ChatColor.RED + "The rent price is too high (must be lower than %price%)."),
- RENT_PERIOD_TOO_SHORT("rent.period_too_short", ChatColor.RED + "The rent period is too short (must be longer than %period% seconds)."),
- RENT_PERIOD_TOO_LONG("rent.period_too_long", ChatColor.RED + "The rent period is too long (must be shorter than %period% seconds)."),
- RENT_PERIOD_INVALID("rent.period_invalid", ChatColor.RED + "Invalid period format! Example: 24h for once a day."),
- RENT_CANNOT_BREAK_WHILE_RENTING("rent.cannot_break_while_renting", ChatColor.RED + "You cannot break the region when it is being rented out."),
-
- // ps tax
- TAX_HELP("tax.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps tax"),
- TAX_HELP_DESC("tax.help_desc", "Use this command to manage and pay taxes."),
- TAX_HELP_HEADER("tax.help_header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Taxes Help " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- TAX_DISABLED_REGION("tax.disabled_region", ChatColor.RED + "Taxes are disabled for this region."),
- TAX_SET_AS_AUTOPAYER("tax.set_as_autopayer", ChatColor.GRAY + "Taxes for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " will now be automatically paid by you."),
- TAX_SET_NO_AUTOPAYER("tax.set_no_autopayer", ChatColor.GRAY + "Taxes for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " now have to be manually paid for."),
- TAX_PAID("tax.paid", ChatColor.GRAY + "Paid " + ChatColor.AQUA + "$%amount%" + ChatColor.GRAY + " in taxes for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
- TAX_INFO_HEADER("tax.info_header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Tax Info (click for more info) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- TAX_JOIN_MSG_PENDING_PAYMENTS("tax.join_msg_pending_payments", ChatColor.GRAY + "You have " + ChatColor.AQUA + "$%money%" + ChatColor.GRAY + " in tax payments due on your regions!\nView them with /ps tax info."),
- TAX_PLAYER_REGION_INFO("tax.player_region_info", ChatColor.GRAY + "> " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " - " + ChatColor.DARK_AQUA + "$%money% due"),
- TAX_PLAYER_REGION_INFO_AUTOPAYER("tax.player_region_info_autopayer", ChatColor.GRAY + "> " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " - " + ChatColor.DARK_AQUA + "$%money% due" + ChatColor.GRAY + " (you autopay)"),
- TAX_CLICK_TO_SHOW_MORE_INFO("tax.click_to_show_more_info", "Click to show more information."),
- TAX_REGION_INFO_HEADER("tax.region_info_header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " %region% Tax Info " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- TAX_REGION_INFO("tax.region_info", ChatColor.BLUE + "Tax Rate: " + ChatColor.GRAY + "$%taxrate% (sum of all merged regions)" + "\n"
- + ChatColor.BLUE + "Time between tax cycles: " + ChatColor.GRAY + "%taxperiod%" + "\n"
- + ChatColor.BLUE + "Time to pay taxes after cycle: " + ChatColor.GRAY + "%taxpaymentperiod%" + "\n"
- + ChatColor.BLUE + "Tax Autopayer: " + ChatColor.GRAY + "%taxautopayer%" + "\n"
- + ChatColor.BLUE + "Taxes Owed: " + ChatColor.GRAY + "$%taxowed%"),
- TAX_NEXT("tax.next_page", ChatColor.GRAY + "Do /ps tax info -p %page% to go to the next page!"),
-
- // ps buy
- BUY_HELP("buy.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps buy"),
- BUY_HELP_DESC("buy.help_desc", "Buy the region you are currently in."),
- BUY_NOT_FOR_SALE("buy.not_for_sale", ChatColor.RED + "This region is not for sale."),
- BUY_STOP_SELL("buy.stop_sell", ChatColor.GRAY + "The region is now not for sale."),
- BUY_SOLD_BUYER("buy.sold_buyer", ChatColor.GRAY + "Bought region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " for " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + " from " + ChatColor.AQUA + "%player%" + ChatColor.GRAY + "."),
- BUY_SOLD_SELLER("buy.sold_seller", ChatColor.GRAY + "Sold region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " for " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + " to " + ChatColor.AQUA + "%player%" + ChatColor.GRAY + "."),
-
- // ps sell
- SELL_HELP("sell.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps sell [price|stop]"),
- SELL_HELP_DESC("sell.help_desc", "Sell the region you are currently in."),
- SELL_RENTED_OUT("sell.rented_out", ChatColor.RED + "The region is being rented out! You must stop renting it out to sell."),
- SELL_FOR_SALE("sell.for_sale", ChatColor.GRAY + "The region is now for sale for " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + "."),
-
- // ps hide/unhide
- VISIBILITY_HIDE_HELP("visibility.hide_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps hide"),
- VISIBILITY_HIDE_HELP_DESC("visibility.hide_help_desc", "Use this command to hide or unhide your protection block."),
- VISIBILITY_UNHIDE_HELP("visibility.unhide_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps unhide"),
- VISIBILITY_UNHIDE_HELP_DESC("visibility.unhide_help_desc", "Use this command to hide or unhide your protection block."),
- ALREADY_NOT_HIDDEN("visibility.already_not_hidden", ChatColor.GRAY + "The protection stone doesn't appear hidden..."),
- ALREADY_HIDDEN("visibility.already_hidden", ChatColor.GRAY + "The protection stone appears to already be hidden..."),
-
- // ps info
- INFO_HELP("info.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps info members|owners|flags"),
- INFO_HELP_DESC("info.help_desc", "Use this command inside a ps region to see more information about it."),
- INFO_HEADER("info.header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " PS Info " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- INFO_TYPE2("info.type2", "&9Type: &7%type%", "%type%"),
- INFO_MAY_BE_MERGED("info.may_be_merged", "(may be merged with other types)"),
- INFO_MERGED2("info.merged2", ChatColor.BLUE + "Merged regions: " + ChatColor.GRAY + "%merged%", "%merged%"),
- INFO_MEMBERS2("info.members2", "&9Members: &7%members%", "%members%"),
- INFO_NO_MEMBERS("info.no_members", ChatColor.RED + "(no members)"),
- INFO_OWNERS2("info.owners2", "&9Owners: &7%owners%", "%owners%"),
- INFO_NO_OWNERS("info.no_owners", ChatColor.RED + "(no owners)"),
- INFO_FLAGS2("info.flags2", "&9Flags: &7%flags%", "%flags%"),
- INFO_NO_FLAGS("info.no_flags", "(none)"),
- INFO_REGION2("info.region2", "&9Region: &b%region%", "%region%"),
- INFO_PRIORITY2("info.priority2", "&9Priority: &b%priority%", "%priority%"),
- INFO_PARENT2("info.parent2", "&9Parent: &b%parentregion%", "%parentregion%"),
- INFO_BOUNDS_XYZ("info.bounds_xyz", "&9Bounds: &b(%minx%,%miny%,%minz%) -> (%maxx%,%maxy%,%maxz%)",
- "%minx%", "%miny%", "%minz%", "%maxx%", "%maxy%", "%maxz%"
- ),
- INFO_BOUNDS_XZ("info.bounds_xz", "&9Bounds: &b(%minx%, %minz%) -> (%maxx%, %maxz%)",
- "%minx%", "%minz%", "%maxx%", "%maxz%"
- ),
- INFO_SELLER2("info.seller2", "&9Seller: &7%seller%", "%seller%"),
- INFO_PRICE2("info.price2", "&9Price: &7%price%", "%price%"),
- INFO_TENANT2("info.tenant2", "&9Tenant: &7%tenant%", "%tenant%"),
- INFO_LANDLORD2("info.landlord2", "&9Landlord: &7%landlord%", "%landlord%"),
- INFO_RENT2("info.rent2", "&9Rent: &7%rent%", "%rent%"),
- INFO_AVAILABLE_FOR_SALE("info.available_for_sale", ChatColor.AQUA + "Region available for sale!"),
- INFO_AVAILABLE_FOR_RENT("info.available_for_rent", ChatColor.AQUA + "Region available for rent!"),
-
- // ps priority
- PRIORITY_HELP("priority.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps priority [number|null]"),
- PRIORITY_HELP_DESC("priority.help_desc", "Use this command to set your region's priority."),
- PRIORITY_INFO("priority.info", ChatColor.GRAY + "Priority: %priority%"),
- PRIORITY_SET("priority.set", ChatColor.YELLOW + "Priority has been set."),
- PRIORITY_ERROR("priority.error", ChatColor.RED + "Error parsing input, check it again?"),
-
- // ps region
- REGION_HELP("region.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps region [list|remove|disown] [playername]"),
- REGION_HELP_DESC("region.help_desc", "Use this command to find information or edit other players' (or your own) protected regions."),
- REGION_NOT_FOUND_FOR_PLAYER("region.not_found_for_player", ChatColor.GRAY + "No regions found for %player% in this world."),
- REGION_LIST("region.list", ChatColor.GRAY + "%player%'s regions in this world: " + ChatColor.AQUA + "%regions%"),
- REGION_REMOVE("region.remove", ChatColor.YELLOW + "%player%'s regions have been removed in this world, and they have been removed from regions they co-owned."),
- REGION_DISOWN("region.disown", ChatColor.YELLOW + "%player% has been removed as owner from all regions on this world."),
- REGION_ERROR_SEARCH("region.error_search", ChatColor.RED + "Error while searching for %player%'s regions. Please make sure you have entered the correct name."),
-
- // ps tp
- TP_HELP("tp.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps tp [id/player] [num (optional)]"),
- TP_HELP_DESC("tp.help_desc", "Teleports you to one of a given player's regions."),
- NUMBER_ABOVE_ZERO("tp.number_above_zero", ChatColor.RED + "Please enter a number above 0."),
- TP_VALID_NUMBER("tp.valid_number", ChatColor.RED + "Please enter a valid number."),
- ONLY_HAS_REGIONS("tp.only_has_regions", ChatColor.RED + "%player% only has %num% protected regions in this world!"),
- TPING("tp.tping", ChatColor.GREEN + "Teleporting..."),
- TP_ERROR_NAME("tp.error_name", ChatColor.RED + "Error in teleporting to protected region! (parsing WG region name error)"),
- TP_ERROR_TP("tp.error_tp", ChatColor.RED + "Error in finding the region to teleport to!"),
- TP_IN_SECONDS("tp.in_seconds", ChatColor.GRAY + "Teleporting in " + ChatColor.AQUA + "%seconds%" + ChatColor.GRAY + " seconds."),
- TP_CANCELLED_MOVED("tp.cancelled_moved", ChatColor.RED + "Teleport cancelled. You moved!"),
-
- // ps home
- HOME_HELP("home.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps home [name/id]"),
- HOME_HELP_DESC("home.help_desc", "Teleports you to one of your protected regions."),
- HOME_HEADER("home.header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Homes (click to teleport) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- HOME_CLICK_TO_TP("home.click_to_tp", "Click to teleport!"),
- HOME_NEXT("home.next_page", ChatColor.GRAY + "Do /ps home -p %page% to go to the next page!"),
-
- // ps unclaim
- UNCLAIM_HELP("unclaim.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps unclaim"),
- UNCLAIM_HELP_DESC("unclaim.help_desc", "Use this command to pickup a placed protection stone and remove the region."),
- UNCLAIM_HEADER("unclaim.header",ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Unclaim (click to unclaim) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
-
- // ps view
- VIEW_HELP("view.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps view"),
- VIEW_HELP_DESC("view.help_desc", "Use this command to view the borders of a protected region."),
- VIEW_COOLDOWN("view.cooldown", ChatColor.RED + "Please wait a while before using /ps view again."),
- VIEW_GENERATING("view.generating", ChatColor.GRAY + "Generating border..."),
- VIEW_GENERATE_DONE("view.generate_done", ChatColor.GREEN + "Done! The border will disappear after 30 seconds!"),
- VIEW_REMOVING("view.removing", ChatColor.AQUA + "Removing border...\n" + ChatColor.GREEN + "If you still see ghost blocks, relog!"),
-
- // ps admin
- ADMIN_HELP("admin.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps admin"),
- ADMIN_HELP_DESC("admin.help_desc", "Do /ps admin help for more information."),
- ADMIN_CLEANUP_HEADER("admin.cleanup_header", ChatColor.YELLOW + "Cleanup %arg% %days% days\n================"),
- ADMIN_CLEANUP_FOOTER("admin.cleanup_footer", ChatColor.YELLOW + "================\nCompleted %arg% cleanup."),
- ADMIN_HIDE_TOGGLED("admin.hide_toggled", ChatColor.YELLOW + "All protection stones have been %message% in this world."),
- ADMIN_LAST_LOGON("admin.last_logon", ChatColor.YELLOW + "%player% last played %days% days ago."),
- ADMIN_IS_BANNED("admin.is_banned", ChatColor.YELLOW + "%player% is banned."),
- ADMIN_ERROR_PARSING("admin.error_parsing", ChatColor.RED + "Error parsing days, are you sure it is a number?"),
- ADMIN_CONSOLE_WORLD("admin.console_world", ChatColor.RED + "Please specify the world as the last parameter."),
- ADMIN_LASTLOGONS_HEADER("admin.lastlogons_header", ChatColor.YELLOW + "%days% Days Plus:\n================"),
- ADMIN_LASTLOGONS_LINE("admin.lastlogons_line", ChatColor.YELLOW + "%player% %time% days"),
- ADMIN_LASTLOGONS_FOOTER("admin.lastlogons_footer", ChatColor.YELLOW + "================\n%count% Total Players Shown\n%checked% Total Players Checked"),
-
- // ps reload
- RELOAD_HELP("reload.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps reload"),
- RELOAD_HELP_DESC("reload.help_desc", "Reload settings from the config."),
- RELOAD_START("reload.start", ChatColor.AQUA + "Reloading config..."),
- RELOAD_COMPLETE("reload.complete", ChatColor.AQUA + "Completed config reload!"),
-
- // ps add/remove
- ADDREMOVE_HELP("addremove.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps add|remove [playername]"),
- ADDREMOVE_HELP_DESC("addremove.help_desc", "Use this command to add or remove a member of your protected region."),
- ADDREMOVE_OWNER_HELP("addremove.owner_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps addowner|removeowner [playername]"),
- ADDREMOVE_OWNER_HELP_DESC("addremove.owner_help_desc", "Use this command to add or remove an owner of your protected region."),
- ADDREMOVE_PLAYER_REACHED_LIMIT("addremove.player_reached_limit", ChatColor.RED + "This player has reached their region limit."),
- ADDREMOVE_PLAYER_NEEDS_TO_BE_ONLINE("addremove.player_needs_to_be_online", ChatColor.RED + "The player needs to be online to add them."),
-
- // ps get
- GET_HELP("get.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps get [block]"),
- GET_HELP_DESC("get.help_desc", "Use this command to get or purchase a protection block."),
- GET_GOTTEN("get.gotten", ChatColor.AQUA + "Added protection block to inventory!"),
- GET_NO_PERMISSION_BLOCK("get.no_permission_block", ChatColor.RED + "You don't have permission to get this block."),
- GET_HEADER("get.header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Protect Blocks (click to get) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- GET_GUI_BLOCK("get.gui_block", ChatColor.GRAY + "> " + ChatColor.AQUA + "%alias% " + ChatColor.GRAY + "- %description% (" + ChatColor.WHITE + "$%price%" + ChatColor.GRAY + ")"),
- GET_GUI_HOVER("get.gui_hover", "Click to buy a %alias%!"),
-
- // ps give
- GIVE_HELP("give.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps give [block] [player] [amount (optional)]"),
- GIVE_HELP_DESC("give.help_desc", "Use this command to give a player a protection block."),
- GIVE_GIVEN("give.given", ChatColor.GRAY + "Gave " + ChatColor.AQUA + "%block%" + ChatColor.GRAY + " to " + ChatColor.AQUA + "%player%" + ChatColor.GRAY + "."),
- GIVE_NO_INVENTORY_ROOM("give.no_inventory_room", ChatColor.RED + "The player does not have enough inventory room."),
-
- // ps sethome
- SETHOME_HELP("sethome.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps sethome"),
- SETHOME_HELP_DESC("sethome.help_desc", "Use this command to set the home of a region to where you are right now."),
- SETHOME_SET("sethome.set", ChatColor.GRAY + "The home for " + ChatColor.AQUA + "%psid%" + ChatColor.GRAY + " has been set to your location."),
-
- // ps list
- LIST_HELP("list.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps list [player (optional)]"),
- LIST_HELP_DESC("list.help_desc", "Use this command to list the regions you, or another player owns."),
- LIST_HEADER("list.header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " %player%'s Regions " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- LIST_OWNER("list.owner", ChatColor.GRAY + "Owner of:"),
- LIST_MEMBER("list.member", ChatColor.GRAY + "Member of:"),
- LIST_NO_REGIONS("list.no_regions", ChatColor.GRAY + "You currently do not own and are not a member of any regions."),
- LIST_NO_REGIONS_PLAYER("list.no_regions_player", ChatColor.AQUA + "%player% " + ChatColor.GRAY + "does not own and is not a member of any regions."),
-
- // ps name
- NAME_HELP("name.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps name [name|none]"),
- NAME_HELP_DESC("name.help_desc", "Use this command to give a nickname to your region, to make identifying your region easier."),
- NAME_REMOVED("name.removed", ChatColor.GRAY + "Removed the name for %id%."),
- NAME_SET_NAME("name.set_name", ChatColor.GRAY + "Set the name of %id% to " + ChatColor.AQUA + "%name%" + ChatColor.GRAY + "."),
- NAME_TAKEN("name.taken", ChatColor.GRAY + "The region name " + ChatColor.AQUA + "%name%" + ChatColor.GRAY + " has already been taken! Try another one."),
-
- // ps setparent
- SETPARENT_HELP("setparent.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps setparent [region|none]"),
- SETPARENT_HELP_DESC("setparent.help_desc", "Use this command to allow this region to inherit properties from another region (owners, members, flags, etc.)."),
- SETPARENT_SUCCESS("setparent.success", ChatColor.GRAY + "Successfully set the parent of " + ChatColor.AQUA + "%id%" + ChatColor.GRAY + " to " + ChatColor.AQUA + "%parent%" + ChatColor.GRAY + "."),
- SETPARENT_SUCCESS_REMOVE("setparent.success_remove", ChatColor.GRAY + "Successfully removed the parent of " + ChatColor.AQUA + "%id%" + ChatColor.GRAY + "."),
- SETPARENT_CIRCULAR_INHERITANCE("setparent.circular_inheritance", ChatColor.RED + "Detected circular inheritance (the parent already inherits from this region?). Parent not set."),
-
- // ps merge
- MERGE_HELP("merge.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps merge"),
- MERGE_HELP_DESC("merge.help_desc", "Use this command to merge the region you are in with other overlapping regions."),
- MERGE_DISABLED("merge.disabled", "Merging regions is disabled in the config!"),
- MERGE_MERGED("merge.merged", ChatColor.AQUA + "Regions were successfully merged!"),
- MERGE_HEADER("merge.header", ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Merge %region% (click to merge) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
- MERGE_WARNING("merge.warning", ChatColor.GRAY + "Note: This will delete all of the settings for the current region!"),
- MERGE_NOT_ALLOWED("merge.not_allowed", ChatColor.RED + "You are not allowed to merge this protection region type."),
- MERGE_INTO("merge.into", ChatColor.AQUA + "This region overlaps other regions you can merge into!"),
- MERGE_NO_REGIONS("merge.no_region", ChatColor.GRAY + "There are no overlapping regions to merge into."),
- MERGE_CLICK_TO_MERGE("merge.click_to_merge", "Click to merge with %region%!"),
- MERGE_AUTO_MERGED("merge.auto_merged", ChatColor.GRAY + "Region automatically merged with " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
-
- ;
-
- private final String path;
- private final String defaultMessage;
-
- private final String[] placeholders;
- private final int placeholdersCount;
- private String message;
- private boolean isEmpty;
-
- private static final File conf = new File(ProtectionStones.getInstance().getDataFolder(), "messages.yml");
-
- PSL(String path, String defaultMessage, String... placeholders) {
- this.path = path;
- this.defaultMessage = defaultMessage;
-
- this.placeholders = placeholders;
- this.placeholdersCount = placeholders.length;
- this.message = defaultMessage;
- this.isEmpty = message.isEmpty();
- }
-
- public String msg() {
- return message;
- }
-
- public boolean isEmpty() {
- return isEmpty;
- }
-
- @Nullable
- public String format(final Object... args) {
- if (isEmpty) {
- return null;
+ // messages.yml
+
+ COOLDOWN("cooldown",
+ ChatColor.GOLD + "Warning: " + ChatColor.GRAY
+ + "Please wait for %time% seconds before placing again!"),
+ NO_SUCH_COMMAND("no_such_command", ChatColor.RED + "No such command. please type /ps help for more info"),
+ NO_ACCESS("no_access", ChatColor.RED + "You are not allowed to do that here."),
+ NO_ROOM_IN_INVENTORY("no_room_in_inventory", ChatColor.RED + "You don't have enough room in your inventory."),
+ NO_ROOM_DROPPING_ON_FLOOR("no_room_dropping_on_floor",
+ ChatColor.RED + "You don't have enough room in your inventory. Dropping item on floor."),
+ INVALID_BLOCK("invalid_block", ChatColor.RED + "Invalid protection block."),
+ NOT_ENOUGH_MONEY("not_enough_money", ChatColor.RED + "You don't have enough money! The price is %price%."),
+ PAID_MONEY("paid_money", ChatColor.AQUA + "You've paid $%price%."),
+ INVALID_WORLD("invalid_world", ChatColor.RED + "Invalid world."),
+ MUST_BE_PLAYER("must_be_player", ChatColor.RED + "You must be a player to execute this command."),
+ GO_BACK_PAGE("go_back_page", "Go back a page."),
+ GO_NEXT_PAGE("go_next_page", "Go to next page."),
+ PAGE_DOES_NOT_EXIST("page_does_not_exist", ChatColor.RED + "Page does not exist."),
+
+ HELP("help",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " PS Help "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "=====\n" + ChatColor.AQUA
+ + "> " + ChatColor.GRAY
+ + "/ps help"),
+ HELP_NEXT("help_next", ChatColor.GRAY + "Do /ps help %page% to go to the next page!"),
+
+ COMMAND_REQUIRES_PLAYER_NAME("command_requires_player_name",
+ ChatColor.RED + "This command requires a player name."),
+
+ NO_PERMISSION_TOGGLE("no_permission_toggle",
+ ChatColor.RED + "You don't have permission to use the toggle command."),
+ NO_PERMISSION_CREATE("no_permission_create",
+ ChatColor.RED + "You don't have permission to place a protection block."),
+ NO_PERMISSION_CREATE_SPECIFIC("no_permission_create_specific",
+ ChatColor.RED + "You don't have permission to place this protection block type."),
+ NO_PERMISSION_DESTROY("no_permission_destroy",
+ ChatColor.RED + "You don't have permission to destroy a protection block."),
+ NO_PERMISSION_MEMBERS("no_permission_members", "&cYou don't have permission to use member commands."),
+ NO_PERMISSION_OWNERS("no_permission_owners", "&cYou don't have permission to use owner commands."),
+ NO_PERMISSION_ADMIN("no_permission_admin", ChatColor.RED + "You do not have permission to use that command."),
+ NO_PERMISSION_COUNT("no_permission_count", ChatColor.RED + "You do not have permission to use that command."),
+ NO_PERMISSION_COUNT_OTHERS("no_permission_count_others",
+ ChatColor.RED + "You do not have permission to use that command."),
+ NO_PERMISSION_FLAGS("no_permission_flags", "&cYou do not have permission to use flag commands."),
+ NO_PERMISSION_PER_FLAG("no_permission_per_flag",
+ ChatColor.RED + "You do not have permission to use that flag."),
+ NO_PERMISSION_RENT("no_permission_rent", ChatColor.RED + "You do not have permission for renting."),
+ NO_PERMISSION_TAX("no_permission_tax", ChatColor.RED + "You do not have permission to use the tax command."),
+ NO_PERMISSION_BUYSELL("no_permission_buysell",
+ ChatColor.RED + "You do not have permission to buy and sell regions."),
+ NO_PERMISSION_UNHIDE("no_permission_unhide",
+ ChatColor.RED + "You do not have permission to unhide protection blocks."),
+ NO_PERMISSION_HIDE("no_permission_hide",
+ ChatColor.RED + "You do not have permission to hide protection blocks."),
+ NO_PERMISSION_INFO("no_permission_info",
+ ChatColor.RED + "You do not have permission to use the region info command."),
+ NO_PERMISSION_PRIORITY("no_permission_priority",
+ ChatColor.RED + "You do not have permission to use the priority command."),
+ NO_PERMISSION_REGION("no_permission_region",
+ ChatColor.RED + "You do not have permission to use region commands."),
+ NO_PERMISSION_TP("no_permission_tp",
+ ChatColor.RED + "You do not have permission to teleport to other players' protection blocks."),
+ NO_PERMISSION_HOME("no_permission_home",
+ ChatColor.RED + "You do not have permission to teleport to your protection blocks."),
+ NO_PERMISSION_UNCLAIM("no_permission_unclaim",
+ ChatColor.RED + "You do not have permission to use the unclaim command."),
+ NO_PERMISSION_UNCLAIM_REMOTE("no_permission_unclaim_remote",
+ ChatColor.RED + "You do not have permission to use the unclaim remote command."),
+ NO_PERMISSION_VIEW("no_permission_view", ChatColor.RED + "You do not have permission to use the view command."),
+ NO_PERMISSION_GIVE("no_permission_give", ChatColor.RED + "You do not have permission to use the give command."),
+ NO_PERMISSION_GET("no_permission_get", ChatColor.RED + "You do not have permission to use the get command."),
+ NO_PERMISSION_SETHOME("no_permission_sethome",
+ ChatColor.RED + "You do not have permission to use the sethome command."),
+ NO_PERMISSION_LIST("no_permission_list", ChatColor.RED + "You do not have permission to use the list command."),
+ NO_PERMISSION_LIST_OTHERS("no_permission_list_others",
+ ChatColor.RED + "You do not have permission to use the list command for others."),
+ NO_PERMISSION_NAME("no_permission_name", ChatColor.RED + "You do not have permission to use the name command."),
+ NO_PERMISSION_SETPARENT("no_permission_setparent",
+ ChatColor.RED + "You do not have permission to use the setparent command."),
+ NO_PERMISSION_SETPARENT_OTHERS("no_permission_setparent_others",
+ ChatColor.RED + "You do not have permission to inherit from regions you don't own."),
+ NO_PERMISSION_MERGE("no_permission_merge", ChatColor.RED + "You do not have permission to use /ps merge."),
+
+ ADDED_TO_REGION("psregion.added_to_region",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been added to this region."),
+ ADDED_TO_REGION_SPECIFIC("psregion.added_to_region_specific",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been added to region %region%."),
+ REMOVED_FROM_REGION("psregion.removed_from_region",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been removed from region."),
+ REMOVED_FROM_REGION_SPECIFIC("psregion.removed_from_region_specific",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has been removed from region %region%."),
+ NOT_IN_REGION("psregion.not_in_region", ChatColor.RED + "You are not in a protection stones region!"),
+ PLAYER_NOT_FOUND("psregion.player_not_found", ChatColor.RED + "Player not found."),
+ NOT_PS_REGION("psregion.not_ps_region", ChatColor.RED + "Not a protection stones region."),
+ REGION_DOES_NOT_EXIST("psregion.region_does_not_exist", ChatColor.RED + "Region does not exist."),
+ NO_REGIONS_OWNED("psregion.no_regions_owned",
+ ChatColor.RED + "You don't own any protected regions in this world!"),
+ NO_REGION_PERMISSION("psregion.no_region_permission",
+ ChatColor.RED + "You do not have permission to do this in this region."),
+ PROTECTED("psregion.protected", ChatColor.AQUA + "This area is now protected."),
+ NO_LONGER_PROTECTED("psregion.no_longer_protected", ChatColor.YELLOW + "This area is no longer protected."),
+ CANT_PROTECT_THAT("psregion.cant_protect_that", ChatColor.RED + "You can't protect that area."),
+ REACHED_REGION_LIMIT("psregion.reached_region_limit",
+ ChatColor.RED + "You can not have any more protected regions (%limit%)."),
+ REACHED_PER_BLOCK_REGION_LIMIT("psregion.reached_per_block_region_limit",
+ ChatColor.RED + "You can not have any more regions of this type (%limit%)."),
+ WORLD_DENIED_CREATE("psregion.world_denied_create",
+ ChatColor.RED + "You can not create protections in this world."),
+ REGION_OVERLAP("psregion.region_overlap",
+ ChatColor.RED + "You can not place a protection block here as it overlaps another region."),
+ REGION_TOO_CLOSE("psregion.region_too_close",
+ ChatColor.RED + "Your protection block must be a minimum of %num% blocks from the edge of other regions!"),
+ REGION_CANT_TELEPORT("psregion.cant_teleport",
+ ChatColor.RED + "Your teleportation was blocked by a protection region!"),
+ SPECIFY_ID_INSTEAD_OF_ALIAS("psregion.specify_id_instead_of_alias", ChatColor.GRAY
+ + "There were multiple regions found with this name! Please use an ID instead.\n Regions with this name: "
+ + ChatColor.AQUA + "%regions%"),
+ REGION_NOT_ADJACENT("psregion.region_not_adjacent", ChatColor.RED
+ + "You've passed the limit of non-adjacent regions! Try putting your protection block closer to other regions you already own."),
+ REGION_NOT_OVERLAPPING("psregion.not_overlapping", ChatColor.RED + "These regions don't overlap each other!"),
+ MULTI_REGION_DOES_NOT_EXIST("psregion.multi_region_does_not_exist", "One of these regions don't exist!"),
+ NO_REGION_HOLES("psregion.no_region_holes",
+ ChatColor.RED + "Unprotected area detected inside region! This is not allowed!"),
+ DELETE_REGION_PREVENTED_NO_HOLES("psregion.delete_region_prevented",
+ ChatColor.GRAY
+ + "The region could not be removed, possibly because it creates a hole in the existing region."),
+ NOT_OWNER("psregion.not_owner", ChatColor.RED + "You are not an owner of this region!"),
+ CANNOT_MERGE_RENTED_REGION("psregion.cannot_merge_rented_region",
+ ChatColor.RED + "Cannot merge regions because region %region% is in the process of being rented out!"),
+ NO_PERMISSION_REGION_TYPE("psregion.no_permission_region_type",
+ ChatColor.RED + "You do not have permission to have this region type."),
+ REGION_HIDDEN("psregion.hidden", ChatColor.GRAY + "The protection block is now hidden."),
+ MUST_BE_PLACED_IN_EXISTING_REGION("psregion.must_be_placed_in_existing_region",
+ ChatColor.RED + "This must be placed inside of an existing region!"),
+ REGION_ALREADY_IN_LOCATION_IS_HIDDEN("psregion.already_in_location_is_hidden",
+ ChatColor.RED + "A region already exists in this location (is the protection block hidden?)"),
+ CANNOT_REMOVE_YOURSELF_LAST_OWNER("psregion.cannot_remove_yourself_last_owner",
+ ChatColor.RED + "You cannot remove yourself as you are the last owner."),
+ CANNOT_REMOVE_YOURSELF_FROM_ALL_REGIONS("psregion.cannot_remove_yourself_all_regions",
+ ChatColor.RED + "You cannot remove yourself from all of your regions at once, for safety reasons."),
+
+ // ps toggle
+ TOGGLE_HELP("toggle.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps toggle|on|off"),
+ TOGGLE_HELP_DESC("toggle.help_desc", "Use this command to turn on or off placement of protection blocks."),
+ TOGGLE_ON("toggle.toggle_on", ChatColor.AQUA + "Protection block placement turned on."),
+ TOGGLE_OFF("toggle.toggle_off", ChatColor.AQUA + "Protection block placement turned off."),
+
+ // ps count
+ COUNT_HELP("count.count_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps count [player (optional)]"),
+ COUNT_HELP_DESC("count.count_help_desc", "Count the number of regions you own or another player."),
+ PERSONAL_REGION_COUNT("count.personal_region_count",
+ ChatColor.GRAY + "Your region count in this world: " + ChatColor.AQUA + "%num%"),
+ PERSONAL_REGION_COUNT_MERGED("count.personal_region_count_merged",
+ ChatColor.GRAY + "- Including each merged region: " + ChatColor.AQUA + "%num%"),
+ OTHER_REGION_COUNT("count.other_region_count",
+ ChatColor.GRAY + "%player%'s region count in this world: " + ChatColor.AQUA + "%num%"),
+ OTHER_REGION_COUNT_MERGED("count.other_region_count_merged",
+ ChatColor.GRAY + "- Including each merged region: " + ChatColor.AQUA + "%num%"),
+
+ // ps flag
+ FLAG_HELP("flag.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps flag [flagname] [value|null|default]"),
+ FLAG_HELP_DESC("flag.help_desc", "Use this command to set a flag in your protected region."),
+ FLAG_SET("flag.flag_set", ChatColor.AQUA + "%flag%" + ChatColor.GRAY + " flag has been set."),
+ FLAG_NOT_SET("flag.flag_not_set",
+ ChatColor.AQUA + "%flag%" + ChatColor.GRAY + " flag has " + ChatColor.RED + "not"
+ + ChatColor.GRAY
+ + " been set. Check your values again."),
+ FLAG_PREVENT_EXPLOIT("flag.flag_prevent_exploit",
+ ChatColor.RED + "This has been disabled to prevent exploits."),
+ FLAG_PREVENT_EXPLOIT_HOVER("flag.flag_prevent_exploit_hover", ChatColor.RED + "Disabled for security reasons."),
+ FLAG_GUI_HEADER("flag.gui_header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Flags (click to change) "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ FLAG_GUI_HOVER_SET("flag.gui_hover_set", ChatColor.AQUA + "Click to set."),
+ FLAG_GUI_HOVER_SET_TEXT("flag.gui_hover_set_text",
+ ChatColor.AQUA + "Click to change." + ChatColor.WHITE + "\nCurrent value:\n%value%"),
+ FLAG_GUI_HOVER_CHANGE_GROUP("flag.hover_change_group", "Click to set this flag to apply to only %group%."),
+ FLAG_GUI_HOVER_CHANGE_GROUP_NULL("flag.hover_change_group_null",
+ ChatColor.RED + "You must set this flag to a value before changing the group."),
+
+ // ps rent
+ RENT_HELP("rent.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps rent"),
+ RENT_HELP_DESC("rent.help_desc", "Use this command to manage rents (buying and selling)."),
+ RENT_HELP_HEADER("rent.help_header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Rent Help "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ RENT_ALREADY_RENTING("rent.already_renting",
+ ChatColor.RED + "The region is already being rented out! You must stop leasing the region first."),
+ RENT_NOT_RENTED("rent.not_rented", ChatColor.RED + "This region is not being rented."),
+ RENT_LEASE_SUCCESS("rent.lease_success",
+ ChatColor.AQUA + "Region leasing terms set:\n" + ChatColor.AQUA + "Price: " + ChatColor.GRAY
+ + "%price%\n"
+ + ChatColor.AQUA + "Payment Term: " + ChatColor.GRAY + "%period%"),
+ RENT_STOPPED("rent.stopped", ChatColor.AQUA + "Leasing stopped."),
+ RENT_EVICTED("rent.evicted", ChatColor.GRAY + "Evicted tenant %tenant%."),
+ RENT_NOT_RENTING("rent.not_renting", ChatColor.RED + "This region is not being rented out to tenants."),
+ RENT_PAID_LANDLORD("rent.paid_landlord",
+ ChatColor.AQUA + "%tenant%" + ChatColor.GRAY + " has paid " + ChatColor.AQUA + "$%price%"
+ + ChatColor.GRAY
+ + " for renting out " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
+ RENT_PAID_TENANT("rent.paid_tenant",
+ ChatColor.GRAY + "Paid " + ChatColor.AQUA + "$%price%" + ChatColor.GRAY + " to "
+ + ChatColor.AQUA
+ + "%landlord%" + ChatColor.GRAY + " for region " + ChatColor.AQUA + "%region%"
+ + ChatColor.GRAY
+ + "."),
+ RENT_RENTING_LANDLORD("rent.renting_landlord",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " is now renting out region " + ChatColor.AQUA
+ + "%region%"
+ + ChatColor.GRAY + "."),
+ RENT_RENTING_TENANT("rent.renting_tenant",
+ ChatColor.GRAY + "You are now renting out region " + ChatColor.AQUA + "%region%"
+ + ChatColor.GRAY + " for "
+ + ChatColor.AQUA + "%price%" + ChatColor.GRAY + " per " + ChatColor.AQUA
+ + "%period%"
+ + ChatColor.GRAY + "."),
+ RENT_NOT_TENANT("rent.not_tenant", ChatColor.RED + "You are not the tenant of this region!"),
+ RENT_TENANT_STOPPED_LANDLORD("rent.tenant_stopped_landlord",
+ ChatColor.AQUA + "%player%" + ChatColor.GRAY + " has stopped renting out region "
+ + ChatColor.AQUA
+ + "%region%" + ChatColor.GRAY + ". It is now available for others to rent."),
+ RENT_TENANT_STOPPED_TENANT("rent.tenant_stopped_tenant",
+ ChatColor.AQUA + "You have stopped renting out region %region%."),
+ RENT_BEING_SOLD("rent.being_sold", ChatColor.RED + "The region is being sold! Do /ps sell stop first."),
+ RENT_EVICT_NO_MONEY_TENANT("rent.evict_no_money_tenant",
+ ChatColor.GRAY + "You have been " + ChatColor.RED + "evicted" + ChatColor.GRAY + " from region "
+ + ChatColor.AQUA + "%region%" + ChatColor.GRAY
+ + " because you do not have enough money (%price%) to pay for rent."),
+ RENT_EVICT_NO_MONEY_LANDLORD("rent.evict_no_money_landlord",
+ ChatColor.AQUA + "%tenant%" + ChatColor.GRAY + " has been " + ChatColor.RED + "evicted"
+ + ChatColor.GRAY
+ + " from region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY
+ + " because they are unable to afford rent."),
+ RENT_CANNOT_RENT_OWN_REGION("rent.cannot_rent_own_region", ChatColor.RED + "You cannot rent your own region!"),
+ RENT_REACHED_LIMIT("rent.reached_limit",
+ ChatColor.RED + "You've reached the limit of regions you are allowed to rent!"),
+ RENT_PRICE_TOO_LOW("rent.price_too_low",
+ ChatColor.RED + "The rent price is too low (must be larger than %price%)."),
+ RENT_PRICE_TOO_HIGH("rent.price_too_high",
+ ChatColor.RED + "The rent price is too high (must be lower than %price%)."),
+ RENT_PERIOD_TOO_SHORT("rent.period_too_short",
+ ChatColor.RED + "The rent period is too short (must be longer than %period% seconds)."),
+ RENT_PERIOD_TOO_LONG("rent.period_too_long",
+ ChatColor.RED + "The rent period is too long (must be shorter than %period% seconds)."),
+ RENT_PERIOD_INVALID("rent.period_invalid",
+ ChatColor.RED + "Invalid period format! Example: 24h for once a day."),
+ RENT_CANNOT_BREAK_WHILE_RENTING("rent.cannot_break_while_renting",
+ ChatColor.RED + "You cannot break the region when it is being rented out."),
+
+ // ps tax
+ TAX_HELP("tax.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps tax"),
+ TAX_HELP_DESC("tax.help_desc", "Use this command to manage and pay taxes."),
+ TAX_HELP_HEADER("tax.help_header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " Taxes Help "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ TAX_DISABLED_REGION("tax.disabled_region", ChatColor.RED + "Taxes are disabled for this region."),
+ TAX_SET_AS_AUTOPAYER("tax.set_as_autopayer",
+ ChatColor.GRAY + "Taxes for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY
+ + " will now be automatically paid by you."),
+ TAX_SET_NO_AUTOPAYER("tax.set_no_autopayer",
+ ChatColor.GRAY + "Taxes for region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY
+ + " now have to be manually paid for."),
+ TAX_PAID("tax.paid",
+ ChatColor.GRAY + "Paid " + ChatColor.AQUA + "$%amount%" + ChatColor.GRAY
+ + " in taxes for region "
+ + ChatColor.AQUA + "%region%" + ChatColor.GRAY + "."),
+ TAX_INFO_HEADER("tax.info_header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Tax Info (click for more info) " + ChatColor.DARK_GRAY
+ + ChatColor.STRIKETHROUGH + "====="),
+ TAX_JOIN_MSG_PENDING_PAYMENTS("tax.join_msg_pending_payments",
+ ChatColor.GRAY + "You have " + ChatColor.AQUA + "$%money%" + ChatColor.GRAY
+ + " in tax payments due on your regions!\nView them with /ps tax info."),
+ TAX_PLAYER_REGION_INFO("tax.player_region_info",
+ ChatColor.GRAY + "> " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " - "
+ + ChatColor.DARK_AQUA
+ + "$%money% due"),
+ TAX_PLAYER_REGION_INFO_AUTOPAYER("tax.player_region_info_autopayer",
+ ChatColor.GRAY + "> " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " - "
+ + ChatColor.DARK_AQUA
+ + "$%money% due" + ChatColor.GRAY + " (you autopay)"),
+ TAX_CLICK_TO_SHOW_MORE_INFO("tax.click_to_show_more_info", "Click to show more information."),
+ TAX_REGION_INFO_HEADER("tax.region_info_header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " %region% Tax Info "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ TAX_REGION_INFO("tax.region_info",
+ ChatColor.BLUE + "Tax Rate: " + ChatColor.GRAY + "$%taxrate% (sum of all merged regions)" + "\n"
+ + ChatColor.BLUE + "Time between tax cycles: " + ChatColor.GRAY + "%taxperiod%"
+ + "\n"
+ + ChatColor.BLUE + "Time to pay taxes after cycle: " + ChatColor.GRAY
+ + "%taxpaymentperiod%" + "\n"
+ + ChatColor.BLUE + "Tax Autopayer: " + ChatColor.GRAY + "%taxautopayer%" + "\n"
+ + ChatColor.BLUE + "Taxes Owed: " + ChatColor.GRAY + "$%taxowed%"),
+ TAX_NEXT("tax.next_page", ChatColor.GRAY + "Do /ps tax info -p %page% to go to the next page!"),
+
+ // ps buy
+ BUY_HELP("buy.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps buy"),
+ BUY_HELP_DESC("buy.help_desc", "Buy the region you are currently in."),
+ BUY_NOT_FOR_SALE("buy.not_for_sale", ChatColor.RED + "This region is not for sale."),
+ BUY_STOP_SELL("buy.stop_sell", ChatColor.GRAY + "The region is now not for sale."),
+ BUY_SOLD_BUYER("buy.sold_buyer",
+ ChatColor.GRAY + "Bought region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " for "
+ + ChatColor.AQUA
+ + "$%price%" + ChatColor.GRAY + " from " + ChatColor.AQUA + "%player%"
+ + ChatColor.GRAY + "."),
+ BUY_SOLD_SELLER("buy.sold_seller",
+ ChatColor.GRAY + "Sold region " + ChatColor.AQUA + "%region%" + ChatColor.GRAY + " for "
+ + ChatColor.AQUA
+ + "$%price%" + ChatColor.GRAY + " to " + ChatColor.AQUA + "%player%"
+ + ChatColor.GRAY + "."),
+
+ // ps sell
+ SELL_HELP("sell.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps sell [price|stop]"),
+ SELL_HELP_DESC("sell.help_desc", "Sell the region you are currently in."),
+ SELL_RENTED_OUT("sell.rented_out",
+ ChatColor.RED + "The region is being rented out! You must stop renting it out to sell."),
+ SELL_FOR_SALE("sell.for_sale",
+ ChatColor.GRAY + "The region is now for sale for " + ChatColor.AQUA + "$%price%"
+ + ChatColor.GRAY + "."),
+
+ // ps hide/unhide
+ VISIBILITY_HIDE_HELP("visibility.hide_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps hide"),
+ VISIBILITY_HIDE_HELP_DESC("visibility.hide_help_desc",
+ "Use this command to hide or unhide your protection block."),
+ VISIBILITY_UNHIDE_HELP("visibility.unhide_help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps unhide"),
+ VISIBILITY_UNHIDE_HELP_DESC("visibility.unhide_help_desc",
+ "Use this command to hide or unhide your protection block."),
+ ALREADY_NOT_HIDDEN("visibility.already_not_hidden",
+ ChatColor.GRAY + "The protection stone doesn't appear hidden..."),
+ ALREADY_HIDDEN("visibility.already_hidden",
+ ChatColor.GRAY + "The protection stone appears to already be hidden..."),
+
+ // ps info
+ INFO_HELP("info.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps info members|owners|flags"),
+ INFO_HELP_DESC("info.help_desc", "Use this command inside a ps region to see more information about it."),
+ INFO_HEADER("info.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET + " PS Info "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ INFO_TYPE2("info.type2", "&9Type: &7%type%", "%type%"),
+ INFO_MAY_BE_MERGED("info.may_be_merged", "(may be merged with other types)"),
+ INFO_MERGED2("info.merged2", ChatColor.BLUE + "Merged regions: " + ChatColor.GRAY + "%merged%", "%merged%"),
+ INFO_MEMBERS2("info.members2", "&9Members: &7%members%", "%members%"),
+ INFO_NO_MEMBERS("info.no_members", ChatColor.RED + "(no members)"),
+ INFO_OWNERS2("info.owners2", "&9Owners: &7%owners%", "%owners%"),
+ INFO_NO_OWNERS("info.no_owners", ChatColor.RED + "(no owners)"),
+ INFO_FLAGS2("info.flags2", "&9Flags: &7%flags%", "%flags%"),
+ INFO_NO_FLAGS("info.no_flags", "(none)"),
+ INFO_REGION2("info.region2", "&9Region: &b%region%", "%region%"),
+ INFO_PRIORITY2("info.priority2", "&9Priority: &b%priority%", "%priority%"),
+ INFO_PARENT2("info.parent2", "&9Parent: &b%parentregion%", "%parentregion%"),
+ INFO_BOUNDS_XYZ("info.bounds_xyz", "&9Bounds: &b(%minx%,%miny%,%minz%) -> (%maxx%,%maxy%,%maxz%)",
+ "%minx%", "%miny%", "%minz%", "%maxx%", "%maxy%", "%maxz%"),
+ INFO_BOUNDS_XZ("info.bounds_xz", "&9Bounds: &b(%minx%, %minz%) -> (%maxx%, %maxz%)",
+ "%minx%", "%minz%", "%maxx%", "%maxz%"),
+ INFO_SELLER2("info.seller2", "&9Seller: &7%seller%", "%seller%"),
+ INFO_PRICE2("info.price2", "&9Price: &7%price%", "%price%"),
+ INFO_TENANT2("info.tenant2", "&9Tenant: &7%tenant%", "%tenant%"),
+ INFO_LANDLORD2("info.landlord2", "&9Landlord: &7%landlord%", "%landlord%"),
+ INFO_RENT2("info.rent2", "&9Rent: &7%rent%", "%rent%"),
+ INFO_AVAILABLE_FOR_SALE("info.available_for_sale", ChatColor.AQUA + "Region available for sale!"),
+ INFO_AVAILABLE_FOR_RENT("info.available_for_rent", ChatColor.AQUA + "Region available for rent!"),
+
+ // ps priority
+ PRIORITY_HELP("priority.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps priority [number|null]"),
+ PRIORITY_HELP_DESC("priority.help_desc", "Use this command to set your region's priority."),
+ PRIORITY_INFO("priority.info", ChatColor.GRAY + "Priority: %priority%"),
+ PRIORITY_SET("priority.set", ChatColor.YELLOW + "Priority has been set."),
+ PRIORITY_ERROR("priority.error", ChatColor.RED + "Error parsing input, check it again?"),
+
+ // ps region
+ REGION_HELP("region.help",
+ ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps region [list|remove|disown] [playername]"),
+ REGION_HELP_DESC("region.help_desc",
+ "Use this command to find information or edit other players' (or your own) protected regions."),
+ REGION_NOT_FOUND_FOR_PLAYER("region.not_found_for_player",
+ ChatColor.GRAY + "No regions found for %player% in this world."),
+ REGION_LIST("region.list",
+ ChatColor.GRAY + "%player%'s regions in this world: " + ChatColor.AQUA + "%regions%"),
+ REGION_REMOVE("region.remove", ChatColor.YELLOW
+ + "%player%'s regions have been removed in this world, and they have been removed from regions they co-owned."),
+ REGION_DISOWN("region.disown",
+ ChatColor.YELLOW + "%player% has been removed as owner from all regions on this world."),
+ REGION_ERROR_SEARCH("region.error_search", ChatColor.RED
+ + "Error while searching for %player%'s regions. Please make sure you have entered the correct name."),
+
+ // ps tp
+ TP_HELP("tp.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps tp [id/player] [num (optional)]"),
+ TP_HELP_DESC("tp.help_desc", "Teleports you to one of a given player's regions."),
+ NUMBER_ABOVE_ZERO("tp.number_above_zero", ChatColor.RED + "Please enter a number above 0."),
+ TP_VALID_NUMBER("tp.valid_number", ChatColor.RED + "Please enter a valid number."),
+ ONLY_HAS_REGIONS("tp.only_has_regions",
+ ChatColor.RED + "%player% only has %num% protected regions in this world!"),
+ TPING("tp.tping", ChatColor.GREEN + "Teleporting..."),
+ TP_ERROR_NAME("tp.error_name",
+ ChatColor.RED + "Error in teleporting to protected region! (parsing WG region name error)"),
+ TP_ERROR_TP("tp.error_tp", ChatColor.RED + "Error in finding the region to teleport to!"),
+ TP_IN_SECONDS("tp.in_seconds",
+ ChatColor.GRAY + "Teleporting in " + ChatColor.AQUA + "%seconds%" + ChatColor.GRAY
+ + " seconds."),
+ TP_CANCELLED_MOVED("tp.cancelled_moved", ChatColor.RED + "Teleport cancelled. You moved!"),
+
+ // ps home
+ HOME_HELP("home.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps home [name/id]"),
+ HOME_HELP_DESC("home.help_desc", "Teleports you to one of your protected regions."),
+ HOME_HEADER("home.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Homes (click to teleport) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH
+ + "====="),
+ HOME_CLICK_TO_TP("home.click_to_tp", "Click to teleport!"),
+ HOME_NEXT("home.next_page", ChatColor.GRAY + "Do /ps home -p %page% to go to the next page!"),
+
+ // ps unclaim
+ UNCLAIM_HELP("unclaim.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps unclaim"),
+ UNCLAIM_HELP_DESC("unclaim.help_desc",
+ "Use this command to pickup a placed protection stone and remove the region."),
+ UNCLAIM_HEADER("unclaim.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Unclaim (click to unclaim) " + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH
+ + "====="),
+
+ // ps view
+ VIEW_HELP("view.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps view"),
+ VIEW_HELP_DESC("view.help_desc", "Use this command to view the borders of a protected region."),
+ VIEW_COOLDOWN("view.cooldown", ChatColor.RED + "Please wait a while before using /ps view again."),
+ VIEW_GENERATING("view.generating", ChatColor.GRAY + "Generating border..."),
+ VIEW_GENERATE_DONE("view.generate_done", ChatColor.GREEN + "Done! The border will disappear after 30 seconds!"),
+ VIEW_REMOVING("view.removing",
+ ChatColor.AQUA + "Removing border...\n" + ChatColor.GREEN
+ + "If you still see ghost blocks, relog!"),
+
+ // ps admin
+ ADMIN_HELP("admin.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps admin"),
+ ADMIN_HELP_DESC("admin.help_desc", "Do /ps admin help for more information."),
+ ADMIN_CLEANUP_HEADER("admin.cleanup_header", ChatColor.YELLOW + "Cleanup %arg% %days% days\n================"),
+ ADMIN_CLEANUP_FOOTER("admin.cleanup_footer", ChatColor.YELLOW + "================\nCompleted %arg% cleanup."),
+ ADMIN_HIDE_TOGGLED("admin.hide_toggled",
+ ChatColor.YELLOW + "All protection stones have been %message% in this world."),
+ ADMIN_LAST_LOGON("admin.last_logon", ChatColor.YELLOW + "%player% last played %days% days ago."),
+ ADMIN_IS_BANNED("admin.is_banned", ChatColor.YELLOW + "%player% is banned."),
+ ADMIN_ERROR_PARSING("admin.error_parsing", ChatColor.RED + "Error parsing days, are you sure it is a number?"),
+ ADMIN_CONSOLE_WORLD("admin.console_world", ChatColor.RED + "Please specify the world as the last parameter."),
+ ADMIN_LASTLOGONS_HEADER("admin.lastlogons_header", ChatColor.YELLOW + "%days% Days Plus:\n================"),
+ ADMIN_LASTLOGONS_LINE("admin.lastlogons_line", ChatColor.YELLOW + "%player% %time% days"),
+ ADMIN_LASTLOGONS_FOOTER("admin.lastlogons_footer",
+ ChatColor.YELLOW + "================\n%count% Total Players Shown\n%checked% Total Players Checked"),
+
+ // ps reload
+ RELOAD_HELP("reload.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps reload"),
+ RELOAD_HELP_DESC("reload.help_desc", "Reload settings from the config."),
+ RELOAD_START("reload.start", ChatColor.AQUA + "Reloading config..."),
+ RELOAD_COMPLETE("reload.complete", ChatColor.AQUA + "Completed config reload!"),
+
+ // ps add/remove
+ ADDREMOVE_HELP("addremove.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps add|remove [playername]"),
+ ADDREMOVE_HELP_DESC("addremove.help_desc",
+ "Use this command to add or remove a member of your protected region."),
+ ADDREMOVE_OWNER_HELP("addremove.owner_help",
+ ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps addowner|removeowner [playername]"),
+ ADDREMOVE_OWNER_HELP_DESC("addremove.owner_help_desc",
+ "Use this command to add or remove an owner of your protected region."),
+ ADDREMOVE_PLAYER_REACHED_LIMIT("addremove.player_reached_limit",
+ ChatColor.RED + "This player has reached their region limit."),
+ ADDREMOVE_PLAYER_NEEDS_TO_BE_ONLINE("addremove.player_needs_to_be_online",
+ ChatColor.RED + "The player needs to be online to add them."),
+
+ // ps get
+ GET_HELP("get.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps get [block]"),
+ GET_HELP_DESC("get.help_desc", "Use this command to get or purchase a protection block."),
+ GET_GOTTEN("get.gotten", ChatColor.AQUA + "Added protection block to inventory!"),
+ GET_NO_PERMISSION_BLOCK("get.no_permission_block",
+ ChatColor.RED + "You don't have permission to get this block."),
+ GET_HEADER("get.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Protect Blocks (click to get) " + ChatColor.DARK_GRAY
+ + ChatColor.STRIKETHROUGH + "====="),
+ GET_GUI_BLOCK("get.gui_block",
+ ChatColor.GRAY + "> " + ChatColor.AQUA + "%alias% " + ChatColor.GRAY + "- %description% ("
+ + ChatColor.WHITE
+ + "$%price%" + ChatColor.GRAY + ")"),
+ GET_GUI_HOVER("get.gui_hover", "Click to buy a %alias%!"),
+
+ // ps give
+ GIVE_HELP("give.help",
+ ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps give [block] [player] [amount (optional)]"),
+ GIVE_HELP_DESC("give.help_desc", "Use this command to give a player a protection block."),
+ GIVE_GIVEN("give.given",
+ ChatColor.GRAY + "Gave " + ChatColor.AQUA + "%block%" + ChatColor.GRAY + " to " + ChatColor.AQUA
+ + "%player%" + ChatColor.GRAY + "."),
+ GIVE_NO_INVENTORY_ROOM("give.no_inventory_room",
+ ChatColor.RED + "The player does not have enough inventory room."),
+
+ // ps sethome
+ SETHOME_HELP("sethome.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps sethome"),
+ SETHOME_HELP_DESC("sethome.help_desc",
+ "Use this command to set the home of a region to where you are right now."),
+ SETHOME_SET("sethome.set",
+ ChatColor.GRAY + "The home for " + ChatColor.AQUA + "%psid%" + ChatColor.GRAY
+ + " has been set to your location."),
+
+ // ps list
+ LIST_HELP("list.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps list [player (optional)]"),
+ LIST_HELP_DESC("list.help_desc", "Use this command to list the regions you, or another player owns."),
+ LIST_HEADER("list.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " %player%'s Regions "
+ + ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH + "====="),
+ LIST_OWNER("list.owner", ChatColor.GRAY + "Owner of:"),
+ LIST_MEMBER("list.member", ChatColor.GRAY + "Member of:"),
+ LIST_NO_REGIONS("list.no_regions",
+ ChatColor.GRAY + "You currently do not own and are not a member of any regions."),
+ LIST_NO_REGIONS_PLAYER("list.no_regions_player",
+ ChatColor.AQUA + "%player% " + ChatColor.GRAY
+ + "does not own and is not a member of any regions."),
+
+ // ps name
+ NAME_HELP("name.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps name [name|none]"),
+ NAME_HELP_DESC("name.help_desc",
+ "Use this command to give a nickname to your region, to make identifying your region easier."),
+ NAME_REMOVED("name.removed", ChatColor.GRAY + "Removed the name for %id%."),
+ NAME_SET_NAME("name.set_name",
+ ChatColor.GRAY + "Set the name of %id% to " + ChatColor.AQUA + "%name%" + ChatColor.GRAY + "."),
+ NAME_TAKEN("name.taken",
+ ChatColor.GRAY + "The region name " + ChatColor.AQUA + "%name%" + ChatColor.GRAY
+ + " has already been taken! Try another one."),
+
+ // ps setparent
+ SETPARENT_HELP("setparent.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps setparent [region|none]"),
+ SETPARENT_HELP_DESC("setparent.help_desc",
+ "Use this command to allow this region to inherit properties from another region (owners, members, flags, etc.)."),
+ SETPARENT_SUCCESS("setparent.success",
+ ChatColor.GRAY + "Successfully set the parent of " + ChatColor.AQUA + "%id%" + ChatColor.GRAY
+ + " to "
+ + ChatColor.AQUA + "%parent%" + ChatColor.GRAY + "."),
+ SETPARENT_SUCCESS_REMOVE("setparent.success_remove",
+ ChatColor.GRAY + "Successfully removed the parent of " + ChatColor.AQUA + "%id%"
+ + ChatColor.GRAY + "."),
+ SETPARENT_CIRCULAR_INHERITANCE("setparent.circular_inheritance",
+ ChatColor.RED
+ + "Detected circular inheritance (the parent already inherits from this region?). Parent not set."),
+
+ // ps merge
+ MERGE_HELP("merge.help", ChatColor.AQUA + "> " + ChatColor.GRAY + "/ps merge"),
+ MERGE_HELP_DESC("merge.help_desc",
+ "Use this command to merge the region you are in with other overlapping regions."),
+ MERGE_DISABLED("merge.disabled", "Merging regions is disabled in the config!"),
+ MERGE_MERGED("merge.merged", ChatColor.AQUA + "Regions were successfully merged!"),
+ MERGE_HEADER("merge.header",
+ ChatColor.DARK_GRAY + "" + ChatColor.STRIKETHROUGH + "=====" + ChatColor.RESET
+ + " Merge %region% (click to merge) " + ChatColor.DARK_GRAY
+ + ChatColor.STRIKETHROUGH + "====="),
+ MERGE_WARNING("merge.warning",
+ ChatColor.GRAY + "Note: This will delete all of the settings for the current region!"),
+ MERGE_NOT_ALLOWED("merge.not_allowed",
+ ChatColor.RED + "You are not allowed to merge this protection region type."),
+ MERGE_INTO("merge.into", ChatColor.AQUA + "This region overlaps other regions you can merge into!"),
+ MERGE_NO_REGIONS("merge.no_region", ChatColor.GRAY + "There are no overlapping regions to merge into."),
+ MERGE_CLICK_TO_MERGE("merge.click_to_merge", "Click to merge with %region%!"),
+ MERGE_AUTO_MERGED("merge.auto_merged",
+ ChatColor.GRAY + "Region automatically merged with " + ChatColor.AQUA + "%region%"
+ + ChatColor.GRAY + "."),
+
+ ;
+
+ private final String path;
+ private final String defaultMessage;
+
+ private final String[] placeholders;
+ private final int placeholdersCount;
+ private String message;
+ private boolean isEmpty;
+
+ private static final File conf = new File(ProtectionStones.getInstance().getDataFolder(), "messages.yml");
+
+ PSL(String path, String defaultMessage, String... placeholders) {
+ this.path = path;
+ this.defaultMessage = defaultMessage;
+
+ this.placeholders = placeholders;
+ this.placeholdersCount = placeholders.length;
+ this.message = defaultMessage;
+ this.isEmpty = message.isEmpty();
}
- if (this.placeholdersCount == 0) {
- return this.message;
+ public String msg() {
+ return message;
}
- if (this.placeholdersCount != args.length) {
- throw new IllegalArgumentException("Expected " + this.placeholdersCount + " arguments but got " + args.length);
+ public boolean isEmpty() {
+ return isEmpty;
}
- return StringUtils.replaceEach(
- this.message,
- this.placeholders,
- Arrays.stream(args).filter(Objects::nonNull).map(Object::toString).toArray(String[]::new)
- );
- }
+ @Nullable
+ public String format(final Object... args) {
+ if (isEmpty) {
+ return null;
+ }
- public boolean send(@NotNull final CommandSender receiver, @NotNull final Object... args) {
- final String msg = this.format(args);
+ if (this.placeholdersCount == 0) {
+ return this.message;
+ }
+
+ if (this.placeholdersCount != args.length) {
+ throw new IllegalArgumentException(
+ "Expected " + this.placeholdersCount + " arguments but got " + args.length);
+ }
- if (msg != null) {
- receiver.sendMessage(msg);
+ return StringUtils.replaceEach(
+ this.message,
+ this.placeholders,
+ Arrays.stream(args).filter(Objects::nonNull).map(Object::toString)
+ .toArray(String[]::new));
}
- return true;
- }
+ public boolean send(@NotNull final CommandSender receiver, @NotNull final Object... args) {
+ final String msg = this.format(args);
- public void append(@NotNull final StringBuilder builder, @NotNull final Object... args) {
- final String msg = this.format(args);
+ if (msg != null) {
+ receiver.sendMessage(msg);
+ }
- if (msg != null) {
- builder.append(msg);
+ return true;
}
- }
- // Sends a message to a commandsender if the string is not empty
+ public void append(@NotNull final StringBuilder builder, @NotNull final Object... args) {
+ final String msg = this.format(args);
- public static boolean msg(CommandSender p, String str) {
- if (str != null && !str.isEmpty() && p != null) {
- p.sendMessage(str);
- }
- return true;
- }
-
- public static boolean msg(PSPlayer p, String str) {
- return msg(p.getPlayer(), str);
- }
-
- public static void loadConfig() {
- YamlConfiguration yml = new YamlConfiguration();
-
- // check if messages.yml exists
- if (!conf.exists()) {
- try {
- conf.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ if (msg != null) {
+ builder.append(msg);
+ }
}
- // load config
- try {
- yml.load(conf); // can throw error
- for (PSL psl : PSL.values()) {
-
- // fix message if need be
- if (yml.getString(psl.path) == null) { // if msg not found in config
- yml.set(psl.path, applyConfigColours(psl.defaultMessage));
- } else {
- // perform message upgrades
- messageUpgrades(psl, yml);
+ // Sends a message to a commandsender if the string is not empty
+
+ public static boolean msg(CommandSender p, String str) {
+ if (str != null && !str.isEmpty() && p != null) {
+ String mm = legacyToMiniMessage(str);
+ ProtectionStones.getAdventure().sender(p)
+ .sendMessage(MiniMessage.miniMessage().deserialize(mm));
}
+ return true;
+ }
- // load message
- psl.message = applyInGameColours(yml.getString(psl.path));
- psl.isEmpty = psl.message.isEmpty();
- }
- try {
- yml.save(conf);
- } catch (IOException e) {
- e.printStackTrace();
- }
- } catch (Exception e) { // prevent bad messages.yml file from resetting the file
- e.printStackTrace();
+ public static boolean msg(PSPlayer p, String str) {
+ return msg(p.getPlayer(), str);
}
- }
-
- // message upgrades over time
- private static void messageUpgrades(PSL psl, YamlConfiguration yml) {
- String value = yml.getString(psl.path);
- assert(value != null);
-
- // psl upgrade conversions
- if (psl == PSL.REACHED_REGION_LIMIT && value.equals("&cYou can not create any more protected regions.")) {
- yml.set(psl.path, psl.defaultMessage);
- } else if (psl == PSL.REACHED_PER_BLOCK_REGION_LIMIT && value.equals("&cYou can not create any more regions of this type.")) {
- yml.set(psl.path, psl.defaultMessage);
- } else if (value.contains("§")) {
- yml.set(psl.path, applyConfigColours(value));
+
+ public static void loadConfig() {
+ YamlConfiguration yml = new YamlConfiguration();
+
+ // check if messages.yml exists
+ if (!conf.exists()) {
+ try {
+ conf.createNewFile();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // load config
+ try {
+ yml.load(conf); // can throw error
+ for (PSL psl : PSL.values()) {
+
+ // fix message if need be
+ if (yml.getString(psl.path) == null) { // if msg not found in config
+ yml.set(psl.path, applyConfigColours(psl.defaultMessage));
+ } else {
+ // perform message upgrades
+ messageUpgrades(psl, yml);
+ }
+
+ // load message
+ psl.message = applyInGameColours(yml.getString(psl.path));
+ psl.isEmpty = psl.message.isEmpty();
+ }
+ try {
+ yml.save(conf);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } catch (Exception e) { // prevent bad messages.yml file from resetting the file
+ e.printStackTrace();
+ }
}
- }
- // match all {abc format for hex
- private static final Pattern hexPattern = Pattern.compile("(?");
+ return msg.replace('&', '§');
}
- return msg.replace('&', '§');
- }
+ public static String legacyToMiniMessage(String str) {
+ // Handle null
+ if (str == null)
+ return "";
+
+ // Convert RRGGBB to <#RRGGBB>
+ str = str.replaceAll("(?i)[&§]#([a-f0-9]{6})", "<#$1>");
+
+ // Convert &x&r&r&g&g&b&b to <#rrggbb> (BungeeCord format) - uncommon but good
+ // to support
+ // This regex is complex, usually easier to just handle the standard formats.
+ // Let's stick to the standard conversions for now as regex for &x is verbose.
+
+ // Replace legacy characters
+ return str
+ .replace("&0", "").replace("§0", "")
+ .replace("&1", "").replace("§1", "")
+ .replace("&2", "").replace("§2", "")
+ .replace("&3", "").replace("§3", "")
+ .replace("&4", "").replace("§4", "")
+ .replace("&5", "").replace("§5", "")
+ .replace("&6", "").replace("§6", "")
+ .replace("&7", "").replace("§7", "")
+ .replace("&8", "").replace("§8", "")
+ .replace("&9", "").replace("§9", "")
+ .replace("&a", "").replace("§a", "")
+ .replace("&b", "").replace("§b", "")
+ .replace("&c", "").replace("§c", "")
+ .replace("&d", "").replace("§d", "")
+ .replace("&e", "").replace("§e", "")
+ .replace("&f", "").replace("§f", "")
+ .replace("&k", "").replace("§k", "")
+ .replace("&l", "").replace("§l", "")
+ .replace("&m", "").replace("§m", "")
+ .replace("&n", "").replace("§n", "")
+ .replace("&o", "").replace("§o", "")
+ .replace("&r", "").replace("§r", "");
+ }
- private static String applyConfigColours(String msg) {
- return msg.replace('§', '&');
- }
+ private static String applyConfigColours(String msg) {
+ return msg.replace('§', '&');
+ }
}
diff --git a/src/main/java/dev/espi/protectionstones/PSRegion.java b/src/main/java/dev/espi/protectionstones/PSRegion.java
index 2c2e285a..27de6a67 100644
--- a/src/main/java/dev/espi/protectionstones/PSRegion.java
+++ b/src/main/java/dev/espi/protectionstones/PSRegion.java
@@ -49,11 +49,14 @@ public abstract class PSRegion {
// ~~~~~~~~~~~~~~~~~ static ~~~~~~~~~~~~~~~~~
/**
- * Get the protection stone region that the location is in, or the closest one if there are overlapping regions.
- * Returns either {@link PSGroupRegion}, {@link PSStandardRegion} or {@link PSMergedRegion}.
+ * Get the protection stone region that the location is in, or the closest one
+ * if there are overlapping regions.
+ * Returns either {@link PSGroupRegion}, {@link PSStandardRegion} or
+ * {@link PSMergedRegion}.
*
* @param l the location
- * @return the {@link PSRegion} object if the location is in a region, or null if the location is not in a region
+ * @return the {@link PSRegion} object if the location is in a region, or null
+ * if the location is not in a region
*/
public static PSRegion fromLocation(Location l) {
PSRegion r = fromLocationUnsafe(l);
@@ -61,21 +64,27 @@ public static PSRegion fromLocation(Location l) {
}
/**
- * Get the protection stone region that the location is in, or the closest one if there are overlapping regions.
- * May return a region with an unconfigured block type (getTypeOptions returns null).
- * Returns either {@link PSGroupRegion}, {@link PSStandardRegion} or {@link PSMergedRegion}.
+ * Get the protection stone region that the location is in, or the closest one
+ * if there are overlapping regions.
+ * May return a region with an unconfigured block type (getTypeOptions returns
+ * null).
+ * Returns either {@link PSGroupRegion}, {@link PSStandardRegion} or
+ * {@link PSMergedRegion}.
*
* @param l the location
- * @return the {@link PSRegion} object if the location is in a region, or null if the location is not in a region
+ * @return the {@link PSRegion} object if the location is in a region, or null
+ * if the location is not in a region
*/
public static PSRegion fromLocationUnsafe(Location l) {
checkNotNull(checkNotNull(l).getWorld());
RegionManager rgm = WGUtils.getRegionManagerWithWorld(l.getWorld());
- if (rgm == null) return null;
+ if (rgm == null)
+ return null;
// check exact location first for merged region block
PSMergedRegion pr = PSMergedRegion.getMergedRegion(l);
- if (pr != null) return pr;
+ if (pr != null)
+ return pr;
return fromLocationGroupUnsafe(l);
}
@@ -85,7 +94,8 @@ public static PSRegion fromLocationUnsafe(Location l) {
* Returns either {@link PSGroupRegion} or {@link PSStandardRegion}.
*
* @param l the location
- * @return the {@link PSRegion} object if the location is in a region, or null if the location is not in a region
+ * @return the {@link PSRegion} object if the location is in a region, or null
+ * if the location is not in a region
*/
public static PSRegion fromLocationGroup(Location l) {
PSRegion r = fromLocationGroupUnsafe(l);
@@ -94,16 +104,19 @@ public static PSRegion fromLocationGroup(Location l) {
/**
* Get the protection stone parent region that the location is in.
- * May return a region with an unconfigured block type (getTypeOptions returns null).
+ * May return a region with an unconfigured block type (getTypeOptions returns
+ * null).
* Returns either {@link PSGroupRegion} or {@link PSStandardRegion}.
*
* @param l the location
- * @return the {@link PSRegion} object if the location is in a region, or null if the location is not in a region
+ * @return the {@link PSRegion} object if the location is in a region, or null
+ * if the location is not in a region
*/
public static PSRegion fromLocationGroupUnsafe(Location l) {
checkNotNull(checkNotNull(l).getWorld());
RegionManager rgm = WGUtils.getRegionManagerWithWorld(l.getWorld());
- if (rgm == null) return null;
+ if (rgm == null)
+ return null;
// check if location is in a region
String psID = WGUtils.matchLocationToPSID(l);
@@ -112,7 +125,9 @@ public static PSRegion fromLocationGroupUnsafe(Location l) {
if (r == null) {
return null;
} else if (r.getFlag(FlagHandler.PS_MERGED_REGIONS) != null) {
- return new PSGroupRegion(r, rgm, l.getWorld());
+ PSGroupRegion gr = new PSGroupRegion(r, rgm, l.getWorld());
+ PSRegion mr = gr.getMergedRegion(l);
+ return mr != null ? mr : gr;
} else {
return new PSStandardRegion(r, rgm, l.getWorld());
}
@@ -120,14 +135,17 @@ public static PSRegion fromLocationGroupUnsafe(Location l) {
/**
* Get the protection stone region with the world and region.
- * It returns a WGRegion with a null type if the block type isn't configured in the config.
+ * It returns a WGRegion with a null type if the block type isn't configured in
+ * the config.
*
* @param w the world
* @param r the WorldGuard region
- * @return the {@link PSRegion} based on the parameters, or null if the region given is not a protectionstones region
+ * @return the {@link PSRegion} based on the parameters, or null if the region
+ * given is not a protectionstones region
*/
public static PSRegion fromWGRegion(World w, ProtectedRegion r) {
- if (!ProtectionStones.isPSRegionFormat(r)) return null;
+ if (!ProtectionStones.isPSRegionFormat(r))
+ return null;
if (r.getFlag(FlagHandler.PS_MERGED_REGIONS) != null) {
return new PSGroupRegion(r, WGUtils.getRegionManagerWithWorld(checkNotNull(w)), w);
} else {
@@ -136,7 +154,8 @@ public static PSRegion fromWGRegion(World w, ProtectedRegion r) {
}
/**
- * Get the protection stones regions that have the given name as their set nickname (/ps name)
+ * Get the protection stones regions that have the given name as their set
+ * nickname (/ps name)
*
* @param w the world to look for regions in
* @param name the nickname of the region
@@ -145,12 +164,14 @@ public static PSRegion fromWGRegion(World w, ProtectedRegion r) {
public static List fromName(World w, String name) {
RegionManager rgm = WGUtils.getRegionManagerWithWorld(w);
- if (rgm == null) return new ArrayList<>();
+ if (rgm == null)
+ return new ArrayList<>();
List l = new ArrayList<>();
List rIds = ProtectionStones.regionNameToID.get(w.getUID()).get(name);
- if (rIds == null) return l;
+ if (rIds == null)
+ return l;
for (int i = 0; i < rIds.size(); i++) {
String id = rIds.get(i);
@@ -165,7 +186,8 @@ public static List fromName(World w, String name) {
}
/**
- * Get the protection stones regions that have the given name as their set nickname (/ps name), from all worlds.
+ * Get the protection stones regions that have the given name as their set
+ * nickname (/ps name), from all worlds.
*
* @param name the nickname of the regions
* @return the map of worlds, to the regions that have the name
@@ -195,13 +217,16 @@ public String getID() {
}
/**
- * Get the WorldGuard ID of the region. Note that this is not guaranteed to be unique between worlds.
+ * Get the WorldGuard ID of the region. Note that this is not guaranteed to be
+ * unique between worlds.
+ *
* @return the id of the region
*/
public abstract String getId();
/**
* Get the name (nickname) of the region from /ps name.
+ *
* @return the name of the region, or null if the region does not have a name
*/
@@ -209,6 +234,7 @@ public String getID() {
/**
* Set the name of the region (from /ps name).
+ *
* @param name new name, or null to remove the name
*/
@@ -216,14 +242,18 @@ public String getID() {
/**
* Set the parent of this region.
+ *
* @param r the region to be the parent, or null for no parent
- * @throws ProtectedRegion.CircularInheritanceException thrown when the parent already inherits from the child
+ * @throws ProtectedRegion.CircularInheritanceException thrown when the parent
+ * already inherits from
+ * the child
*/
public abstract void setParent(PSRegion r) throws ProtectedRegion.CircularInheritanceException;
/**
* Get the parent of this region, if there is one.
+ *
* @return the parent of the region, or null if there isn't one
*/
@@ -231,12 +261,14 @@ public String getID() {
/**
* Get the location of the set home the region has (for /ps tp).
+ *
* @return the location of the home, or null if the ps_home flag is not set.
*/
public abstract Location getHome();
/**
* Set the home of the region (internally changes the flag).
+ *
* @param blockX block x location
* @param blockY block y location
* @param blockZ block z location
@@ -245,11 +277,12 @@ public String getID() {
/**
* Set the home of the region (internally changes the flag).
+ *
* @param blockX block x location
* @param blockY block y location
* @param blockZ block z location
- * @param yaw location yaw
- * @param pitch location pitch
+ * @param yaw location yaw
+ * @param pitch location pitch
*/
public abstract void setHome(double blockX, double blockY, double blockZ, float yaw, float pitch);
@@ -275,6 +308,7 @@ public enum RentStage {
/**
* Sells the region to a player at the price listed.
+ *
* @param player player to transfer the region to
*/
public abstract void sell(UUID player);
@@ -286,36 +320,42 @@ public enum RentStage {
/**
* Get the landlord of the region.
+ *
* @return returns the UUID of the landlord, or null if there is none.
*/
public abstract UUID getLandlord();
/**
* Set the landlord of the region.
+ *
* @param landlord uuid of landlord, or null to remove
*/
public abstract void setLandlord(UUID landlord);
/**
* Get the tenant of the region.
+ *
* @return returns the UUID of the tenant, or null if there is none.
*/
public abstract UUID getTenant();
/**
* Set the tenant of the region
+ *
* @param tenant uuid of tenant, or null to remove
*/
public abstract void setTenant(UUID tenant);
/**
* Get the rent period of the region
+ *
* @return returns the rent duration, or null if there is none
*/
public abstract String getRentPeriod();
/**
* Set the rent period of the region
+ *
* @param s the duration between rent payments (d h m s), or null to remove
*/
public abstract void setRentPeriod(String s);
@@ -324,7 +364,8 @@ public enum RentStage {
* Get the price of the region
* This applies to either the rent or the full purchase of a region.
*
- * @return the price of the region during rent payments, or null if there is no rent
+ * @return the price of the region during rent payments, or null if there is no
+ * rent
*/
public abstract Double getPrice();
@@ -338,12 +379,14 @@ public enum RentStage {
/**
* Set the unix timestamp of when rent was last paid.
+ *
* @param timestamp the unix timestamp of when rent was last paid, or null
*/
public abstract void setRentLastPaid(Long timestamp);
/**
* Get the unix timestamp of when rent was last paid.
+ *
* @return the unix timestamp of when rent was last paid, or null if not renting
*/
public abstract Long getRentLastPaid();
@@ -379,7 +422,8 @@ public enum RentStage {
public static class TaxPayment implements Comparable {
long whenPaymentIsDue;
double amount;
- String regionId; // the region that caused the payment (especially applicable for group regions); also used since hashsets don't have duplicates
+ String regionId; // the region that caused the payment (especially applicable for group regions);
+ // also used since hashsets don't have duplicates
public TaxPayment(long whenPaymentIsDue, double amount, String regionId) {
this.whenPaymentIsDue = whenPaymentIsDue;
@@ -388,13 +432,16 @@ public TaxPayment(long whenPaymentIsDue, double amount, String regionId) {
}
/**
- * Convert a flag entry to a tax payment object. The flag entry is in the form "timestamp amount regionId".
+ * Convert a flag entry to a tax payment object. The flag entry is in the form
+ * "timestamp amount regionId".
+ *
* @param s the flag value
* @return the tax payment object, or null if the string was invalid
*/
public static TaxPayment fromString(String s) {
String[] arr = s.split(" ");
- if (arr.length < 3) return null;
+ if (arr.length < 3)
+ return null;
try {
return new TaxPayment(Long.parseLong(arr[0]), Double.parseDouble(arr[1]), arr[2]);
} catch (NumberFormatException e) {
@@ -404,6 +451,7 @@ public static TaxPayment fromString(String s) {
/**
* Converts the tax payment object into its flag representation.
+ *
* @return the flag representation of this object
*/
public String toFlagEntry() {
@@ -450,13 +498,17 @@ public LastRegionTaxPaymentEntry(String regionId, long lastPaymentAdded) {
}
/**
- * Convert a flag entry to a last region tax payment entry object. The flag entry is in the form "regionId timestamp".
+ * Convert a flag entry to a last region tax payment entry object. The flag
+ * entry is in the form "regionId timestamp".
+ *
* @param s the flag value
- * @return the last region tax payment entry object, or null if the string was invalid
+ * @return the last region tax payment entry object, or null if the string was
+ * invalid
*/
public static LastRegionTaxPaymentEntry fromString(String s) {
String[] arr = s.split(" ");
- if (arr.length < 2) return null;
+ if (arr.length < 2)
+ return null;
try {
return new LastRegionTaxPaymentEntry(arr[0], Long.parseLong(arr[1]));
} catch (NumberFormatException e) {
@@ -465,7 +517,9 @@ public static LastRegionTaxPaymentEntry fromString(String s) {
}
/**
- * Converts the last region tax payment entry object into its flag representation.
+ * Converts the last region tax payment entry object into its flag
+ * representation.
+ *
* @return the flag representation of this object
*/
public String toFlagEntry() {
@@ -491,6 +545,7 @@ public void setLastPaymentAdded(long lastPaymentAdded) {
/**
* Get the tax rate for this region type.
+ *
* @return the tax rate
*/
public double getTaxRate() {
@@ -500,66 +555,83 @@ public double getTaxRate() {
/**
* Get the formatted period(s) between tax payments for this region type.
* If you simply wanted the number of seconds, use getTypeOptions().taxPeriod
- * @return the duration between tax payments, or multiple if there are several different ones
+ *
+ * @return the duration between tax payments, or multiple if there are several
+ * different ones
*/
public abstract String getTaxPeriod();
/**
* Get the formatted period(s) allowed for the payment of tax.
- * If you simply wanted the number of seconds, use getTypeOptions().taxPaymentTime
- * @return the duration of time allowed to pay a tax, or multiple if there are several different ones
+ * If you simply wanted the number of seconds, use
+ * getTypeOptions().taxPaymentTime
+ *
+ * @return the duration of time allowed to pay a tax, or multiple if there are
+ * several different ones
*/
public abstract String getTaxPaymentPeriod();
/**
* Get the list of tax payments that are due.
+ *
* @return the list of tax payments outstanding
*/
public abstract List getTaxPaymentsDue();
/**
* Save the list of tax payments due onto the region.
+ *
* @param taxPayments the full list of tax payments that are due
*/
public abstract void setTaxPaymentsDue(List taxPayments);
/**
- * Get the list of timestamps of the last time regions and sub regions have added to the tax payments list.
- * @return the list of the last time regions and sub regions have added to the tax payment list
+ * Get the list of timestamps of the last time regions and sub regions have
+ * added to the tax payments list.
+ *
+ * @return the list of the last time regions and sub regions have added to the
+ * tax payment list
*/
public abstract List getRegionLastTaxPaymentAddedEntries();
/**
- * Save the list of timestamps of the last time regions and sub regions have added to the tax payments list on to the base region.
+ * Save the list of timestamps of the last time regions and sub regions have
+ * added to the tax payments list on to the base region.
+ *
* @param entries the full list of {@link LastRegionTaxPaymentEntry} entries.
*/
public abstract void setRegionLastTaxPaymentAddedEntries(List entries);
/**
* Get the player that is set to autopay the tax amount.
+ *
* @return the player that is set as the autopayer, or null if no player is set
*/
public abstract UUID getTaxAutopayer();
/**
* Set a player to auto-pay taxes for this region.
+ *
* @param player the player to use to auto-pay taxes
*/
public abstract void setTaxAutopayer(UUID player);
/**
* Pay outstanding taxes.
- * It will only withdraw the amount required to pay the taxes, and will take up to the amount
+ * It will only withdraw the amount required to pay the taxes, and will take up
+ * to the amount
* specified if the outstanding payments are larger.
*
- * @param p the player to take money from
+ * @param p the player to take money from
* @param amount the amount to take
* @return the {@link EconomyResponse} returned by Vault
*/
public abstract EconomyResponse payTax(PSPlayer p, double amount);
/**
- * Check if any tax payments are now late (exceeded tax payment time shown in config).
+ * Check if any tax payments are now late (exceeded tax payment time shown in
+ * config).
+ *
* @return whether or not any tax payments are now late
*/
public abstract boolean isTaxPaymentLate();
@@ -573,6 +645,7 @@ public double getTaxRate() {
/**
* Must be run sync (calls Bukkit API)
+ *
* @return whether or not the protection block is hidden (/ps hide)
*/
public boolean isHidden() {
@@ -581,6 +654,7 @@ public boolean isHidden() {
/**
* Hides the protection block, if it is not hidden.
+ *
* @return whether or not the block was hidden
*/
public boolean hide() {
@@ -594,6 +668,7 @@ public boolean hide() {
/**
* Unhides the protection block, if it is hidden.
+ *
* @return whether or not the block was unhidden
*/
public boolean unhide() {
@@ -616,12 +691,15 @@ public boolean unhide() {
* Toggle whether or not the protection block is hidden.
*/
public void toggleHide() {
- if (!hide()) unhide();
+ if (!hide())
+ unhide();
}
/**
- * This method returns the block that is supposed to contain the protection block.
- * Warning: If the protection stone is hidden, this will give the block that took its place!
+ * This method returns the block that is supposed to contain the protection
+ * block.
+ * Warning: If the protection stone is hidden, this will give the block that
+ * took its place!
*
* @return returns the block that may contain the protection stone
*/
@@ -634,17 +712,20 @@ public void toggleHide() {
public abstract PSProtectBlock getTypeOptions();
/**
- * @return returns the protect block type (may include custom player heads PLAYER_HEAD:playername) that the region is
+ * @return returns the protect block type (may include custom player heads
+ * PLAYER_HEAD:playername) that the region is
*/
public abstract String getType();
/**
* Change the type of the protection region.
+ *
* @param type the type of protection region to switch to
*/
public void setType(PSProtectBlock type) {
if (!isHidden()) {
- Material set = Material.matchMaterial(type.type) == null ? Material.PLAYER_HEAD : Material.matchMaterial(type.type);
+ Material set = Material.matchMaterial(type.type) == null ? Material.PLAYER_HEAD
+ : Material.matchMaterial(type.type);
getProtectBlock().setType(set);
if (type.type.startsWith("PLAYER_HEAD") && type.type.split(":").length > 1) {
BlockUtil.setHeadType(type.type, getProtectBlock());
@@ -654,6 +735,7 @@ public void setType(PSProtectBlock type) {
/**
* Get whether or not a player is an owner of this region.
+ *
* @param uuid the player's uuid
* @return whether or not the player is a member
*/
@@ -662,6 +744,7 @@ public void setType(PSProtectBlock type) {
/**
* Get whether or not a player is a member of this region.
+ *
* @param uuid the player's uuid
* @return whether or not the player is a member
*/
@@ -680,25 +763,30 @@ public void setType(PSProtectBlock type) {
/**
* Add an owner to the region.
+ *
* @param uuid the uuid of the player to add
*/
public abstract void addOwner(UUID uuid);
/**
* Add a member to the region.
+ *
* @param uuid the uuid of the player to add
*/
public abstract void addMember(UUID uuid);
/**
* Remove an owner of the region, and deal with side-effects.
- * Examples of side-effects: removing player as landlord, removing player as auto taxpayer
+ * Examples of side-effects: removing player as landlord, removing player as
+ * auto taxpayer
+ *
* @param uuid the uuid of the player to remove
*/
public abstract void removeOwner(UUID uuid);
/**
* Remove a member of the region, and deal with side-effects
+ *
* @param uuid the uuid of the player to remove
*/
public abstract void removeMember(UUID uuid);
@@ -709,7 +797,8 @@ public void setType(PSProtectBlock type) {
public abstract List getPoints();
/**
- * Get a list of regions that the current region can merge into, taking into account a player's permissions.
+ * Get a list of regions that the current region can merge into, taking into
+ * account a player's permissions.
*
* @param p the player to compare permissions with
* @return the list of regions that the current region can merge into
@@ -719,7 +808,8 @@ public void setType(PSProtectBlock type) {
/**
* Deletes the region forever. Can be cancelled by event cancellation.
*
- * @param deleteBlock whether or not to also set the protection block to air (if not hidden)
+ * @param deleteBlock whether or not to also set the protection block to air (if
+ * not hidden)
* @return whether or not the region was able to be successfully removed
*/
public abstract boolean deleteRegion(boolean deleteBlock);
@@ -727,7 +817,8 @@ public void setType(PSProtectBlock type) {
/**
* Deletes the region forever. Can be cancelled by event cancellation.
*
- * @param deleteBlock whether or not to also set the protection block to air (if not hidden)
+ * @param deleteBlock whether or not to also set the protection block to air (if
+ * not hidden)
* @param cause the player that caused the region to break
* @return whether or not the region was able to be successfully removed
*/
@@ -747,8 +838,10 @@ public RegionManager getWGRegionManager() {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
PSRegion psRegion = (PSRegion) o;
return Objects.equals(getId(), psRegion.getId()) && Objects.equals(getWorld(), psRegion.getWorld());
}
diff --git a/src/main/java/dev/espi/protectionstones/ProtectionStones.java b/src/main/java/dev/espi/protectionstones/ProtectionStones.java
index bd1775f9..d2ecebee 100644
--- a/src/main/java/dev/espi/protectionstones/ProtectionStones.java
+++ b/src/main/java/dev/espi/protectionstones/ProtectionStones.java
@@ -52,9 +52,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
-
/**
- * The base class for the plugin. Some utilities are static, and others are instance methods, so they need to
+ * The base class for the plugin. Some utilities are static, and others are
+ * instance methods, so they need to
* be accessed through getInstance().
*/
@@ -76,7 +76,6 @@ public class ProtectionStones extends JavaPlugin {
private PSConfig configOptions;
static HashMap protectionStonesOptions = new HashMap<>();
-
// ps alias to id cache
// >
static HashMap>> regionNameToID = new HashMap<>();
@@ -94,6 +93,15 @@ public class ProtectionStones extends JavaPlugin {
// ps toggle/on/off list
public static Set toggleList = new HashSet<>();
+ private static net.kyori.adventure.platform.bukkit.BukkitAudiences adventure;
+
+ public static net.kyori.adventure.platform.bukkit.BukkitAudiences getAdventure() {
+ if (adventure == null) {
+ throw new IllegalStateException("Tried to access Adventure when the plugin was disabled!");
+ }
+ return adventure;
+ }
+
/* ~~~~~~~~~~ Instance methods ~~~~~~~~~~~~ */
/**
@@ -164,6 +172,7 @@ public boolean isDebug() {
/**
* Print a debug message (only prints if the plugin is in debug mode).
+ *
* @param msg the message to print
*/
public void debug(String msg) {
@@ -194,12 +203,12 @@ public void setConfigOptions(PSConfig conf) {
public List getConfiguredBlocks() {
List l = new ArrayList<>();
for (PSProtectBlock b : protectionStonesOptions.values()) {
- if (!l.contains(b)) l.add(b);
+ if (!l.contains(b))
+ l.add(b);
}
return l;
}
-
/* ~~~~~~~~~~ Static methods ~~~~~~~~~~~~~~ */
/**
@@ -227,18 +236,21 @@ public static PSEconomy getEconomy() {
* Get the protection block config options for the block specified.
*
* @param block the block to get the block options of
- * @return the config options for the protect block specified (null if not found)
+ * @return the config options for the protect block specified (null if not
+ * found)
*/
public static PSProtectBlock getBlockOptions(Block block) {
- if (block == null) return null;
+ if (block == null)
+ return null;
return getBlockOptions(BlockUtil.getProtectBlockType(block));
}
/**
* Get the protection block config options for the item specified.
*
- * If the options has restrict-obtaining enabled, and the item does not contain the required NBT tag, null will
+ * If the options has restrict-obtaining enabled, and the item does not contain
+ * the required NBT tag, null will
* be returned.
*
* @param item the item to get the block options of
@@ -246,16 +258,20 @@ public static PSProtectBlock getBlockOptions(Block block) {
*/
public static PSProtectBlock getBlockOptions(ItemStack item) {
- if (!isProtectBlockItem(item)) return null;
+ if (!isProtectBlockItem(item))
+ return null;
return getBlockOptions(BlockUtil.getProtectBlockType(item));
}
/**
- * Gets the config options for the protection block type specified. It is recommended to use the block parameter overloaded
+ * Gets the config options for the protection block type specified. It is
+ * recommended to use the block parameter overloaded
* method instead if possible, since it deals better with heads.
*
- * @param blockType the material type name (Bukkit) of the protect block to get the options for, or "PLAYER_HEAD name" for heads
- * @return the config options for the protect block specified (null if not found)
+ * @param blockType the material type name (Bukkit) of the protect block to get
+ * the options for, or "PLAYER_HEAD name" for heads
+ * @return the config options for the protect block specified (null if not
+ * found)
*/
public static PSProtectBlock getBlockOptions(String blockType) {
return protectionStonesOptions.get(blockType);
@@ -266,10 +282,13 @@ public static boolean isProtectBlockType(Block b) {
}
/**
- * Get whether or not a material is used as a protection block. It is recommended to use the block
- * parameter overloaded method if possible since player heads have a different format.
+ * Get whether or not a material is used as a protection block. It is
+ * recommended to use the block
+ * parameter overloaded method if possible since player heads have a different
+ * format.
*
- * @param material material type to check (Bukkit material name), or "PLAYER_HEAD name" for heads
+ * @param material material type to check (Bukkit material name), or
+ * "PLAYER_HEAD name" for heads
* @return whether or not that material is being used for a protection block
*/
public static boolean isProtectBlockType(String material) {
@@ -277,41 +296,52 @@ public static boolean isProtectBlockType(String material) {
}
/**
- * Check whether or not a given block is a protection block, and actually protects a region.
+ * Check whether or not a given block is a protection block, and actually
+ * protects a region.
+ *
* @param b the block to look at
- * @return whether or not the block is a protection block responsible for a region.
+ * @return whether or not the block is a protection block responsible for a
+ * region.
*/
public static boolean isProtectBlock(Block b) {
- if (!isProtectBlockType(b)) return false;
+ if (!isProtectBlockType(b))
+ return false;
RegionManager rgm = WGUtils.getRegionManagerWithWorld(b.getWorld());
- if (rgm == null) return false;
- return rgm.getRegion(WGUtils.createPSID(b.getLocation())) != null || PSMergedRegion.getMergedRegion(b.getLocation()) != null;
+ if (rgm == null)
+ return false;
+ return rgm.getRegion(WGUtils.createPSID(b.getLocation())) != null
+ || PSMergedRegion.getMergedRegion(b.getLocation()) != null;
}
/**
- * Check if a WorldGuard {@link ProtectedRegion} is a ProtectionStones region, and is configured in the config.
+ * Check if a WorldGuard {@link ProtectedRegion} is a ProtectionStones region,
+ * and is configured in the config.
*
* @param r the region to check
- * @return true if the WorldGuard region is a ProtectionStones region, and false if it isn't
+ * @return true if the WorldGuard region is a ProtectionStones region, and false
+ * if it isn't
*/
public static boolean isPSRegion(ProtectedRegion r) {
return isPSRegionFormat(r) && getBlockOptions(r.getFlag(FlagHandler.PS_BLOCK_MATERIAL)) != null;
}
/**
- * Check if a WorldGuard {@link ProtectedRegion} has the format of a ProtectionStones region, but is not necessarily configured
+ * Check if a WorldGuard {@link ProtectedRegion} has the format of a
+ * ProtectionStones region, but is not necessarily configured
* in the config.
*
* @param r the region to check
- * @return true if the WorldGuard region is a ProtectionStones region, and false if it isn't
+ * @return true if the WorldGuard region is a ProtectionStones region, and false
+ * if it isn't
*/
public static boolean isPSRegionFormat(ProtectedRegion r) {
return r != null && r.getId().startsWith("ps") && r.getFlag(FlagHandler.PS_BLOCK_MATERIAL) != null;
}
/**
- * Check if a ProtectionStones name is already used by a region globally (from /ps name)
+ * Check if a ProtectionStones name is already used by a region globally (from
+ * /ps name)
*
* @param name the name to search for
* @return whether or not there is a region with this name
@@ -322,14 +352,16 @@ public static boolean isPSNameAlreadyUsed(String name) {
RegionManager rgm = WGUtils.getRegionManagerWithWorld(Bukkit.getWorld(worldUid));
List l = regionNameToID.get(worldUid).get(name);
- if (l == null) continue;
+ if (l == null)
+ continue;
for (int i = 0; i < l.size(); i++) { // remove outdated cache
if (rgm.getRegion(l.get(i)) == null) {
l.remove(i);
i--;
}
}
- if (!l.isEmpty()) return true;
+ if (!l.isEmpty())
+ return true;
}
return false;
}
@@ -337,14 +369,17 @@ public static boolean isPSNameAlreadyUsed(String name) {
/**
* Get protection stone regions using an ID or alias.
*
- * @param w the world to search in (only if it is an id; aliases/names are global)
+ * @param w the world to search in (only if it is an id; aliases/names
+ * are global)
* @param identifier id or alias of the region
- * @return a list of psregions that match the id or alias; will be empty if no regions were found
+ * @return a list of psregions that match the id or alias; will be empty if no
+ * regions were found
*/
public static List getPSRegions(World w, String identifier) {
RegionManager rgm = WGUtils.getRegionManagerWithWorld(w);
- if (rgm == null) return new ArrayList<>();
+ if (rgm == null)
+ return new ArrayList<>();
PSRegion r = PSRegion.fromWGRegion(w, rgm.getRegion(identifier));
if (r != null) { // return id based query
@@ -357,7 +392,8 @@ public static List getPSRegions(World w, String identifier) {
}
/**
- * Removes a protection stone region given its ID, and the region manager it is stored in
+ * Removes a protection stone region given its ID, and the region manager it is
+ * stored in
* Note: Does not remove the PS block.
*
* @param w the world that the region is in
@@ -366,13 +402,16 @@ public static List getPSRegions(World w, String identifier) {
*/
public static boolean removePSRegion(World w, String psID) {
- PSRegion r = PSRegion.fromWGRegion(checkNotNull(w), checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
+ PSRegion r = PSRegion.fromWGRegion(checkNotNull(w),
+ checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
return r != null && r.deleteRegion(false);
}
/**
- * Removes a protection stone region given its ID, and the region manager it is stored in, with a player as its cause
- * Note: Does not remove the PS block, and does not check if the player (cause) has permission to do this.
+ * Removes a protection stone region given its ID, and the region manager it is
+ * stored in, with a player as its cause
+ * Note: Does not remove the PS block, and does not check if the player (cause)
+ * has permission to do this.
*
* @param w the world that the region is in
* @param psID the worldguard region ID of the region
@@ -381,7 +420,8 @@ public static boolean removePSRegion(World w, String psID) {
*/
public static boolean removePSRegion(World w, String psID, Player cause) {
- PSRegion r = PSRegion.fromWGRegion(checkNotNull(w), checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
+ PSRegion r = PSRegion.fromWGRegion(checkNotNull(w),
+ checkNotNull(WGUtils.getRegionManagerWithWorld(w).getRegion(psID)));
return r != null && r.deleteRegion(false, cause);
}
@@ -393,41 +433,54 @@ public static boolean removePSRegion(World w, String psID, Player cause) {
*/
public static PSProtectBlock getProtectBlockFromAlias(String name) {
- if (name == null) return null;
+ if (name == null)
+ return null;
for (PSProtectBlock cpb : ProtectionStones.protectionStonesOptions.values()) {
- if (cpb.alias.equalsIgnoreCase(name) || cpb.type.equalsIgnoreCase(name)) return cpb;
+ if (cpb.alias.equalsIgnoreCase(name) || cpb.type.equalsIgnoreCase(name))
+ return cpb;
}
return null;
}
/**
- * Check if an item is a valid protection block, and if checkNBT is true, check if it was created by
- * ProtectionStones. Be aware that blocks may have restrict-obtaining off, meaning that it is ignored whether or not
+ * Check if an item is a valid protection block, and if checkNBT is true, check
+ * if it was created by
+ * ProtectionStones. Be aware that blocks may have restrict-obtaining off,
+ * meaning that it is ignored whether or not
* the item is created by ProtectionStones (in this case have checkNBT false).
*
* @param item the item to check
- * @param checkNBT whether or not to check if the plugin signed off on the item (restrict-obtaining)
- * @return whether or not the item is a valid protection block item, and was created by protection stones
+ * @param checkNBT whether or not to check if the plugin signed off on the item
+ * (restrict-obtaining)
+ * @return whether or not the item is a valid protection block item, and was
+ * created by protection stones
*/
public static boolean isProtectBlockItem(ItemStack item, boolean checkNBT) {
- if (item == null) return false;
+ if (item == null)
+ return false;
// check basic item
- if (!ProtectionStones.isProtectBlockType(BlockUtil.getProtectBlockType(item))) return false;
+ if (!ProtectionStones.isProtectBlockType(BlockUtil.getProtectBlockType(item)))
+ return false;
// check for player heads
- if (!checkNBT) return true; // if not checking nbt, you only need to check type
+ if (!checkNBT)
+ return true; // if not checking nbt, you only need to check type
boolean tag = false;
- // otherwise, check if the item was created by protection stones (stored in custom tag)
+ // otherwise, check if the item was created by protection stones (stored in
+ // custom tag)
if (item.getItemMeta() != null) {
CustomItemTagContainer tagContainer = item.getItemMeta().getCustomTagContainer();
try { // check if tag byte is 1
- Byte isPSBlock = tagContainer.getCustomTag(new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.BYTE);
+ Byte isPSBlock = tagContainer
+ .getCustomTag(new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.BYTE);
tag = isPSBlock != null && isPSBlock == 1;
} catch (IllegalArgumentException es) {
- try { // some nbt data may be using a string (legacy nbt from ps version 2.0.0 -> 2.0.6)
- String isPSBlock = tagContainer.getCustomTag(new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.STRING);
+ try { // some nbt data may be using a string (legacy nbt from ps version 2.0.0 ->
+ // 2.0.6)
+ String isPSBlock = tagContainer.getCustomTag(
+ new NamespacedKey(ProtectionStones.getInstance(), "isPSBlock"), ItemTagType.STRING);
tag = isPSBlock != null && isPSBlock.equals("true");
} catch (IllegalArgumentException ignored) {
}
@@ -438,18 +491,24 @@ public static boolean isProtectBlockItem(ItemStack item, boolean checkNBT) {
}
/**
- * Check if an item is a valid protection block, and if the block type has restrict-obtaining on, check if it was
- * created by ProtectionStones (custom NBT tag). Be aware that blocks may have restrict-obtaining
- * off, meaning that it ignores whether or not the item is created by ProtectionStones.
+ * Check if an item is a valid protection block, and if the block type has
+ * restrict-obtaining on, check if it was
+ * created by ProtectionStones (custom NBT tag). Be aware that blocks may have
+ * restrict-obtaining
+ * off, meaning that it ignores whether or not the item is created by
+ * ProtectionStones.
*
- * @param item the item to check
- * @return whether or not the item is a valid protection block item, and was created by protection stones
+ * @param item the item to check
+ * @return whether or not the item is a valid protection block item, and was
+ * created by protection stones
*/
public static boolean isProtectBlockItem(ItemStack item) {
- if (item == null) return false;
+ if (item == null)
+ return false;
PSProtectBlock b = ProtectionStones.getBlockOptions(BlockUtil.getProtectBlockType(item));
- if (b == null) return false;
+ if (b == null)
+ return false;
return isProtectBlockItem(item, b.restrictObtaining);
}
@@ -457,7 +516,8 @@ public static boolean isProtectBlockItem(ItemStack item) {
* Get a protection block item from a protect block config object.
*
* @param b the config options for the protection block
- * @return the item with NBT and other metadata to signify that it was created by protection stones
+ * @return the item with NBT and other metadata to signify that it was created
+ * by protection stones
*/
public static ItemStack createProtectBlockItem(PSProtectBlock b) {
@@ -482,11 +542,21 @@ public static ItemStack createProtectBlockItem(PSProtectBlock b) {
}
// add display name and lore
+ net.kyori.adventure.text.minimessage.MiniMessage mm = net.kyori.adventure.text.minimessage.MiniMessage
+ .miniMessage();
+ net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer lcs = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
+ .builder().hexColors().useUnusualXRepeatedCharacterHexFormat().build(); // Standard hex format
+
if (!b.displayName.equals("")) {
- im.setDisplayName(ChatColor.translateAlternateColorCodes('&', b.displayName));
+ // Convert legacy to mm first if needed, or straight mm
+ String parsed = lcs.serialize(mm.deserialize(PSL.legacyToMiniMessage(b.displayName)));
+ im.setDisplayName(parsed);
}
List lore = new ArrayList<>();
- for (String s : b.lore) lore.add(ChatColor.translateAlternateColorCodes('&', s));
+ for (String s : b.lore) {
+ String parsed = lcs.serialize(mm.deserialize(PSL.legacyToMiniMessage(s)));
+ lore.add(parsed);
+ }
im.setLore(lore);
// hide enchant name (cannot call addUnsafeEnchantment here)
@@ -495,7 +565,8 @@ public static ItemStack createProtectBlockItem(PSProtectBlock b) {
}
// add identifier for protection stone created items
- im.getCustomTagContainer().setCustomTag(new NamespacedKey(plugin, "isPSBlock"), ItemTagType.BYTE, (byte) 1);
+ im.getPersistentDataContainer().set(new NamespacedKey(plugin, "isPSBlock"),
+ org.bukkit.persistence.PersistentDataType.BYTE, (byte) 1);
is.setItemMeta(im);
@@ -517,7 +588,8 @@ public static void loadConfig(boolean isReload) {
ArgHelp.initHelpMenu();
// load economy
- if (ProtectionStones.getInstance().economy != null) ProtectionStones.getInstance().economy.stop();
+ if (ProtectionStones.getInstance().economy != null)
+ ProtectionStones.getInstance().economy.stop();
ProtectionStones.getInstance().economy = new PSEconomy();
// add command to Bukkit (using reflection)
@@ -549,6 +621,7 @@ public void onLoad() {
@Override
public void onEnable() {
+ adventure = net.kyori.adventure.platform.bukkit.BukkitAudiences.create(this);
FlagHandler.registerHandlers(); // register custom WG flag handlers
TomlFormat.instance();
@@ -560,7 +633,11 @@ public void onEnable() {
// metrics (bStats)
// https://bstats.org/plugin/bukkit/ProtectionStones/4071
- new Metrics(this, 4071);
+ try {
+ new Metrics(this, 4071);
+ } catch (Throwable t) {
+ getLogger().log(java.util.logging.Level.WARNING, "bStats metrics disabled due to error", t);
+ }
// load command arguments
PSCommand.addDefaultArguments();
@@ -568,15 +645,19 @@ public void onEnable() {
// register event listeners
getServer().getPluginManager().registerEvents(new ListenerClass(), this);
- // check that WorldGuard and WorldEdit are enabled (WorldGuard will only be enabled if there's WorldEdit)
- if (getServer().getPluginManager().getPlugin("WorldGuard") == null || !getServer().getPluginManager().getPlugin("WorldGuard").isEnabled()) {
+ // check that WorldGuard and WorldEdit are enabled (WorldGuard will only be
+ // enabled if there's WorldEdit)
+ if (getServer().getPluginManager().getPlugin("WorldGuard") == null
+ || !getServer().getPluginManager().getPlugin("WorldGuard").isEnabled()) {
getLogger().severe("WorldGuard or WorldEdit not enabled! Disabling ProtectionStones...");
getServer().getPluginManager().disablePlugin(this);
}
// check if Vault is enabled (for economy support)
- if (getServer().getPluginManager().getPlugin("Vault") != null && getServer().getPluginManager().getPlugin("Vault").isEnabled()) {
- RegisteredServiceProvider econ = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
+ if (getServer().getPluginManager().getPlugin("Vault") != null
+ && getServer().getPluginManager().getPlugin("Vault").isEnabled()) {
+ RegisteredServiceProvider econ = getServer().getServicesManager()
+ .getRegistration(net.milkbowl.vault.economy.Economy.class);
if (econ == null) {
getLogger().warning("No economy plugin found by Vault! There will be no economy support!");
vaultSupportEnabled = false;
@@ -589,7 +670,8 @@ public void onEnable() {
}
// check for PlaceholderAPI
- if (getServer().getPluginManager().getPlugin("PlaceholderAPI") != null && getServer().getPluginManager().getPlugin("PlaceholderAPI").isEnabled()) {
+ if (getServer().getPluginManager().getPlugin("PlaceholderAPI") != null
+ && getServer().getPluginManager().getPlugin("PlaceholderAPI").isEnabled()) {
getLogger().info("PlaceholderAPI support enabled!");
placeholderAPISupportEnabled = true;
new PSPlaceholderExpansion().register();
@@ -598,7 +680,8 @@ public void onEnable() {
}
// check for LuckPerms
- if (getServer().getPluginManager().getPlugin("LuckPerms") != null && getServer().getPluginManager().getPlugin("LuckPerms").isEnabled()) {
+ if (getServer().getPluginManager().getPlugin("LuckPerms") != null
+ && getServer().getPluginManager().getPlugin("LuckPerms").isEnabled()) {
try {
luckPermsSupportEnabled = true;
luckPerms = getServer().getServicesManager().load(LuckPerms.class);
@@ -661,4 +744,11 @@ public void onEnable() {
getLogger().info(ChatColor.WHITE + "ProtectionStones has successfully started!");
}
+ @Override
+ public void onDisable() {
+ if (adventure != null) {
+ adventure.close();
+ adventure = null;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/dev/espi/protectionstones/flags/FarewellFlagHandler.java b/src/main/java/dev/espi/protectionstones/flags/FarewellFlagHandler.java
index 86deb3c8..f98038ad 100644
--- a/src/main/java/dev/espi/protectionstones/flags/FarewellFlagHandler.java
+++ b/src/main/java/dev/espi/protectionstones/flags/FarewellFlagHandler.java
@@ -27,15 +27,14 @@
import dev.espi.protectionstones.FlagHandler;
import dev.espi.protectionstones.PSRegion;
import dev.espi.protectionstones.ProtectionStones;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.TextComponent;
+import dev.espi.protectionstones.ProtectionStones;
import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
// farewell-action flag
public class FarewellFlagHandler extends FlagValueChangeHandler {
public static final FarewellFlagHandler.Factory FACTORY = new FarewellFlagHandler.Factory();
+
public static class Factory extends Handler.Factory {
@Override
public FarewellFlagHandler create(Session session) {
@@ -53,26 +52,33 @@ protected void onInitialValue(LocalPlayer localPlayer, ApplicableRegionSet appli
}
@Override
- protected boolean onSetValue(LocalPlayer localPlayer, Location from, Location to, ApplicableRegionSet toSet, String currentValue, String lastValue, MoveType moveType) {
+ protected boolean onSetValue(LocalPlayer localPlayer, Location from, Location to, ApplicableRegionSet toSet,
+ String currentValue, String lastValue, MoveType moveType) {
Player p = Bukkit.getPlayer(localPlayer.getUniqueId());
- // the greeting action flag for the other region should show instead if it is set
+ // the greeting action flag for the other region should show instead if it is
+ // set
for (ProtectedRegion r : toSet.getRegions()) {
if (r.getFlag(FlagHandler.GREET_ACTION) != null) {
return true;
}
}
if (p != null && lastValue != null && !lastValue.equals(currentValue)) {
- p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', lastValue)));
+ ProtectionStones.getAdventure().player(p)
+ .sendActionBar(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage()
+ .deserialize(dev.espi.protectionstones.PSL.legacyToMiniMessage(lastValue)));
}
return true;
}
@Override
- protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) {
+ protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1,
+ ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) {
Player p = Bukkit.getPlayer(localPlayer.getUniqueId());
if (p != null && lastValue != null) {
- p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', lastValue)));
+ ProtectionStones.getAdventure().player(p)
+ .sendActionBar(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage()
+ .deserialize(dev.espi.protectionstones.PSL.legacyToMiniMessage(lastValue)));
}
return true;
}
diff --git a/src/main/java/dev/espi/protectionstones/flags/GreetingFlagHandler.java b/src/main/java/dev/espi/protectionstones/flags/GreetingFlagHandler.java
index 5462592e..1c889567 100644
--- a/src/main/java/dev/espi/protectionstones/flags/GreetingFlagHandler.java
+++ b/src/main/java/dev/espi/protectionstones/flags/GreetingFlagHandler.java
@@ -23,15 +23,15 @@
import com.sk89q.worldguard.session.handler.FlagValueChangeHandler;
import com.sk89q.worldguard.session.handler.Handler;
import dev.espi.protectionstones.FlagHandler;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.TextComponent;
+import dev.espi.protectionstones.ProtectionStones;
+import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
// greeting-action flag
public class GreetingFlagHandler extends FlagValueChangeHandler {
public static final Factory FACTORY = new Factory();
+
public static class Factory extends Handler.Factory {
@Override
public GreetingFlagHandler create(Session session) {
@@ -49,15 +49,20 @@ protected void onInitialValue(LocalPlayer localPlayer, ApplicableRegionSet appli
}
@Override
- protected boolean onSetValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String currentValue, String lastValue, MoveType moveType) {
- if (currentValue != null && !currentValue.equals(lastValue) && Bukkit.getPlayer(localPlayer.getUniqueId()) != null) {
- Bukkit.getPlayer(localPlayer.getUniqueId()).spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(ChatColor.translateAlternateColorCodes('&', currentValue)));
+ protected boolean onSetValue(LocalPlayer localPlayer, Location location, Location location1,
+ ApplicableRegionSet applicableRegionSet, String currentValue, String lastValue, MoveType moveType) {
+ if (currentValue != null && !currentValue.equals(lastValue)
+ && Bukkit.getPlayer(localPlayer.getUniqueId()) != null) {
+ ProtectionStones.getAdventure().player(Bukkit.getPlayer(localPlayer.getUniqueId()))
+ .sendActionBar(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage()
+ .deserialize(dev.espi.protectionstones.PSL.legacyToMiniMessage(currentValue)));
}
return true;
}
@Override
- protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1, ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) {
+ protected boolean onAbsentValue(LocalPlayer localPlayer, Location location, Location location1,
+ ApplicableRegionSet applicableRegionSet, String lastValue, MoveType moveType) {
return true;
}
}
diff --git a/src/main/java/dev/espi/protectionstones/flags/PSMessageFlagHandler.java b/src/main/java/dev/espi/protectionstones/flags/PSMessageFlagHandler.java
new file mode 100644
index 00000000..826cf950
--- /dev/null
+++ b/src/main/java/dev/espi/protectionstones/flags/PSMessageFlagHandler.java
@@ -0,0 +1,100 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package dev.espi.protectionstones.flags;
+
+import com.sk89q.worldedit.util.Location;
+import com.sk89q.worldguard.LocalPlayer;
+import com.sk89q.worldguard.protection.ApplicableRegionSet;
+import com.sk89q.worldguard.protection.flags.Flag;
+import com.sk89q.worldguard.session.MoveType;
+import com.sk89q.worldguard.session.Session;
+import com.sk89q.worldguard.session.handler.FlagValueChangeHandler;
+import com.sk89q.worldguard.session.handler.Handler;
+import dev.espi.protectionstones.PSL;
+import dev.espi.protectionstones.ProtectionStones;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+public class PSMessageFlagHandler extends FlagValueChangeHandler {
+
+ private final boolean isFarewell;
+ private final boolean isActionBar;
+
+ public static class Factory extends Handler.Factory {
+ private final Flag flag;
+ private final boolean isFarewell;
+ private final boolean isActionBar;
+
+ public Factory(Flag flag, boolean isFarewell, boolean isActionBar) {
+ this.flag = flag;
+ this.isFarewell = isFarewell;
+ this.isActionBar = isActionBar;
+ }
+
+ @Override
+ public PSMessageFlagHandler create(Session session) {
+ return new PSMessageFlagHandler(session, flag, isFarewell, isActionBar);
+ }
+ }
+
+ public PSMessageFlagHandler(Session session, Flag flag, boolean isFarewell, boolean isActionBar) {
+ super(session, flag);
+ this.isFarewell = isFarewell;
+ this.isActionBar = isActionBar;
+ }
+
+ @Override
+ protected void onInitialValue(LocalPlayer localPlayer, ApplicableRegionSet applicableRegionSet, String s) {
+ }
+
+ private void sendMessage(LocalPlayer localPlayer, String message) {
+ if (message == null || message.isEmpty())
+ return;
+ Player p = Bukkit.getPlayer(localPlayer.getUniqueId());
+ if (p == null)
+ return;
+
+ var component = MiniMessage.miniMessage().deserialize(PSL.legacyToMiniMessage(message));
+ var audience = ProtectionStones.getAdventure().player(p);
+
+ if (isActionBar) {
+ audience.sendActionBar(component);
+ } else {
+ audience.sendMessage(component);
+ }
+ }
+
+ @Override
+ protected boolean onSetValue(LocalPlayer localPlayer, Location from, Location to, ApplicableRegionSet toSet,
+ String currentValue, String lastValue, MoveType moveType) {
+ if (!isFarewell && currentValue != null && !currentValue.equals(lastValue)) {
+ sendMessage(localPlayer, currentValue);
+ } else if (isFarewell && lastValue != null && !lastValue.equals(currentValue)) {
+ sendMessage(localPlayer, lastValue);
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean onAbsentValue(LocalPlayer localPlayer, Location from, Location to, ApplicableRegionSet toSet,
+ String lastValue, MoveType moveType) {
+ if (isFarewell && lastValue != null) {
+ sendMessage(localPlayer, lastValue);
+ }
+ return true;
+ }
+}
diff --git a/src/main/resources/block2.toml b/src/main/resources/block2.toml
new file mode 100644
index 00000000..7a6320f5
--- /dev/null
+++ b/src/main/resources/block2.toml
@@ -0,0 +1,300 @@
+# Define your protection block below
+# Use block type from here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
+# --------------------------------------------------------------------------------------------------
+# If you want to use player heads, you can use "PLAYER_HEAD:player_name" (ex. "PLAYER_HEAD:Notch")
+# To use custom player heads, you need the base24 value of the head. On minecraft-heads.com, you will find this value in the Other section under "Value:".
+# To use UUIDs for player heads, go to https://sessionserver.mojang.com/session/minecraft/profile/PUT-UUID-HERE and copy the value from the "value" field not including quotes.
+# When you have the value, you can set the type to "PLAYER_HEAD:value"
+type = "DIAMOND_ORE"
+
+# Another way to refer to the protection stone
+# Can be used for /ps give and /ps get
+# Must be one word (no spaces)
+alias = "24"
+
+# Description of the protection block type
+# Shows up in /ps get menu
+description = "24 block radius protection zone."
+
+# Whether or not to restrict obtaining of the protection stone to only /ps get and /ps give and custom crafting recipes.
+# Other ways to obtain this block (ex. mining) will not work as a protection stone.
+# Useful to allow the protection block to only be obtained from a shop or command.
+# Set to "false" if you want to allow players to obtain a protection stone naturally
+restrict_obtaining = true
+
+# Enable or disable the use of this protection stone in specific worlds
+# "blacklist" mode prevents this protect block from being used in the worlds in "worlds"
+# "whitelist" mode allows this protect block to only be used in the worlds in "worlds"
+# Can be overridden with protectionstones.admin permission (including OP)!
+world_list_type = "blacklist"
+worlds = [
+ "exampleworld1",
+ "exampleworld2"
+]
+
+# Whether or not to actually restrict the protection stone from being placed when the world is restricted (in blacklist/whitelist)
+# The block will place normally, without PS behaviour.
+prevent_block_place_in_restricted_world = true
+
+# Whether or not to allow the block to be placed in the wild.
+# If set to false, the protection block can only be placed in existing regions.
+allow_placing_in_wild = true
+
+# Whether or not to allow the block to bypass the WorldGuard passthrough flag.
+# This allows the protection block to be placed even if WorldGuard prevents block placing in the wild.
+placing_bypasses_wg_passthrough = true
+
+[region]
+ # Minimum distance between claims (that aren't owned by the same owner), measured from the protection block to the edge of another region
+ # You will probably have to change this between blocks, since the region sizes will be different
+ # Set to -1 for no minimum, but will still check for overlapping regions
+ distance_between_claims = -1
+
+ # Protection radius of block (radius of 24 -> 129 x 129 region)
+ # Set y_radius to -1 if you want it to protect for all y levels.
+ # y_radius must be -1 if you are allowing the region to be merged ("allow_merging" option)
+ x_radius = 24
+ y_radius = -1
+ z_radius = 24
+
+ # Enables "chunk snapping mode", where the region boundaries will be determined by the chunk the block is in, and the
+ # chunk_radius (how many chunks away from the center chunk).
+ # Allows players to not have to worry about the exact placement of their block, and removes the issue of messy overlapping
+ # regions (as they all conform to chunk boundaries).
+ # Set to -1 to disable, and any number larger than or equal to 1 to enable.
+ # Note: If enabled, x_radius and z_radius will be ignored!
+ chunk_radius = -1
+
+ # How many blocks to offset the default location of /ps home from the protection block
+ home_x_offset = 0.0
+ home_y_offset = 1.0
+ home_z_offset = 0.0
+
+ # Specify the default flags to be set when a new protected region is created.
+ # Can use -g [group] before the flag to set group flags (ex. -g members pvp deny).
+ # Can use PlaceholderAPI placeholders in string flags (ex. greeting, farewell).
+ flags = [
+ "pvp deny",
+ "tnt deny",
+ "greeting Entering %player%'s protected area",
+ "farewell Leaving &b&l%player%'s &f&lprotected area",
+ "greeting-action Entering %player%'s protected area",
+ "farewell-action Leaving &b&l%player%'s &f&lprotected area",
+ "creeper-explosion deny",
+ "wither-damage deny",
+ "ghast-fireball deny",
+ ]
+
+ # List all the flags that can be set by region owners.
+ # If you want to whitelist the groups that can be set as well, use -g (ex. "-g all,members pvp" restricts it to no group flag, and members group)
+ # "-g all pvp" - Prevents players setting the group to nonmembers, and being invulnerable to attacks.
+ allowed_flags = [
+ "-g all pvp",
+ "greeting",
+ "greeting-title",
+ "greeting-action",
+ "farewell",
+ "farewell-title",
+ "farewell-action",
+ "mob-spawning",
+ "creeper-explosion",
+ "wither-damage",
+ "ghast-fireball",
+ ]
+
+ # Which flags to hide from /ps info
+ hidden_flags_from_info = [
+ "ps-name",
+ "ps-merged-regions",
+ "ps-merged-regions-types",
+ "ps-block-material",
+ "ps-price",
+ "ps-landlord",
+ "ps-tenant",
+ "ps-rent-period",
+ "ps-rent-last-paid",
+ "ps-for-sale",
+ "ps-rent-settings",
+ "ps-tax-payments-due",
+ "ps-tax-last-payment-added",
+ "ps-tax-autopayer"
+ ]
+
+ # Default priority type for this block type protection stone
+ priority = 0
+
+ # Whether or not to allow creation of regions that overlap other regions you don't own
+ # This is dangerous, so think about this carefully if you set it to true.
+ allow_overlap_unowned_regions = false
+
+ # Whether or not to allow players to create other regions that overlap this region.
+ # "owner" - only allow owners to overlap this (default)
+ # "member" - allow members and owners to overlap this region type. (useful for city plots)
+ # "all" - allow all players to overlap this region type.
+ # "none" - no players, not even the owners of the region can overlap it
+ # allow_overlap_unowned_regions does not need to be true for this to work.
+ allow_other_regions_to_overlap = "owner"
+
+ # Whether or not to allow this regions created with this block to merge with other regions
+ # allow_merging_regions must be set to true in config.toml
+ allow_merging = true
+
+ # Allowed types of regions to merge into (referred to by alias)
+ # Be sure to add the alias of this current region type to allow merging with it ex. ["24"]
+ # Add "all" if you want to allow this region to merge into any region
+ allowed_merging_into_types = [
+ "all"
+ ]
+
+[block_data]
+ # Name given to protection block when obtained with /ps give or /ps get
+ # Also affects custom crafted items (see custom_recipe)
+ # Leave as '' for no name
+ display_name = "&a&m<---&r&b 24 Radius Protection Block &r&a&m--->"
+
+ # Lore given to protection block when obtained with /ps give or /ps get
+ # Also affects custom crafted items (see custom_recipe)
+ # Leave as [] for no lore
+ lore = [
+ "&It's beautiful, isn't it?",
+ ]
+
+ # Whether the item should have an "glow/enchant" effect look when in a player's inventory.
+ enchanted_effect = false
+
+ # Add price when using /ps get
+ # Must have compatible economy plugin (requires Vault, ie. Essentials)
+ # Must be a decimal (ex. not 10, but 10.0)
+ price = 0.0
+
+ # Whether or not to allow crafting this item using a custom recipe
+ # Useful to allow crafting the item when restrict_obtaining is set to true
+ allow_craft_with_custom_recipe = false
+ # Specify the custom crafting recipe below
+ # You must fill the item spots with names from here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
+ # You can also use other protection stone items as ingredients in the recipe, in the format PROTECTION_STONES:alias
+ # Make sure that you set allow_use_in_crafting for that block to true, or else you can't use it in crafting
+ # If you want air, you can just leave the spot as ""
+ custom_recipe = [
+ ["", "STONE", ""],
+ ["STONE", "EMERALD", "STONE"],
+ ["", "STONE", ""]
+ ]
+ # Amount of the protection item to give when crafted
+ recipe_amount = 1
+
+ # The custom model data of the block item, useful for resource packs. Set to -1 to disable.
+ custom_model_data = -1
+
+[economy]
+ # Taxes must be enabled in config.toml first (tax_enabled)
+ # The amount to tax the region per tax cycle.
+ # Must be a decimal (ex. not 10, but 10.0)
+ tax_amount = 0.0
+
+ # The amount of seconds between tax cycles. Set to -1 to disable taxes.
+ tax_period = -1
+
+ # Amount of time to pay taxes in seconds after tax cycle before there is punishment.
+ tax_payment_time = 82400
+
+ # Automatically set the player that created the region as the taxpayer.
+ start_with_tax_autopay = true
+
+ # What role tenants should be added as (for rents). It can either be "owner" or "member".
+ tenant_rent_role = "member"
+
+ # Should the landlords of rented out regions still be an owner while it is rented out?
+ landlord_still_owner = false
+
+[behaviour]
+ # Hide protection stone right away when placed?
+ auto_hide = false
+
+ # Whether or not to automatically merge into other regions when placed if there is only one overlapping and allow_merging is true
+ auto_merge = false
+
+ # Disable returning the block when removed/unclaimed?
+ no_drop = false
+
+ # Prevents piston pushing of the block. Recommended to keep as true.
+ prevent_piston_push = true
+
+ # Prevents the block from being destroyed when exploded.
+ # Recommended to keep true to prevent players from exploiting more protection stones with /ps unhide (when the block is destroyed)
+ prevent_explode = true
+
+ # Destroys the protection stone region when block is exploded. Can be useful for PVP/Factions servers.
+ # prevent_explode must be false for this to work.
+ destroy_region_when_explode = false
+
+ # Silk Touch: if true, ore-blocks that are also configured by ProtectionStones will disallow Silk Touch drops
+ # This was the old behaviour to prevent natural obtaining of the protection stone.
+ # Recommended to keep false if "Restrict Obtaining" (the new way) is true
+ prevent_silk_touch = false
+
+ # Set cost for when a protection block is placed (separate from /ps get cost)
+ cost_to_place = 0.0
+
+ # Allow protect block item to be smelt in furnaces
+ allow_smelt_item = false
+
+ # Allows the protection block to be used in crafting recipes
+ # You may want it set to false to prevent players decomposing its elements
+ allow_use_in_crafting = false
+
+[player]
+ # Whether or not to allow breaking the protection block with a shift-right click
+ # Useful if the protection block is unbreakable (bedrock, command block), etc.
+ allow_shift_right_break = false
+
+ # Whether or not to prevent teleporting into a protected region if the player doesn't own it (except with ender pearl and chorus fruit)
+ # Does not prevent entry, use the flag "entry deny" for preventing entry.
+ # Bypass with protectionstones.tp.bypassprevent
+ prevent_teleport_in = false
+
+ # Can't move for x seconds before teleporting with /ps home or /ps tp. Can be disabled with 0.
+ # Option to teleport only if player stands still.
+ # Can override with permission protectionstones.tp.bypasswait
+ no_moving_when_tp_waiting = true
+ tp_waiting_seconds = 0
+
+ # Whether or not to prevent obtaining this block through /ps get.
+ # Ignored with protectionstones.admin
+ prevent_ps_get = false
+
+ # Whether or not to prevent this region type from showing up in /ps home, and allowing teleport.
+ # Note: admins can still use /ps tp to this region type
+ prevent_ps_home = false
+
+ # Extra permission required to place this specific protection block (you still need protectionstones.create)
+ # Also applies to /ps get (you still need protectionstones.get)
+ # '' for no extra permission
+ permission = ''
+
+[event]
+
+ # Events section
+ # ~~~~~~~~~~~~~~
+ # For each line on events, it is the format 'type: action'
+ # The following are accepted types:
+ # player_command - Execute command by player that caused event (won't execute if not applicable)
+ # console_command - Execute command by console
+ # message - Send message to player or console if applicable (colour support with &)
+ # global_message - Send message to all players and console (colour support with &)
+ # console_message - Send message to console (colour support with &)
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ # Whether or not to enable event tracking (API events will still be enabled)
+ enable = false
+
+ # Execute commands when a region is created (ex. player place protection block)
+ # Variables: %player%, %world%, %region%, %block_x%, %block_y%, %block_z%
+ on_region_create = [
+ 'global_message: &l%player% created the region %region%!',
+ ]
+
+ # Execute commands when a region is destroyed (ex. when player destroy protection block)
+ # Variables: %player%, %world%, %region%, %block_x%, %block_y%, %block_z%
+ on_region_destroy = [
+ 'console_command: say %player% has destroyed region %region%!',
+ ]
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index d29b6003..66ec20d6 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,7 +1,8 @@
name: ProtectionStones
version: ${version}
description: ${description}
-authors: [EspiDev]
+authors: [EspiDev 2018 - 2026, jerzean +2026, Dianelito]
+contribuitors: https://github.com/espidev/ProtectionStones/graphs/contributors
depend: [WorldGuard, WorldEdit]
softdepend: [Vault, PlaceholderAPI, LuckPerms]