- io.papermc.paper
- paper-api
- 1.20.4-R0.1-SNAPSHOT
+ org.spigotmc
+ spigot-api
+ 1.21-R0.1-SNAPSHOT
provided
diff --git a/src/main/java/com/griefprevention/protection/ProtectionHelper.java b/src/main/java/com/griefprevention/protection/ProtectionHelper.java
new file mode 100644
index 00000000..f5c8daaa
--- /dev/null
+++ b/src/main/java/com/griefprevention/protection/ProtectionHelper.java
@@ -0,0 +1,108 @@
+package com.griefprevention.protection;
+
+import me.ryanhamshire.GriefPrevention.Claim;
+import me.ryanhamshire.GriefPrevention.ClaimPermission;
+import me.ryanhamshire.GriefPrevention.ClaimsMode;
+import me.ryanhamshire.GriefPrevention.DataStore;
+import me.ryanhamshire.GriefPrevention.GriefPrevention;
+import me.ryanhamshire.GriefPrevention.Messages;
+import me.ryanhamshire.GriefPrevention.PlayerData;
+import me.ryanhamshire.GriefPrevention.events.PreventBlockBreakEvent;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.Supplier;
+
+/**
+ * A utility used to simplify various protection-related checks.
+ */
+public final class ProtectionHelper
+{
+
+ private ProtectionHelper() {}
+
+ /**
+ * Check the {@link ClaimPermission} state for a {@link Player} at a particular {@link Location}.
+ *
+ * This respects ignoring claims, wilderness rules, etc.
+ *
+ * @param player the person performing the action
+ * @param location the affected {@link Location}
+ * @param permission the required permission
+ * @param trigger the triggering {@link Event}, if any
+ * @return the denial message supplier, or {@code null} if the action is not denied
+ */
+ public static @Nullable Supplier checkPermission(
+ @NotNull Player player,
+ @NotNull Location location,
+ @NotNull ClaimPermission permission,
+ @Nullable Event trigger)
+ {
+ World world = location.getWorld();
+ if (world == null || !GriefPrevention.instance.claimsEnabledForWorld(world)) return null;
+
+ PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
+
+ // Administrators ignoring claims always have permission.
+ if (playerData.ignoreClaims) return null;
+
+ Claim claim = GriefPrevention.instance.dataStore.getClaimAt(location, false, playerData.lastClaim);
+
+
+ // If there is no claim here, use wilderness rules.
+ if (claim == null)
+ {
+ ClaimsMode mode = GriefPrevention.instance.config_claims_worldModes.get(world);
+ if (mode == ClaimsMode.Creative || mode == ClaimsMode.SurvivalRequiringClaims)
+ {
+ // Allow placing chest if it would create an automatic claim.
+ if (trigger instanceof BlockPlaceEvent placeEvent
+ && placeEvent.getBlock().getType() == Material.CHEST
+ && playerData.getClaims().isEmpty()
+ && GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius > -1)
+ return null;
+
+ // If claims are required, provide relevant information.
+ return () ->
+ {
+ String reason = GriefPrevention.instance.dataStore.getMessage(Messages.NoBuildOutsideClaims);
+ if (player.hasPermission("griefprevention.ignoreclaims"))
+ reason += " " + GriefPrevention.instance.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
+ reason += " " + GriefPrevention.instance.dataStore.getMessage(Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL);
+ return reason;
+ };
+ }
+
+ // If claims are not required, then the player has permission.
+ return null;
+ }
+
+ // Update cached claim.
+ playerData.lastClaim = claim;
+
+ // Apply claim rules.
+ Supplier cancel = claim.checkPermission(player, permission, trigger);
+
+ // Apply additional specific rules.
+ if (cancel != null && trigger instanceof BlockBreakEvent breakEvent)
+ {
+ PreventBlockBreakEvent preventionEvent = new PreventBlockBreakEvent(breakEvent);
+ Bukkit.getPluginManager().callEvent(preventionEvent);
+ if (preventionEvent.isCancelled())
+ {
+ cancel = null;
+ }
+ }
+
+ return cancel;
+ }
+
+}
diff --git a/src/main/java/com/griefprevention/visualization/BoundaryVisualization.java b/src/main/java/com/griefprevention/visualization/BoundaryVisualization.java
index 13fb4cb1..342f1233 100644
--- a/src/main/java/com/griefprevention/visualization/BoundaryVisualization.java
+++ b/src/main/java/com/griefprevention/visualization/BoundaryVisualization.java
@@ -26,7 +26,7 @@
/**
* A representation of a system for displaying rectangular {@link Boundary Boundaries} to {@link Player Players}.
- * This is used to display claim areas, visualize affected area during nature restoration, and more.
+ * This is used to display claim areas, conflicting claims, and more.
*/
public abstract class BoundaryVisualization
{
diff --git a/src/main/java/com/griefprevention/visualization/VisualizationType.java b/src/main/java/com/griefprevention/visualization/VisualizationType.java
index 3af06915..4c0ab317 100644
--- a/src/main/java/com/griefprevention/visualization/VisualizationType.java
+++ b/src/main/java/com/griefprevention/visualization/VisualizationType.java
@@ -15,8 +15,6 @@ public enum VisualizationType
/** Boundaries for a new claim area. */
INITIALIZE_ZONE,
/** Boundaries for a conflicting area. */
- CONFLICT_ZONE,
- /** Boundaries for area in which nature has been restored. */
- NATURE_RESTORATION_ZONE
+ CONFLICT_ZONE
}
diff --git a/src/main/java/com/griefprevention/visualization/impl/FakeBlockVisualization.java b/src/main/java/com/griefprevention/visualization/impl/FakeBlockVisualization.java
index fe106e42..03ded33c 100644
--- a/src/main/java/com/griefprevention/visualization/impl/FakeBlockVisualization.java
+++ b/src/main/java/com/griefprevention/visualization/impl/FakeBlockVisualization.java
@@ -44,7 +44,7 @@ public FakeBlockVisualization(@NotNull World world, @NotNull IntVector visualize
return addBlockElement(switch (boundary.type())
{
case SUBDIVISION -> Material.IRON_BLOCK.createBlockData();
- case INITIALIZE_ZONE, NATURE_RESTORATION_ZONE -> Material.DIAMOND_BLOCK.createBlockData();
+ case INITIALIZE_ZONE -> Material.DIAMOND_BLOCK.createBlockData();
case CONFLICT_ZONE -> {
BlockData fakeData = Material.REDSTONE_ORE.createBlockData();
((Lightable) fakeData).setLit(true);
@@ -63,7 +63,7 @@ public FakeBlockVisualization(@NotNull World world, @NotNull IntVector visualize
{
case ADMIN_CLAIM -> Material.PUMPKIN.createBlockData();
case SUBDIVISION -> Material.WHITE_WOOL.createBlockData();
- case INITIALIZE_ZONE, NATURE_RESTORATION_ZONE -> Material.DIAMOND_BLOCK.createBlockData();
+ case INITIALIZE_ZONE -> Material.DIAMOND_BLOCK.createBlockData();
case CONFLICT_ZONE -> Material.NETHERRACK.createBlockData();
default -> Material.GOLD_BLOCK.createBlockData();
});
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/AutoExtendClaimTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/AutoExtendClaimTask.java
index 5fdd083a..014e091e 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/AutoExtendClaimTask.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/AutoExtendClaimTask.java
@@ -5,6 +5,8 @@
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location;
import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
@@ -15,6 +17,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -78,6 +81,12 @@ public static void scheduleAsync(@NotNull Claim claim)
private final Map> biomePlayerMaterials = new HashMap<>();
private final int minY;
private final int lowestExistingY;
+ // Definitions of biomes where sand covers surfaces instead of grass.
+ static final Set SAND_SOIL_BIOMES = Set.of(
+ NamespacedKey.minecraft("snowy_beach"),
+ NamespacedKey.minecraft("beach"),
+ NamespacedKey.minecraft("desert")
+ );
private AutoExtendClaimTask(
@NotNull Claim claim,
@@ -177,12 +186,232 @@ private Set getBiomePlayerBlocks(Biome biome)
{
return biomePlayerMaterials.computeIfAbsent(biome, newBiome ->
{
- Set playerBlocks = RestoreNatureProcessingTask.getPlayerBlocks(this.worldType, newBiome);
+ Set playerBlocks = AutoExtendClaimTask.getPlayerBlocks(this.worldType, newBiome);
playerBlocks.removeAll(BlockEventHandler.TRASH_BLOCKS);
return playerBlocks;
});
}
+ static Set getPlayerBlocks(Environment environment, Biome biome)
+ {
+ Set playerBlocks = new HashSet<>();
+ playerBlocks.addAll(Tag.ANVIL.getValues());
+ playerBlocks.addAll(Tag.BANNERS.getValues());
+ playerBlocks.addAll(Tag.BEACON_BASE_BLOCKS.getValues());
+ playerBlocks.addAll(Tag.BEDS.getValues());
+ playerBlocks.addAll(Tag.BUTTONS.getValues());
+ playerBlocks.addAll(Tag.CAMPFIRES.getValues());
+ playerBlocks.addAll(Tag.CANDLE_CAKES.getValues());
+ playerBlocks.addAll(Tag.CANDLES.getValues());
+ playerBlocks.addAll(Tag.WOOL_CARPETS.getValues());
+ playerBlocks.addAll(Tag.CAULDRONS.getValues());
+ playerBlocks.addAll(Tag.DOORS.getValues());
+ playerBlocks.addAll(Tag.FENCE_GATES.getValues());
+ playerBlocks.addAll(Tag.FENCES.getValues());
+ playerBlocks.addAll(Tag.FIRE.getValues());
+ playerBlocks.addAll(Tag.FLOWER_POTS.getValues());
+ playerBlocks.addAll(Tag.IMPERMEABLE.getValues()); // Glass block variants
+ playerBlocks.addAll(Tag.LOGS.getValues());
+ playerBlocks.addAll(Tag.PLANKS.getValues());
+ playerBlocks.addAll(Tag.PRESSURE_PLATES.getValues());
+ playerBlocks.addAll(Tag.RAILS.getValues());
+ playerBlocks.addAll(Tag.SHULKER_BOXES.getValues());
+ playerBlocks.addAll(Tag.SIGNS.getValues());
+ playerBlocks.addAll(Tag.SLABS.getValues());
+ playerBlocks.addAll(Tag.STAIRS.getValues());
+ playerBlocks.addAll(Tag.STONE_BRICKS.getValues());
+ playerBlocks.addAll(Tag.TRAPDOORS.getValues());
+ playerBlocks.addAll(Tag.WALLS.getValues());
+ playerBlocks.addAll(Tag.WOOL.getValues());
+ playerBlocks.add(Material.BOOKSHELF);
+ playerBlocks.add(Material.BREWING_STAND);
+ playerBlocks.add(Material.BRICK);
+ playerBlocks.add(Material.COBBLESTONE);
+ playerBlocks.add(Material.LAPIS_BLOCK);
+ playerBlocks.add(Material.DISPENSER);
+ playerBlocks.add(Material.NOTE_BLOCK);
+ playerBlocks.add(Material.STICKY_PISTON);
+ playerBlocks.add(Material.PISTON);
+ playerBlocks.add(Material.PISTON_HEAD);
+ playerBlocks.add(Material.MOVING_PISTON);
+ playerBlocks.add(Material.WHEAT);
+ playerBlocks.add(Material.TNT);
+ playerBlocks.add(Material.MOSSY_COBBLESTONE);
+ playerBlocks.add(Material.TORCH);
+ playerBlocks.add(Material.CHEST);
+ playerBlocks.add(Material.REDSTONE_WIRE);
+ playerBlocks.add(Material.CRAFTING_TABLE);
+ playerBlocks.add(Material.FURNACE);
+ playerBlocks.add(Material.LADDER);
+ playerBlocks.add(Material.SCAFFOLDING);
+ playerBlocks.add(Material.LEVER);
+ playerBlocks.add(Material.REDSTONE_TORCH);
+ playerBlocks.add(Material.SNOW_BLOCK);
+ playerBlocks.add(Material.JUKEBOX);
+ playerBlocks.add(Material.NETHER_PORTAL);
+ playerBlocks.add(Material.JACK_O_LANTERN);
+ playerBlocks.add(Material.CAKE);
+ playerBlocks.add(Material.REPEATER);
+ playerBlocks.add(Material.MUSHROOM_STEM);
+ playerBlocks.add(Material.RED_MUSHROOM_BLOCK);
+ playerBlocks.add(Material.BROWN_MUSHROOM_BLOCK);
+ playerBlocks.add(Material.IRON_BARS);
+ playerBlocks.add(Material.GLASS_PANE);
+ playerBlocks.add(Material.MELON_STEM);
+ playerBlocks.add(Material.ENCHANTING_TABLE);
+ playerBlocks.add(Material.COBWEB);
+ playerBlocks.add(Material.GRAVEL);
+ playerBlocks.add(Material.SANDSTONE);
+ playerBlocks.add(Material.ENDER_CHEST);
+ playerBlocks.add(Material.COMMAND_BLOCK);
+ playerBlocks.add(Material.REPEATING_COMMAND_BLOCK);
+ playerBlocks.add(Material.CHAIN_COMMAND_BLOCK);
+ playerBlocks.add(Material.BEACON);
+ playerBlocks.add(Material.CARROT);
+ playerBlocks.add(Material.POTATO);
+ playerBlocks.add(Material.SKELETON_SKULL);
+ playerBlocks.add(Material.WITHER_SKELETON_SKULL);
+ playerBlocks.add(Material.CREEPER_HEAD);
+ playerBlocks.add(Material.ZOMBIE_HEAD);
+ playerBlocks.add(Material.PLAYER_HEAD);
+ playerBlocks.add(Material.DRAGON_HEAD);
+ playerBlocks.add(Material.SPONGE);
+ playerBlocks.add(Material.WHITE_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.ORANGE_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.MAGENTA_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.LIGHT_BLUE_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.YELLOW_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.LIME_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.PINK_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.GRAY_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.LIGHT_GRAY_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.CYAN_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.PURPLE_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.BLUE_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.BROWN_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.GREEN_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.RED_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.BLACK_STAINED_GLASS_PANE);
+ playerBlocks.add(Material.TRAPPED_CHEST);
+ playerBlocks.add(Material.COMPARATOR);
+ playerBlocks.add(Material.DAYLIGHT_DETECTOR);
+ playerBlocks.add(Material.REDSTONE_BLOCK);
+ playerBlocks.add(Material.HOPPER);
+ playerBlocks.add(Material.QUARTZ_BLOCK);
+ playerBlocks.add(Material.DROPPER);
+ playerBlocks.add(Material.SLIME_BLOCK);
+ playerBlocks.add(Material.PRISMARINE);
+ playerBlocks.add(Material.HAY_BLOCK);
+ playerBlocks.add(Material.SEA_LANTERN);
+ playerBlocks.add(Material.COAL_BLOCK);
+ playerBlocks.add(Material.REDSTONE_LAMP);
+ playerBlocks.add(Material.RED_NETHER_BRICKS);
+ playerBlocks.add(Material.POLISHED_ANDESITE);
+ playerBlocks.add(Material.POLISHED_DIORITE);
+ playerBlocks.add(Material.POLISHED_GRANITE);
+ playerBlocks.add(Material.POLISHED_BASALT);
+ playerBlocks.add(Material.POLISHED_DEEPSLATE);
+ playerBlocks.add(Material.DEEPSLATE_BRICKS);
+ playerBlocks.add(Material.CRACKED_DEEPSLATE_BRICKS);
+ playerBlocks.add(Material.DEEPSLATE_TILES);
+ playerBlocks.add(Material.CRACKED_DEEPSLATE_TILES);
+ playerBlocks.add(Material.CHISELED_DEEPSLATE);
+ playerBlocks.add(Material.RAW_COPPER_BLOCK);
+ playerBlocks.add(Material.RAW_IRON_BLOCK);
+ playerBlocks.add(Material.RAW_GOLD_BLOCK);
+ playerBlocks.add(Material.LIGHTNING_ROD);
+ playerBlocks.add(Material.DECORATED_POT);
+
+ //these are unnatural in the nether and end
+ if (environment != Environment.NORMAL && environment != Environment.CUSTOM)
+ {
+ playerBlocks.addAll(Tag.BASE_STONE_OVERWORLD.getValues());
+ playerBlocks.addAll(Tag.DIRT.getValues());
+ playerBlocks.addAll(Tag.SAND.getValues());
+ }
+
+ //these are unnatural in the standard world, but not in the nether
+ if (environment != Environment.NETHER)
+ {
+ playerBlocks.addAll(Tag.NYLIUM.getValues());
+ playerBlocks.addAll(Tag.WART_BLOCKS.getValues());
+ playerBlocks.addAll(Tag.BASE_STONE_NETHER.getValues());
+ playerBlocks.add(Material.POLISHED_BLACKSTONE);
+ playerBlocks.add(Material.CHISELED_POLISHED_BLACKSTONE);
+ playerBlocks.add(Material.CRACKED_POLISHED_BLACKSTONE_BRICKS);
+ playerBlocks.add(Material.GILDED_BLACKSTONE);
+ playerBlocks.add(Material.BONE_BLOCK);
+ playerBlocks.add(Material.SOUL_SAND);
+ playerBlocks.add(Material.SOUL_SOIL);
+ playerBlocks.add(Material.GLOWSTONE);
+ playerBlocks.add(Material.NETHER_BRICK);
+ playerBlocks.add(Material.MAGMA_BLOCK);
+ playerBlocks.add(Material.ANCIENT_DEBRIS);
+ playerBlocks.add(Material.CHAIN);
+ playerBlocks.add(Material.SHROOMLIGHT);
+ playerBlocks.add(Material.NETHER_GOLD_ORE);
+ playerBlocks.add(Material.NETHER_SPROUTS);
+ playerBlocks.add(Material.CRIMSON_FUNGUS);
+ playerBlocks.add(Material.CRIMSON_ROOTS);
+ playerBlocks.add(Material.NETHER_WART_BLOCK);
+ playerBlocks.add(Material.WEEPING_VINES);
+ playerBlocks.add(Material.WEEPING_VINES_PLANT);
+ playerBlocks.add(Material.WARPED_FUNGUS);
+ playerBlocks.add(Material.WARPED_ROOTS);
+ playerBlocks.add(Material.WARPED_WART_BLOCK);
+ playerBlocks.add(Material.TWISTING_VINES);
+ playerBlocks.add(Material.TWISTING_VINES_PLANT);
+ }
+ //blocks from tags that are natural in the nether
+ else
+ {
+ playerBlocks.remove(Material.CRIMSON_STEM);
+ playerBlocks.remove(Material.CRIMSON_HYPHAE);
+ playerBlocks.remove(Material.NETHER_BRICK_FENCE);
+ playerBlocks.remove(Material.NETHER_BRICK_STAIRS);
+ playerBlocks.remove(Material.SOUL_FIRE);
+ playerBlocks.remove(Material.WARPED_STEM);
+ playerBlocks.remove(Material.WARPED_HYPHAE);
+ }
+
+ //these are unnatural in the standard and nether worlds, but not in the end
+ if (environment != Environment.THE_END)
+ {
+ playerBlocks.add(Material.CHORUS_PLANT);
+ playerBlocks.add(Material.CHORUS_FLOWER);
+ playerBlocks.add(Material.END_ROD);
+ playerBlocks.add(Material.END_STONE);
+ playerBlocks.add(Material.END_STONE_BRICKS);
+ playerBlocks.add(Material.OBSIDIAN);
+ playerBlocks.add(Material.PURPUR_BLOCK);
+ playerBlocks.add(Material.PURPUR_PILLAR);
+ }
+ //blocks from tags that are natural in the end
+ else
+ {
+ playerBlocks.remove(Material.PURPUR_SLAB);
+ playerBlocks.remove(Material.PURPUR_STAIRS);
+ }
+
+ //these are unnatural in sandy biomes, but not elsewhere
+ if (SAND_SOIL_BIOMES.contains(biome.getKey()) || environment != Environment.NORMAL)
+ {
+ playerBlocks.addAll(Tag.LEAVES.getValues());
+ }
+ //blocks from tags that are natural in non-sandy normal biomes
+ else
+ {
+ playerBlocks.remove(Material.OAK_LOG);
+ playerBlocks.remove(Material.SPRUCE_LOG);
+ playerBlocks.remove(Material.BIRCH_LOG);
+ playerBlocks.remove(Material.JUNGLE_LOG);
+ playerBlocks.remove(Material.ACACIA_LOG);
+ playerBlocks.remove(Material.DARK_OAK_LOG);
+ }
+
+ return playerBlocks;
+ }
+
//runs in the main execution thread, where it can safely change claims and save those changes
private record ExecuteExtendClaimTask(Claim claim, int newY) implements Runnable
{
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/BlockEventHandler.java b/src/main/java/me/ryanhamshire/GriefPrevention/BlockEventHandler.java
index 35fa5da1..2c341dd5 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/BlockEventHandler.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/BlockEventHandler.java
@@ -21,6 +21,7 @@
import com.griefprevention.visualization.BoundaryVisualization;
import com.griefprevention.visualization.VisualizationType;
import me.ryanhamshire.GriefPrevention.util.BoundingBox;
+import com.griefprevention.protection.ProtectionHelper;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
@@ -126,10 +127,10 @@ public void onBlockBreak(BlockBreakEvent breakEvent)
Block block = breakEvent.getBlock();
//make sure the player is allowed to break at the location
- String noBuildReason = GriefPrevention.instance.allowBreak(player, block, block.getLocation(), breakEvent);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, breakEvent);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
breakEvent.setCancelled(true);
return;
}
@@ -144,10 +145,10 @@ public void onSignChanged(SignChangeEvent event)
if (player == null || sign == null) return;
- String noBuildReason = GriefPrevention.instance.allowBuild(player, sign.getLocation(), sign.getType());
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, sign.getLocation(), ClaimPermission.Build, event);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
event.setCancelled(true);
return;
}
@@ -213,10 +214,10 @@ public void onBlocksPlace(BlockMultiPlaceEvent placeEvent)
//make sure the player is allowed to build at the location
for (BlockState block : placeEvent.getReplacedBlockStates())
{
- String noBuildReason = GriefPrevention.instance.allowBuild(player, block.getLocation(), block.getType());
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, placeEvent);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
placeEvent.setCancelled(true);
return;
}
@@ -271,7 +272,7 @@ public void onBlockPlace(BlockPlaceEvent placeEvent)
if (!GriefPrevention.instance.claimsEnabledForWorld(placeEvent.getBlock().getWorld())) return;
//make sure the player is allowed to build at the location
- String noBuildReason = GriefPrevention.instance.allowBuild(player, block.getLocation(), block.getType());
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, placeEvent);
if (noBuildReason != null)
{
// Allow players with container trust to place books in lecterns
@@ -291,7 +292,7 @@ public void onBlockPlace(BlockPlaceEvent placeEvent)
return;
}
}
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
placeEvent.setCancelled(true);
return;
}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/BlockSnapshot.java b/src/main/java/me/ryanhamshire/GriefPrevention/BlockSnapshot.java
deleted file mode 100644
index 8f198936..00000000
--- a/src/main/java/me/ryanhamshire/GriefPrevention/BlockSnapshot.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- GriefPrevention Server Plugin for Minecraft
- Copyright (C) 2012 Ryan Hamshire
-
- 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 me.ryanhamshire.GriefPrevention;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.data.BlockData;
-
-//basically, just a few data points from a block conveniently encapsulated in a class
-//this is used only by the RestoreNature code
-public class BlockSnapshot
-{
- public Location location;
- public Material typeId;
- public BlockData data;
-
- public BlockSnapshot(Location location, Material typeId, BlockData data)
- {
- this.location = location;
- this.typeId = typeId;
- this.data = data;
- }
-}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/Claim.java b/src/main/java/me/ryanhamshire/GriefPrevention/Claim.java
index 5cdc074c..a8537cd6 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/Claim.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/Claim.java
@@ -123,86 +123,6 @@ public Long getID()
this.modifiedDate = Calendar.getInstance().getTime();
}
- //removes any lava above sea level in a claim
- //exclusionClaim is another claim indicating an sub-area to be excluded from this operation
- //it may be null
- public void removeSurfaceFluids(Claim exclusionClaim)
- {
- //don't do this for administrative claims
- if (this.isAdminClaim()) return;
-
- //don't do it for very large claims
- if (this.getArea() > 10000) return;
-
- //only in creative mode worlds
- if (!GriefPrevention.instance.creativeRulesApply(this.lesserBoundaryCorner)) return;
-
- Location lesser = this.getLesserBoundaryCorner();
- Location greater = this.getGreaterBoundaryCorner();
-
- if (lesser.getWorld().getEnvironment() == Environment.NETHER) return; //don't clean up lava in the nether
-
- int seaLevel = 0; //clean up all fluids in the end
-
- //respect sea level in normal worlds
- if (lesser.getWorld().getEnvironment() == Environment.NORMAL)
- seaLevel = GriefPrevention.instance.getSeaLevel(lesser.getWorld());
-
- for (int x = lesser.getBlockX(); x <= greater.getBlockX(); x++)
- {
- for (int z = lesser.getBlockZ(); z <= greater.getBlockZ(); z++)
- {
- for (int y = seaLevel - 1; y <= lesser.getWorld().getMaxHeight(); y++)
- {
- //dodge the exclusion claim
- Block block = lesser.getWorld().getBlockAt(x, y, z);
- if (exclusionClaim != null && exclusionClaim.contains(block.getLocation(), true, false)) continue;
-
- if (block.getType() == Material.LAVA || block.getType() == Material.WATER)
- {
- block.setType(Material.AIR);
- }
- }
- }
- }
- }
-
- //determines whether or not a claim has surface lava
- //used to warn players when they abandon their claims about automatic fluid cleanup
- boolean hasSurfaceFluids()
- {
- Location lesser = this.getLesserBoundaryCorner();
- Location greater = this.getGreaterBoundaryCorner();
-
- //don't bother for very large claims, too expensive
- if (this.getArea() > 10000) return false;
-
- int seaLevel = 0; //clean up all fluids in the end
-
- //respect sea level in normal worlds
- if (lesser.getWorld().getEnvironment() == Environment.NORMAL)
- seaLevel = GriefPrevention.instance.getSeaLevel(lesser.getWorld());
-
- for (int x = lesser.getBlockX(); x <= greater.getBlockX(); x++)
- {
- for (int z = lesser.getBlockZ(); z <= greater.getBlockZ(); z++)
- {
- for (int y = seaLevel - 1; y <= lesser.getWorld().getMaxHeight(); y++)
- {
- //dodge the exclusion claim
- Block block = lesser.getWorld().getBlockAt(x, y, z);
-
- if (block.getType() == Material.WATER || block.getType() == Material.LAVA)
- {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
//main constructor. note that only creating a claim instance does nothing - a claim must be added to the data store to be effective
Claim(Location lesserBoundaryCorner, Location greaterBoundaryCorner, UUID ownerID, List builderIDs, List containerIDs, List accessorIDs, List managerIDs, boolean inheritNothing, Long id)
{
@@ -873,63 +793,6 @@ boolean greaterThan(Claim otherClaim)
}
- long getPlayerInvestmentScore()
- {
- //decide which blocks will be considered player placed
- Location lesserBoundaryCorner = this.getLesserBoundaryCorner();
- Set playerBlocks = RestoreNatureProcessingTask.getPlayerBlocks(lesserBoundaryCorner.getWorld().getEnvironment(), lesserBoundaryCorner.getBlock().getBiome());
-
- //scan the claim for player placed blocks
- double score = 0;
-
- boolean creativeMode = GriefPrevention.instance.creativeRulesApply(lesserBoundaryCorner);
-
- for (int x = this.lesserBoundaryCorner.getBlockX(); x <= this.greaterBoundaryCorner.getBlockX(); x++)
- {
- for (int z = this.lesserBoundaryCorner.getBlockZ(); z <= this.greaterBoundaryCorner.getBlockZ(); z++)
- {
- int y = this.lesserBoundaryCorner.getBlockY();
- for (; y < GriefPrevention.instance.getSeaLevel(this.lesserBoundaryCorner.getWorld()) - 5; y++)
- {
- Block block = this.lesserBoundaryCorner.getWorld().getBlockAt(x, y, z);
- if (playerBlocks.contains(block.getType()))
- {
- if (block.getType() == Material.CHEST && !creativeMode)
- {
- score += 10;
- }
- else
- {
- score += .5;
- }
- }
- }
-
- for (; y < this.lesserBoundaryCorner.getWorld().getMaxHeight(); y++)
- {
- Block block = this.lesserBoundaryCorner.getWorld().getBlockAt(x, y, z);
- if (playerBlocks.contains(block.getType()))
- {
- if (block.getType() == Material.CHEST && !creativeMode)
- {
- score += 10;
- }
- else if (creativeMode && (block.getType() == Material.LAVA))
- {
- score -= 10;
- }
- else
- {
- score += 1;
- }
- }
- }
- }
- }
-
- return (long) score;
- }
-
public ArrayList getChunks()
{
ArrayList chunks = new ArrayList<>();
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimTask.java
index ce3f1c6f..81189a83 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimTask.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimTask.java
@@ -61,15 +61,8 @@ public void run()
{
if (expireEventCanceled())
return;
- claim.removeSurfaceFluids(null);
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
- //if configured to do so, restore the land to natural
- if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
- {
- GriefPrevention.instance.restoreClaim(claim, 0);
- }
-
GriefPrevention.AddLogEntry(" " + claim.getOwnerName() + "'s new player claim expired.", CustomLogEntryTypes.AdminActivity);
}
}
@@ -92,43 +85,6 @@ else if (GriefPrevention.instance.config_claims_expirationDays > 0)
GriefPrevention.AddLogEntry(" All of " + claim.getOwnerName() + "'s claims have expired.", CustomLogEntryTypes.AdminActivity);
GriefPrevention.AddLogEntry("earliestPermissibleLastLogin#getTime: " + earliestPermissibleLastLogin.getTime(), CustomLogEntryTypes.Debug, true);
GriefPrevention.AddLogEntry("ownerInfo#getLastPlayed: " + ownerInfo.getLastPlayed(), CustomLogEntryTypes.Debug, true);
-
- for (Claim claim : claims)
- {
- //if configured to do so, restore the land to natural
- if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
- {
- GriefPrevention.instance.restoreClaim(claim, 0);
- }
- }
- }
- }
- else if (GriefPrevention.instance.config_claims_unusedClaimExpirationDays > 0 && GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
- {
- //avoid scanning large claims and administrative claims
- if (claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return;
-
- //otherwise scan the claim content
- int minInvestment = 400;
-
- long investmentScore = claim.getPlayerInvestmentScore();
-
- if (investmentScore < minInvestment)
- {
- //if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed
- Calendar sevenDaysAgo = Calendar.getInstance();
- sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays);
- boolean claimExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed()));
- if (claimExpired)
- {
- if (expireEventCanceled())
- return;
- GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
- GriefPrevention.AddLogEntry("Removed " + claim.getOwnerName() + "'s unused claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
-
- //restore the claim area to natural state
- GriefPrevention.instance.restoreClaim(claim, 0);
- }
}
}
}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java b/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java
deleted file mode 100644
index b0cb406d..00000000
--- a/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- GriefPrevention Server Plugin for Minecraft
- Copyright (C) 2012 Ryan Hamshire
-
- 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 me.ryanhamshire.GriefPrevention;
-
-public class CustomizableMessage
-{
- public Messages id;
- public String text;
- public String notes;
-
- public CustomizableMessage(Messages id, String text, String notes)
- {
- this.id = id;
- this.text = text;
- this.notes = notes;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java b/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java
index 89b5e49d..b8701431 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java
@@ -48,7 +48,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -1126,15 +1125,7 @@ synchronized public void deleteClaimsForPlayer(UUID playerID, boolean releasePet
//delete them one by one
for (Claim claim : claimsToDelete)
{
- claim.removeSurfaceFluids(null);
-
this.deleteClaim(claim);
-
- //if in a creative mode world, delete the claim
- if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
- {
- GriefPrevention.instance.restoreClaim(claim, 0);
- }
}
}
@@ -1236,21 +1227,6 @@ void resizeClaimWithChecks(Player player, PlayerData playerData, int newx1, int
//return here if event is cancelled
if (event.isCancelled()) return;
- //special rule for making a top-level claim smaller. to check this, verifying the old claim's corners are inside the new claim's boundaries.
- //rule: in any mode, shrinking a claim removes any surface fluids
- boolean smaller = false;
- if (oldClaim.parent == null)
- {
- //if the new claim is smaller
- if (!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
- {
- smaller = true;
-
- //remove surface fluids about to be unclaimed
- oldClaim.removeSurfaceFluids(newClaim);
- }
- }
-
//ask the datastore to try and resize the claim, this checks for conflicts with other claims
CreateClaimResult result = GriefPrevention.instance.dataStore.resizeClaim(
playerData.claimResizing,
@@ -1306,14 +1282,6 @@ void resizeClaimWithChecks(Player player, PlayerData playerData, int newx1, int
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SubdivisionVideo2, 201L, DataStore.SUBDIVISION_VIDEO_URL);
}
- //if in a creative mode world and shrinking an existing claim, restore any unclaimed area
- if (smaller && GriefPrevention.instance.creativeRulesApply(oldClaim.getLesserBoundaryCorner()))
- {
- GriefPrevention.sendMessage(player, TextMode.Warn, Messages.UnclaimCleanupWarning);
- GriefPrevention.instance.restoreClaim(oldClaim, 20L * 60 * 2); //2 minutes
- GriefPrevention.AddLogEntry(player.getName() + " shrank a claim @ " + GriefPrevention.getfriendlyLocationString(playerData.claimResizing.getLesserBoundaryCorner()));
- }
-
//clean up
playerData.claimResizing = null;
playerData.lastShovelLocation = null;
@@ -1355,268 +1323,60 @@ else if (player.hasPermission("griefprevention.adjustclaimblocks"))
protected void loadMessages()
{
Messages[] messageIDs = Messages.values();
- this.messages = new String[Messages.values().length];
-
- HashMap defaults = new HashMap<>();
-
- //initialize defaults
- this.addDefault(defaults, Messages.RespectingClaims, "Now respecting claims.", null);
- this.addDefault(defaults, Messages.IgnoringClaims, "Now ignoring claims.", null);
- this.addDefault(defaults, Messages.NoCreativeUnClaim, "You can't unclaim this land. You can only make this claim larger or create additional claims.", null);
- this.addDefault(defaults, Messages.SuccessfulAbandon, "Claims abandoned. You now have {0} available claim blocks.", "0: remaining blocks");
- this.addDefault(defaults, Messages.RestoreNatureActivate, "Ready to restore some nature! Right click to restore nature, and use /basicclaims to stop.", null);
- this.addDefault(defaults, Messages.RestoreNatureAggressiveActivate, "Aggressive mode activated. Do NOT use this underneath anything you want to keep! Right click to aggressively restore nature, and use /basicclaims to stop.", null);
- this.addDefault(defaults, Messages.FillModeActive, "Fill mode activated with radius {0}. Right click an area to fill.", "0: fill radius");
- this.addDefault(defaults, Messages.TransferClaimPermission, "That command requires the administrative claims permission.", null);
- this.addDefault(defaults, Messages.TransferClaimMissing, "There's no claim here. Stand in the administrative claim you want to transfer.", null);
- this.addDefault(defaults, Messages.TransferClaimAdminOnly, "Only administrative claims may be transferred to a player.", null);
- this.addDefault(defaults, Messages.PlayerNotFound2, "No player by that name has logged in recently.", null);
- this.addDefault(defaults, Messages.TransferTopLevel, "Only top level claims (not subdivisions) may be transferred. Stand outside of the subdivision and try again.", null);
- this.addDefault(defaults, Messages.TransferSuccess, "Claim transferred.", null);
- this.addDefault(defaults, Messages.TrustListNoClaim, "Stand inside the claim you're curious about.", null);
- this.addDefault(defaults, Messages.ClearPermsOwnerOnly, "Only the claim owner can clear all permissions.", null);
- this.addDefault(defaults, Messages.UntrustIndividualAllClaims, "Revoked {0}'s access to ALL your claims. To set permissions for a single claim, stand inside it.", "0: untrusted player");
- this.addDefault(defaults, Messages.UntrustEveryoneAllClaims, "Cleared permissions in ALL your claims. To set permissions for a single claim, stand inside it.", null);
- this.addDefault(defaults, Messages.NoPermissionTrust, "You don't have {0}'s permission to manage permissions here.", "0: claim owner's name");
- this.addDefault(defaults, Messages.ClearPermissionsOneClaim, "Cleared permissions in this claim. To set permission for ALL your claims, stand outside them.", null);
- this.addDefault(defaults, Messages.UntrustIndividualSingleClaim, "Revoked {0}'s access to this claim. To set permissions for a ALL your claims, stand outside them.", "0: untrusted player");
- this.addDefault(defaults, Messages.AdminClaimsMode, "Administrative claims mode active. Any claims created will be free and editable by other administrators.", null);
- this.addDefault(defaults, Messages.BasicClaimsMode, "Returned to basic claim creation mode.", null);
- this.addDefault(defaults, Messages.SubdivisionMode, "Subdivision mode. Use your shovel to create subdivisions in your existing claims. Use /basicclaims to exit.", null);
- this.addDefault(defaults, Messages.SubdivisionVideo2, "Click for Subdivision Help: {0}", "0:video URL");
- this.addDefault(defaults, Messages.DeleteClaimMissing, "There's no claim here.", null);
- this.addDefault(defaults, Messages.DeletionSubdivisionWarning, "This claim includes subdivisions. If you're sure you want to delete it, use /deleteclaim again.", null);
- this.addDefault(defaults, Messages.DeleteSuccess, "Claim deleted.", null);
- this.addDefault(defaults, Messages.CantDeleteAdminClaim, "You don't have permission to delete administrative claims.", null);
- this.addDefault(defaults, Messages.DeleteAllSuccess, "Deleted all of {0}'s claims.", "0: owner's name");
- this.addDefault(defaults, Messages.NoDeletePermission, "You don't have permission to delete claims.", null);
- this.addDefault(defaults, Messages.AllAdminDeleted, "Deleted all administrative claims.", null);
- this.addDefault(defaults, Messages.AdjustBlocksSuccess, "Adjusted {0}'s bonus claim blocks by {1}. New total bonus blocks: {2}.", "0: player; 1: adjustment; 2: new total");
- this.addDefault(defaults, Messages.AdjustBlocksAllSuccess, "Adjusted all online players' bonus claim blocks by {0}.", "0: adjustment amount");
- this.addDefault(defaults, Messages.NotTrappedHere, "You can build here. Save yourself.", null);
- this.addDefault(defaults, Messages.RescuePending, "If you stay put for 10 seconds, you'll be teleported out. Please wait.", null);
- this.addDefault(defaults, Messages.AbandonClaimMissing, "Stand in the claim you want to delete, or consider /abandonallclaims.", null);
- this.addDefault(defaults, Messages.NotYourClaim, "This isn't your claim.", null);
- this.addDefault(defaults, Messages.DeleteTopLevelClaim, "To delete a subdivision, stand inside it. Otherwise, use /abandontoplevelclaim to delete this claim and all subdivisions.", null);
- this.addDefault(defaults, Messages.AbandonSuccess, "Claim abandoned. You now have {0} available claim blocks.", "0: remaining claim blocks");
- this.addDefault(defaults, Messages.ConfirmAbandonAllClaims, "Are you sure you want to abandon ALL of your claims? Please confirm with /abandonallclaims confirm", null);
- this.addDefault(defaults, Messages.CantGrantThatPermission, "You can't grant a permission you don't have yourself.", null);
- this.addDefault(defaults, Messages.GrantPermissionNoClaim, "Stand inside the claim where you want to grant permission.", null);
- this.addDefault(defaults, Messages.GrantPermissionConfirmation, "Granted {0} permission to {1} {2}.", "0: target player; 1: permission description; 2: scope (changed claims)");
- this.addDefault(defaults, Messages.ManageUniversalPermissionsInstruction, "To manage permissions for ALL your claims, stand outside them.", null);
- this.addDefault(defaults, Messages.ManageOneClaimPermissionsInstruction, "To manage permissions for a specific claim, stand inside it.", null);
- this.addDefault(defaults, Messages.CollectivePublic, "the public", "as in 'granted the public permission to...'");
- this.addDefault(defaults, Messages.BuildPermission, "build", null);
- this.addDefault(defaults, Messages.ContainersPermission, "access containers and animals", null);
- this.addDefault(defaults, Messages.AccessPermission, "use buttons and levers", null);
- this.addDefault(defaults, Messages.PermissionsPermission, "manage permissions", null);
- this.addDefault(defaults, Messages.LocationCurrentClaim, "in this claim", null);
- this.addDefault(defaults, Messages.LocationAllClaims, "in all your claims", null);
- this.addDefault(defaults, Messages.PvPImmunityStart, "You're protected from attack by other players as long as your inventory is empty.", null);
- this.addDefault(defaults, Messages.DonateItemsInstruction, "To give away the item(s) in your hand, left-click the chest again.", null);
- this.addDefault(defaults, Messages.ChestFull, "This chest is full.", null);
- this.addDefault(defaults, Messages.DonationSuccess, "Item(s) transferred to chest!", null);
- this.addDefault(defaults, Messages.PlayerTooCloseForFire2, "You can't start a fire this close to another player.", null);
- this.addDefault(defaults, Messages.TooDeepToClaim, "This chest can't be protected because it's too deep underground. Consider moving it.", null);
- this.addDefault(defaults, Messages.ChestClaimConfirmation, "This chest is protected.", null);
- this.addDefault(defaults, Messages.AutomaticClaimNotification, "This chest and nearby blocks are protected from breakage and theft.", null);
- this.addDefault(defaults, Messages.AutomaticClaimOtherClaimTooClose, "Cannot create a claim for your chest, there is another claim too close!", null);
- this.addDefault(defaults, Messages.UnprotectedChestWarning, "This chest is NOT protected. Consider using a golden shovel to expand an existing claim or to create a new one.", null);
- this.addDefault(defaults, Messages.ThatPlayerPvPImmune, "You can't injure defenseless players.", null);
- this.addDefault(defaults, Messages.CantFightWhileImmune, "You can't fight someone while you're protected from PvP.", null);
- this.addDefault(defaults, Messages.NoDamageClaimedEntity, "That belongs to {0}.", "0: owner name");
- this.addDefault(defaults, Messages.ShovelBasicClaimMode, "Shovel returned to basic claims mode.", null);
- this.addDefault(defaults, Messages.RemainingBlocks, "You may claim up to {0} more blocks.", "0: remaining blocks");
- this.addDefault(defaults, Messages.CreativeBasicsVideo2, "Click for Land Claim Help: {0}", "{0}: video URL");
- this.addDefault(defaults, Messages.SurvivalBasicsVideo2, "Click for Land Claim Help: {0}", "{0}: video URL");
- this.addDefault(defaults, Messages.TrappedChatKeyword, "trapped;stuck", "When mentioned in chat, players get information about the /trapped command (multiple words can be separated with semi-colons)");
- this.addDefault(defaults, Messages.TrappedInstructions, "Are you trapped in someone's land claim? Try the /trapped command.", null);
- this.addDefault(defaults, Messages.PvPNoDrop, "You can't drop items while in PvP combat.", null);
- this.addDefault(defaults, Messages.PvPNoContainers, "You can't access containers during PvP combat.", null);
- this.addDefault(defaults, Messages.PvPImmunityEnd, "Now you can fight with other players.", null);
- this.addDefault(defaults, Messages.NoBedPermission, "{0} hasn't given you permission to sleep here.", "0: claim owner");
- this.addDefault(defaults, Messages.NoWildernessBuckets, "You may only dump buckets inside your claim(s) or underground.", null);
- this.addDefault(defaults, Messages.NoLavaNearOtherPlayer, "You can't place lava this close to {0}.", "0: nearby player");
- this.addDefault(defaults, Messages.TooFarAway, "That's too far away.", null);
- this.addDefault(defaults, Messages.BlockNotClaimed, "No one has claimed this block.", null);
- this.addDefault(defaults, Messages.BlockClaimed, "That block has been claimed by {0}.", "0: claim owner");
- this.addDefault(defaults, Messages.RestoreNaturePlayerInChunk, "Unable to restore. {0} is in that chunk.", "0: nearby player");
- this.addDefault(defaults, Messages.NoCreateClaimPermission, "You don't have permission to claim land.", null);
- this.addDefault(defaults, Messages.ResizeClaimTooNarrow, "This new size would be too small. Claims must be at least {0} blocks wide.", "0: minimum claim width");
- this.addDefault(defaults, Messages.ResizeNeedMoreBlocks, "You don't have enough blocks for this size. You need {0} more.", "0: how many needed");
- this.addDefault(defaults, Messages.ClaimResizeSuccess, "Claim resized. {0} available claim blocks remaining.", "0: remaining blocks");
- this.addDefault(defaults, Messages.ResizeFailOverlap, "Can't resize here because it would overlap another nearby claim.", null);
- this.addDefault(defaults, Messages.ResizeStart, "Resizing claim. Use your shovel again at the new location for this corner.", null);
- this.addDefault(defaults, Messages.ResizeFailOverlapSubdivision, "You can't create a subdivision here because it would overlap another subdivision. Consider /abandonclaim to delete it, or use your shovel at a corner to resize it.", null);
- this.addDefault(defaults, Messages.SubdivisionStart, "Subdivision corner set! Use your shovel at the location for the opposite corner of this new subdivision.", null);
- this.addDefault(defaults, Messages.CreateSubdivisionOverlap, "Your selected area overlaps another subdivision.", null);
- this.addDefault(defaults, Messages.SubdivisionSuccess, "Subdivision created! Use /trust to share it with friends.", null);
- this.addDefault(defaults, Messages.CreateClaimFailOverlap, "You can't create a claim here because it would overlap your other claim. Use /abandonclaim to delete it, or use your shovel at a corner to resize it.", null);
- this.addDefault(defaults, Messages.CreateClaimFailOverlapOtherPlayer, "You can't create a claim here because it would overlap {0}'s claim.", "0: other claim owner");
- this.addDefault(defaults, Messages.ClaimsDisabledWorld, "Land claims are disabled in this world.", null);
- this.addDefault(defaults, Messages.ClaimStart, "Claim corner set! Use the shovel again at the opposite corner to claim a rectangle of land. To cancel, put your shovel away.", null);
- this.addDefault(defaults, Messages.NewClaimTooNarrow, "This claim would be too small. Any claim must be at least {0} blocks wide.", "0: minimum claim width");
- this.addDefault(defaults, Messages.ResizeClaimInsufficientArea, "This claim would be too small. Any claim must use at least {0} total claim blocks.", "0: minimum claim area");
- this.addDefault(defaults, Messages.CreateClaimInsufficientBlocks, "You don't have enough blocks to claim that entire area. You need {0} more blocks.", "0: additional blocks needed");
- this.addDefault(defaults, Messages.AbandonClaimAdvertisement, "To delete another claim and free up some blocks, use /abandonclaim.", null);
- this.addDefault(defaults, Messages.CreateClaimFailOverlapShort, "Your selected area overlaps an existing claim.", null);
- this.addDefault(defaults, Messages.CreateClaimSuccess, "Claim created! Use /trust to share it with friends.", null);
- this.addDefault(defaults, Messages.RescueAbortedMoved, "You moved! Rescue cancelled.", null);
- this.addDefault(defaults, Messages.OnlyOwnersModifyClaims, "Only {0} can modify this claim.", "0: owner name");
- this.addDefault(defaults, Messages.NoBuildPvP, "You can't build in claims during PvP combat.", null);
- this.addDefault(defaults, Messages.NoBuildPermission, "You don't have {0}'s permission to build here.", "0: owner name");
- this.addDefault(defaults, Messages.NoAccessPermission, "You don't have {0}'s permission to use that.", "0: owner name. access permission controls buttons, levers, and beds");
- this.addDefault(defaults, Messages.NoContainersPermission, "You don't have {0}'s permission to use that.", "0: owner's name. containers also include crafting blocks");
- this.addDefault(defaults, Messages.OwnerNameForAdminClaims, "an administrator", "as in 'You don't have an administrator's permission to build here.'");
- this.addDefault(defaults, Messages.UnknownPlayerName, "someone", "Name used for unknown players. UUID will be appended if available: \"someone (01234567-0123-0123-0123-0123456789ab)\"");
- this.addDefault(defaults, Messages.ClaimTooSmallForEntities, "This claim isn't big enough for that. Try enlarging it.", null);
- this.addDefault(defaults, Messages.TooManyEntitiesInClaim, "This claim has too many entities already. Try enlarging the claim or removing some animals, monsters, paintings, or minecarts.", null);
- this.addDefault(defaults, Messages.YouHaveNoClaims, "You don't have any land claims.", null);
- this.addDefault(defaults, Messages.ConfirmFluidRemoval, "Abandoning this claim will remove lava inside the claim. If you're sure, use /abandonclaim again.", null);
- this.addDefault(defaults, Messages.AutoBanNotify, "Auto-banned {0}({1}). See logs for details.", null);
- this.addDefault(defaults, Messages.AdjustGroupBlocksSuccess, "Adjusted bonus claim blocks for players with the {0} permission by {1}. New total: {2}.", "0: permission; 1: adjustment amount; 2: new total bonus");
- this.addDefault(defaults, Messages.InvalidPermissionID, "Please specify a player name, or a permission in [brackets].", null);
- this.addDefault(defaults, Messages.HowToClaimRegex, "(^|.*\\W)how\\W.*\\W(claim|protect|lock)(\\W.*|$)", "This is a Java Regular Expression. Look it up before editing! It's used to tell players about the demo video when they ask how to claim land.");
- this.addDefault(defaults, Messages.NoBuildOutsideClaims, "You can't build here unless you claim some land first.", null);
- this.addDefault(defaults, Messages.PlayerOfflineTime, " Last login: {0} days ago.", "0: number of full days since last login");
- this.addDefault(defaults, Messages.BuildingOutsideClaims, "Other players can build here, too. Consider creating a land claim to protect your work!", null);
- this.addDefault(defaults, Messages.TrappedWontWorkHere, "Sorry, unable to find a safe location to teleport you to. Contact an admin.", null);
- this.addDefault(defaults, Messages.CommandBannedInPvP, "You can't use that command while in PvP combat.", null);
- this.addDefault(defaults, Messages.UnclaimCleanupWarning, "The land you've unclaimed may be changed by other players or cleaned up by administrators. If you've built something there you want to keep, you should reclaim it.", null);
- this.addDefault(defaults, Messages.NoTeleportPvPCombat, "You can't teleport while fighting another player.", null);
- this.addDefault(defaults, Messages.NoTNTDamageAboveSeaLevel, "Warning: TNT will not destroy blocks above sea level.", null);
- this.addDefault(defaults, Messages.NoTNTDamageClaims, "Warning: TNT will not destroy claimed blocks.", null);
- this.addDefault(defaults, Messages.IgnoreClaimsAdvertisement, "To override, use /ignoreclaims.", null);
- this.addDefault(defaults, Messages.NoPermissionForCommand, "You don't have permission to do that.", null);
- this.addDefault(defaults, Messages.ClaimsListNoPermission, "You don't have permission to get information about another player's land claims.", null);
- this.addDefault(defaults, Messages.ExplosivesDisabled, "This claim is now protected from explosions. Use /claimexplosions again to disable.", null);
- this.addDefault(defaults, Messages.ExplosivesEnabled, "This claim is now vulnerable to explosions. Use /claimexplosions again to re-enable protections.", null);
- this.addDefault(defaults, Messages.ClaimExplosivesAdvertisement, "To allow explosives to destroy blocks in this land claim, use /claimexplosions.", null);
- this.addDefault(defaults, Messages.PlayerInPvPSafeZone, "That player is in a PvP safe zone.", null);
- this.addDefault(defaults, Messages.NoPistonsOutsideClaims, "Warning: Pistons won't move blocks outside land claims.", null);
- this.addDefault(defaults, Messages.SoftMuted, "Soft-muted {0}.", "0: The changed player's name.");
- this.addDefault(defaults, Messages.UnSoftMuted, "Un-soft-muted {0}.", "0: The changed player's name.");
- this.addDefault(defaults, Messages.DropUnlockAdvertisement, "Other players can't pick up your dropped items unless you /unlockdrops first.", null);
- this.addDefault(defaults, Messages.PickupBlockedExplanation, "You can't pick this up unless {0} uses /unlockdrops.", "0: The item stack's owner.");
- this.addDefault(defaults, Messages.DropUnlockConfirmation, "Unlocked your drops. Other players may now pick them up (until you die again).", null);
- this.addDefault(defaults, Messages.DropUnlockOthersConfirmation, "Unlocked {0}'s drops.", "0: The owner of the unlocked drops.");
- this.addDefault(defaults, Messages.AdvertiseACandACB, "You may use /acb to give yourself more claim blocks, or /adminclaims to create a free administrative claim.", null);
- this.addDefault(defaults, Messages.AdvertiseAdminClaims, "You could create an administrative land claim instead using /adminclaims, which you'd share with other administrators.", null);
- this.addDefault(defaults, Messages.AdvertiseACB, "You may use /acb to give yourself more claim blocks.", null);
- this.addDefault(defaults, Messages.NotYourPet, "That belongs to {0} until it's given to you with /givepet.", "0: owner name");
- this.addDefault(defaults, Messages.PetGiveawayConfirmation, "Pet transferred.", null);
- this.addDefault(defaults, Messages.PetTransferCancellation, "Pet giveaway cancelled.", null);
- this.addDefault(defaults, Messages.ReadyToTransferPet, "Ready to transfer! Right-click the pet you'd like to give away, or cancel with /givepet cancel.", null);
- this.addDefault(defaults, Messages.AvoidGriefClaimLand, "Prevent grief! If you claim your land, you will be grief-proof.", null);
- this.addDefault(defaults, Messages.BecomeMayor, "Subdivide your land claim and become a mayor!", null);
- this.addDefault(defaults, Messages.ClaimCreationFailedOverClaimCountLimit, "You've reached your limit on land claims. Use /abandonclaim to remove one before creating another.", null);
- this.addDefault(defaults, Messages.CreateClaimFailOverlapRegion, "You can't claim all of this because you're not allowed to build here.", null);
- this.addDefault(defaults, Messages.ResizeFailOverlapRegion, "You don't have permission to build there, so you can't claim that area.", null);
- this.addDefault(defaults, Messages.ShowNearbyClaims, "Found {0} land claims.", "0: Number of claims found.");
- this.addDefault(defaults, Messages.NoChatUntilMove, "Sorry, but you have to move a little more before you can chat. We get lots of spam bots here. :)", null);
- this.addDefault(defaults, Messages.SetClaimBlocksSuccess, "Updated accrued claim blocks.", null);
- this.addDefault(defaults, Messages.IgnoreConfirmation, "You're now ignoring chat messages from that player.", null);
- this.addDefault(defaults, Messages.UnIgnoreConfirmation, "You're no longer ignoring chat messages from that player.", null);
- this.addDefault(defaults, Messages.NotIgnoringPlayer, "You're not ignoring that player.", null);
- this.addDefault(defaults, Messages.SeparateConfirmation, "Those players will now ignore each other in chat.", null);
- this.addDefault(defaults, Messages.UnSeparateConfirmation, "Those players will no longer ignore each other in chat.", null);
- this.addDefault(defaults, Messages.NotIgnoringAnyone, "You're not ignoring anyone.", null);
- this.addDefault(defaults, Messages.TrustListHeader, "Explicit permissions here:", "0: The claim's owner");
- this.addDefault(defaults, Messages.Manage, "Manage", null);
- this.addDefault(defaults, Messages.Build, "Build", null);
- this.addDefault(defaults, Messages.Containers, "Containers", null);
- this.addDefault(defaults, Messages.Access, "Access", null);
- this.addDefault(defaults, Messages.HasSubclaimRestriction, "This subclaim does not inherit permissions from the parent", null);
- this.addDefault(defaults, Messages.StartBlockMath, "{0} blocks from play + {1} bonus = {2} total.", null);
- this.addDefault(defaults, Messages.ClaimsListHeader, "Claims:", null);
- this.addDefault(defaults, Messages.ContinueBlockMath, " (-{0} blocks)", null);
- this.addDefault(defaults, Messages.EndBlockMath, " = {0} blocks left to spend", null);
- this.addDefault(defaults, Messages.NoClaimDuringPvP, "You can't claim lands during PvP combat.", null);
- this.addDefault(defaults, Messages.UntrustAllOwnerOnly, "Only the claim owner can clear all its permissions.", null);
- this.addDefault(defaults, Messages.ManagersDontUntrustManagers, "Only the claim owner can demote a manager.", null);
- this.addDefault(defaults, Messages.PlayerNotIgnorable, "You can't ignore that player.", null);
- this.addDefault(defaults, Messages.NoEnoughBlocksForChestClaim, "Because you don't have any claim blocks available, no automatic land claim was created for you. You can use /claimslist to monitor your available claim block total.", null);
- this.addDefault(defaults, Messages.MustHoldModificationToolForThat, "You must be holding a golden shovel to do that.", null);
- this.addDefault(defaults, Messages.StandInClaimToResize, "Stand inside the land claim you want to resize.", null);
- this.addDefault(defaults, Messages.ClaimsExtendToSky, "Land claims always extend to max build height.", null);
- this.addDefault(defaults, Messages.ClaimsAutoExtendDownward, "Land claims auto-extend deeper into the ground when you place blocks under them.", null);
- this.addDefault(defaults, Messages.MinimumRadius, "Minimum radius is {0}.", "0: minimum radius");
- this.addDefault(defaults, Messages.RadiusRequiresGoldenShovel, "You must be holding a golden shovel when specifying a radius.", null);
- this.addDefault(defaults, Messages.ClaimTooSmallForActiveBlocks, "This claim isn't big enough to support any active block types (hoppers, spawners, beacons...). Make the claim bigger first.", null);
- this.addDefault(defaults, Messages.TooManyActiveBlocksInClaim, "This claim is at its limit for active block types (hoppers, spawners, beacons...). Either make it bigger, or remove other active blocks first.", null);
-
- this.addDefault(defaults, Messages.BookAuthor, "BigScary", null);
- this.addDefault(defaults, Messages.BookTitle, "How to Claim Land", null);
- this.addDefault(defaults, Messages.BookLink, "Click: {0}", "{0}: video URL");
- this.addDefault(defaults, Messages.BookIntro, "Claim land to protect your stuff! Click the link above to learn land claims in 3 minutes or less. :)", null);
- this.addDefault(defaults, Messages.BookTools, "Our claim tools are {0} and {1}.", "0: claim modification tool name; 1:claim information tool name");
- this.addDefault(defaults, Messages.BookDisabledChestClaims, " On this server, placing a chest will NOT claim land for you.", null);
- this.addDefault(defaults, Messages.BookUsefulCommands, "Useful Commands:", null);
- this.addDefault(defaults, Messages.NoProfanity, "Please moderate your language.", null);
- this.addDefault(defaults, Messages.IsIgnoringYou, "That player is ignoring you.", null);
- this.addDefault(defaults, Messages.ConsoleOnlyCommand, "That command may only be executed from the server console.", null);
- this.addDefault(defaults, Messages.WorldNotFound, "World not found.", null);
- this.addDefault(defaults, Messages.TooMuchIpOverlap, "Sorry, there are too many players logged in with your IP address.", null);
-
- this.addDefault(defaults, Messages.StandInSubclaim, "You need to be standing in a subclaim to restrict it", null);
- this.addDefault(defaults, Messages.SubclaimRestricted, "This subclaim's permissions will no longer inherit from the parent claim", null);
- this.addDefault(defaults, Messages.SubclaimUnrestricted, "This subclaim's permissions will now inherit from the parent claim", null);
-
- this.addDefault(defaults, Messages.NetherPortalTrapDetectionMessage, "It seems you might be stuck inside a nether portal. We will rescue you in a few seconds if that is the case!", "Sent to player on join, if they left while inside a nether portal.");
+ this.messages = new String[messageIDs.length];
//load the config file
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
//for each message ID
- for (Messages messageID : messageIDs)
+ for (Messages message : messageIDs)
{
- //get default for this message
- CustomizableMessage messageData = defaults.get(messageID.name());
-
- //if default is missing, log an error and use some fake data for now so that the plugin can run
- if (messageData == null)
+ String messagePath = "Messages." + message.name();
+ // If available, migrate legacy path.
+ if (config.isString(messagePath + ".Text"))
{
- GriefPrevention.AddLogEntry("Missing message for " + messageID.name() + ". Please contact the developer.");
- messageData = new CustomizableMessage(messageID, "Missing message! ID: " + messageID.name() + ". Please contact a server admin.", null);
+ this.messages[message.ordinal()] = config.getString(messagePath + ".Text", message.defaultValue);
}
-
- //read the message from the file, use default if necessary
- this.messages[messageID.ordinal()] = config.getString("Messages." + messageID.name() + ".Text", messageData.text);
- config.set("Messages." + messageID.name() + ".Text", this.messages[messageID.ordinal()]);
+ // Otherwise prefer current value if available.
+ else
+ {
+ this.messages[message.ordinal()] = config.getString(messagePath, message.defaultValue);
+ }
+ config.set(messagePath, this.messages[message.ordinal()]);
//support color codes
- if (messageID != Messages.HowToClaimRegex)
+ if (message != Messages.HowToClaimRegex)
{
- this.messages[messageID.ordinal()] = this.messages[messageID.ordinal()].replace('$', (char) 0x00A7);
+ this.messages[message.ordinal()] = this.messages[message.ordinal()].replace('$', (char) 0x00A7);
}
- if (messageData.notes != null)
+ if (message.notes != null)
{
- messageData.notes = config.getString("Messages." + messageID.name() + ".Notes", messageData.notes);
- config.set("Messages." + messageID.name() + ".Notes", messageData.notes);
+ // Import old non-comment notes.
+ String notesString = config.getString(messagePath + ".Notes", message.notes);
+ // Import existing comment notes.
+ List notes = config.getComments(messagePath);
+ if (notes.isEmpty()) {
+ notes = List.of(notesString);
+ }
+ config.setComments(messagePath, notes);
}
}
//save any changes
try
{
- config.options().header("Use a YAML editor like NotepadPlusPlus to edit this file. \nAfter editing, back up your changes before reloading the server in case you made a syntax error. \nUse dollar signs ($) for formatting codes, which are documented here: http://minecraft.gamepedia.com/Formatting_codes");
+ config.options().setHeader(List.of(
+ "Use a YAML editor like NotepadPlusPlus to edit this file.",
+ "After editing, back up your changes before reloading the server in case you made a syntax error.",
+ "Use dollar signs ($) for formatting codes, which are documented here: http://minecraft.wiki/Formatting_codes#Color_codes"
+ ));
config.save(DataStore.messagesFilePath);
}
catch (IOException exception)
{
GriefPrevention.AddLogEntry("Unable to write to the configuration file at \"" + DataStore.messagesFilePath + "\"");
}
-
- defaults.clear();
- System.gc();
- }
-
- private void addDefault(HashMap defaults,
- Messages id, String text, String notes)
- {
- CustomizableMessage message = new CustomizableMessage(id, text, notes);
- defaults.put(id.name(), message);
}
synchronized public String getMessage(Messages messageID, String... args)
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/EntityDamageHandler.java b/src/main/java/me/ryanhamshire/GriefPrevention/EntityDamageHandler.java
index 0a5e6ccf..56a7d025 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/EntityDamageHandler.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/EntityDamageHandler.java
@@ -45,6 +45,7 @@
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
+import org.bukkit.potion.PotionEffectTypeCategory;
import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
@@ -63,34 +64,13 @@ public class EntityDamageHandler implements Listener
private static final Set GRIEF_EFFECTS = Set.of(
// Damaging effects
- PotionEffectType.HARM,
+ PotionEffectType.INSTANT_DAMAGE,
PotionEffectType.POISON,
PotionEffectType.WITHER,
// Effects that could remove entities from normally-secure pens
- PotionEffectType.JUMP,
+ PotionEffectType.JUMP_BOOST,
PotionEffectType.LEVITATION
);
- private static final Set POSITIVE_EFFECTS = Set.of(
- PotionEffectType.ABSORPTION,
- PotionEffectType.CONDUIT_POWER,
- PotionEffectType.DAMAGE_RESISTANCE,
- PotionEffectType.DOLPHINS_GRACE,
- PotionEffectType.FAST_DIGGING,
- PotionEffectType.FIRE_RESISTANCE,
- PotionEffectType.HEAL,
- PotionEffectType.HEALTH_BOOST,
- PotionEffectType.HERO_OF_THE_VILLAGE,
- PotionEffectType.INCREASE_DAMAGE,
- PotionEffectType.INVISIBILITY,
- PotionEffectType.JUMP,
- PotionEffectType.LUCK,
- PotionEffectType.NIGHT_VISION,
- PotionEffectType.REGENERATION,
- PotionEffectType.SATURATION,
- PotionEffectType.SLOW_FALLING,
- PotionEffectType.SPEED,
- PotionEffectType.WATER_BREATHING
- );
private static final Set TEMPTABLE_SEMI_HOSTILES = Set.of(
EntityType.HOGLIN,
EntityType.POLAR_BEAR,
@@ -150,7 +130,7 @@ private void handleEntityDamageEvent(@NotNull EntityDamageInstance event, boolea
if (event.damaged() instanceof Mule && !instance.config_claims_protectDonkeys) return;
if (event.damaged() instanceof Llama && !instance.config_claims_protectLlamas) return;
//protected death loot can't be destroyed, only picked up or despawned due to expiration
- if (event.damaged().getType() == EntityType.DROPPED_ITEM)
+ if (event.damaged().getType() == EntityType.ITEM)
{
if (event.damaged().hasMetadata("GP_ITEMOWNER"))
{
@@ -582,7 +562,7 @@ private boolean handleClaimedBuildTrustDamageByEntity(
&& entityType != EntityType.GLOW_ITEM_FRAME
&& entityType != EntityType.ARMOR_STAND
&& entityType != EntityType.VILLAGER
- && entityType != EntityType.ENDER_CRYSTAL)
+ && entityType != EntityType.END_CRYSTAL)
{
return false;
}
@@ -663,7 +643,7 @@ private boolean handleCreatureDamageByEntity(
if (attacker == null
&& damageSourceType != EntityType.CREEPER
&& damageSourceType != EntityType.WITHER
- && damageSourceType != EntityType.ENDER_CRYSTAL
+ && damageSourceType != EntityType.END_CRYSTAL
&& damageSourceType != EntityType.AREA_EFFECT_CLOUD
&& damageSourceType != EntityType.WITCH
&& !(damageSource instanceof Projectile)
@@ -699,7 +679,7 @@ private boolean handleCreatureDamageByEntity(
playerData.lastClaim = claim;
// Do not message players about fireworks to prevent spam due to multi-hits.
- sendMessages &= damageSourceType != EntityType.FIREWORK;
+ sendMessages &= damageSourceType != EntityType.FIREWORK_ROCKET;
Supplier override = null;
if (sendMessages)
@@ -880,7 +860,7 @@ else if (damageSource instanceof Projectile projectile)
}
//if not a player and not an explosion, always allow
- if (attacker == null && damageSourceType != EntityType.CREEPER && damageSourceType != EntityType.WITHER && damageSourceType != EntityType.PRIMED_TNT)
+ if (attacker == null && damageSourceType != EntityType.CREEPER && damageSourceType != EntityType.WITHER && damageSourceType != EntityType.TNT)
{
return;
}
@@ -999,7 +979,7 @@ public void onPotionSplash(@NotNull PotionSplashEvent event)
if (thrower == null) return;
//otherwise, no restrictions for positive effects
- if (POSITIVE_EFFECTS.contains(effectType)) continue;
+ if (effectType.getCategory() == PotionEffectTypeCategory.BENEFICIAL) continue;
for (LivingEntity affected : event.getAffectedEntities())
{
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/EntityEventHandler.java b/src/main/java/me/ryanhamshire/GriefPrevention/EntityEventHandler.java
index 2ff26678..8fb4c460 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/EntityEventHandler.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/EntityEventHandler.java
@@ -18,8 +18,10 @@
package me.ryanhamshire.GriefPrevention;
+import com.griefprevention.protection.ProtectionHelper;
import me.ryanhamshire.GriefPrevention.events.ProtectDeathDropsEvent;
import org.bukkit.Bukkit;
+import org.bukkit.ExplosionResult;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
@@ -36,10 +38,12 @@
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Vehicle;
+import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockExplodeEvent;
+import org.bukkit.event.block.CauldronLevelChangeEvent;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
@@ -89,14 +93,10 @@ public EntityEventHandler(DataStore dataStore, GriefPrevention plugin)
public void onEntityFormBlock(EntityBlockFormEvent event)
{
Entity entity = event.getEntity();
- if (entity.getType() == EntityType.PLAYER)
+ if (entity instanceof Player player
+ && ProtectionHelper.checkPermission(player, event.getBlock().getLocation(), ClaimPermission.Build, event) != null)
{
- Player player = (Player) event.getEntity();
- String noBuildReason = GriefPrevention.instance.allowBuild(player, event.getBlock().getLocation(), event.getNewState().getType());
- if (noBuildReason != null)
- {
- event.setCancelled(true);
- }
+ event.setCancelled(true);
}
}
@@ -148,15 +148,14 @@ else if (event.getEntityType() == EntityType.WITHER)
//don't allow crops to be trampled, except by a player with build permission
else if (event.getTo() == Material.DIRT && event.getBlock().getType() == Material.FARMLAND)
{
- if (event.getEntityType() != EntityType.PLAYER)
+ if (!(event.getEntity() instanceof Player player))
{
event.setCancelled(true);
}
else
{
- Player player = (Player) event.getEntity();
Block block = event.getBlock();
- if (GriefPrevention.instance.allowBreak(player, block, block.getLocation()) != null)
+ if (ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, event) != null)
{
event.setCancelled(true);
}
@@ -173,10 +172,10 @@ else if (event.getBlock().getType() == Material.POWDER_SNOW && event.getTo() ==
else if (event.getEntity() instanceof Vehicle && !event.getEntity().getPassengers().isEmpty())
{
Entity driver = event.getEntity().getPassengers().get(0);
- if (driver instanceof Player)
+ if (driver instanceof Player player)
{
Block block = event.getBlock();
- if (GriefPrevention.instance.allowBreak((Player) driver, block, block.getLocation()) != null)
+ if (ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, event) != null)
{
event.setCancelled(true);
}
@@ -327,7 +326,7 @@ else if (mob.isLeashed() && mob.getLeashHolder() instanceof Player localPlayer)
if (player != null)
{
Block block = event.getBlock();
- if (GriefPrevention.instance.allowBreak(player, block, block.getLocation()) != null)
+ if (ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, event) != null)
{
event.setCancelled(true);
}
@@ -379,23 +378,99 @@ public void onEntityInteract(EntityInteractEvent event)
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onEntityExplode(EntityExplodeEvent explodeEvent)
{
- this.handleExplosion(explodeEvent.getLocation(), explodeEvent.getEntity(), explodeEvent.blockList());
+ // If there aren't any affected blocks, there's nothing to do. Vanilla mob griefing rule causes this.
+ if (explodeEvent.blockList().isEmpty()) return;
+
+ // Explosion causes interactable blocks (levers, buttons, etc.) to change state.
+ if (explodeEvent.getExplosionResult() == ExplosionResult.TRIGGER_BLOCK)
+ {
+ handleExplodeInteract(explodeEvent.getLocation(), explodeEvent.getEntity(), explodeEvent.blockList(), explodeEvent);
+ }
+ // Explosion damages world.
+ else
+ {
+ handleExplosion(explodeEvent.getLocation(), explodeEvent.getEntity(), explodeEvent.blockList());
+ }
}
//when a block explodes...
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onBlockExplode(BlockExplodeEvent explodeEvent)
{
- this.handleExplosion(explodeEvent.getBlock().getLocation(), null, explodeEvent.blockList());
+ // If there aren't any affected blocks, there's nothing to do. Vanilla mob griefing rule causes this.
+ if (explodeEvent.blockList().isEmpty()) return;
+
+ // Explosion causes interactable blocks (levers, buttons, etc.) to change state.
+ if (explodeEvent.getExplosionResult() == ExplosionResult.TRIGGER_BLOCK)
+ {
+ handleExplodeInteract(explodeEvent.getBlock().getLocation(), null, explodeEvent.blockList(), explodeEvent);
+ }
+ // Explosion damages world.
+ else
+ {
+ handleExplosion(explodeEvent.getBlock().getLocation(), null, explodeEvent.blockList());
+ }
}
+ void handleExplodeInteract(@NotNull Location location, @Nullable Entity entity, @NotNull List blocks, @NotNull Event event)
+ {
+ World world = location.getWorld();
+
+ if (world == null || !GriefPrevention.instance.claimsEnabledForWorld(world)) return;
+
+ Player player = null;
+ PlayerData playerData = null;
+ ProjectileSource source = null;
+ if (entity instanceof Projectile projectile)
+ {
+ source = projectile.getShooter();
+ if (source instanceof Player)
+ {
+ player = (Player) source;
+ playerData = dataStore.getPlayerData(player.getUniqueId());
+ }
+ }
+
+ List removed = new ArrayList<>();
+ Claim cachedClaim = playerData != null ? playerData.lastClaim : null;
+
+ for (Block block : blocks)
+ {
+ // Always ignore air blocks.
+ if (block.getType().isAir()) continue;
+
+ Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, cachedClaim);
+
+ // Is it in a land claim?
+ if (claim == null) continue;
+
+ cachedClaim = claim;
+
+ if (player == null)
+ {
+ // If the source is not part of the claim, prevent interaction.
+ if (!isBlockSourceInClaim(source, claim))
+ removed.add(block);
+ continue;
+ }
+
+ // If the player is not allowed to interact with blocks, prevent interaction.
+ if (claim.checkPermission(player, ClaimPermission.Access, event) != null)
+ removed.add(block);
+ }
+
+ if (playerData != null && cachedClaim != null)
+ playerData.lastClaim = cachedClaim;
+
+ blocks.removeAll(removed);
+ }
- void handleExplosion(Location location, Entity entity, List blocks)
+ void handleExplosion(@NotNull Location location, @Nullable Entity entity, @NotNull List blocks)
{
//only applies to claims-enabled worlds
World world = location.getWorld();
- if (!GriefPrevention.instance.claimsEnabledForWorld(world)) return;
+ if (world == null || !GriefPrevention.instance.claimsEnabledForWorld(world)) return;
//FEATURE: explosions don't destroy surface blocks by default
boolean isCreeper = (entity != null && entity.getType() == EntityType.CREEPER);
@@ -407,8 +482,6 @@ void handleExplosion(Location location, Entity entity, List blocks)
{
for (int i = 0; i < blocks.size(); i++)
{
- Block block = blocks.get(i);
-
blocks.remove(i--);
}
@@ -421,7 +494,7 @@ void handleExplosion(Location location, Entity entity, List blocks)
for (Block block : blocks)
{
//always ignore air blocks
- if (block.getType() == Material.AIR) continue;
+ if (block.getType().isAir()) continue;
//is it in a land claim?
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, cachedClaim);
@@ -652,19 +725,18 @@ public void onHangingBreak(HangingBreakEvent event)
Entity remover = entityEvent.getRemover();
//again, making sure the breaker is a player
- if (remover.getType() != EntityType.PLAYER)
+ if (!(remover instanceof Player playerRemover))
{
event.setCancelled(true);
return;
}
//if the player doesn't have build permission, don't allow the breakage
- Player playerRemover = (Player) entityEvent.getRemover();
- String noBuildReason = GriefPrevention.instance.allowBuild(playerRemover, event.getEntity().getLocation(), Material.AIR);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(playerRemover, event.getEntity().getLocation(), ClaimPermission.Build, event);
if (noBuildReason != null)
{
event.setCancelled(true);
- GriefPrevention.sendMessage(playerRemover, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(playerRemover, TextMode.Err, noBuildReason.get());
}
}
@@ -674,15 +746,16 @@ public void onPaintingPlace(HangingPlaceEvent event)
{
//don't track in worlds where claims are not enabled
if (!GriefPrevention.instance.claimsEnabledForWorld(event.getBlock().getWorld())) return;
+ if (event.getPlayer() == null) return;
//FEATURE: similar to above, placing a painting requires build permission in the claim
//if the player doesn't have permission, don't allow the placement
- String noBuildReason = GriefPrevention.instance.allowBuild(event.getPlayer(), event.getEntity().getLocation(), Material.PAINTING);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(event.getPlayer(), event.getEntity().getLocation(), ClaimPermission.Build, event);
if (noBuildReason != null)
{
event.setCancelled(true);
- GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, noBuildReason.get());
return;
}
}
@@ -706,6 +779,26 @@ public void onEntityPickUpItem(@NotNull EntityPickupItemEvent event)
preventPvpSpawnCamp(event, player);
}
+ @EventHandler
+ public void onCauldron(@NotNull CauldronLevelChangeEvent event)
+ {
+ //don't track in worlds where claims are not enabled
+ if (!GriefPrevention.instance.claimsEnabledForWorld(event.getBlock().getWorld())) return;
+
+ // Check if the entity is a player
+ Entity entity = event.getEntity();
+ if (entity == null) return;
+ if (!(entity instanceof Player player)) return;
+
+ //if the player doesn't have build permission, don't allow the interaction
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, player.getLocation(), ClaimPermission.Build, event);
+ if (noBuildReason != null)
+ {
+ event.setCancelled(true);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
+ }
+ }
+
private void protectLockedDrops(@NotNull EntityPickupItemEvent event, @Nullable Player player)
{
Item item = event.getItem();
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/main/java/me/ryanhamshire/GriefPrevention/GriefPrevention.java
index c5f05a10..cfe9f6f3 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/GriefPrevention.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/GriefPrevention.java
@@ -22,10 +22,10 @@
import com.google.common.cache.CacheBuilder;
import com.griefprevention.commands.ClaimCommand;
import com.griefprevention.metrics.MetricsHandler;
+import com.griefprevention.protection.ProtectionHelper;
import ltd.lemongaming.lgcore.libs.com.tcoded.folialib.FoliaLib;
import ltd.lemongaming.lgcore.libs.com.tcoded.folialib.wrapper.WrappedTask;
import me.ryanhamshire.GriefPrevention.DataStore.NoTransferException;
-import me.ryanhamshire.GriefPrevention.events.PreventBlockBreakEvent;
import me.ryanhamshire.GriefPrevention.events.SaveTrappedPlayerEvent;
import me.ryanhamshire.GriefPrevention.events.TrustChangedEvent;
import org.bukkit.BanList;
@@ -33,7 +33,6 @@
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
-import org.bukkit.FluidCollisionMode;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -56,11 +55,15 @@
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -68,12 +71,14 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
+import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
+import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -148,8 +153,6 @@ public class GriefPrevention extends JavaPlugin
public int config_claims_minArea; //minimum area for non-admin claims
public int config_claims_chestClaimExpirationDays; //number of days of inactivity before an automatic chest claim will be deleted
- public int config_claims_unusedClaimExpirationDays; //number of days of inactivity before an unused (nothing build) claim will be deleted
- public boolean config_claims_survivalAutoNatureRestoration; //whether survival claims will be automatically restored to nature when auto-deleted
public boolean config_claims_allowTrappedInAdminClaims; //whether it should be allowed to use /trapped in adminclaims.
public Material config_claims_investigationTool; //which material will be used to investigate claims with a right click
@@ -577,11 +580,9 @@ else if (world.getEnvironment() == Environment.NORMAL)
AddLogEntry("Updated default value for GriefPrevention.Claims.MaximumDepth to " + Integer.MIN_VALUE);
}
this.config_claims_chestClaimExpirationDays = config.getInt("GriefPrevention.Claims.Expiration.ChestClaimDays", 7);
- this.config_claims_unusedClaimExpirationDays = config.getInt("GriefPrevention.Claims.Expiration.UnusedClaimDays", 14);
this.config_claims_expirationDays = config.getInt("GriefPrevention.Claims.Expiration.AllClaims.DaysInactive", 60);
this.config_claims_expirationExemptionTotalBlocks = config.getInt("GriefPrevention.Claims.Expiration.AllClaims.ExceptWhenOwnerHasTotalClaimBlocks", 10000);
this.config_claims_expirationExemptionBonusBlocks = config.getInt("GriefPrevention.Claims.Expiration.AllClaims.ExceptWhenOwnerHasBonusClaimBlocks", 5000);
- this.config_claims_survivalAutoNatureRestoration = config.getBoolean("GriefPrevention.Claims.Expiration.AutomaticNatureRestoration.SurvivalWorlds", false);
this.config_claims_allowTrappedInAdminClaims = config.getBoolean("GriefPrevention.Claims.AllowTrappedInAdminClaims", false);
this.config_claims_maxClaimsPerPlayer = config.getInt("GriefPrevention.Claims.MaximumNumberOfClaimsPerPlayer", 0);
@@ -689,9 +690,7 @@ else if (world.getEnvironment() == Environment.NORMAL)
this.config_pvp_protectPets = config.getBoolean("GriefPrevention.PvP.ProtectPetsOutsideLandClaims", false);
//optional database settings
- this.databaseUrl = config.getString("GriefPrevention.Database.URL", "");
- this.databaseUserName = config.getString("GriefPrevention.Database.UserName", "");
- this.databasePassword = config.getString("GriefPrevention.Database.Password", "");
+ loadDatabaseSettings(config);
this.config_advanced_fixNegativeClaimblockAmounts = config.getBoolean("GriefPrevention.Advanced.fixNegativeClaimblockAmounts", true);
this.config_advanced_claim_expiration_check_rate = config.getInt("GriefPrevention.Advanced.ClaimExpirationCheckRate", 60);
@@ -741,11 +740,9 @@ else if (world.getEnvironment() == Environment.NORMAL)
outConfig.set("GriefPrevention.Claims.InvestigationTool", this.config_claims_investigationTool.name());
outConfig.set("GriefPrevention.Claims.ModificationTool", this.config_claims_modificationTool.name());
outConfig.set("GriefPrevention.Claims.Expiration.ChestClaimDays", this.config_claims_chestClaimExpirationDays);
- outConfig.set("GriefPrevention.Claims.Expiration.UnusedClaimDays", this.config_claims_unusedClaimExpirationDays);
outConfig.set("GriefPrevention.Claims.Expiration.AllClaims.DaysInactive", this.config_claims_expirationDays);
outConfig.set("GriefPrevention.Claims.Expiration.AllClaims.ExceptWhenOwnerHasTotalClaimBlocks", this.config_claims_expirationExemptionTotalBlocks);
outConfig.set("GriefPrevention.Claims.Expiration.AllClaims.ExceptWhenOwnerHasBonusClaimBlocks", this.config_claims_expirationExemptionBonusBlocks);
- outConfig.set("GriefPrevention.Claims.Expiration.AutomaticNatureRestoration.SurvivalWorlds", this.config_claims_survivalAutoNatureRestoration);
outConfig.set("GriefPrevention.Claims.AllowTrappedInAdminClaims", this.config_claims_allowTrappedInAdminClaims);
outConfig.set("GriefPrevention.Claims.MaximumNumberOfClaimsPerPlayer", this.config_claims_maxClaimsPerPlayer);
outConfig.set("GriefPrevention.Claims.VillagerTradingRequiresPermission", this.config_claims_villagerTradingRequiresTrust);
@@ -820,10 +817,6 @@ else if (world.getEnvironment() == Environment.NORMAL)
outConfig.set("GriefPrevention.HardModeZombiesBreakDoors", this.config_zombiesBreakDoors);
outConfig.set("GriefPrevention.MobProjectilesChangeBlocks", this.config_mobProjectilesChangeBlocks);
- outConfig.set("GriefPrevention.Database.URL", this.databaseUrl);
- outConfig.set("GriefPrevention.Database.UserName", this.databaseUserName);
- outConfig.set("GriefPrevention.Database.Password", this.databasePassword);
-
outConfig.set("GriefPrevention.UseBanCommand", this.config_ban_useCommand);
outConfig.set("GriefPrevention.BanCommandPattern", this.config_ban_commandFormat);
@@ -885,6 +878,59 @@ else if (world.getEnvironment() == Environment.NORMAL)
}
}
+ private void loadDatabaseSettings(@NotNull FileConfiguration legacyConfig)
+ {
+ File databasePropsFile = new File(DataStore.dataLayerFolderPath, "database.properties");
+ Properties databaseProps = new Properties();
+
+ // If properties file exists, use it - old config has already been migrated.
+ if (databasePropsFile.exists() && databasePropsFile.isFile())
+ {
+ try (FileReader reader = new FileReader(databasePropsFile, StandardCharsets.UTF_8))
+ {
+ // Load properties from file.
+ databaseProps.load(reader);
+
+ // Set values from loaded properties.
+ databaseUrl = databaseProps.getProperty("jdbcUrl", "");
+ databaseUserName = databaseProps.getProperty("username", "");
+ databasePassword = databaseProps.getProperty("password", "");
+ }
+ catch (IOException e)
+ {
+ getLogger().log(Level.SEVERE, "Unable to read database.properties", e);
+ }
+
+ return;
+ }
+
+ // Otherwise, database details may not have been migrated from legacy configuration.
+ // Try to load them.
+ databaseUrl = legacyConfig.getString("GriefPrevention.Database.URL", "");
+ databaseUserName = legacyConfig.getString("GriefPrevention.Database.UserName", "");
+ databasePassword = legacyConfig.getString("GriefPrevention.Database.Password", "");
+
+ // If not in use already, database settings are "secret" to discourage adoption until datastore is rewritten.
+ if (databaseUrl.isBlank()) {
+ return;
+ }
+
+ // Set properties to loaded values.
+ databaseProps.setProperty("jdbcUrl", databaseUrl);
+ databaseProps.setProperty("username", databaseUserName);
+ databaseProps.setProperty("password", databasePassword);
+
+ // Write properties file for future usage.
+ try (FileWriter writer = new FileWriter(databasePropsFile, StandardCharsets.UTF_8))
+ {
+ databaseProps.store(writer, null);
+ }
+ catch (IOException e)
+ {
+ getLogger().log(Level.SEVERE, "Unable to write database.properties", e);
+ }
+ }
+
private ClaimsMode configStringToClaimsMode(String configSetting)
{
if (configSetting.equalsIgnoreCase("Survival"))
@@ -1140,50 +1186,6 @@ else if (cmd.getName().equalsIgnoreCase("abandonallclaims") && player != null)
return true;
}
- //restore nature
- else if (cmd.getName().equalsIgnoreCase("restorenature") && player != null)
- {
- //change shovel mode
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
- playerData.shovelMode = ShovelMode.RestoreNature;
- GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RestoreNatureActivate);
- return true;
- }
-
- //restore nature aggressive mode
- else if (cmd.getName().equalsIgnoreCase("restorenatureaggressive") && player != null)
- {
- //change shovel mode
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
- playerData.shovelMode = ShovelMode.RestoreNatureAggressive;
- GriefPrevention.sendMessage(player, TextMode.Warn, Messages.RestoreNatureAggressiveActivate);
- return true;
- }
-
- //restore nature fill mode
- else if (cmd.getName().equalsIgnoreCase("restorenaturefill") && player != null)
- {
- //change shovel mode
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
- playerData.shovelMode = ShovelMode.RestoreNatureFill;
-
- //set radius based on arguments
- playerData.fillRadius = 2;
- if (args.length > 0)
- {
- try
- {
- playerData.fillRadius = Integer.parseInt(args[0]);
- }
- catch (Exception exception) { }
- }
-
- if (playerData.fillRadius < 0) playerData.fillRadius = 2;
-
- GriefPrevention.sendMessage(player, TextMode.Success, Messages.FillModeActive, String.valueOf(playerData.fillRadius));
- return true;
- }
-
//trust
else if (cmd.getName().equalsIgnoreCase("trust") && player != null)
{
@@ -1638,15 +1640,8 @@ else if (cmd.getName().equalsIgnoreCase("deleteclaim") && player != null)
}
else
{
- claim.removeSurfaceFluids(null);
this.dataStore.deleteClaim(claim, true, true);
- //if in a creative mode world, /restorenature the claim
- if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
- {
- GriefPrevention.instance.restoreClaim(claim, 0);
- }
-
GriefPrevention.sendMessage(player, TextMode.Success, Messages.DeleteSuccess);
GriefPrevention.AddLogEntry(player.getName() + " deleted " + claim.getOwnerName() + "'s claim at " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
@@ -2160,54 +2155,6 @@ else if (cmd.getName().equalsIgnoreCase("gpreload"))
return true;
}
- //givepet
- else if (cmd.getName().equalsIgnoreCase("givepet") && player != null)
- {
- //requires one parameter
- if (args.length < 1) return false;
-
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
-
- //special case: cancellation
- if (args[0].equalsIgnoreCase("cancel"))
- {
- playerData.petGiveawayRecipient = null;
- GriefPrevention.sendMessage(player, TextMode.Success, Messages.PetTransferCancellation);
- return true;
- }
-
- //find the specified player
- OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]);
- if (targetPlayer == null
- || !targetPlayer.isOnline() && !targetPlayer.hasPlayedBefore()
- || targetPlayer.getName() == null)
- {
- GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
- return true;
- }
-
- //remember the player's ID for later pet transfer
- playerData.petGiveawayRecipient = targetPlayer;
-
- //send instructions
- GriefPrevention.sendMessage(player, TextMode.Instr, Messages.ReadyToTransferPet);
-
- return true;
- }
-
- //gpblockinfo
- else if (cmd.getName().equalsIgnoreCase("gpblockinfo") && player != null)
- {
- ItemStack inHand = player.getInventory().getItemInMainHand();
- player.sendMessage("In Hand: " + inHand.getType().name());
-
- Block inWorld = player.getTargetBlockExact(300, FluidCollisionMode.ALWAYS);
- if (inWorld == null) inWorld = player.getEyeLocation().getBlock();
- player.sendMessage("In World: " + inWorld.getType().name());
-
- return true;
- }
-
//ignoreplayer
else if (cmd.getName().equalsIgnoreCase("ignoreplayer") && player != null)
{
@@ -2414,17 +2361,8 @@ else if (claim.children.size() > 0 && !deleteTopLevelClaim)
else
{
//delete it
- claim.removeSurfaceFluids(null);
this.dataStore.deleteClaim(claim, true, false);
- //if in a creative mode world, restore the claim area
- if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
- {
- GriefPrevention.AddLogEntry(player.getName() + " abandoned a claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()));
- GriefPrevention.sendMessage(player, TextMode.Warn, Messages.UnclaimCleanupWarning);
- GriefPrevention.instance.restoreClaim(claim, 20L * 60 * 2);
- }
-
//adjust claim blocks when abandoning a top level claim
if (this.config_claims_abandonReturnRatio != 1.0D && claim.parent == null && claim.ownerID.equals(playerData.playerID))
{
@@ -2962,173 +2900,72 @@ public boolean creativeRulesApply(@NotNull Location location)
return this.config_claims_worldModes.get(location.getWorld()) == ClaimsMode.Creative;
}
- public String allowBuild(Player player, Location location)
+ /**
+ * @deprecated use {@link ProtectionHelper#checkPermission(Player, Location, ClaimPermission, org.bukkit.event.Event)}
+ */
+ @Deprecated(forRemoval = true, since = "17.0.0")
+ public @Nullable String allowBuild(Player player, Location location)
{
- // TODO check all derivatives and rework API
return this.allowBuild(player, location, location.getBlock().getType());
}
- public String allowBuild(Player player, Location location, Material material)
+ /**
+ * @deprecated use {@link ProtectionHelper#checkPermission(Player, Location, ClaimPermission, org.bukkit.event.Event)}
+ */
+ @Deprecated(forRemoval = true, since = "17.0.0")
+ public @Nullable String allowBuild(Player player, Location location, Material material)
{
if (!GriefPrevention.instance.claimsEnabledForWorld(location.getWorld())) return null;
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
- Claim claim = this.dataStore.getClaimAt(location, false, playerData.lastClaim);
-
- //exception: administrators in ignore claims mode
- if (playerData.ignoreClaims) return null;
-
- //wilderness rules
- if (claim == null)
+ ItemStack placed;
+ if (material.isItem())
{
- //no building in the wilderness in creative mode
- if (this.creativeRulesApply(location) || this.config_claims_worldModes.get(location.getWorld()) == ClaimsMode.SurvivalRequiringClaims)
+ placed = new ItemStack(material);
+ }
+ else
+ {
+ var blockType = material.asBlockType();
+ if (blockType != null && blockType.hasItemType())
{
- //exception: when chest claims are enabled, players who have zero land claims and are placing a chest
- if (material != Material.CHEST || playerData.getClaims().size() > 0 || GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius == -1)
- {
- String reason = this.dataStore.getMessage(Messages.NoBuildOutsideClaims);
- if (player.hasPermission("griefprevention.ignoreclaims"))
- reason += " " + this.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
- reason += " " + this.dataStore.getMessage(Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL);
- return reason;
- }
- else
- {
- return null;
- }
+ placed = blockType.getItemType().createItemStack();
}
-
- //but it's fine in survival mode
else
{
- return null;
+ placed = new ItemStack(Material.DIRT);
}
}
- //if not in the wilderness, then apply claim rules (permissions, etc)
- else
- {
- //cache the claim for later reference
- playerData.lastClaim = claim;
- Block block = location.getBlock();
-
- Supplier supplier = claim.checkPermission(player, ClaimPermission.Build, new BlockPlaceEvent(block, block.getState(), block, new ItemStack(material), player, true, EquipmentSlot.HAND));
-
- if (supplier == null) return null;
-
- return supplier.get();
- }
+ Block block = location.getBlock();
+ Supplier result = ProtectionHelper.checkPermission(player, location, ClaimPermission.Build, new BlockPlaceEvent(block, block.getState(), block, placed, player, true, EquipmentSlot.HAND));
+ return result == null ? null : result.get();
}
- public String allowBreak(Player player, Block block, Location location)
+ /**
+ * @deprecated use {@link ProtectionHelper#checkPermission(Player, Location, ClaimPermission, org.bukkit.event.Event)}
+ */
+ @Deprecated(forRemoval = true, since = "17.0.0")
+ public @Nullable String allowBreak(Player player, Block block, Location location)
{
return this.allowBreak(player, block, location, new BlockBreakEvent(block, player));
}
- public String allowBreak(Player player, Material material, Location location, BlockBreakEvent breakEvent)
+ /**
+ * @deprecated use {@link ProtectionHelper#checkPermission(Player, Location, ClaimPermission, org.bukkit.event.Event)}
+ */
+ @Deprecated(forRemoval = true, since = "17.0.0")
+ public @Nullable String allowBreak(Player player, Material material, Location location, BlockBreakEvent breakEvent)
{
return this.allowBreak(player, location.getBlock(), location, breakEvent);
}
- public String allowBreak(Player player, Block block, Location location, BlockBreakEvent breakEvent)
+ /**
+ * @deprecated use {@link ProtectionHelper#checkPermission(Player, Location, ClaimPermission, org.bukkit.event.Event)}
+ */
+ @Deprecated(forRemoval = true, since = "17.0.0")
+ public @Nullable String allowBreak(Player player, Block block, Location location, BlockBreakEvent breakEvent)
{
- if (!GriefPrevention.instance.claimsEnabledForWorld(location.getWorld())) return null;
-
- PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
- Claim claim = this.dataStore.getClaimAt(location, false, playerData.lastClaim);
-
- //exception: administrators in ignore claims mode
- if (playerData.ignoreClaims) return null;
-
- //wilderness rules
- if (claim == null)
- {
- //no building in the wilderness in creative mode
- if (this.creativeRulesApply(location) || this.config_claims_worldModes.get(location.getWorld()) == ClaimsMode.SurvivalRequiringClaims)
- {
- String reason = this.dataStore.getMessage(Messages.NoBuildOutsideClaims);
- if (player.hasPermission("griefprevention.ignoreclaims"))
- reason += " " + this.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
- reason += " " + this.dataStore.getMessage(Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL);
- return reason;
- }
-
- //but it's fine in survival mode
- else
- {
- return null;
- }
- }
- else
- {
- //cache the claim for later reference
- playerData.lastClaim = claim;
-
- //if not in the wilderness, then apply claim rules (permissions, etc)
- Supplier cancel = claim.checkPermission(player, ClaimPermission.Build, breakEvent);
- if (cancel != null && breakEvent != null)
- {
- PreventBlockBreakEvent preventionEvent = new PreventBlockBreakEvent(breakEvent);
- Bukkit.getPluginManager().callEvent(preventionEvent);
- if (preventionEvent.isCancelled())
- {
- cancel = null;
- }
- }
-
- if (cancel == null) return null;
-
- return cancel.get();
- }
- }
-
- //restores nature in multiple chunks, as described by a claim instance
- //this restores all chunks which have ANY number of claim blocks from this claim in them
- //if the claim is still active (in the data store), then the claimed blocks will not be changed (only the area bordering the claim)
- public void restoreClaim(Claim claim, long delayInTicks)
- {
- //admin claims aren't automatically cleaned up when deleted or abandoned
- if (claim.isAdminClaim()) return;
-
- //it's too expensive to do this for huge claims
- if (claim.getArea() > 10000 || claim.getWidth() > 250 || claim.getHeight() > 250) return;
-
- ArrayList chunks = claim.getChunks();
- for (Chunk chunk : chunks)
- {
- this.restoreChunk(chunk, this.getSeaLevel(chunk.getWorld()) - 15, false, delayInTicks, null);
- }
- }
-
-
- public void restoreChunk(Chunk chunk, int miny, boolean aggressiveMode, long delayInTicks, Player playerReceivingVisualization)
- {
- //build a snapshot of this chunk, including 1 block boundary outside of the chunk all the way around
- int maxHeight = chunk.getWorld().getMaxHeight();
- BlockSnapshot[][][] snapshots = new BlockSnapshot[18][maxHeight][18];
- Block startBlock = chunk.getBlock(0, 0, 0);
- Location startLocation = new Location(chunk.getWorld(), startBlock.getX() - 1, 0, startBlock.getZ() - 1);
- for (int x = 0; x < snapshots.length; x++)
- {
- for (int z = 0; z < snapshots[0][0].length; z++)
- {
- for (int y = 0; y < snapshots[0].length; y++)
- {
- Block block = chunk.getWorld().getBlockAt(startLocation.getBlockX() + x, startLocation.getBlockY() + y, startLocation.getBlockZ() + z);
- snapshots[x][y][z] = new BlockSnapshot(block.getLocation(), block.getType(), block.getBlockData());
- }
- }
- }
-
- //create task to process those data in another thread
- Location lesserBoundaryCorner = chunk.getBlock(0, 0, 0).getLocation();
- Location greaterBoundaryCorner = chunk.getBlock(15, 0, 15).getLocation();
-
- //create task
- //when done processing, this task will create a main thread task to actually update the world with processing results
- RestoreNatureProcessingTask task = new RestoreNatureProcessingTask(snapshots, miny, chunk.getWorld().getEnvironment(), lesserBoundaryCorner.getBlock().getBiome(), lesserBoundaryCorner, greaterBoundaryCorner, this.getSeaLevel(chunk.getWorld()), aggressiveMode, GriefPrevention.instance.creativeRulesApply(lesserBoundaryCorner), playerReceivingVisualization);
- scheduler.getImpl().runAtLocationLater(lesserBoundaryCorner, task, delayInTicks * 50L, TimeUnit.MILLISECONDS);
+ Supplier result = ProtectionHelper.checkPermission(player, location, ClaimPermission.Build, breakEvent);
+ return result == null ? null : result.get();
}
private Set parseMaterialListFromConfig(List stringsToParse)
@@ -3234,8 +3071,8 @@ static void banPlayer(Player player, String reason, String source)
}
else
{
- BanList> bans = Bukkit.getServer().getBanList(Type.NAME);
- bans.addBan(player.getName(), reason, (Date) null, source);
+ BanList bans = Bukkit.getServer().getBanList(Type.PROFILE);
+ bans.addBan(player.getPlayerProfile(), reason, (Date) null, source);
//kick
if (player.isOnline())
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/Messages.java b/src/main/java/me/ryanhamshire/GriefPrevention/Messages.java
index df9e6cba..af95e7aa 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/Messages.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/Messages.java
@@ -18,206 +18,214 @@
package me.ryanhamshire.GriefPrevention;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
public enum Messages
{
- RespectingClaims,
- IgnoringClaims,
- SuccessfulAbandon,
- RestoreNatureActivate,
- RestoreNatureAggressiveActivate,
- FillModeActive,
- TransferClaimPermission,
- TransferClaimMissing,
- TransferClaimAdminOnly,
- PlayerNotFound2,
- TransferTopLevel,
- TransferSuccess,
- TrustListNoClaim,
- ClearPermsOwnerOnly,
- UntrustIndividualAllClaims,
- UntrustEveryoneAllClaims,
- NoPermissionTrust,
- ClearPermissionsOneClaim,
- UntrustIndividualSingleClaim,
- AdminClaimsMode,
- BasicClaimsMode,
- SubdivisionMode,
- SubdivisionVideo2,
- DeleteClaimMissing,
- DeletionSubdivisionWarning,
- DeleteSuccess,
- CantDeleteAdminClaim,
- DeleteAllSuccess,
- NoDeletePermission,
- AllAdminDeleted,
- AdjustBlocksSuccess,
- NotTrappedHere,
- RescuePending,
- AbandonClaimMissing,
- NotYourClaim,
- DeleteTopLevelClaim,
- AbandonSuccess,
- ConfirmAbandonAllClaims,
- CantGrantThatPermission,
- GrantPermissionNoClaim,
- GrantPermissionConfirmation,
- ManageUniversalPermissionsInstruction,
- ManageOneClaimPermissionsInstruction,
- CollectivePublic,
- BuildPermission,
- ContainersPermission,
- AccessPermission,
- PermissionsPermission,
- LocationCurrentClaim,
- LocationAllClaims,
- PvPImmunityStart,
- DonateItemsInstruction,
- ChestFull,
- DonationSuccess,
- PlayerTooCloseForFire2,
- TooDeepToClaim,
- ChestClaimConfirmation,
- AutomaticClaimNotification,
- AutomaticClaimOtherClaimTooClose,
- UnprotectedChestWarning,
- ThatPlayerPvPImmune,
- CantFightWhileImmune,
- NoDamageClaimedEntity,
- ShovelBasicClaimMode,
- RemainingBlocks,
- CreativeBasicsVideo2,
- SurvivalBasicsVideo2,
- TrappedChatKeyword,
- TrappedInstructions,
- PvPNoDrop,
- PvPNoContainers,
- PvPImmunityEnd,
- NoBedPermission,
- NoWildernessBuckets,
- NoLavaNearOtherPlayer,
- TooFarAway,
- BlockNotClaimed,
- BlockClaimed,
- RestoreNaturePlayerInChunk,
- NoCreateClaimPermission,
- ResizeNeedMoreBlocks,
- NoCreativeUnClaim,
- ClaimResizeSuccess,
- ResizeFailOverlap,
- ResizeStart,
- ResizeFailOverlapSubdivision,
- SubdivisionStart,
- CreateSubdivisionOverlap,
- SubdivisionSuccess,
- CreateClaimFailOverlap,
- CreateClaimFailOverlapOtherPlayer,
- ClaimsDisabledWorld,
- ClaimStart,
- NewClaimTooNarrow,
- CreateClaimInsufficientBlocks,
- AbandonClaimAdvertisement,
- CreateClaimFailOverlapShort,
- CreateClaimSuccess,
- RescueAbortedMoved,
- OnlyOwnersModifyClaims,
- NoBuildPvP,
- NoBuildPermission,
- NoAccessPermission,
- NoContainersPermission,
- OwnerNameForAdminClaims,
- UnknownPlayerName,
- ClaimTooSmallForEntities,
- TooManyEntitiesInClaim,
- YouHaveNoClaims,
- ConfirmFluidRemoval,
- AutoBanNotify,
- AdjustGroupBlocksSuccess,
- InvalidPermissionID,
- HowToClaimRegex,
- NoBuildOutsideClaims,
- PlayerOfflineTime,
- BuildingOutsideClaims,
- TrappedWontWorkHere,
- CommandBannedInPvP,
- UnclaimCleanupWarning,
- NoTeleportPvPCombat,
- NoTNTDamageAboveSeaLevel,
- NoTNTDamageClaims,
- IgnoreClaimsAdvertisement,
- NoPermissionForCommand,
- ClaimsListNoPermission,
- ExplosivesDisabled,
- ExplosivesEnabled,
- ClaimExplosivesAdvertisement,
- PlayerInPvPSafeZone,
- NoPistonsOutsideClaims,
- SoftMuted,
- UnSoftMuted,
- DropUnlockAdvertisement,
- PickupBlockedExplanation,
- DropUnlockConfirmation,
- DropUnlockOthersConfirmation,
- AdvertiseACandACB,
- AdvertiseAdminClaims,
- AdvertiseACB,
- NotYourPet,
- PetGiveawayConfirmation,
- PetTransferCancellation,
- ReadyToTransferPet,
- AvoidGriefClaimLand,
- BecomeMayor,
- ClaimCreationFailedOverClaimCountLimit,
- CreateClaimFailOverlapRegion,
- ResizeFailOverlapRegion,
- ShowNearbyClaims,
- NoChatUntilMove,
- SetClaimBlocksSuccess,
- IgnoreConfirmation,
- NotIgnoringPlayer,
- UnIgnoreConfirmation,
- SeparateConfirmation,
- UnSeparateConfirmation,
- NotIgnoringAnyone,
- TrustListHeader,
- Manage,
- Build,
- Containers,
- Access,
- HasSubclaimRestriction,
- StartBlockMath,
- ClaimsListHeader,
- ContinueBlockMath,
- EndBlockMath,
- NoClaimDuringPvP,
- UntrustAllOwnerOnly,
- ManagersDontUntrustManagers,
- BookAuthor,
- BookTitle,
- BookIntro,
- BookDisabledChestClaims,
- BookUsefulCommands,
- BookLink,
- BookTools,
- ResizeClaimTooNarrow,
- ResizeClaimInsufficientArea,
- NoProfanity,
- PlayerNotIgnorable,
- NoEnoughBlocksForChestClaim,
- IsIgnoringYou,
- MustHoldModificationToolForThat,
- StandInClaimToResize,
- ClaimsExtendToSky,
- ClaimsAutoExtendDownward,
- MinimumRadius,
- RadiusRequiresGoldenShovel,
- ClaimTooSmallForActiveBlocks,
- TooManyActiveBlocksInClaim,
- ConsoleOnlyCommand,
- WorldNotFound,
- AdjustBlocksAllSuccess,
- TooMuchIpOverlap,
- StandInSubclaim,
- SubclaimRestricted,
- SubclaimUnrestricted,
- NetherPortalTrapDetectionMessage
+ RespectingClaims("Now respecting claims."),
+ IgnoringClaims("Now ignoring claims."),
+ NoCreativeUnClaim("You can't unclaim this land. You can only make this claim larger or create additional claims."),
+ SuccessfulAbandon("Claims abandoned. You now have {0} available claim blocks.", "0: remaining blocks"),
+ TransferClaimPermission("That command requires the administrative claims permission."),
+ TransferClaimMissing("There's no claim here. Stand in the administrative claim you want to transfer."),
+ TransferClaimAdminOnly("Only administrative claims may be transferred to a player."),
+ PlayerNotFound2("No player by that name has logged in recently."),
+ TransferTopLevel("Only top level claims (not subdivisions) may be transferred. Stand outside of the subdivision and try again."),
+ TransferSuccess("Claim transferred."),
+ TrustListNoClaim("Stand inside the claim you're curious about."),
+ ClearPermsOwnerOnly("Only the claim owner can clear all permissions."),
+ UntrustIndividualAllClaims("Revoked {0}'s access to ALL your claims. To set permissions for a single claim, stand inside it.", "0: untrusted player"),
+ UntrustEveryoneAllClaims("Cleared permissions in ALL your claims. To set permissions for a single claim, stand inside it."),
+ NoPermissionTrust("You don't have {0}'s permission to manage permissions here.", "0: claim owner's name"),
+ ClearPermissionsOneClaim("Cleared permissions in this claim. To set permission for ALL your claims, stand outside them."),
+ UntrustIndividualSingleClaim("Revoked {0}'s access to this claim. To set permissions for a ALL your claims, stand outside them.", "0: untrusted player"),
+ AdminClaimsMode("Administrative claims mode active. Any claims created will be free and editable by other administrators."),
+ BasicClaimsMode("Returned to basic claim creation mode."),
+ SubdivisionMode("Subdivision mode. Use your shovel to create subdivisions in your existing claims. Use /basicclaims to exit."),
+ SubdivisionVideo2("Click for Subdivision Help: {0}", "0:video URL"),
+ DeleteClaimMissing("There's no claim here."),
+ DeletionSubdivisionWarning("This claim includes subdivisions. If you're sure you want to delete it, use /deleteclaim again."),
+ DeleteSuccess("Claim deleted."),
+ CantDeleteAdminClaim("You don't have permission to delete administrative claims."),
+ DeleteAllSuccess("Deleted all of {0}'s claims.", "0: owner's name"),
+ NoDeletePermission("You don't have permission to delete claims."),
+ AllAdminDeleted("Deleted all administrative claims."),
+ AdjustBlocksSuccess("Adjusted {0}'s bonus claim blocks by {1}. New total bonus blocks: {2}.", "0: player; 1: adjustment; 2: new total"),
+ AdjustBlocksAllSuccess("Adjusted all online players' bonus claim blocks by {0}.", "0: adjustment amount"),
+ NotTrappedHere("You can build here. Save yourself."),
+ RescuePending("If you stay put for 10 seconds, you'll be teleported out. Please wait."),
+ AbandonClaimMissing("Stand in the claim you want to delete, or consider /abandonallclaims."),
+ NotYourClaim("This isn't your claim."),
+ DeleteTopLevelClaim("To delete a subdivision, stand inside it. Otherwise, use /abandontoplevelclaim to delete this claim and all subdivisions."),
+ AbandonSuccess("Claim abandoned. You now have {0} available claim blocks.", "0: remaining claim blocks"),
+ ConfirmAbandonAllClaims("Are you sure you want to abandon ALL of your claims? Please confirm with /abandonallclaims confirm"),
+ CantGrantThatPermission("You can't grant a permission you don't have yourself."),
+ GrantPermissionNoClaim("Stand inside the claim where you want to grant permission."),
+ GrantPermissionConfirmation("Granted {0} permission to {1} {2}.", "0: target player; 1: permission description; 2: scope (changed claims)"),
+ ManageUniversalPermissionsInstruction("To manage permissions for ALL your claims, stand outside them."),
+ ManageOneClaimPermissionsInstruction("To manage permissions for a specific claim, stand inside it."),
+ CollectivePublic("the public", "as in 'granted the public permission to...'"),
+ BuildPermission("build"),
+ ContainersPermission("access containers and animals"),
+ AccessPermission("use buttons and levers"),
+ PermissionsPermission("manage permissions"),
+ LocationCurrentClaim("in this claim"),
+ LocationAllClaims("in all your claims"),
+ PvPImmunityStart("You're protected from attack by other players as long as your inventory is empty."),
+ DonateItemsInstruction("To give away the item(s) in your hand, left-click the chest again."),
+ ChestFull("This chest is full."),
+ DonationSuccess("Item(s) transferred to chest!"),
+ PlayerTooCloseForFire2("You can't start a fire this close to another player."),
+ TooDeepToClaim("This chest can't be protected because it's too deep underground. Consider moving it."),
+ ChestClaimConfirmation("This chest is protected."),
+ AutomaticClaimNotification("This chest and nearby blocks are protected from breakage and theft."),
+ AutomaticClaimOtherClaimTooClose("Cannot create a claim for your chest, there is another claim too close!"),
+ UnprotectedChestWarning("This chest is NOT protected. Consider using a golden shovel to expand an existing claim or to create a new one."),
+ ThatPlayerPvPImmune("You can't injure defenseless players."),
+ CantFightWhileImmune("You can't fight someone while you're protected from PvP."),
+ NoDamageClaimedEntity("That belongs to {0}.", "0: owner name"),
+ ShovelBasicClaimMode("Shovel returned to basic claims mode."),
+ RemainingBlocks("You may claim up to {0} more blocks.", "0: remaining blocks"),
+ CreativeBasicsVideo2("Click for Land Claim Help: {0}", "{0}: video URL"),
+ SurvivalBasicsVideo2("Click for Land Claim Help: {0}", "{0}: video URL"),
+ TrappedChatKeyword("trapped;stuck", "When mentioned in chat, players get information about the /trapped command (multiple words can be separated with semi-colons)"),
+ TrappedInstructions("Are you trapped in someone's land claim? Try the /trapped command."),
+ PvPNoDrop("You can't drop items while in PvP combat."),
+ PvPNoContainers("You can't access containers during PvP combat."),
+ PvPImmunityEnd("Now you can fight with other players."),
+ NoBedPermission("{0} hasn't given you permission to sleep here.", "0: claim owner"),
+ NoWildernessBuckets("You may only dump buckets inside your claim(s) or underground."),
+ NoLavaNearOtherPlayer("You can't place lava this close to {0}.", "0: nearby player"),
+ TooFarAway("That's too far away."),
+ BlockNotClaimed("No one has claimed this block."),
+ BlockClaimed("That block has been claimed by {0}.", "0: claim owner"),
+ NoCreateClaimPermission("You don't have permission to claim land."),
+ ResizeClaimTooNarrow("This new size would be too small. Claims must be at least {0} blocks wide.", "0: minimum claim width"),
+ ResizeNeedMoreBlocks("You don't have enough blocks for this size. You need {0} more.", "0: how many needed"),
+ ClaimResizeSuccess("Claim resized. {0} available claim blocks remaining.", "0: remaining blocks"),
+ ResizeFailOverlap("Can't resize here because it would overlap another nearby claim."),
+ ResizeStart("Resizing claim. Use your shovel again at the new location for this corner."),
+ ResizeFailOverlapSubdivision("You can't create a subdivision here because it would overlap another subdivision. Consider /abandonclaim to delete it, or use your shovel at a corner to resize it."),
+ SubdivisionStart("Subdivision corner set! Use your shovel at the location for the opposite corner of this new subdivision."),
+ CreateSubdivisionOverlap("Your selected area overlaps another subdivision."),
+ SubdivisionSuccess("Subdivision created! Use /trust to share it with friends."),
+ CreateClaimFailOverlap("You can't create a claim here because it would overlap your other claim. Use /abandonclaim to delete it, or use your shovel at a corner to resize it."),
+ CreateClaimFailOverlapOtherPlayer("You can't create a claim here because it would overlap {0}'s claim.", "0: other claim owner"),
+ ClaimsDisabledWorld("Land claims are disabled in this world."),
+ ClaimStart("Claim corner set! Use the shovel again at the opposite corner to claim a rectangle of land. To cancel, put your shovel away."),
+ NewClaimTooNarrow("This claim would be too small. Any claim must be at least {0} blocks wide.", "0: minimum claim width"),
+ ResizeClaimInsufficientArea("This claim would be too small. Any claim must use at least {0} total claim blocks.", "0: minimum claim area"),
+ CreateClaimInsufficientBlocks("You don't have enough blocks to claim that entire area. You need {0} more blocks.", "0: additional blocks needed"),
+ AbandonClaimAdvertisement("To delete another claim and free up some blocks, use /abandonclaim."),
+ CreateClaimFailOverlapShort("Your selected area overlaps an existing claim."),
+ CreateClaimSuccess("Claim created! Use /trust to share it with friends."),
+ RescueAbortedMoved("You moved! Rescue cancelled."),
+ OnlyOwnersModifyClaims("Only {0} can modify this claim.", "0: owner name"),
+ NoBuildPvP("You can't build in claims during PvP combat."),
+ NoBuildPermission("You don't have {0}'s permission to build here.", "0: owner name"),
+ NoAccessPermission("You don't have {0}'s permission to use that.", "0: owner name. access permission controls buttons, levers, and beds"),
+ NoContainersPermission("You don't have {0}'s permission to use that.", "0: owner's name. containers also include crafting blocks"),
+ OwnerNameForAdminClaims("an administrator", "as in 'You don't have an administrator's permission to build here.'"),
+ UnknownPlayerName("someone", "Name used for unknown players. UUID will be appended if available: \"someone (01234567-0123-0123-0123-0123456789ab)\""),
+ ClaimTooSmallForEntities("This claim isn't big enough for that. Try enlarging it."),
+ TooManyEntitiesInClaim("This claim has too many entities already. Try enlarging the claim or removing some animals, monsters, paintings, or minecarts."),
+ YouHaveNoClaims("You don't have any land claims."),
+ AutoBanNotify("Auto-banned {0}({1}). See logs for details."),
+ AdjustGroupBlocksSuccess("Adjusted bonus claim blocks for players with the {0} permission by {1}. New total: {2}.", "0: permission; 1: adjustment amount; 2: new total bonus"),
+ InvalidPermissionID("Please specify a player name, or a permission in [brackets]."),
+ HowToClaimRegex("(^|.*\\W)how\\W.*\\W(claim|protect|lock)(\\W.*|$)", "This is a Java Regular Expression. Look it up before editing! It's used to tell players about the demo video when they ask how to claim land."),
+ NoBuildOutsideClaims("You can't build here unless you claim some land first."),
+ PlayerOfflineTime(" Last login: {0} days ago.", "0: number of full days since last login"),
+ BuildingOutsideClaims("Other players can build here, too. Consider creating a land claim to protect your work!"),
+ TrappedWontWorkHere("Sorry, unable to find a safe location to teleport you to. Contact an admin."),
+ CommandBannedInPvP("You can't use that command while in PvP combat."),
+ NoTeleportPvPCombat("You can't teleport while fighting another player."),
+ NoTNTDamageAboveSeaLevel("Warning: TNT will not destroy blocks above sea level."),
+ NoTNTDamageClaims("Warning: TNT will not destroy claimed blocks."),
+ IgnoreClaimsAdvertisement("To override, use /ignoreclaims."),
+ NoPermissionForCommand("You don't have permission to do that."),
+ ClaimsListNoPermission("You don't have permission to get information about another player's land claims."),
+ ExplosivesDisabled("This claim is now protected from explosions. Use /claimexplosions again to disable."),
+ ExplosivesEnabled("This claim is now vulnerable to explosions. Use /claimexplosions again to re-enable protections."),
+ ClaimExplosivesAdvertisement("To allow explosives to destroy blocks in this land claim, use /claimexplosions."),
+ PlayerInPvPSafeZone("That player is in a PvP safe zone."),
+ NoPistonsOutsideClaims("Warning: Pistons won't move blocks outside land claims."),
+ SoftMuted("Soft-muted {0}.", "0: The changed player's name."),
+ UnSoftMuted("Un-soft-muted {0}.", "0: The changed player's name."),
+ DropUnlockAdvertisement("Other players can't pick up your dropped items unless you /unlockdrops first."),
+ PickupBlockedExplanation("You can't pick this up unless {0} uses /unlockdrops.", "0: The item stack's owner."),
+ DropUnlockConfirmation("Unlocked your drops. Other players may now pick them up (until you die again)."),
+ DropUnlockOthersConfirmation("Unlocked {0}'s drops.", "0: The owner of the unlocked drops."),
+ AdvertiseACandACB("You may use /acb to give yourself more claim blocks, or /adminclaims to create a free administrative claim."),
+ AdvertiseAdminClaims("You could create an administrative land claim instead using /adminclaims, which you'd share with other administrators."),
+ AdvertiseACB("You may use /acb to give yourself more claim blocks."),
+ NotYourPet("That belongs to {0}.", "0: owner name"),
+ AvoidGriefClaimLand("Prevent grief! If you claim your land, you will be grief-proof."),
+ BecomeMayor("Subdivide your land claim and become a mayor!"),
+ ClaimCreationFailedOverClaimCountLimit("You've reached your limit on land claims. Use /abandonclaim to remove one before creating another."),
+ CreateClaimFailOverlapRegion("You can't claim all of this because you're not allowed to build here."),
+ ResizeFailOverlapRegion("You don't have permission to build there, so you can't claim that area."),
+ ShowNearbyClaims("Found {0} land claims.", "0: Number of claims found."),
+ NoChatUntilMove("Sorry, but you have to move a little more before you can chat. We get lots of spam bots here. :)"),
+ SetClaimBlocksSuccess("Updated accrued claim blocks."),
+ IgnoreConfirmation("You're now ignoring chat messages from that player."),
+ UnIgnoreConfirmation("You're no longer ignoring chat messages from that player."),
+ NotIgnoringPlayer("You're not ignoring that player."),
+ SeparateConfirmation("Those players will now ignore each other in chat."),
+ UnSeparateConfirmation("Those players will no longer ignore each other in chat."),
+ NotIgnoringAnyone("You're not ignoring anyone."),
+ TrustListHeader("Explicit permissions here:", "0: The claim's owner"),
+ Manage("Manage"),
+ Build("Build"),
+ Containers("Containers"),
+ Access("Access"),
+ HasSubclaimRestriction("This subclaim does not inherit permissions from the parent"),
+ StartBlockMath("{0} blocks from play + {1} bonus = {2} total."),
+ ClaimsListHeader("Claims:"),
+ ContinueBlockMath(" (-{0} blocks)"),
+ EndBlockMath(" = {0} blocks left to spend"),
+ NoClaimDuringPvP("You can't claim lands during PvP combat."),
+ UntrustAllOwnerOnly("Only the claim owner can clear all its permissions."),
+ ManagersDontUntrustManagers("Only the claim owner can demote a manager."),
+ PlayerNotIgnorable("You can't ignore that player."),
+ NoEnoughBlocksForChestClaim("Because you don't have any claim blocks available, no automatic land claim was created for you. You can use /claimslist to monitor your available claim block total."),
+ MustHoldModificationToolForThat("You must be holding a golden shovel to do that."),
+ StandInClaimToResize("Stand inside the land claim you want to resize."),
+ ClaimsExtendToSky("Land claims always extend to max build height."),
+ ClaimsAutoExtendDownward("Land claims auto-extend deeper into the ground when you place blocks under them."),
+ MinimumRadius("Minimum radius is {0}.", "0: minimum radius"),
+ RadiusRequiresGoldenShovel("You must be holding a golden shovel when specifying a radius."),
+ ClaimTooSmallForActiveBlocks("This claim isn't big enough to support any active block types (hoppers, spawners, beacons...). Make the claim bigger first."),
+ TooManyActiveBlocksInClaim("This claim is at its limit for active block types (hoppers, spawners, beacons...). Either make it bigger, or remove other active blocks first."),
+ BookAuthor("BigScary"),
+ BookTitle("How to Claim Land"),
+ BookLink("Click: {0}", "{0}: video URL"),
+ BookIntro("Claim land to protect your stuff! Click the link above to learn land claims in 3 minutes or less. :)"),
+ BookTools("Our claim tools are {0} and {1}.", "0: claim modification tool name; 1:claim information tool name"),
+ BookDisabledChestClaims(" On this server, placing a chest will NOT claim land for you."),
+ BookUsefulCommands("Useful Commands:"),
+ NoProfanity("Please moderate your language."),
+ IsIgnoringYou("That player is ignoring you."),
+ ConsoleOnlyCommand("That command may only be executed from the server console."),
+ WorldNotFound("World not found."),
+ TooMuchIpOverlap("Sorry, there are too many players logged in with your IP address."),
+ StandInSubclaim("You need to be standing in a subclaim to restrict it"),
+ SubclaimRestricted("This subclaim's permissions will no longer inherit from the parent claim"),
+ SubclaimUnrestricted("This subclaim's permissions will now inherit from the parent claim"),
+ NetherPortalTrapDetectionMessage("It seems you might be stuck inside a nether portal. We will rescue you in a few seconds if that is the case!", "Sent to player on join, if they left while inside a nether portal.");
+
+ final @NotNull String defaultValue;
+ final @Nullable String notes;
+
+ Messages(@NotNull String defaultValue, @NotNull String notes) {
+ this.defaultValue = defaultValue;
+ this.notes = notes;
+ }
+
+ Messages(@NotNull String defaultValue) {
+ this.defaultValue = defaultValue;
+ this.notes = null;
+ }
+
}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerData.java b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerData.java
index 56313032..6072f7d0 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerData.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerData.java
@@ -54,9 +54,6 @@ public class PlayerData
//what "mode" the shovel is in determines what it will do when it's used
public ShovelMode shovelMode = ShovelMode.Basic;
- //radius for restore nature fill mode
- int fillRadius = 0;
-
//last place the player used the shovel, useful in creating and resizing claims,
//because the player must use the shovel twice in those instances
public Location lastShovelLocation = null;
@@ -114,9 +111,6 @@ public class PlayerData
//message to send to player after he respawns
String messageOnRespawn = null;
- //player which a pet will be given to when it's right-clicked
- OfflinePlayer petGiveawayRecipient = null;
-
//timestamp for last "you're building outside your land claims" message
Long buildWarningTimestamp = null;
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java
index c4479eab..b1cc97b1 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java
@@ -18,6 +18,7 @@
package me.ryanhamshire.GriefPrevention;
+import com.griefprevention.protection.ProtectionHelper;
import com.griefprevention.util.command.MonitorableCommand;
import com.griefprevention.util.command.MonitoredCommands;
import com.griefprevention.visualization.BoundaryVisualization;
@@ -28,7 +29,6 @@
import org.bukkit.BanList;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
-import org.bukkit.Chunk;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -39,7 +39,6 @@
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
-import org.bukkit.block.data.Levelled;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Animals;
@@ -89,6 +88,7 @@
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.profile.PlayerProfile;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.BlockIterator;
@@ -690,7 +690,8 @@ else if (address.equals(playerData.ipAddress.toString()))
if (info2.address.toString().equals(address))
{
OfflinePlayer bannedAccount = instance.getServer().getOfflinePlayer(info2.bannedAccountName);
- instance.getServer().getBanList(BanList.Type.NAME).pardon(bannedAccount.getName());
+ BanList banList = instance.getServer().getBanList(BanList.Type.PROFILE);
+ banList.pardon(bannedAccount.getPlayerProfile());
this.tempBannedIps.remove(j--);
}
}
@@ -1082,9 +1083,8 @@ public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
//if entity is tameable and has an owner, apply special rules
- if (entity instanceof Tameable)
+ if (entity instanceof Tameable tameable)
{
- Tameable tameable = (Tameable) entity;
if (tameable.isTamed())
{
if (tameable.getOwner() != null)
@@ -1094,15 +1094,6 @@ public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
//if the player interacting is the owner or an admin in ignore claims mode, always allow
if (player.getUniqueId().equals(ownerID) || playerData.ignoreClaims)
{
- //if giving away pet, do that instead
- if (playerData.petGiveawayRecipient != null)
- {
- tameable.setOwner(playerData.petGiveawayRecipient);
- playerData.petGiveawayRecipient = null;
- GriefPrevention.sendMessage(player, TextMode.Success, Messages.PetGiveawayConfirmation);
- event.setCancelled(true);
- }
-
return;
}
if (!instance.pvpRulesApply(entity.getLocation().getWorld()) || instance.config_pvp_protectPets)
@@ -1135,10 +1126,10 @@ public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
//don't allow interaction with item frames or armor stands in claimed areas without build permission
if (entity.getType() == EntityType.ARMOR_STAND || entity instanceof Hanging)
{
- String noBuildReason = instance.allowBuild(player, entity.getLocation(), Material.ITEM_FRAME);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, entity.getLocation(), ClaimPermission.Build, event);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
event.setCancelled(true);
return;
}
@@ -1366,10 +1357,10 @@ public void onPlayerBucketEmpty(PlayerBucketEmptyEvent bucketEvent)
}
//make sure the player is allowed to build at the location
- String noBuildReason = instance.allowBuild(player, block.getLocation(), Material.WATER);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, bucketEvent);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
bucketEvent.setCancelled(true);
return;
}
@@ -1465,22 +1456,22 @@ public void onPlayerBucketFill(PlayerBucketFillEvent bucketEvent)
if (!instance.claimsEnabledForWorld(block.getWorld())) return;
- //make sure the player is allowed to build at the location
- String noBuildReason = instance.allowBuild(player, block.getLocation(), Material.AIR);
- if (noBuildReason != null)
+ //exemption for cow milking (permissions will be handled by player interact with entity event instead)
+ Material blockType = block.getType();
+ if (blockType == Material.AIR)
+ return;
+ if (blockType.isSolid())
{
- //exemption for cow milking (permissions will be handled by player interact with entity event instead)
- Material blockType = block.getType();
- if (blockType == Material.AIR)
+ BlockData blockData = block.getBlockData();
+ if (!(blockData instanceof Waterlogged) || !((Waterlogged) blockData).isWaterlogged())
return;
- if (blockType.isSolid())
- {
- BlockData blockData = block.getBlockData();
- if (!(blockData instanceof Waterlogged) || !((Waterlogged) blockData).isWaterlogged())
- return;
- }
+ }
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ //make sure the player is allowed to build at the location
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, block.getLocation(), ClaimPermission.Build, bucketEvent);
+ if (noBuildReason != null)
+ {
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
bucketEvent.setCancelled(true);
return;
}
@@ -1497,14 +1488,14 @@ void onPlayerSignOpen(@NotNull PlayerSignOpenEvent event)
}
Player player = event.getPlayer();
- String denial = instance.allowBuild(player, event.getSign().getLocation(), event.getSign().getType());
+ Supplier denial = ProtectionHelper.checkPermission(player, event.getSign().getLocation(), ClaimPermission.Build, event);
// If user is allowed to build, do nothing.
if (denial == null)
return;
// If user is not allowed to build, prevent sign UI opening and send message.
- GriefPrevention.sendMessage(player, TextMode.Err, denial);
+ GriefPrevention.sendMessage(player, TextMode.Err, denial.get());
event.setCancelled(true);
}
@@ -1737,13 +1728,10 @@ else if (clickedBlock != null &&
|| materialInHand == Material.HONEYCOMB
|| dyes.contains(materialInHand)))
{
- String noBuildReason = instance
- .allowBuild(player, clickedBlock
- .getLocation(),
- clickedBlockType);
+ Supplier noBuildReason = ProtectionHelper.checkPermission(player, event.getClickedBlock().getLocation(), ClaimPermission.Build, event);
if (noBuildReason != null)
{
- GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
+ GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason.get());
event.setCancelled(true);
}
@@ -1927,168 +1915,6 @@ else if (materialInHand == instance.config_claims_investigationTool && hand == E
return;
}
- //if the player is in restore nature mode, do only that
- UUID playerID = player.getUniqueId();
- playerData = this.dataStore.getPlayerData(player.getUniqueId());
- if (playerData.shovelMode == ShovelMode.RestoreNature || playerData.shovelMode == ShovelMode.RestoreNatureAggressive)
- {
- //if the clicked block is in a claim, visualize that claim and deliver an error message
- Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
- if (claim != null)
- {
- GriefPrevention.sendMessage(player, TextMode.Err, Messages.BlockClaimed, claim.getOwnerName());
- BoundaryVisualization.visualizeClaim(player, claim, VisualizationType.CONFLICT_ZONE, clickedBlock);
- return;
- }
-
- //figure out which chunk to repair
- Chunk chunk = player.getWorld().getChunkAt(clickedBlock.getLocation());
- //start the repair process
-
- //set boundaries for processing
- int miny = clickedBlock.getY();
-
- //if not in aggressive mode, extend the selection down to a little below sea level
- if (!(playerData.shovelMode == ShovelMode.RestoreNatureAggressive))
- {
- if (miny > instance.getSeaLevel(chunk.getWorld()) - 10)
- {
- miny = instance.getSeaLevel(chunk.getWorld()) - 10;
- }
- }
-
- instance.restoreChunk(chunk, miny, playerData.shovelMode == ShovelMode.RestoreNatureAggressive, 0, player);
-
- return;
- }
-
- //if in restore nature fill mode
- if (playerData.shovelMode == ShovelMode.RestoreNatureFill)
- {
- ArrayList allowedFillBlocks = new ArrayList<>();
- Environment environment = clickedBlock.getWorld().getEnvironment();
- if (environment == Environment.NETHER)
- {
- allowedFillBlocks.add(Material.NETHERRACK);
- }
- else if (environment == Environment.THE_END)
- {
- allowedFillBlocks.add(Material.END_STONE);
- }
- else
- {
- allowedFillBlocks.add(Material.SHORT_GRASS);
- allowedFillBlocks.add(Material.DIRT);
- allowedFillBlocks.add(Material.STONE);
- allowedFillBlocks.add(Material.SAND);
- allowedFillBlocks.add(Material.SANDSTONE);
- allowedFillBlocks.add(Material.ICE);
- }
-
- Block centerBlock = clickedBlock;
-
- int maxHeight = centerBlock.getY();
- int minx = centerBlock.getX() - playerData.fillRadius;
- int maxx = centerBlock.getX() + playerData.fillRadius;
- int minz = centerBlock.getZ() - playerData.fillRadius;
- int maxz = centerBlock.getZ() + playerData.fillRadius;
- int minHeight = maxHeight - 10;
- minHeight = Math.max(minHeight, clickedBlock.getWorld().getMinHeight());
-
- Claim cachedClaim = null;
- for (int x = minx; x <= maxx; x++)
- {
- for (int z = minz; z <= maxz; z++)
- {
- //circular brush
- Location location = new Location(centerBlock.getWorld(), x, centerBlock.getY(), z);
- if (location.distance(centerBlock.getLocation()) > playerData.fillRadius) continue;
-
- //default fill block is initially the first from the allowed fill blocks list above
- Material defaultFiller = allowedFillBlocks.get(0);
-
- //prefer to use the block the player clicked on, if it's an acceptable fill block
- if (allowedFillBlocks.contains(centerBlock.getType()))
- {
- defaultFiller = centerBlock.getType();
- }
-
- //if the player clicks on water, try to sink through the water to find something underneath that's useful for a filler
- else if (centerBlock.getType() == Material.WATER)
- {
- Block block = centerBlock.getWorld().getBlockAt(centerBlock.getLocation());
- while (!allowedFillBlocks.contains(block.getType()) && block.getY() > centerBlock.getY() - 10)
- {
- block = block.getRelative(BlockFace.DOWN);
- }
- if (allowedFillBlocks.contains(block.getType()))
- {
- defaultFiller = block.getType();
- }
- }
-
- //fill bottom to top
- for (int y = minHeight; y <= maxHeight; y++)
- {
- Block block = centerBlock.getWorld().getBlockAt(x, y, z);
-
- //respect claims
- Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, cachedClaim);
- if (claim != null)
- {
- cachedClaim = claim;
- break;
- }
-
- //only replace air, spilling water, snow, long grass
- if (block.getType() == Material.AIR || block.getType() == Material.SNOW || (block.getType() == Material.WATER && ((Levelled) block.getBlockData()).getLevel() != 0) || block.getType() == Material.SHORT_GRASS)
- {
- //if the top level, always use the default filler picked above
- if (y == maxHeight)
- {
- block.setType(defaultFiller);
- }
-
- //otherwise look to neighbors for an appropriate fill block
- else
- {
- Block eastBlock = block.getRelative(BlockFace.EAST);
- Block westBlock = block.getRelative(BlockFace.WEST);
- Block northBlock = block.getRelative(BlockFace.NORTH);
- Block southBlock = block.getRelative(BlockFace.SOUTH);
-
- //first, check lateral neighbors (ideally, want to keep natural layers)
- if (allowedFillBlocks.contains(eastBlock.getType()))
- {
- block.setType(eastBlock.getType());
- }
- else if (allowedFillBlocks.contains(westBlock.getType()))
- {
- block.setType(westBlock.getType());
- }
- else if (allowedFillBlocks.contains(northBlock.getType()))
- {
- block.setType(northBlock.getType());
- }
- else if (allowedFillBlocks.contains(southBlock.getType()))
- {
- block.setType(southBlock.getType());
- }
-
- //if all else fails, use the default filler selected above
- else
- {
- block.setType(defaultFiller);
- }
- }
- }
- }
- }
- }
-
- return;
- }
-
//if the player doesn't have claims permission, don't do anything
if (!player.hasPermission("griefprevention.createclaims"))
{
@@ -2096,6 +1922,8 @@ else if (allowedFillBlocks.contains(southBlock.getType()))
return;
}
+ playerData = this.dataStore.getPlayerData(player.getUniqueId());
+
//if he's resizing a claim and that claim hasn't been deleted since he started resizing it
if (playerData.claimResizing != null && playerData.claimResizing.inDataStore)
{
@@ -2315,6 +2143,8 @@ else if (playerData.shovelMode == ShovelMode.Subdivide)
}
}
+ UUID playerID = player.getUniqueId();
+
//if not an administrative claim, verify the player has enough claim blocks for this new claim
if (playerData.shovelMode != ShovelMode.Admin)
{
@@ -2445,10 +2275,7 @@ static Block getTargetBlock(Player player, int maxDistance) throws IllegalStateE
{
result = iterator.next();
Material type = result.getType();
- if (type != Material.AIR &&
- (!passThroughWater || type != Material.WATER) &&
- type != Material.SHORT_GRASS &&
- type != Material.SNOW) return result;
+ if (!Tag.REPLACEABLE.isTagged(type) || (!passThroughWater && type == Material.WATER)) return result;
}
return result;
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java
deleted file mode 100644
index f0c5c629..00000000
--- a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- GriefPrevention Server Plugin for Minecraft
- Copyright (C) 2012 Ryan Hamshire
-
- 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 me.ryanhamshire.GriefPrevention;
-
-import com.griefprevention.visualization.BoundaryVisualization;
-import com.griefprevention.visualization.VisualizationType;
-import me.ryanhamshire.GriefPrevention.util.BoundingBox;
-import org.bukkit.Chunk;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.entity.Animals;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.Hanging;
-import org.bukkit.entity.Player;
-
-//this main thread task takes the output from the RestoreNatureProcessingTask\
-//and updates the world accordingly
-class RestoreNatureExecutionTask implements Runnable
-{
- //results from processing thread
- //will be applied to the world
- private final BlockSnapshot[][][] snapshots;
-
- //boundaries for changes
- private final int miny;
- private final Location lesserCorner;
- private final Location greaterCorner;
-
- //player who should be notified about the result (will see a visualization when the restoration is complete)
- private final Player player;
-
- public RestoreNatureExecutionTask(BlockSnapshot[][][] snapshots, int miny, Location lesserCorner, Location greaterCorner, Player player)
- {
- this.snapshots = snapshots;
- this.miny = miny;
- this.lesserCorner = lesserCorner;
- this.greaterCorner = greaterCorner;
- this.player = player;
- }
-
-
- @Override
- public void run()
- {
- //apply changes to the world, but ONLY to unclaimed blocks
- //note that the edge of the results is not applied (the 1-block-wide band around the outside of the chunk)
- //those data were sent to the processing thread for referernce purposes, but aren't part of the area selected for restoration
- Claim cachedClaim = null;
- for (int x = 1; x < this.snapshots.length - 1; x++)
- {
- for (int z = 1; z < this.snapshots[0][0].length - 1; z++)
- {
- for (int y = this.miny; y < this.snapshots[0].length; y++)
- {
- BlockSnapshot blockUpdate = this.snapshots[x][y][z];
- Block currentBlock = blockUpdate.location.getBlock();
- if (blockUpdate.typeId != currentBlock.getType() || !blockUpdate.data.equals(currentBlock.getBlockData()))
- {
- Claim claim = GriefPrevention.instance.dataStore.getClaimAt(blockUpdate.location, false, cachedClaim);
- if (claim != null)
- {
- cachedClaim = claim;
- break;
- }
-
- try
- {
- currentBlock.setType(blockUpdate.typeId, false);
- // currentBlock.setBlockData(blockUpdate.data, false);
- }
- catch (IllegalArgumentException e)
- {
- //just don't update this block and continue trying to update other blocks
- }
- }
- }
- }
- }
-
- //clean up any entities in the chunk, ensure no players are suffocated
- Chunk chunk = this.lesserCorner.getChunk();
- Entity[] entities = chunk.getEntities();
- for (Entity entity : entities)
- {
- if (!(entity instanceof Player || entity instanceof Animals))
- {
- //hanging entities (paintings, item frames) are protected when they're in land claims
- if (!(entity instanceof Hanging) || GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, null) == null)
- {
- //everything else is removed
- entity.remove();
- }
- }
-
- //for players, always ensure there's air where the player is standing
- else
- {
- Block feetBlock = entity.getLocation().getBlock();
- feetBlock.setType(Material.AIR);
- feetBlock.getRelative(BlockFace.UP).setType(Material.AIR);
- }
- }
-
- //show visualization to player who started the restoration
- if (player != null)
- {
- BoundaryVisualization.visualizeArea(
- player,
- new BoundingBox(lesserCorner, greaterCorner),
- VisualizationType.NATURE_RESTORATION_ZONE);
- }
- }
-}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureProcessingTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureProcessingTask.java
deleted file mode 100644
index c15891be..00000000
--- a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureProcessingTask.java
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
- GriefPrevention Server Plugin for Minecraft
- Copyright (C) 2012 Ryan Hamshire
-
- 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 me.ryanhamshire.GriefPrevention;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.NamespacedKey;
-import org.bukkit.Tag;
-import org.bukkit.World.Environment;
-import org.bukkit.block.Biome;
-import org.bukkit.block.data.Levelled;
-import org.bukkit.block.data.type.Leaves;
-import org.bukkit.entity.Player;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-//non-main-thread task which processes world data to repair the unnatural
-//after processing is complete, creates a main thread task to make the necessary changes to the world
-class RestoreNatureProcessingTask implements Runnable
-{
-
- // Definitions of biomes with particularly dense log distribution. These biomes will not have logs reduced.
- private static final Set DENSE_LOG_BIOMES = Set.of(
- NamespacedKey.minecraft("jungle"),
- NamespacedKey.minecraft("bamboo_jungle")
- );
-
- // Definitions of biomes where sand covers surfaces instead of grass.
- private static final Set SAND_SOIL_BIOMES = Set.of(
- NamespacedKey.minecraft("snowy_beach"),
- NamespacedKey.minecraft("beach"),
- NamespacedKey.minecraft("desert")
- );
-
- //world information captured from the main thread
- //will be updated and sent back to main thread to be applied to the world
- private final BlockSnapshot[][][] snapshots;
-
- //other information collected from the main thread.
- //not to be updated, only to be passed back to main thread to provide some context about the operation
- private int miny;
- private final Environment environment;
- private final Location lesserBoundaryCorner;
- private final Location greaterBoundaryCorner;
- private final Player player; //absolutely must not be accessed. not thread safe.
- private final Biome biome;
- private final boolean creativeMode;
- private final int seaLevel;
- private final boolean aggressiveMode;
-
- //two lists of materials
- private final Set notAllowedToHang; //natural blocks which don't naturally hang in their air
- private final Set playerBlocks; //a "complete" list of player-placed blocks. MUST BE MAINTAINED as patches introduce more
-
-
- public RestoreNatureProcessingTask(BlockSnapshot[][][] snapshots, int miny, Environment environment, Biome biome, Location lesserBoundaryCorner, Location greaterBoundaryCorner, int seaLevel, boolean aggressiveMode, boolean creativeMode, Player player)
- {
- this.snapshots = snapshots;
- this.miny = miny;
- if (this.miny < 0) this.miny = 0;
- this.environment = environment;
- this.lesserBoundaryCorner = lesserBoundaryCorner;
- this.greaterBoundaryCorner = greaterBoundaryCorner;
- this.biome = biome;
- this.seaLevel = seaLevel;
- this.aggressiveMode = aggressiveMode;
- this.player = player;
- this.creativeMode = creativeMode;
-
- this.notAllowedToHang = new HashSet<>();
- this.notAllowedToHang.add(Material.DIRT);
- this.notAllowedToHang.add(Material.SHORT_GRASS);
- this.notAllowedToHang.add(Material.SNOW);
- this.notAllowedToHang.add(Material.OAK_LOG);
- this.notAllowedToHang.add(Material.SPRUCE_LOG);
- this.notAllowedToHang.add(Material.BIRCH_LOG);
- this.notAllowedToHang.add(Material.JUNGLE_LOG);
- this.notAllowedToHang.add(Material.ACACIA_LOG);
- this.notAllowedToHang.add(Material.DARK_OAK_LOG);
-
- if (this.aggressiveMode)
- {
- this.notAllowedToHang.add(Material.SHORT_GRASS);
- this.notAllowedToHang.add(Material.STONE);
- }
-
- this.playerBlocks = new HashSet<>();
- this.playerBlocks.addAll(RestoreNatureProcessingTask.getPlayerBlocks(this.environment, this.biome));
-
- //in aggressive or creative world mode, also treat these blocks as user placed, to be removed
- //this is helpful in the few cases where griefers intentionally use natural blocks to grief,
- //like a single-block tower of iron ore or a giant penis constructed with melons
- if (this.aggressiveMode || this.creativeMode)
- {
- this.playerBlocks.addAll(Tag.COPPER_ORES.getValues());
- this.playerBlocks.addAll(Tag.IRON_ORES.getValues());
- this.playerBlocks.addAll(Tag.GOLD_ORES.getValues());
- this.playerBlocks.addAll(Tag.DIAMOND_ORES.getValues());
- this.playerBlocks.addAll(Tag.COAL_ORES.getValues());
- this.playerBlocks.add(Material.MELON);
- this.playerBlocks.add(Material.MELON_STEM);
- this.playerBlocks.add(Material.BEDROCK);
- this.playerBlocks.add(Material.PUMPKIN);
- this.playerBlocks.add(Material.PUMPKIN_STEM);
- }
-
- if (this.aggressiveMode)
- {
- this.playerBlocks.addAll(Tag.LEAVES.getValues());
- this.playerBlocks.addAll(Tag.LOGS.getValues());
- this.playerBlocks.add(Material.VINE);
- }
- }
-
- @Override
- public void run()
- {
- //order is important!
-
- //remove sandstone which appears to be unnatural
- this.removeSandstone();
-
- //remove any blocks which are definitely player placed
- this.removePlayerBlocks();
-
- //reduce large outcroppings of stone, sandstone
- this.reduceStone();
-
- //reduce logs, except in jungle biomes
- this.reduceLogs();
-
- //remove natural blocks which are unnaturally hanging in the air
- this.removeHanging();
-
- //remove natural blocks which are unnaturally stacked high
- this.removeWallsAndTowers();
-
- //fill unnatural thin trenches and single-block potholes
- this.fillHolesAndTrenches();
-
- //fill water depressions and fix unnatural surface ripples
- //this.fixWater();
-
- //remove water/lava above sea level
- this.removeDumpedFluids();
-
- //cover surface stone and gravel with sand or grass, as the biome requires
- this.coverSurfaceStone();
-
- //remove any player-placed leaves
- ///this.removePlayerLeaves();
-
- //schedule main thread task to apply the result to the world
- RestoreNatureExecutionTask task = new RestoreNatureExecutionTask(this.snapshots, this.miny, this.lesserBoundaryCorner, this.greaterBoundaryCorner, this.player);
- GriefPrevention.scheduler.getImpl().runAtLocation(this.lesserBoundaryCorner, task);
- }
-
-
- private void removePlayerLeaves()
- {
- if (this.seaLevel < 1) return;
-
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = this.seaLevel - 1; y < snapshots[0].length; y++)
- {
- BlockSnapshot block = snapshots[x][y][z];
- if (Tag.LEAVES.isTagged(block.typeId) && ((Leaves) block.data).isPersistent())
- {
- block.typeId = Material.AIR;
- }
- }
- }
- }
- }
-
- //converts sandstone adjacent to sand to sand, and any other sandstone to air
-
- private void removeSandstone()
- {
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = snapshots[0].length - 2; y > miny; y--)
- {
- if (snapshots[x][y][z].typeId != Material.SANDSTONE) continue;
-
- BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
- BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
- BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
- BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
- BlockSnapshot underBlock = this.snapshots[x][y - 1][z];
- BlockSnapshot aboveBlock = this.snapshots[x][y + 1][z];
-
- //skip blocks which may cause a cave-in
- if (aboveBlock.typeId == Material.SAND && underBlock.typeId == Material.AIR) continue;
-
- //count adjacent non-air/non-leaf blocks
- if (leftBlock.typeId == Material.SAND ||
- rightBlock.typeId == Material.SAND ||
- upBlock.typeId == Material.SAND ||
- downBlock.typeId == Material.SAND ||
- aboveBlock.typeId == Material.SAND ||
- underBlock.typeId == Material.SAND)
- {
- snapshots[x][y][z].typeId = Material.SAND;
- }
- else
- {
- snapshots[x][y][z].typeId = Material.AIR;
- }
- }
- }
- }
- }
-
-
- private void reduceStone()
- {
- if (this.seaLevel < 1) return;
-
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- int thisy = this.highestY(x, z, true);
-
- while (thisy > this.seaLevel - 1 && (this.snapshots[x][thisy][z].typeId == Material.STONE || this.snapshots[x][thisy][z].typeId == Material.SANDSTONE))
- {
- BlockSnapshot leftBlock = this.snapshots[x + 1][thisy][z];
- BlockSnapshot rightBlock = this.snapshots[x - 1][thisy][z];
- BlockSnapshot upBlock = this.snapshots[x][thisy][z + 1];
- BlockSnapshot downBlock = this.snapshots[x][thisy][z - 1];
-
- //count adjacent non-air/non-leaf blocks
- byte adjacentBlockCount = 0;
- if (leftBlock.typeId != Material.AIR && !Tag.LEAVES.isTagged(leftBlock.typeId) && leftBlock.typeId != Material.VINE)
- {
- adjacentBlockCount++;
- }
- if (rightBlock.typeId != Material.AIR && !Tag.LEAVES.isTagged(rightBlock.typeId) && rightBlock.typeId != Material.VINE)
- {
- adjacentBlockCount++;
- }
- if (downBlock.typeId != Material.AIR && !Tag.LEAVES.isTagged(downBlock.typeId) && downBlock.typeId != Material.VINE)
- {
- adjacentBlockCount++;
- }
- if (upBlock.typeId != Material.AIR && !Tag.LEAVES.isTagged(upBlock.typeId) && upBlock.typeId != Material.VINE)
- {
- adjacentBlockCount++;
- }
-
- if (adjacentBlockCount < 3)
- {
- this.snapshots[x][thisy][z].typeId = Material.AIR;
- }
-
- thisy--;
- }
- }
- }
- }
-
-
- private void reduceLogs()
- {
- if (this.seaLevel < 1) return;
-
- boolean jungleBiome = DENSE_LOG_BIOMES.contains(this.biome.getKey());
-
- //scan all blocks above sea level
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = this.seaLevel - 1; y < snapshots[0].length; y++)
- {
- BlockSnapshot block = snapshots[x][y][z];
-
- //skip non-logs
- if (!Tag.LOGS.isTagged(block.typeId)) continue;
-
- //if in jungle biome, skip jungle logs
- if (jungleBiome && block.typeId == Material.JUNGLE_LOG) continue;
-
- //examine adjacent blocks for logs
- BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
- BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
- BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
- BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
-
- //if any, remove the log
- if (Tag.LOGS.isTagged(leftBlock.typeId) || Tag.LOGS.isTagged(rightBlock.typeId) || Tag.LOGS.isTagged(upBlock.typeId) || Tag.LOGS.isTagged(downBlock.typeId))
- {
- this.snapshots[x][y][z].typeId = Material.AIR;
- }
- }
- }
- }
- }
-
-
- private void removePlayerBlocks()
- {
- int miny = this.miny;
- if (miny < 1) miny = 1;
-
- //remove all player blocks
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = miny; y < snapshots[0].length - 1; y++)
- {
- BlockSnapshot block = snapshots[x][y][z];
-
- if (this.playerBlocks.contains(block.typeId))
- {
- block.typeId = Material.AIR;
- }
- }
- }
- }
- }
-
-
- private void removeHanging()
- {
- int miny = this.miny;
- if (miny < 1) miny = 1;
-
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = miny; y < snapshots[0].length - 1; y++)
- {
- BlockSnapshot block = snapshots[x][y][z];
- BlockSnapshot underBlock = snapshots[x][y - 1][z];
-
- if (underBlock.typeId == Material.AIR || underBlock.typeId == Material.WATER || Tag.LEAVES.isTagged(underBlock.typeId))
- {
- if (this.notAllowedToHang.contains(block.typeId))
- {
- block.typeId = Material.AIR;
- }
- }
- }
- }
- }
- }
-
-
- private void removeWallsAndTowers()
- {
- Material[] excludedBlocksArray = new Material[]
- {
- Material.CACTUS,
- Material.SHORT_GRASS,
- Material.RED_MUSHROOM,
- Material.BROWN_MUSHROOM,
- Material.DEAD_BUSH,
- Material.DANDELION,
- Material.POPPY,
- Material.ALLIUM,
- Material.BLUE_ORCHID,
- Material.AZURE_BLUET,
- Material.RED_TULIP,
- Material.ORANGE_TULIP,
- Material.WHITE_TULIP,
- Material.PINK_TULIP,
- Material.OXEYE_DAISY,
- Material.SUGAR_CANE,
- Material.VINE,
- Material.PUMPKIN,
- Material.LILY_PAD
- };
-
- ArrayList excludedBlocks = new ArrayList<>(Arrays.asList(excludedBlocksArray));
-
- excludedBlocks.addAll(Tag.SAPLINGS.getValues());
- excludedBlocks.addAll(Tag.LEAVES.getValues());
-
- boolean changed;
- do
- {
- changed = false;
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- int thisy = this.highestY(x, z, false);
- if (excludedBlocks.contains(this.snapshots[x][thisy][z].typeId)) continue;
-
- int righty = this.highestY(x + 1, z, false);
- int lefty = this.highestY(x - 1, z, false);
- while (lefty < thisy && righty < thisy)
- {
- this.snapshots[x][thisy--][z].typeId = Material.AIR;
- changed = true;
- }
-
- int upy = this.highestY(x, z + 1, false);
- int downy = this.highestY(x, z - 1, false);
- while (upy < thisy && downy < thisy)
- {
- this.snapshots[x][thisy--][z].typeId = Material.AIR;
- changed = true;
- }
- }
- }
- } while (changed);
- }
-
-
- private void coverSurfaceStone()
- {
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- int y = this.highestY(x, z, true);
- BlockSnapshot block = snapshots[x][y][z];
-
- if (block.typeId == Material.STONE || block.typeId == Material.GRAVEL || block.typeId == Material.FARMLAND || block.typeId == Material.DIRT || block.typeId == Material.SANDSTONE)
- {
- if (SAND_SOIL_BIOMES.contains(this.biome.getKey()))
- {
- this.snapshots[x][y][z].typeId = Material.SAND;
- }
- else
- {
- this.snapshots[x][y][z].typeId = Material.GRASS_BLOCK;
- }
- }
- }
- }
- }
-
-
- private void fillHolesAndTrenches()
- {
- ArrayList fillableBlocks = new ArrayList<>();
- fillableBlocks.add(Material.AIR);
- fillableBlocks.add(Material.WATER);
- fillableBlocks.add(Material.LAVA);
- fillableBlocks.add(Material.SHORT_GRASS);
-
- ArrayList notSuitableForFillBlocks = new ArrayList<>();
- notSuitableForFillBlocks.add(Material.SHORT_GRASS);
- notSuitableForFillBlocks.add(Material.CACTUS);
- notSuitableForFillBlocks.add(Material.WATER);
- notSuitableForFillBlocks.add(Material.LAVA);
- notSuitableForFillBlocks.addAll(Tag.LOGS.getValues());
-
- boolean changed;
- do
- {
- changed = false;
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = 0; y < snapshots[0].length - 1; y++)
- {
- BlockSnapshot block = this.snapshots[x][y][z];
- if (!fillableBlocks.contains(block.typeId)) continue;
-
- BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
- BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
-
- if (!fillableBlocks.contains(leftBlock.typeId) && !fillableBlocks.contains(rightBlock.typeId))
- {
- if (!notSuitableForFillBlocks.contains(rightBlock.typeId))
- {
- block.typeId = rightBlock.typeId;
- changed = true;
- }
- }
-
- BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
- BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
-
- if (!fillableBlocks.contains(upBlock.typeId) && !fillableBlocks.contains(downBlock.typeId))
- {
- if (!notSuitableForFillBlocks.contains(downBlock.typeId))
- {
- block.typeId = downBlock.typeId;
- changed = true;
- }
- }
- }
- }
- }
- } while (changed);
- }
-
-
- private void fixWater()
- {
- int miny = this.miny;
- if (miny < 1) miny = 1;
-
- boolean changed;
-
- //remove hanging water or lava
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = miny; y < snapshots[0].length - 1; y++)
- {
- BlockSnapshot block = this.snapshots[x][y][z];
- BlockSnapshot underBlock = this.snapshots[x][y--][z];
- if (block.typeId == Material.WATER || block.typeId == Material.LAVA)
- {
- // check if block below is air or is a non-source fluid block (level 1-7 = flowing, 8 = falling)
- if (underBlock.typeId == Material.AIR || (underBlock.typeId == Material.WATER && (((Levelled) underBlock.data).getLevel() != 0)))
- {
- block.typeId = Material.AIR;
- }
- }
- }
- }
- }
-
- //fill water depressions
- do
- {
- changed = false;
- for (int y = Math.max(this.seaLevel - 10, 0); y <= this.seaLevel; y++)
- {
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- BlockSnapshot block = snapshots[x][y][z];
-
- //only consider air blocks and flowing water blocks for upgrade to water source blocks
- if (block.typeId == Material.AIR || (block.typeId == Material.WATER && ((Levelled) block.data).getLevel() != 0))
- {
- BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
- BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
- BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
- BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
- BlockSnapshot underBlock = this.snapshots[x][y - 1][z];
-
- //block underneath MUST be source water
- if (!(underBlock.typeId == Material.WATER && ((Levelled) underBlock.data).getLevel() == 0))
- continue;
-
- //count adjacent source water blocks
- byte adjacentSourceWaterCount = 0;
- if (leftBlock.typeId == Material.WATER && ((Levelled) leftBlock.data).getLevel() == 0)
- {
- adjacentSourceWaterCount++;
- }
- if (rightBlock.typeId == Material.WATER && ((Levelled) rightBlock.data).getLevel() == 0)
- {
- adjacentSourceWaterCount++;
- }
- if (upBlock.typeId == Material.WATER && ((Levelled) upBlock.data).getLevel() == 0)
- {
- adjacentSourceWaterCount++;
- }
- if (downBlock.typeId == Material.WATER && ((Levelled) downBlock.data).getLevel() == 0)
- {
- adjacentSourceWaterCount++;
- }
-
- //at least two adjacent blocks must be source water
- if (adjacentSourceWaterCount >= 2)
- {
- block.typeId = Material.WATER;
- ((Levelled) downBlock.data).setLevel(0);
- changed = true;
- }
- }
- }
- }
- }
- } while (changed);
- }
-
-
- private void removeDumpedFluids()
- {
- if (this.seaLevel < 1) return;
-
- //remove any surface water or lava above sea level, presumed to be placed by players
- //sometimes, this is naturally generated. but replacing it is very easy with a bucket, so overall this is a good plan
- if (this.environment == Environment.NETHER) return;
- for (int x = 1; x < snapshots.length - 1; x++)
- {
- for (int z = 1; z < snapshots[0][0].length - 1; z++)
- {
- for (int y = this.seaLevel; y < snapshots[0].length - 1; y++)
- {
- BlockSnapshot block = snapshots[x][y][z];
- if (block.typeId == Material.WATER || block.typeId == Material.LAVA)
- {
- block.typeId = Material.AIR;
- }
- }
- }
- }
- }
-
-
- private int highestY(int x, int z, boolean ignoreLeaves)
- {
- int y;
- for (y = snapshots[0].length - 1; y > 0; y--)
- {
- BlockSnapshot block = this.snapshots[x][y][z];
- if (block.typeId != Material.AIR &&
- !(ignoreLeaves && block.typeId == Material.SNOW) &&
- !(ignoreLeaves && Tag.LEAVES.isTagged(block.typeId)) &&
- !(block.typeId == Material.WATER) &&
- !(block.typeId == Material.LAVA))
- {
- return y;
- }
- }
-
- return y;
- }
-
-
- static Set getPlayerBlocks(Environment environment, Biome biome)
- {
- //NOTE on this list. why not make a list of natural blocks?
- //answer: better to leave a few player blocks than to remove too many natural blocks. remember we're "restoring nature"
- //a few extra player blocks can be manually removed, but it will be impossible to guess exactly which natural materials to use in manual repair of an overzealous block removal
- Set playerBlocks = new HashSet<>();
- playerBlocks.addAll(Tag.ANVIL.getValues());
- playerBlocks.addAll(Tag.BANNERS.getValues());
- playerBlocks.addAll(Tag.BEACON_BASE_BLOCKS.getValues());
- playerBlocks.addAll(Tag.BEDS.getValues());
- playerBlocks.addAll(Tag.BUTTONS.getValues());
- playerBlocks.addAll(Tag.CAMPFIRES.getValues());
- playerBlocks.addAll(Tag.CANDLE_CAKES.getValues());
- playerBlocks.addAll(Tag.CANDLES.getValues());
- playerBlocks.addAll(Tag.WOOL_CARPETS.getValues());
- playerBlocks.addAll(Tag.CAULDRONS.getValues());
- playerBlocks.addAll(Tag.DOORS.getValues());
- playerBlocks.addAll(Tag.FENCE_GATES.getValues());
- playerBlocks.addAll(Tag.FENCES.getValues());
- playerBlocks.addAll(Tag.FIRE.getValues());
- playerBlocks.addAll(Tag.FLOWER_POTS.getValues());
- playerBlocks.addAll(Tag.IMPERMEABLE.getValues()); // Glass block variants
- playerBlocks.addAll(Tag.LOGS.getValues());
- playerBlocks.addAll(Tag.PLANKS.getValues());
- playerBlocks.addAll(Tag.PRESSURE_PLATES.getValues());
- playerBlocks.addAll(Tag.RAILS.getValues());
- playerBlocks.addAll(Tag.SHULKER_BOXES.getValues());
- playerBlocks.addAll(Tag.SIGNS.getValues());
- playerBlocks.addAll(Tag.SLABS.getValues());
- playerBlocks.addAll(Tag.STAIRS.getValues());
- playerBlocks.addAll(Tag.STONE_BRICKS.getValues());
- playerBlocks.addAll(Tag.TRAPDOORS.getValues());
- playerBlocks.addAll(Tag.WALLS.getValues());
- playerBlocks.addAll(Tag.WOOL.getValues());
- playerBlocks.add(Material.BOOKSHELF);
- playerBlocks.add(Material.BREWING_STAND);
- playerBlocks.add(Material.BRICK);
- playerBlocks.add(Material.COBBLESTONE);
- playerBlocks.add(Material.LAPIS_BLOCK);
- playerBlocks.add(Material.DISPENSER);
- playerBlocks.add(Material.NOTE_BLOCK);
- playerBlocks.add(Material.STICKY_PISTON);
- playerBlocks.add(Material.PISTON);
- playerBlocks.add(Material.PISTON_HEAD);
- playerBlocks.add(Material.MOVING_PISTON);
- playerBlocks.add(Material.WHEAT);
- playerBlocks.add(Material.TNT);
- playerBlocks.add(Material.MOSSY_COBBLESTONE);
- playerBlocks.add(Material.TORCH);
- playerBlocks.add(Material.CHEST);
- playerBlocks.add(Material.REDSTONE_WIRE);
- playerBlocks.add(Material.CRAFTING_TABLE);
- playerBlocks.add(Material.FURNACE);
- playerBlocks.add(Material.LADDER);
- playerBlocks.add(Material.SCAFFOLDING);
- playerBlocks.add(Material.LEVER);
- playerBlocks.add(Material.REDSTONE_TORCH);
- playerBlocks.add(Material.SNOW_BLOCK);
- playerBlocks.add(Material.JUKEBOX);
- playerBlocks.add(Material.NETHER_PORTAL);
- playerBlocks.add(Material.JACK_O_LANTERN);
- playerBlocks.add(Material.CAKE);
- playerBlocks.add(Material.REPEATER);
- playerBlocks.add(Material.MUSHROOM_STEM);
- playerBlocks.add(Material.RED_MUSHROOM_BLOCK);
- playerBlocks.add(Material.BROWN_MUSHROOM_BLOCK);
- playerBlocks.add(Material.IRON_BARS);
- playerBlocks.add(Material.GLASS_PANE);
- playerBlocks.add(Material.MELON_STEM);
- playerBlocks.add(Material.ENCHANTING_TABLE);
- playerBlocks.add(Material.COBWEB);
- playerBlocks.add(Material.GRAVEL);
- playerBlocks.add(Material.SANDSTONE);
- playerBlocks.add(Material.ENDER_CHEST);
- playerBlocks.add(Material.COMMAND_BLOCK);
- playerBlocks.add(Material.REPEATING_COMMAND_BLOCK);
- playerBlocks.add(Material.CHAIN_COMMAND_BLOCK);
- playerBlocks.add(Material.BEACON);
- playerBlocks.add(Material.CARROT);
- playerBlocks.add(Material.POTATO);
- playerBlocks.add(Material.SKELETON_SKULL);
- playerBlocks.add(Material.WITHER_SKELETON_SKULL);
- playerBlocks.add(Material.CREEPER_HEAD);
- playerBlocks.add(Material.ZOMBIE_HEAD);
- playerBlocks.add(Material.PLAYER_HEAD);
- playerBlocks.add(Material.DRAGON_HEAD);
- playerBlocks.add(Material.SPONGE);
- playerBlocks.add(Material.WHITE_STAINED_GLASS_PANE);
- playerBlocks.add(Material.ORANGE_STAINED_GLASS_PANE);
- playerBlocks.add(Material.MAGENTA_STAINED_GLASS_PANE);
- playerBlocks.add(Material.LIGHT_BLUE_STAINED_GLASS_PANE);
- playerBlocks.add(Material.YELLOW_STAINED_GLASS_PANE);
- playerBlocks.add(Material.LIME_STAINED_GLASS_PANE);
- playerBlocks.add(Material.PINK_STAINED_GLASS_PANE);
- playerBlocks.add(Material.GRAY_STAINED_GLASS_PANE);
- playerBlocks.add(Material.LIGHT_GRAY_STAINED_GLASS_PANE);
- playerBlocks.add(Material.CYAN_STAINED_GLASS_PANE);
- playerBlocks.add(Material.PURPLE_STAINED_GLASS_PANE);
- playerBlocks.add(Material.BLUE_STAINED_GLASS_PANE);
- playerBlocks.add(Material.BROWN_STAINED_GLASS_PANE);
- playerBlocks.add(Material.GREEN_STAINED_GLASS_PANE);
- playerBlocks.add(Material.RED_STAINED_GLASS_PANE);
- playerBlocks.add(Material.BLACK_STAINED_GLASS_PANE);
- playerBlocks.add(Material.TRAPPED_CHEST);
- playerBlocks.add(Material.COMPARATOR);
- playerBlocks.add(Material.DAYLIGHT_DETECTOR);
- playerBlocks.add(Material.REDSTONE_BLOCK);
- playerBlocks.add(Material.HOPPER);
- playerBlocks.add(Material.QUARTZ_BLOCK);
- playerBlocks.add(Material.DROPPER);
- playerBlocks.add(Material.SLIME_BLOCK);
- playerBlocks.add(Material.PRISMARINE);
- playerBlocks.add(Material.HAY_BLOCK);
- playerBlocks.add(Material.SEA_LANTERN);
- playerBlocks.add(Material.COAL_BLOCK);
- playerBlocks.add(Material.REDSTONE_LAMP);
- playerBlocks.add(Material.RED_NETHER_BRICKS);
- playerBlocks.add(Material.POLISHED_ANDESITE);
- playerBlocks.add(Material.POLISHED_DIORITE);
- playerBlocks.add(Material.POLISHED_GRANITE);
- playerBlocks.add(Material.POLISHED_BASALT);
- playerBlocks.add(Material.POLISHED_DEEPSLATE);
- playerBlocks.add(Material.DEEPSLATE_BRICKS);
- playerBlocks.add(Material.CRACKED_DEEPSLATE_BRICKS);
- playerBlocks.add(Material.DEEPSLATE_TILES);
- playerBlocks.add(Material.CRACKED_DEEPSLATE_TILES);
- playerBlocks.add(Material.CHISELED_DEEPSLATE);
- playerBlocks.add(Material.RAW_COPPER_BLOCK);
- playerBlocks.add(Material.RAW_IRON_BLOCK);
- playerBlocks.add(Material.RAW_GOLD_BLOCK);
- playerBlocks.add(Material.LIGHTNING_ROD);
- playerBlocks.add(Material.DECORATED_POT);
-
- //these are unnatural in the nether and end
- if (environment != Environment.NORMAL && environment != Environment.CUSTOM)
- {
- playerBlocks.addAll(Tag.BASE_STONE_OVERWORLD.getValues());
- playerBlocks.addAll(Tag.DIRT.getValues());
- playerBlocks.addAll(Tag.SAND.getValues());
- }
-
- //these are unnatural in the standard world, but not in the nether
- if (environment != Environment.NETHER)
- {
- playerBlocks.addAll(Tag.NYLIUM.getValues());
- playerBlocks.addAll(Tag.WART_BLOCKS.getValues());
- playerBlocks.addAll(Tag.BASE_STONE_NETHER.getValues());
- playerBlocks.add(Material.POLISHED_BLACKSTONE);
- playerBlocks.add(Material.CHISELED_POLISHED_BLACKSTONE);
- playerBlocks.add(Material.CRACKED_POLISHED_BLACKSTONE_BRICKS);
- playerBlocks.add(Material.GILDED_BLACKSTONE);
- playerBlocks.add(Material.BONE_BLOCK);
- playerBlocks.add(Material.SOUL_SAND);
- playerBlocks.add(Material.SOUL_SOIL);
- playerBlocks.add(Material.GLOWSTONE);
- playerBlocks.add(Material.NETHER_BRICK);
- playerBlocks.add(Material.MAGMA_BLOCK);
- playerBlocks.add(Material.ANCIENT_DEBRIS);
- playerBlocks.add(Material.CHAIN);
- playerBlocks.add(Material.SHROOMLIGHT);
- playerBlocks.add(Material.NETHER_GOLD_ORE);
- playerBlocks.add(Material.NETHER_SPROUTS);
- playerBlocks.add(Material.CRIMSON_FUNGUS);
- playerBlocks.add(Material.CRIMSON_ROOTS);
- playerBlocks.add(Material.NETHER_WART_BLOCK);
- playerBlocks.add(Material.WEEPING_VINES);
- playerBlocks.add(Material.WEEPING_VINES_PLANT);
- playerBlocks.add(Material.WARPED_FUNGUS);
- playerBlocks.add(Material.WARPED_ROOTS);
- playerBlocks.add(Material.WARPED_WART_BLOCK);
- playerBlocks.add(Material.TWISTING_VINES);
- playerBlocks.add(Material.TWISTING_VINES_PLANT);
- }
- //blocks from tags that are natural in the nether
- else
- {
- playerBlocks.remove(Material.CRIMSON_STEM);
- playerBlocks.remove(Material.CRIMSON_HYPHAE);
- playerBlocks.remove(Material.NETHER_BRICK_FENCE);
- playerBlocks.remove(Material.NETHER_BRICK_STAIRS);
- playerBlocks.remove(Material.SOUL_FIRE);
- playerBlocks.remove(Material.WARPED_STEM);
- playerBlocks.remove(Material.WARPED_HYPHAE);
- }
-
- //these are unnatural in the standard and nether worlds, but not in the end
- if (environment != Environment.THE_END)
- {
- playerBlocks.add(Material.CHORUS_PLANT);
- playerBlocks.add(Material.CHORUS_FLOWER);
- playerBlocks.add(Material.END_ROD);
- playerBlocks.add(Material.END_STONE);
- playerBlocks.add(Material.END_STONE_BRICKS);
- playerBlocks.add(Material.OBSIDIAN);
- playerBlocks.add(Material.PURPUR_BLOCK);
- playerBlocks.add(Material.PURPUR_PILLAR);
- }
- //blocks from tags that are natural in the end
- else
- {
- playerBlocks.remove(Material.PURPUR_SLAB);
- playerBlocks.remove(Material.PURPUR_STAIRS);
- }
-
- //these are unnatural in sandy biomes, but not elsewhere
- if (SAND_SOIL_BIOMES.contains(biome.getKey()) || environment != Environment.NORMAL)
- {
- playerBlocks.addAll(Tag.LEAVES.getValues());
- }
- //blocks from tags that are natural in non-sandy normal biomes
- else
- {
- playerBlocks.remove(Material.OAK_LOG);
- playerBlocks.remove(Material.SPRUCE_LOG);
- playerBlocks.remove(Material.BIRCH_LOG);
- playerBlocks.remove(Material.JUNGLE_LOG);
- playerBlocks.remove(Material.ACACIA_LOG);
- playerBlocks.remove(Material.DARK_OAK_LOG);
- }
-
- return playerBlocks;
- }
-}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java b/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java
index 3985be47..af493016 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java
@@ -23,8 +23,5 @@ public enum ShovelMode
{
Basic,
Admin,
- Subdivide,
- RestoreNature,
- RestoreNatureAggressive,
- RestoreNatureFill
+ Subdivide
}
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java
index 669e01e1..88aa9fb9 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java
@@ -29,7 +29,6 @@ public enum VisualizationType
Claim,
Subdivision,
ErrorClaim,
- RestoreNature,
AdminClaim;
@Deprecated(forRemoval = true, since = "16.18")
@@ -40,7 +39,6 @@ com.griefprevention.visualization.VisualizationType convert()
case Claim -> com.griefprevention.visualization.VisualizationType.CLAIM;
case Subdivision -> com.griefprevention.visualization.VisualizationType.SUBDIVISION;
case ErrorClaim -> com.griefprevention.visualization.VisualizationType.CONFLICT_ZONE;
- case RestoreNature -> com.griefprevention.visualization.VisualizationType.NATURE_RESTORATION_ZONE;
case AdminClaim -> com.griefprevention.visualization.VisualizationType.ADMIN_CLAIM;
};
}
@@ -50,7 +48,6 @@ static com.griefprevention.visualization.VisualizationType ofBlockData(BlockData
return switch (accent.getMaterial()) {
case WHITE_WOOL -> com.griefprevention.visualization.VisualizationType.SUBDIVISION;
case NETHERRACK -> com.griefprevention.visualization.VisualizationType.CONFLICT_ZONE;
- case DIAMOND_BLOCK -> com.griefprevention.visualization.VisualizationType.NATURE_RESTORATION_ZONE;
case PUMPKIN -> com.griefprevention.visualization.VisualizationType.ADMIN_CLAIM;
default -> com.griefprevention.visualization.VisualizationType.CLAIM;
};
diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/events/PreventBlockBreakEvent.java b/src/main/java/me/ryanhamshire/GriefPrevention/events/PreventBlockBreakEvent.java
index fee8190f..03e4c72b 100644
--- a/src/main/java/me/ryanhamshire/GriefPrevention/events/PreventBlockBreakEvent.java
+++ b/src/main/java/me/ryanhamshire/GriefPrevention/events/PreventBlockBreakEvent.java
@@ -7,9 +7,10 @@
import org.jetbrains.annotations.NotNull;
/**
- * An {@link Event} called when GriefPrevention prevents a {@link BlockBreakEvent}.
- * If cancelled, GriefPrevention will allow the event to complete normally.
+ * @deprecated Listen to {@link ClaimPermissionCheckEvent} and check if
+ * {@link ClaimPermissionCheckEvent#getTriggeringEvent()} {@code instanceof} {@link BlockBreakEvent}.
*/
+@Deprecated(forRemoval = true, since = "17.0.0")
public class PreventBlockBreakEvent extends Event implements Cancellable
{
private final @NotNull BlockBreakEvent innerEvent;
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 042f6346..d5bc1e02 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -95,21 +95,6 @@ commands:
usage: /
permission: griefprevention.adminclaims
aliases: ac
- restorenature:
- description: Switches the shovel tool to restoration mode.
- usage: /
- permission: griefprevention.restorenature
- aliases: rn
- restorenatureaggressive:
- description: Switches the shovel tool to aggressive restoration mode.
- usage: /
- permission: griefprevention.restorenatureaggressive
- aliases: rna
- restorenaturefill:
- description: Switches the shovel tool to fill mode.
- usage: /
- permission: griefprevention.restorenatureaggressive
- aliases: rnf
basicclaims:
description: Switches the shovel tool back to basic claims mode.
usage: /
@@ -173,14 +158,6 @@ commands:
description: Reloads Grief Prevention's configuration settings. Does NOT totally reload the entire plugin.
usage: /
permission: griefprevention.reload
- givepet:
- description: Allows a player to give away a pet he or she tamed.
- usage: /
- permission: griefprevention.givepet
- gpblockinfo:
- description: Allows an administrator to get technical information about blocks in the world and items in hand.
- usage: /
- permission: griefprevention.gpblockinfo
ignoreplayer:
description: Ignores another player's chat messages.
usage: /
@@ -215,8 +192,6 @@ permissions:
griefprevention.admin.*:
description: Grants all administrative functionality.
children:
- griefprevention.restorenature: true
- griefprevention.restorenatureaggressive: true
griefprevention.ignoreclaims: true
griefprevention.adminclaims: true
griefprevention.adjustclaimblocks: true
@@ -240,9 +215,6 @@ permissions:
griefprevention.deleteclaimsinworld: true
griefprevention.unlockothersdrops: true
griefprevention.seeclaimsize: true
- griefprevention.givepet:
- description: Grants permission to use /givepet.
- default: true
griefprevention.unlockdrops:
description: Grants permission to use /unlockdrops.
default: true
@@ -255,9 +227,6 @@ permissions:
griefprevention.claimslistother:
description: Grants permission to use /claimslist to get another player's information.
default: op
- griefprevention.restorenature:
- description: Grants permission to use /restorenature.
- default: op
griefprevention.transferclaim:
description: Grants permission to use /transferclaim.
default: op
@@ -285,9 +254,6 @@ permissions:
griefprevention.eavesdropsigns:
description: Allows a player to see sign placements as chat messages.
default: op
- griefprevention.restorenatureaggressive:
- description: Grants access to /restorenatureaggressive and /restorenaturefill.
- default: op
griefprevention.reload:
description: Grants access to /gpreload.
default: op
@@ -306,9 +272,6 @@ permissions:
griefprevention.seeclaimsize:
description: Allows a player to see claim size for other players claims when right clicking with investigation tool
default: op
- griefprevention.gpblockinfo:
- description: Grants access to /gpblockinfo.
- default: op
griefprevention.overrideclaimcountlimit:
description: Allows players to create more claims than the limit specified by the config.
default: op