From e3bce9a35ebaaf1f35d81d7635532c59268ede83 Mon Sep 17 00:00:00 2001 From: RoboMWM Date: Mon, 7 Sep 2020 05:32:16 -0700 Subject: [PATCH] git add --renormalize . --- .../GriefPrevention/CustomizableMessage.java | 64 +- .../DeliverClaimBlocksTask.java | 256 +++---- .../GriefPrevention/EntityCleanupTask.java | 298 ++++---- .../EquipShovelProcessingTask.java | 158 ++-- .../GriefPrevention/IpBanInfo.java | 70 +- .../GriefPrevention/MaterialCollection.java | 108 +-- .../GriefPrevention/MaterialInfo.java | 192 ++--- .../GriefPrevention/PlayerRescueTask.java | 150 ++-- .../RestoreNatureExecutionTask.java | 260 +++---- .../GriefPrevention/SecureClaimTask.java | 116 +-- .../SendPlayerMessageTask.java | 122 ++-- .../GriefPrevention/ShovelMode.java | 60 +- .../GriefPrevention/SiegeCheckupTask.java | 220 +++--- .../GriefPrevention/SiegeData.java | 80 +- .../GriefPrevention/Visualization.java | 684 +++++++++--------- .../VisualizationApplicationTask.java | 120 +-- .../GriefPrevention/VisualizationElement.java | 74 +- .../GriefPrevention/VisualizationType.java | 58 +- 18 files changed, 1545 insertions(+), 1545 deletions(-) diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java b/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java index 8d64657..b0cb406 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/CustomizableMessage.java @@ -1,33 +1,33 @@ -/* - 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; - } +/* + 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/DeliverClaimBlocksTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java index ddaec5c..e97bc40 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java @@ -1,128 +1,128 @@ -/* - 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 me.ryanhamshire.GriefPrevention.events.AccrueClaimBlocksEvent; -import org.bukkit.entity.Player; - -import java.util.Collection; - -//FEATURE: give players claim blocks for playing, as long as they're not away from their computer - -//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing -class DeliverClaimBlocksTask implements Runnable -{ - private Player player; - private GriefPrevention instance; - private int idleThresholdSquared; - - public DeliverClaimBlocksTask(Player player, GriefPrevention instance) - { - this.player = player; - this.instance = instance; - this.idleThresholdSquared = instance.config_claims_accruedIdleThreshold * instance.config_claims_accruedIdleThreshold; - } - - @Override - public void run() - { - //if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart - if (this.player == null) - { - @SuppressWarnings("unchecked") - Collection players = (Collection) GriefPrevention.instance.getServer().getOnlinePlayers(); - - long i = 0; - for (Player onlinePlayer : players) - { - DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance); - instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++); - } - - return; //tasks started for each player - } - - //deliver claim blocks to the specified player - if (!this.player.isOnline()) - { - return; //player is not online to receive claim blocks - } - - DataStore dataStore = instance.dataStore; - PlayerData playerData = dataStore.getPlayerData(player.getUniqueId()); - - // check if player is idle. considered idle if - // in vehicle or is in water (pushed by water) - // or has not moved at least defined blocks since last check - boolean isIdle = false; - try - { - isIdle = player.isInsideVehicle() || player.getLocation().getBlock().isLiquid() || - !(playerData.lastAfkCheckLocation == null || playerData.lastAfkCheckLocation.distanceSquared(player.getLocation()) > idleThresholdSquared); - } - catch (IllegalArgumentException ignore) //can't measure distance when to/from are different worlds - { - } - - //remember current location for next time - playerData.lastAfkCheckLocation = player.getLocation(); - - try - { - //determine how fast blocks accrue for this player //RoboMWM: addons determine this instead - int accrualRate = instance.config_claims_blocksAccruedPerHour_default; - - //determine idle accrual rate when idle - if (isIdle) - { - if (instance.config_claims_accruedIdlePercent <= 0) - { - GriefPrevention.AddLogEntry(player.getName() + " wasn't active enough to accrue claim blocks this round.", CustomLogEntryTypes.Debug, true); - return; //idle accrual percentage is disabled - } - - accrualRate = (int) (accrualRate * (instance.config_claims_accruedIdlePercent / 100.0D)); - } - - //fire event for addons - AccrueClaimBlocksEvent event = new AccrueClaimBlocksEvent(player, accrualRate, isIdle); - instance.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) - { - GriefPrevention.AddLogEntry(player.getName() + " claim block delivery was canceled by another plugin.", CustomLogEntryTypes.Debug, true); - return; //event was cancelled - } - - //set actual accrual - accrualRate = event.getBlocksToAccrue(); - if (accrualRate < 0) accrualRate = 0; - playerData.accrueBlocks(accrualRate); - GriefPrevention.AddLogEntry("Delivering " + event.getBlocksToAccrue() + " blocks to " + player.getName(), CustomLogEntryTypes.Debug, true); - - //intentionally NOT saving data here to reduce overall secondary storage access frequency - //many other operations will cause this player's data to save, including his eventual logout - //dataStore.savePlayerData(player.getUniqueIdentifier(), playerData); - } - catch (Exception e) - { - GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":"); - e.printStackTrace(); - } - } -} +/* + 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 me.ryanhamshire.GriefPrevention.events.AccrueClaimBlocksEvent; +import org.bukkit.entity.Player; + +import java.util.Collection; + +//FEATURE: give players claim blocks for playing, as long as they're not away from their computer + +//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing +class DeliverClaimBlocksTask implements Runnable +{ + private Player player; + private GriefPrevention instance; + private int idleThresholdSquared; + + public DeliverClaimBlocksTask(Player player, GriefPrevention instance) + { + this.player = player; + this.instance = instance; + this.idleThresholdSquared = instance.config_claims_accruedIdleThreshold * instance.config_claims_accruedIdleThreshold; + } + + @Override + public void run() + { + //if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart + if (this.player == null) + { + @SuppressWarnings("unchecked") + Collection players = (Collection) GriefPrevention.instance.getServer().getOnlinePlayers(); + + long i = 0; + for (Player onlinePlayer : players) + { + DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance); + instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++); + } + + return; //tasks started for each player + } + + //deliver claim blocks to the specified player + if (!this.player.isOnline()) + { + return; //player is not online to receive claim blocks + } + + DataStore dataStore = instance.dataStore; + PlayerData playerData = dataStore.getPlayerData(player.getUniqueId()); + + // check if player is idle. considered idle if + // in vehicle or is in water (pushed by water) + // or has not moved at least defined blocks since last check + boolean isIdle = false; + try + { + isIdle = player.isInsideVehicle() || player.getLocation().getBlock().isLiquid() || + !(playerData.lastAfkCheckLocation == null || playerData.lastAfkCheckLocation.distanceSquared(player.getLocation()) > idleThresholdSquared); + } + catch (IllegalArgumentException ignore) //can't measure distance when to/from are different worlds + { + } + + //remember current location for next time + playerData.lastAfkCheckLocation = player.getLocation(); + + try + { + //determine how fast blocks accrue for this player //RoboMWM: addons determine this instead + int accrualRate = instance.config_claims_blocksAccruedPerHour_default; + + //determine idle accrual rate when idle + if (isIdle) + { + if (instance.config_claims_accruedIdlePercent <= 0) + { + GriefPrevention.AddLogEntry(player.getName() + " wasn't active enough to accrue claim blocks this round.", CustomLogEntryTypes.Debug, true); + return; //idle accrual percentage is disabled + } + + accrualRate = (int) (accrualRate * (instance.config_claims_accruedIdlePercent / 100.0D)); + } + + //fire event for addons + AccrueClaimBlocksEvent event = new AccrueClaimBlocksEvent(player, accrualRate, isIdle); + instance.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) + { + GriefPrevention.AddLogEntry(player.getName() + " claim block delivery was canceled by another plugin.", CustomLogEntryTypes.Debug, true); + return; //event was cancelled + } + + //set actual accrual + accrualRate = event.getBlocksToAccrue(); + if (accrualRate < 0) accrualRate = 0; + playerData.accrueBlocks(accrualRate); + GriefPrevention.AddLogEntry("Delivering " + event.getBlocksToAccrue() + " blocks to " + player.getName(), CustomLogEntryTypes.Debug, true); + + //intentionally NOT saving data here to reduce overall secondary storage access frequency + //many other operations will cause this player's data to save, including his eventual logout + //dataStore.savePlayerData(player.getUniqueIdentifier(), playerData); + } + catch (Exception e) + { + GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":"); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/EntityCleanupTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/EntityCleanupTask.java index 980ad24..16d03cb 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/EntityCleanupTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/EntityCleanupTask.java @@ -1,149 +1,149 @@ -/* - 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.Material; -import org.bukkit.World; -import org.bukkit.entity.Boat; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; - -import java.util.ArrayList; -import java.util.List; - -//FEATURE: creative mode worlds get a regular entity cleanup - -//this main thread task revisits the location of a partially chopped tree from several minutes ago -//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts -class EntityCleanupTask implements Runnable -{ - //where to start cleaning in the list of entities - private double percentageStart; - - public EntityCleanupTask(double percentageStart) - { - this.percentageStart = percentageStart; - } - - @Override - public void run() - { - ArrayList worlds = new ArrayList(); - for (World world : GriefPrevention.instance.getServer().getWorlds()) - { - if (GriefPrevention.instance.config_claims_worldModes.get(world) == ClaimsMode.Creative) - { - worlds.add(world); - } - } - - for (int i = 0; i < worlds.size(); i++) - { - World world = worlds.get(i); - - List entities = world.getEntities(); - - //starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities - int j = (int) (entities.size() * this.percentageStart); - int k = (int) (entities.size() * (this.percentageStart + .1)); - Claim cachedClaim = null; - for (; j < entities.size() && j < k; j++) - { - Entity entity = entities.get(j); - - boolean remove = false; - if (entity instanceof Boat) //boats must be occupied - { - Boat boat = (Boat) entity; - if (boat.isEmpty()) remove = true; - } - else if (entity instanceof Vehicle) - { - Vehicle vehicle = (Vehicle) entity; - - //minecarts in motion must be occupied by a player - if (vehicle.getVelocity().lengthSquared() != 0) - { - if (vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player)) - { - remove = true; - } - } - - //stationary carts must be on rails - else - { - Material material = world.getBlockAt(vehicle.getLocation()).getType(); - if (material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL) - { - remove = true; - } - } - } - - //all non-player entities must be in claims - else if (!(entity instanceof Player)) - { - Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim); - if (claim != null) - { - cachedClaim = claim; - } - else - { - remove = true; - } - } - - if (remove) - { - GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true); - entity.remove(); - } - } - } - - //starting and stopping point. each execution of the task scans 5% of the server's claims - List claims = GriefPrevention.instance.dataStore.claims; - int j = (int) (claims.size() * this.percentageStart); - int k = (int) (claims.size() * (this.percentageStart + .05)); - for (; j < claims.size() && j < k; j++) - { - Claim claim = claims.get(j); - - //if it's a creative mode claim - if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner())) - { - //check its entity count and remove any extras - claim.allowMoreEntities(true); - } - } - - //schedule the next run of this task, in 3 minutes (20L is approximately 1 second) - double nextRunPercentageStart = this.percentageStart + .05; - if (nextRunPercentageStart > .99) - { - nextRunPercentageStart = 0; - } - - EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart); - GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1); - } -} +/* + 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.Material; +import org.bukkit.World; +import org.bukkit.entity.Boat; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; + +import java.util.ArrayList; +import java.util.List; + +//FEATURE: creative mode worlds get a regular entity cleanup + +//this main thread task revisits the location of a partially chopped tree from several minutes ago +//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts +class EntityCleanupTask implements Runnable +{ + //where to start cleaning in the list of entities + private double percentageStart; + + public EntityCleanupTask(double percentageStart) + { + this.percentageStart = percentageStart; + } + + @Override + public void run() + { + ArrayList worlds = new ArrayList(); + for (World world : GriefPrevention.instance.getServer().getWorlds()) + { + if (GriefPrevention.instance.config_claims_worldModes.get(world) == ClaimsMode.Creative) + { + worlds.add(world); + } + } + + for (int i = 0; i < worlds.size(); i++) + { + World world = worlds.get(i); + + List entities = world.getEntities(); + + //starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities + int j = (int) (entities.size() * this.percentageStart); + int k = (int) (entities.size() * (this.percentageStart + .1)); + Claim cachedClaim = null; + for (; j < entities.size() && j < k; j++) + { + Entity entity = entities.get(j); + + boolean remove = false; + if (entity instanceof Boat) //boats must be occupied + { + Boat boat = (Boat) entity; + if (boat.isEmpty()) remove = true; + } + else if (entity instanceof Vehicle) + { + Vehicle vehicle = (Vehicle) entity; + + //minecarts in motion must be occupied by a player + if (vehicle.getVelocity().lengthSquared() != 0) + { + if (vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player)) + { + remove = true; + } + } + + //stationary carts must be on rails + else + { + Material material = world.getBlockAt(vehicle.getLocation()).getType(); + if (material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL) + { + remove = true; + } + } + } + + //all non-player entities must be in claims + else if (!(entity instanceof Player)) + { + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim); + if (claim != null) + { + cachedClaim = claim; + } + else + { + remove = true; + } + } + + if (remove) + { + GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true); + entity.remove(); + } + } + } + + //starting and stopping point. each execution of the task scans 5% of the server's claims + List claims = GriefPrevention.instance.dataStore.claims; + int j = (int) (claims.size() * this.percentageStart); + int k = (int) (claims.size() * (this.percentageStart + .05)); + for (; j < claims.size() && j < k; j++) + { + Claim claim = claims.get(j); + + //if it's a creative mode claim + if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner())) + { + //check its entity count and remove any extras + claim.allowMoreEntities(true); + } + } + + //schedule the next run of this task, in 3 minutes (20L is approximately 1 second) + double nextRunPercentageStart = this.percentageStart + .05; + if (nextRunPercentageStart > .99) + { + nextRunPercentageStart = 0; + } + + EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart); + GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1); + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/EquipShovelProcessingTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/EquipShovelProcessingTask.java index b27abef..3ead14e 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/EquipShovelProcessingTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/EquipShovelProcessingTask.java @@ -1,79 +1,79 @@ -/* - 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.entity.Player; -import org.bukkit.inventory.EquipmentSlot; - -//tells a player about how many claim blocks he has, etc -//implemented as a task so that it can be delayed -//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars -class EquipShovelProcessingTask implements Runnable -{ - //player data - private Player player; - - public EquipShovelProcessingTask(Player player) - { - this.player = player; - } - - @Override - public void run() - { - //if he's not holding the golden shovel anymore, do nothing - if (GriefPrevention.instance.getItemInHand(player, EquipmentSlot.HAND).getType() != GriefPrevention.instance.config_claims_modificationTool) - return; - - PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); - - //reset any work he might have been doing - playerData.lastShovelLocation = null; - playerData.claimResizing = null; - - //always reset to basic claims mode - if (playerData.shovelMode != ShovelMode.Basic) - { - playerData.shovelMode = ShovelMode.Basic; - GriefPrevention.sendMessage(player, TextMode.Info, Messages.ShovelBasicClaimMode); - } - - //tell him how many claim blocks he has available - int remainingBlocks = playerData.getRemainingClaimBlocks(); - GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks)); - - //link to a video demo of land claiming, based on world type - if (GriefPrevention.instance.creativeRulesApply(player.getLocation())) - { - GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL); - } - else if (GriefPrevention.instance.claimsEnabledForWorld(player.getLocation().getWorld())) - { - GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL); - } - - //if standing in a claim owned by the player, visualize it - Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, playerData.lastClaim); - if (claim != null && claim.allowEdit(player) == null) - { - playerData.lastClaim = claim; - Visualization.Apply(player, Visualization.FromClaim(claim, player.getEyeLocation().getBlockY(), VisualizationType.Claim, player.getLocation())); - } - } -} +/* + 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.entity.Player; +import org.bukkit.inventory.EquipmentSlot; + +//tells a player about how many claim blocks he has, etc +//implemented as a task so that it can be delayed +//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars +class EquipShovelProcessingTask implements Runnable +{ + //player data + private Player player; + + public EquipShovelProcessingTask(Player player) + { + this.player = player; + } + + @Override + public void run() + { + //if he's not holding the golden shovel anymore, do nothing + if (GriefPrevention.instance.getItemInHand(player, EquipmentSlot.HAND).getType() != GriefPrevention.instance.config_claims_modificationTool) + return; + + PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); + + //reset any work he might have been doing + playerData.lastShovelLocation = null; + playerData.claimResizing = null; + + //always reset to basic claims mode + if (playerData.shovelMode != ShovelMode.Basic) + { + playerData.shovelMode = ShovelMode.Basic; + GriefPrevention.sendMessage(player, TextMode.Info, Messages.ShovelBasicClaimMode); + } + + //tell him how many claim blocks he has available + int remainingBlocks = playerData.getRemainingClaimBlocks(); + GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks)); + + //link to a video demo of land claiming, based on world type + if (GriefPrevention.instance.creativeRulesApply(player.getLocation())) + { + GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL); + } + else if (GriefPrevention.instance.claimsEnabledForWorld(player.getLocation().getWorld())) + { + GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL); + } + + //if standing in a claim owned by the player, visualize it + Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, playerData.lastClaim); + if (claim != null && claim.allowEdit(player) == null) + { + playerData.lastClaim = claim; + Visualization.Apply(player, Visualization.FromClaim(claim, player.getEyeLocation().getBlockY(), VisualizationType.Claim, player.getLocation())); + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/IpBanInfo.java b/src/main/java/me/ryanhamshire/GriefPrevention/IpBanInfo.java index 2d147f1..a4e6173 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/IpBanInfo.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/IpBanInfo.java @@ -1,35 +1,35 @@ -/* - 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 java.net.InetAddress; - -public class IpBanInfo -{ - InetAddress address; - long expirationTimestamp; - String bannedAccountName; - - IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName) - { - this.address = address; - this.expirationTimestamp = expirationTimestamp; - this.bannedAccountName = bannedAccountName; - } -} +/* + 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 java.net.InetAddress; + +public class IpBanInfo +{ + InetAddress address; + long expirationTimestamp; + String bannedAccountName; + + IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName) + { + this.address = address; + this.expirationTimestamp = expirationTimestamp; + this.bannedAccountName = bannedAccountName; + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/MaterialCollection.java b/src/main/java/me/ryanhamshire/GriefPrevention/MaterialCollection.java index 795c643..3ef7bd3 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/MaterialCollection.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/MaterialCollection.java @@ -1,54 +1,54 @@ -/* - 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 java.util.HashSet; -import java.util.Set; - -//ordered list of material info objects, for fast searching -public class MaterialCollection -{ - Set materials = new HashSet(); - - void Add(MaterialInfo material) - { - this.materials.add(material); - } - - boolean Contains(MaterialInfo material) - { - return this.materials.contains(material); - } - - @Override - public String toString() - { - return materials.toString(); - } - - public int size() - { - return this.materials.size(); - } - - public void clear() - { - this.materials.clear(); - } -} +/* + 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 java.util.HashSet; +import java.util.Set; + +//ordered list of material info objects, for fast searching +public class MaterialCollection +{ + Set materials = new HashSet(); + + void Add(MaterialInfo material) + { + this.materials.add(material); + } + + boolean Contains(MaterialInfo material) + { + return this.materials.contains(material); + } + + @Override + public String toString() + { + return materials.toString(); + } + + public int size() + { + return this.materials.size(); + } + + public void clear() + { + this.materials.clear(); + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/MaterialInfo.java b/src/main/java/me/ryanhamshire/GriefPrevention/MaterialInfo.java index 98e6451..16da4ce 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/MaterialInfo.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/MaterialInfo.java @@ -1,96 +1,96 @@ -/* - 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; - -//represents a material or collection of materials - -import org.bukkit.Material; - -public class MaterialInfo -{ - Material typeID; - byte data; - boolean allDataValues; - String description; - - public MaterialInfo(Material typeID, byte data, String description) - { - this.typeID = typeID; - this.data = data; - this.allDataValues = false; - this.description = description; - } - - public MaterialInfo(Material typeID, String description) - { - this.typeID = typeID; - this.data = 0; - this.allDataValues = true; - this.description = description; - } - - private MaterialInfo(Material typeID, byte data, boolean allDataValues, String description) - { - this.typeID = typeID; - this.data = data; - this.allDataValues = allDataValues; - this.description = description; - } - - @Override - public String toString() - { - String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues ? "*" : String.valueOf(this.data)); - if (this.description != null) returnValue += ":" + this.description; - - return returnValue; - } - - public static MaterialInfo fromString(String string) - { - if (string == null || string.isEmpty()) return null; - - String[] parts = string.split(":"); - if (parts.length < 3) return null; - - try - { - Material typeID = Material.matchMaterial(parts[0]); - - byte data; - boolean allDataValues; - if (parts[1].equals("*")) - { - allDataValues = true; - data = 0; - } - else - { - allDataValues = false; - data = Byte.parseByte(parts[1]); - } - - return new MaterialInfo(typeID, data, allDataValues, parts[2]); - } - catch (NumberFormatException exception) - { - return null; - } - } -} +/* + 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; + +//represents a material or collection of materials + +import org.bukkit.Material; + +public class MaterialInfo +{ + Material typeID; + byte data; + boolean allDataValues; + String description; + + public MaterialInfo(Material typeID, byte data, String description) + { + this.typeID = typeID; + this.data = data; + this.allDataValues = false; + this.description = description; + } + + public MaterialInfo(Material typeID, String description) + { + this.typeID = typeID; + this.data = 0; + this.allDataValues = true; + this.description = description; + } + + private MaterialInfo(Material typeID, byte data, boolean allDataValues, String description) + { + this.typeID = typeID; + this.data = data; + this.allDataValues = allDataValues; + this.description = description; + } + + @Override + public String toString() + { + String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues ? "*" : String.valueOf(this.data)); + if (this.description != null) returnValue += ":" + this.description; + + return returnValue; + } + + public static MaterialInfo fromString(String string) + { + if (string == null || string.isEmpty()) return null; + + String[] parts = string.split(":"); + if (parts.length < 3) return null; + + try + { + Material typeID = Material.matchMaterial(parts[0]); + + byte data; + boolean allDataValues; + if (parts[1].equals("*")) + { + allDataValues = true; + data = 0; + } + else + { + allDataValues = false; + data = Byte.parseByte(parts[1]); + } + + return new MaterialInfo(typeID, data, allDataValues, parts[2]); + } + catch (NumberFormatException exception) + { + return null; + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerRescueTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerRescueTask.java index d07927b..6d6ddeb 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/PlayerRescueTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/PlayerRescueTask.java @@ -1,75 +1,75 @@ -/* - 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.entity.Player; - -//tries to rescue a trapped player from a claim where he doesn't have permission to save himself -//related to the /trapped slash command -//this does run in the main thread, so it's okay to make non-thread-safe calls -class PlayerRescueTask implements Runnable -{ - //original location where /trapped was used - private Location location; - - //rescue destination, may be decided at instantiation or at execution - private Location destination; - - //player data - private Player player; - - public PlayerRescueTask(Player player, Location location, Location destination) - { - this.player = player; - this.location = location; - this.destination = destination; - } - - @Override - public void run() - { - //if he logged out, don't do anything - if (!player.isOnline()) return; - - //he no longer has a pending /trapped slash command, so he can try to use it again now - PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); - playerData.pendingTrapped = false; - - //if the player moved three or more blocks from where he used /trapped, admonish him and don't save him - if (!player.getLocation().getWorld().equals(this.location.getWorld()) || player.getLocation().distance(this.location) > 3) - { - GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved); - return; - } - - //otherwise find a place to teleport him - if (this.destination == null) - { - this.destination = GriefPrevention.instance.ejectPlayer(this.player); - } - else - { - player.teleport(this.destination); - } - - //log entry, in case admins want to investigate the "trap" - GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(this.destination) + "."); - } -} +/* + 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.entity.Player; + +//tries to rescue a trapped player from a claim where he doesn't have permission to save himself +//related to the /trapped slash command +//this does run in the main thread, so it's okay to make non-thread-safe calls +class PlayerRescueTask implements Runnable +{ + //original location where /trapped was used + private Location location; + + //rescue destination, may be decided at instantiation or at execution + private Location destination; + + //player data + private Player player; + + public PlayerRescueTask(Player player, Location location, Location destination) + { + this.player = player; + this.location = location; + this.destination = destination; + } + + @Override + public void run() + { + //if he logged out, don't do anything + if (!player.isOnline()) return; + + //he no longer has a pending /trapped slash command, so he can try to use it again now + PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); + playerData.pendingTrapped = false; + + //if the player moved three or more blocks from where he used /trapped, admonish him and don't save him + if (!player.getLocation().getWorld().equals(this.location.getWorld()) || player.getLocation().distance(this.location) > 3) + { + GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved); + return; + } + + //otherwise find a place to teleport him + if (this.destination == null) + { + this.destination = GriefPrevention.instance.ejectPlayer(this.player); + } + else + { + player.teleport(this.destination); + } + + //log entry, in case admins want to investigate the "trap" + GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(this.destination) + "."); + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java index 2febb0f..c58c6fe 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/RestoreNatureExecutionTask.java @@ -1,130 +1,130 @@ -/* - 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.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; - -import java.util.ArrayList; - -//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 BlockSnapshot[][][] snapshots; - - //boundaries for changes - private int miny; - private Location lesserCorner; - private Location greaterCorner; - - //player who should be notified about the result (will see a visualization when the restoration is complete) - private 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 (int i = 0; i < entities.length; i++) - { - Entity entity = entities[i]; - 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) - { - Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), null); - Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation()); - Visualization.Apply(player, visualization); - } - } -} +/* + 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.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; + +import java.util.ArrayList; + +//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 BlockSnapshot[][][] snapshots; + + //boundaries for changes + private int miny; + private Location lesserCorner; + private Location greaterCorner; + + //player who should be notified about the result (will see a visualization when the restoration is complete) + private 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 (int i = 0; i < entities.length; i++) + { + Entity entity = entities[i]; + 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) + { + Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), null); + Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation()); + Visualization.Apply(player, visualization); + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/SecureClaimTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/SecureClaimTask.java index e63199f..6f7ed22 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/SecureClaimTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/SecureClaimTask.java @@ -1,58 +1,58 @@ -/* - 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.entity.Player; - -import java.util.Collection; - -//secures a claim after a siege looting window has closed -class SecureClaimTask implements Runnable -{ - private SiegeData siegeData; - - public SecureClaimTask(SiegeData siegeData) - { - this.siegeData = siegeData; - } - - @Override - public void run() - { - //for each claim involved in this siege - for (int i = 0; i < this.siegeData.claims.size(); i++) - { - //lock the doors - Claim claim = this.siegeData.claims.get(i); - claim.doorsOpen = false; - - //eject bad guys - @SuppressWarnings("unchecked") - Collection onlinePlayers = (Collection) GriefPrevention.instance.getServer().getOnlinePlayers(); - for (Player player : onlinePlayers) - { - if (claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null) - { - GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection); - GriefPrevention.instance.ejectPlayer(player); - } - } - } - } -} +/* + 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.entity.Player; + +import java.util.Collection; + +//secures a claim after a siege looting window has closed +class SecureClaimTask implements Runnable +{ + private SiegeData siegeData; + + public SecureClaimTask(SiegeData siegeData) + { + this.siegeData = siegeData; + } + + @Override + public void run() + { + //for each claim involved in this siege + for (int i = 0; i < this.siegeData.claims.size(); i++) + { + //lock the doors + Claim claim = this.siegeData.claims.get(i); + claim.doorsOpen = false; + + //eject bad guys + @SuppressWarnings("unchecked") + Collection onlinePlayers = (Collection) GriefPrevention.instance.getServer().getOnlinePlayers(); + for (Player player : onlinePlayers) + { + if (claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null) + { + GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection); + GriefPrevention.instance.ejectPlayer(player); + } + } + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/SendPlayerMessageTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/SendPlayerMessageTask.java index 9979b9a..e65652d 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/SendPlayerMessageTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/SendPlayerMessageTask.java @@ -1,61 +1,61 @@ -/* - 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.ChatColor; -import org.bukkit.entity.Player; - -//sends a message to a player -//used to send delayed messages, for example help text triggered by a player's chat -class SendPlayerMessageTask implements Runnable -{ - private Player player; - private ChatColor color; - private String message; - - public SendPlayerMessageTask(Player player, ChatColor color, String message) - { - this.player = player; - this.color = color; - this.message = message; - } - - @Override - public void run() - { - if (player == null) - { - GriefPrevention.AddLogEntry(color + message); - return; - } - - //if the player is dead, save it for after his respawn - if (this.player.isDead()) - { - PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId()); - playerData.messageOnRespawn = this.color + this.message; - } - - //otherwise send it immediately - else - { - GriefPrevention.sendMessage(this.player, this.color, this.message); - } - } -} +/* + 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.ChatColor; +import org.bukkit.entity.Player; + +//sends a message to a player +//used to send delayed messages, for example help text triggered by a player's chat +class SendPlayerMessageTask implements Runnable +{ + private Player player; + private ChatColor color; + private String message; + + public SendPlayerMessageTask(Player player, ChatColor color, String message) + { + this.player = player; + this.color = color; + this.message = message; + } + + @Override + public void run() + { + if (player == null) + { + GriefPrevention.AddLogEntry(color + message); + return; + } + + //if the player is dead, save it for after his respawn + if (this.player.isDead()) + { + PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId()); + playerData.messageOnRespawn = this.color + this.message; + } + + //otherwise send it immediately + else + { + GriefPrevention.sendMessage(this.player, this.color, this.message); + } + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java b/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java index 1fbb5fe..3985be4 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/ShovelMode.java @@ -1,30 +1,30 @@ -/* - 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; - -//enumeration for golden shovel modes -public enum ShovelMode -{ - Basic, - Admin, - Subdivide, - RestoreNature, - RestoreNatureAggressive, - RestoreNatureFill -} +/* + 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; + +//enumeration for golden shovel modes +public enum ShovelMode +{ + Basic, + Admin, + Subdivide, + RestoreNature, + RestoreNatureAggressive, + RestoreNatureFill +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/SiegeCheckupTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/SiegeCheckupTask.java index 346e6ce..3a52cbd 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/SiegeCheckupTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/SiegeCheckupTask.java @@ -1,110 +1,110 @@ -/* - 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.entity.Player; - -//checks to see whether or not a siege should end based on the locations of the players -//for example, defender escaped or attacker gave up and left -class SiegeCheckupTask implements Runnable -{ - private SiegeData siegeData; - - public SiegeCheckupTask(SiegeData siegeData) - { - this.siegeData = siegeData; - } - - @Override - public void run() - { - DataStore dataStore = GriefPrevention.instance.dataStore; - Player defender = this.siegeData.defender; - Player attacker = this.siegeData.attacker; - - //where is the defender? - Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null); - - //if this is a new claim and he has some permission there, extend the siege to include it - if (defenderClaim != null) - { - String noAccessReason = defenderClaim.allowAccess(defender); - if (defenderClaim.canSiege(defender) && noAccessReason == null) - { - this.siegeData.claims.add(defenderClaim); - defenderClaim.siegeData = this.siegeData; - } - } - - //determine who's close enough to the siege area to be considered "still here" - boolean attackerRemains = this.playerRemains(attacker); - boolean defenderRemains = this.playerRemains(defender); - - //if they're both here, just plan to come check again later - if (attackerRemains && defenderRemains) - { - this.scheduleAnotherCheck(); - } - - //otherwise attacker wins if the defender runs away - else if (attackerRemains && !defenderRemains) - { - dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); - } - - //or defender wins if the attacker leaves - else if (!attackerRemains && defenderRemains) - { - dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), null); - } - - //if they both left, but are still close together, the battle continues (check again later) - else if (attacker.getWorld().equals(defender.getWorld()) && attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing - { - this.scheduleAnotherCheck(); - } - - //otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase) - else - { - dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); - } - } - - //a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight - private boolean playerRemains(Player player) - { - for (int i = 0; i < this.siegeData.claims.size(); i++) - { - Claim claim = this.siegeData.claims.get(i); - if (claim.isNear(player.getLocation(), 25)) - { - return true; - } - } - - return false; - } - - //schedules another checkup later - private void scheduleAnotherCheck() - { - this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30); - } -} +/* + 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.entity.Player; + +//checks to see whether or not a siege should end based on the locations of the players +//for example, defender escaped or attacker gave up and left +class SiegeCheckupTask implements Runnable +{ + private SiegeData siegeData; + + public SiegeCheckupTask(SiegeData siegeData) + { + this.siegeData = siegeData; + } + + @Override + public void run() + { + DataStore dataStore = GriefPrevention.instance.dataStore; + Player defender = this.siegeData.defender; + Player attacker = this.siegeData.attacker; + + //where is the defender? + Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null); + + //if this is a new claim and he has some permission there, extend the siege to include it + if (defenderClaim != null) + { + String noAccessReason = defenderClaim.allowAccess(defender); + if (defenderClaim.canSiege(defender) && noAccessReason == null) + { + this.siegeData.claims.add(defenderClaim); + defenderClaim.siegeData = this.siegeData; + } + } + + //determine who's close enough to the siege area to be considered "still here" + boolean attackerRemains = this.playerRemains(attacker); + boolean defenderRemains = this.playerRemains(defender); + + //if they're both here, just plan to come check again later + if (attackerRemains && defenderRemains) + { + this.scheduleAnotherCheck(); + } + + //otherwise attacker wins if the defender runs away + else if (attackerRemains && !defenderRemains) + { + dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); + } + + //or defender wins if the attacker leaves + else if (!attackerRemains && defenderRemains) + { + dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), null); + } + + //if they both left, but are still close together, the battle continues (check again later) + else if (attacker.getWorld().equals(defender.getWorld()) && attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing + { + this.scheduleAnotherCheck(); + } + + //otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase) + else + { + dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); + } + } + + //a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight + private boolean playerRemains(Player player) + { + for (int i = 0; i < this.siegeData.claims.size(); i++) + { + Claim claim = this.siegeData.claims.get(i); + if (claim.isNear(player.getLocation(), 25)) + { + return true; + } + } + + return false; + } + + //schedules another checkup later + private void scheduleAnotherCheck() + { + this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30); + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/SiegeData.java b/src/main/java/me/ryanhamshire/GriefPrevention/SiegeData.java index 2fdd7c5..847e691 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/SiegeData.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/SiegeData.java @@ -1,40 +1,40 @@ -/* - 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.entity.Player; - -import java.util.ArrayList; - -//information about an ongoing siege -public class SiegeData -{ - public Player defender; - public Player attacker; - public ArrayList claims; - public int checkupTaskID; - - public SiegeData(Player attacker, Player defender, Claim claim) - { - this.defender = defender; - this.attacker = attacker; - this.claims = new ArrayList(); - this.claims.add(claim); - } -} +/* + 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.entity.Player; + +import java.util.ArrayList; + +//information about an ongoing siege +public class SiegeData +{ + public Player defender; + public Player attacker; + public ArrayList claims; + public int checkupTaskID; + + public SiegeData(Player attacker, Player defender, Claim claim) + { + this.defender = defender; + this.attacker = attacker; + this.claims = new ArrayList(); + this.claims.add(claim); + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/Visualization.java b/src/main/java/me/ryanhamshire/GriefPrevention/Visualization.java index e1631f0..54e495a 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/Visualization.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/Visualization.java @@ -1,342 +1,342 @@ -/* - 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.Tag; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Lightable; -import org.bukkit.entity.Player; -import org.bukkit.util.BoundingBox; -import org.bukkit.util.Vector; - -import java.util.ArrayList; - -//represents a visualization sent to a player -//FEATURE: to show players visually where claim boundaries are, we send them fake block change packets -//the result is that those players see new blocks, but the world hasn't been changed. other players can't see the new blocks, either. -public class Visualization -{ - public ArrayList elements = new ArrayList(); - - //sends a visualization to a player - public static void Apply(Player player, Visualization visualization) - { - PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); - - //if he has any current visualization, clear it first - if (playerData.currentVisualization != null) - { - Visualization.Revert(player); - } - - //if he's online, create a task to send him the visualization - if (player.isOnline() && visualization.elements.size() > 0 && visualization.elements.get(0).location.getWorld().equals(player.getWorld())) - { - GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new VisualizationApplicationTask(player, playerData, visualization), 1L); - } - } - - //reverts a visualization by sending another block change list, this time with the real world block values - - public static void Revert(Player player) - { - if (!player.isOnline()) return; - - PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); - - Visualization visualization = playerData.currentVisualization; - - if (playerData.currentVisualization != null) - { - //locality - int minx = player.getLocation().getBlockX() - 100; - int minz = player.getLocation().getBlockZ() - 100; - int maxx = player.getLocation().getBlockX() + 100; - int maxz = player.getLocation().getBlockZ() + 100; - - //remove any elements which are too far away - visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz); - - //send real block information for any remaining elements - for (int i = 0; i < visualization.elements.size(); i++) - { - VisualizationElement element = visualization.elements.get(i); - - //check player still in world where visualization exists - if (i == 0) - { - if (!player.getWorld().equals(element.location.getWorld())) return; - } - - player.sendBlockChange(element.location, element.realBlock); - } - - playerData.currentVisualization = null; - } - } - - //convenience method to build a visualization from a claim - //visualizationType determines the style (gold blocks, silver, red, diamond, etc) - public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality) - { - //visualize only top level claims - if (claim.parent != null) - { - return FromClaim(claim.parent, height, visualizationType, locality); - } - - Visualization visualization = new Visualization(); - - //add subdivisions first - for (int i = 0; i < claim.children.size(); i++) - { - Claim child = claim.children.get(i); - if (!child.inDataStore) continue; - visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality); - } - - //special visualization for administrative land claims - if (claim.isAdminClaim() && visualizationType == VisualizationType.Claim) - { - visualizationType = VisualizationType.AdminClaim; - } - - //add top level last so that it takes precedence (it shows on top when the child claim boundaries overlap with its boundaries) - visualization.addClaimElements(claim, height, visualizationType, locality); - - return visualization; - } - - //adds a claim's visualization to the current visualization - //handy for combining several visualizations together, as when visualization a top level claim with several subdivisions inside - //locality is a performance consideration. only create visualization blocks for around 100 blocks of the locality - - public void addClaimElements(Claim claim, int height, VisualizationType visualizationType, Location locality) - { - BlockData cornerBlockData; - BlockData accentBlockData; - - if (visualizationType == VisualizationType.Claim) - { - cornerBlockData = Material.GLOWSTONE.createBlockData(); - accentBlockData = Material.GOLD_BLOCK.createBlockData(); - } - else if (visualizationType == VisualizationType.AdminClaim) - { - cornerBlockData = Material.GLOWSTONE.createBlockData(); - accentBlockData = Material.PUMPKIN.createBlockData(); - } - else if (visualizationType == VisualizationType.Subdivision) - { - cornerBlockData = Material.IRON_BLOCK.createBlockData(); - accentBlockData = Material.WHITE_WOOL.createBlockData(); - } - else if (visualizationType == VisualizationType.RestoreNature) - { - cornerBlockData = Material.DIAMOND_BLOCK.createBlockData(); - accentBlockData = Material.DIAMOND_BLOCK.createBlockData(); - } - else - { - cornerBlockData = Material.REDSTONE_ORE.createBlockData(); - ((Lightable) cornerBlockData).setLit(true); - accentBlockData = Material.NETHERRACK.createBlockData(); - } - - addClaimElements(claim.getLesserBoundaryCorner(), claim.getGreaterBoundaryCorner(), locality, height, cornerBlockData, accentBlockData, 10); - } - - //adds a general claim cuboid (represented by min and max) visualization to the current visualization - public void addClaimElements(Location min, Location max, Location locality, int height, BlockData cornerBlockData, BlockData accentBlockData, int STEP) { - World world = min.getWorld(); - boolean waterIsTransparent = locality.getBlock().getType() == Material.WATER; - - int smallx = min.getBlockX(); - int smallz = min.getBlockZ(); - int bigx = max.getBlockX(); - int bigz = max.getBlockZ(); - - ArrayList newElements = new ArrayList<>(); - - //initialize visualization elements without Y values and real data - //that will be added later for only the visualization elements within visualization range - - //locality - int minx = locality.getBlockX() - 75; - int minz = locality.getBlockZ() - 75; - int maxx = locality.getBlockX() + 75; - int maxz = locality.getBlockZ() + 75; - - //top line - newElements.add(new VisualizationElement(new Location(world, smallx, 0, bigz), cornerBlockData, Material.AIR.createBlockData())); - newElements.add(new VisualizationElement(new Location(world, smallx + 1, 0, bigz), accentBlockData, Material.AIR.createBlockData())); - for (int x = smallx + STEP; x < bigx - STEP / 2; x += STEP) - { - if (x > minx && x < maxx) - newElements.add(new VisualizationElement(new Location(world, x, 0, bigz), accentBlockData, Material.AIR.createBlockData())); - } - newElements.add(new VisualizationElement(new Location(world, bigx - 1, 0, bigz), accentBlockData, Material.AIR.createBlockData())); - - //bottom line - newElements.add(new VisualizationElement(new Location(world, smallx + 1, 0, smallz), accentBlockData, Material.AIR.createBlockData())); - for (int x = smallx + STEP; x < bigx - STEP / 2; x += STEP) - { - if (x > minx && x < maxx) - newElements.add(new VisualizationElement(new Location(world, x, 0, smallz), accentBlockData, Material.AIR.createBlockData())); - } - newElements.add(new VisualizationElement(new Location(world, bigx - 1, 0, smallz), accentBlockData, Material.AIR.createBlockData())); - - //left line - newElements.add(new VisualizationElement(new Location(world, smallx, 0, smallz), cornerBlockData, Material.AIR.createBlockData())); - newElements.add(new VisualizationElement(new Location(world, smallx, 0, smallz + 1), accentBlockData, Material.AIR.createBlockData())); - for (int z = smallz + STEP; z < bigz - STEP / 2; z += STEP) - { - if (z > minz && z < maxz) - newElements.add(new VisualizationElement(new Location(world, smallx, 0, z), accentBlockData, Material.AIR.createBlockData())); - } - newElements.add(new VisualizationElement(new Location(world, smallx, 0, bigz - 1), accentBlockData, Material.AIR.createBlockData())); - - //right line - newElements.add(new VisualizationElement(new Location(world, bigx, 0, smallz), cornerBlockData, Material.AIR.createBlockData())); - newElements.add(new VisualizationElement(new Location(world, bigx, 0, smallz + 1), accentBlockData, Material.AIR.createBlockData())); - for (int z = smallz + STEP; z < bigz - STEP / 2; z += STEP) - { - if (z > minz && z < maxz) - newElements.add(new VisualizationElement(new Location(world, bigx, 0, z), accentBlockData, Material.AIR.createBlockData())); - } - newElements.add(new VisualizationElement(new Location(world, bigx, 0, bigz - 1), accentBlockData, Material.AIR.createBlockData())); - newElements.add(new VisualizationElement(new Location(world, bigx, 0, bigz), cornerBlockData, Material.AIR.createBlockData())); - - //remove any out of range elements - this.removeElementsOutOfRange(newElements, minx, minz, maxx, maxz); - - //remove any elements outside the claim - BoundingBox box = BoundingBox.of(min, max); - for (int i = 0; i < newElements.size(); i++) - { - VisualizationElement element = newElements.get(i); - if (!containsIncludingIgnoringHeight(box, element.location.toVector())) - { - newElements.remove(i--); - } - } - - //set Y values and real block information for any remaining visualization blocks - for (VisualizationElement element : newElements) - { - Location tempLocation = element.location; - element.location = getVisibleLocation(tempLocation.getWorld(), tempLocation.getBlockX(), height, tempLocation.getBlockZ(), waterIsTransparent); - height = element.location.getBlockY(); - element.realBlock = element.location.getBlock().getBlockData(); - } - - this.elements.addAll(newElements); - } - - private boolean containsIncludingIgnoringHeight(BoundingBox box, Vector vector) { - return vector.getBlockX() >= box.getMinX() - && vector.getBlockX() <= box.getMaxX() - && vector.getBlockZ() >= box.getMinZ() - && vector.getBlockZ() <= box.getMaxZ(); - } - - //removes any elements which are out of visualization range - private void removeElementsOutOfRange(ArrayList elements, int minx, int minz, int maxx, int maxz) - { - for (int i = 0; i < elements.size(); i++) - { - Location location = elements.get(i).location; - if (location.getX() < minx || location.getX() > maxx || location.getZ() < minz || location.getZ() > maxz) - { - elements.remove(i--); - } - } - } - - //finds a block the player can probably see. this is how visualizations "cling" to the ground or ceiling - private static Location getVisibleLocation(World world, int x, int y, int z, boolean waterIsTransparent) - { - Block block = world.getBlockAt(x, y, z); - BlockFace direction = (isTransparent(block, waterIsTransparent)) ? BlockFace.DOWN : BlockFace.UP; - - while (block.getY() >= 1 && - block.getY() < world.getMaxHeight() - 1 && - (!isTransparent(block.getRelative(BlockFace.UP), waterIsTransparent) || isTransparent(block, waterIsTransparent))) - { - block = block.getRelative(direction); - } - - return block.getLocation(); - } - - //helper method for above. allows visualization blocks to sit underneath partly transparent blocks like grass and fence - private static boolean isTransparent(Block block, boolean waterIsTransparent) - { - Material blockMaterial = block.getType(); - //Blacklist - switch (blockMaterial) - { - case SNOW: - return false; - } - - //Whitelist TODO: some of this might already be included in isTransparent() - switch (blockMaterial) - { - case AIR: - case OAK_FENCE: - case ACACIA_FENCE: - case BIRCH_FENCE: - case DARK_OAK_FENCE: - case JUNGLE_FENCE: - case NETHER_BRICK_FENCE: - case SPRUCE_FENCE: - case OAK_FENCE_GATE: - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case SPRUCE_FENCE_GATE: - case JUNGLE_FENCE_GATE: - return true; - } - - if (Tag.SIGNS.isTagged(blockMaterial) || Tag.WALL_SIGNS.isTagged(blockMaterial)) - return true; - - return (waterIsTransparent && block.getType() == Material.WATER) || - block.getType().isTransparent(); - } - - public static Visualization fromClaims(Iterable claims, int height, VisualizationType type, Location locality) - { - Visualization visualization = new Visualization(); - - for (Claim claim : claims) - { - visualization.addClaimElements(claim, height, type, locality); - } - - return visualization; - } -} +/* + 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.Tag; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Lightable; +import org.bukkit.entity.Player; +import org.bukkit.util.BoundingBox; +import org.bukkit.util.Vector; + +import java.util.ArrayList; + +//represents a visualization sent to a player +//FEATURE: to show players visually where claim boundaries are, we send them fake block change packets +//the result is that those players see new blocks, but the world hasn't been changed. other players can't see the new blocks, either. +public class Visualization +{ + public ArrayList elements = new ArrayList(); + + //sends a visualization to a player + public static void Apply(Player player, Visualization visualization) + { + PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); + + //if he has any current visualization, clear it first + if (playerData.currentVisualization != null) + { + Visualization.Revert(player); + } + + //if he's online, create a task to send him the visualization + if (player.isOnline() && visualization.elements.size() > 0 && visualization.elements.get(0).location.getWorld().equals(player.getWorld())) + { + GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new VisualizationApplicationTask(player, playerData, visualization), 1L); + } + } + + //reverts a visualization by sending another block change list, this time with the real world block values + + public static void Revert(Player player) + { + if (!player.isOnline()) return; + + PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); + + Visualization visualization = playerData.currentVisualization; + + if (playerData.currentVisualization != null) + { + //locality + int minx = player.getLocation().getBlockX() - 100; + int minz = player.getLocation().getBlockZ() - 100; + int maxx = player.getLocation().getBlockX() + 100; + int maxz = player.getLocation().getBlockZ() + 100; + + //remove any elements which are too far away + visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz); + + //send real block information for any remaining elements + for (int i = 0; i < visualization.elements.size(); i++) + { + VisualizationElement element = visualization.elements.get(i); + + //check player still in world where visualization exists + if (i == 0) + { + if (!player.getWorld().equals(element.location.getWorld())) return; + } + + player.sendBlockChange(element.location, element.realBlock); + } + + playerData.currentVisualization = null; + } + } + + //convenience method to build a visualization from a claim + //visualizationType determines the style (gold blocks, silver, red, diamond, etc) + public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality) + { + //visualize only top level claims + if (claim.parent != null) + { + return FromClaim(claim.parent, height, visualizationType, locality); + } + + Visualization visualization = new Visualization(); + + //add subdivisions first + for (int i = 0; i < claim.children.size(); i++) + { + Claim child = claim.children.get(i); + if (!child.inDataStore) continue; + visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality); + } + + //special visualization for administrative land claims + if (claim.isAdminClaim() && visualizationType == VisualizationType.Claim) + { + visualizationType = VisualizationType.AdminClaim; + } + + //add top level last so that it takes precedence (it shows on top when the child claim boundaries overlap with its boundaries) + visualization.addClaimElements(claim, height, visualizationType, locality); + + return visualization; + } + + //adds a claim's visualization to the current visualization + //handy for combining several visualizations together, as when visualization a top level claim with several subdivisions inside + //locality is a performance consideration. only create visualization blocks for around 100 blocks of the locality + + public void addClaimElements(Claim claim, int height, VisualizationType visualizationType, Location locality) + { + BlockData cornerBlockData; + BlockData accentBlockData; + + if (visualizationType == VisualizationType.Claim) + { + cornerBlockData = Material.GLOWSTONE.createBlockData(); + accentBlockData = Material.GOLD_BLOCK.createBlockData(); + } + else if (visualizationType == VisualizationType.AdminClaim) + { + cornerBlockData = Material.GLOWSTONE.createBlockData(); + accentBlockData = Material.PUMPKIN.createBlockData(); + } + else if (visualizationType == VisualizationType.Subdivision) + { + cornerBlockData = Material.IRON_BLOCK.createBlockData(); + accentBlockData = Material.WHITE_WOOL.createBlockData(); + } + else if (visualizationType == VisualizationType.RestoreNature) + { + cornerBlockData = Material.DIAMOND_BLOCK.createBlockData(); + accentBlockData = Material.DIAMOND_BLOCK.createBlockData(); + } + else + { + cornerBlockData = Material.REDSTONE_ORE.createBlockData(); + ((Lightable) cornerBlockData).setLit(true); + accentBlockData = Material.NETHERRACK.createBlockData(); + } + + addClaimElements(claim.getLesserBoundaryCorner(), claim.getGreaterBoundaryCorner(), locality, height, cornerBlockData, accentBlockData, 10); + } + + //adds a general claim cuboid (represented by min and max) visualization to the current visualization + public void addClaimElements(Location min, Location max, Location locality, int height, BlockData cornerBlockData, BlockData accentBlockData, int STEP) { + World world = min.getWorld(); + boolean waterIsTransparent = locality.getBlock().getType() == Material.WATER; + + int smallx = min.getBlockX(); + int smallz = min.getBlockZ(); + int bigx = max.getBlockX(); + int bigz = max.getBlockZ(); + + ArrayList newElements = new ArrayList<>(); + + //initialize visualization elements without Y values and real data + //that will be added later for only the visualization elements within visualization range + + //locality + int minx = locality.getBlockX() - 75; + int minz = locality.getBlockZ() - 75; + int maxx = locality.getBlockX() + 75; + int maxz = locality.getBlockZ() + 75; + + //top line + newElements.add(new VisualizationElement(new Location(world, smallx, 0, bigz), cornerBlockData, Material.AIR.createBlockData())); + newElements.add(new VisualizationElement(new Location(world, smallx + 1, 0, bigz), accentBlockData, Material.AIR.createBlockData())); + for (int x = smallx + STEP; x < bigx - STEP / 2; x += STEP) + { + if (x > minx && x < maxx) + newElements.add(new VisualizationElement(new Location(world, x, 0, bigz), accentBlockData, Material.AIR.createBlockData())); + } + newElements.add(new VisualizationElement(new Location(world, bigx - 1, 0, bigz), accentBlockData, Material.AIR.createBlockData())); + + //bottom line + newElements.add(new VisualizationElement(new Location(world, smallx + 1, 0, smallz), accentBlockData, Material.AIR.createBlockData())); + for (int x = smallx + STEP; x < bigx - STEP / 2; x += STEP) + { + if (x > minx && x < maxx) + newElements.add(new VisualizationElement(new Location(world, x, 0, smallz), accentBlockData, Material.AIR.createBlockData())); + } + newElements.add(new VisualizationElement(new Location(world, bigx - 1, 0, smallz), accentBlockData, Material.AIR.createBlockData())); + + //left line + newElements.add(new VisualizationElement(new Location(world, smallx, 0, smallz), cornerBlockData, Material.AIR.createBlockData())); + newElements.add(new VisualizationElement(new Location(world, smallx, 0, smallz + 1), accentBlockData, Material.AIR.createBlockData())); + for (int z = smallz + STEP; z < bigz - STEP / 2; z += STEP) + { + if (z > minz && z < maxz) + newElements.add(new VisualizationElement(new Location(world, smallx, 0, z), accentBlockData, Material.AIR.createBlockData())); + } + newElements.add(new VisualizationElement(new Location(world, smallx, 0, bigz - 1), accentBlockData, Material.AIR.createBlockData())); + + //right line + newElements.add(new VisualizationElement(new Location(world, bigx, 0, smallz), cornerBlockData, Material.AIR.createBlockData())); + newElements.add(new VisualizationElement(new Location(world, bigx, 0, smallz + 1), accentBlockData, Material.AIR.createBlockData())); + for (int z = smallz + STEP; z < bigz - STEP / 2; z += STEP) + { + if (z > minz && z < maxz) + newElements.add(new VisualizationElement(new Location(world, bigx, 0, z), accentBlockData, Material.AIR.createBlockData())); + } + newElements.add(new VisualizationElement(new Location(world, bigx, 0, bigz - 1), accentBlockData, Material.AIR.createBlockData())); + newElements.add(new VisualizationElement(new Location(world, bigx, 0, bigz), cornerBlockData, Material.AIR.createBlockData())); + + //remove any out of range elements + this.removeElementsOutOfRange(newElements, minx, minz, maxx, maxz); + + //remove any elements outside the claim + BoundingBox box = BoundingBox.of(min, max); + for (int i = 0; i < newElements.size(); i++) + { + VisualizationElement element = newElements.get(i); + if (!containsIncludingIgnoringHeight(box, element.location.toVector())) + { + newElements.remove(i--); + } + } + + //set Y values and real block information for any remaining visualization blocks + for (VisualizationElement element : newElements) + { + Location tempLocation = element.location; + element.location = getVisibleLocation(tempLocation.getWorld(), tempLocation.getBlockX(), height, tempLocation.getBlockZ(), waterIsTransparent); + height = element.location.getBlockY(); + element.realBlock = element.location.getBlock().getBlockData(); + } + + this.elements.addAll(newElements); + } + + private boolean containsIncludingIgnoringHeight(BoundingBox box, Vector vector) { + return vector.getBlockX() >= box.getMinX() + && vector.getBlockX() <= box.getMaxX() + && vector.getBlockZ() >= box.getMinZ() + && vector.getBlockZ() <= box.getMaxZ(); + } + + //removes any elements which are out of visualization range + private void removeElementsOutOfRange(ArrayList elements, int minx, int minz, int maxx, int maxz) + { + for (int i = 0; i < elements.size(); i++) + { + Location location = elements.get(i).location; + if (location.getX() < minx || location.getX() > maxx || location.getZ() < minz || location.getZ() > maxz) + { + elements.remove(i--); + } + } + } + + //finds a block the player can probably see. this is how visualizations "cling" to the ground or ceiling + private static Location getVisibleLocation(World world, int x, int y, int z, boolean waterIsTransparent) + { + Block block = world.getBlockAt(x, y, z); + BlockFace direction = (isTransparent(block, waterIsTransparent)) ? BlockFace.DOWN : BlockFace.UP; + + while (block.getY() >= 1 && + block.getY() < world.getMaxHeight() - 1 && + (!isTransparent(block.getRelative(BlockFace.UP), waterIsTransparent) || isTransparent(block, waterIsTransparent))) + { + block = block.getRelative(direction); + } + + return block.getLocation(); + } + + //helper method for above. allows visualization blocks to sit underneath partly transparent blocks like grass and fence + private static boolean isTransparent(Block block, boolean waterIsTransparent) + { + Material blockMaterial = block.getType(); + //Blacklist + switch (blockMaterial) + { + case SNOW: + return false; + } + + //Whitelist TODO: some of this might already be included in isTransparent() + switch (blockMaterial) + { + case AIR: + case OAK_FENCE: + case ACACIA_FENCE: + case BIRCH_FENCE: + case DARK_OAK_FENCE: + case JUNGLE_FENCE: + case NETHER_BRICK_FENCE: + case SPRUCE_FENCE: + case OAK_FENCE_GATE: + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case SPRUCE_FENCE_GATE: + case JUNGLE_FENCE_GATE: + return true; + } + + if (Tag.SIGNS.isTagged(blockMaterial) || Tag.WALL_SIGNS.isTagged(blockMaterial)) + return true; + + return (waterIsTransparent && block.getType() == Material.WATER) || + block.getType().isTransparent(); + } + + public static Visualization fromClaims(Iterable claims, int height, VisualizationType type, Location locality) + { + Visualization visualization = new Visualization(); + + for (Claim claim : claims) + { + visualization.addClaimElements(claim, height, type, locality); + } + + return visualization; + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationApplicationTask.java b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationApplicationTask.java index d1d9560..43c3dca 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationApplicationTask.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationApplicationTask.java @@ -1,60 +1,60 @@ -/* - 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.entity.Player; - -//applies a visualization for a player by sending him block change packets -class VisualizationApplicationTask implements Runnable -{ - private Visualization visualization; - private Player player; - private PlayerData playerData; - - public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization) - { - this.visualization = visualization; - this.playerData = playerData; - this.player = player; - } - - - @Override - public void run() - { - //for each element (=block) of the visualization - for (int i = 0; i < visualization.elements.size(); i++) - { - VisualizationElement element = visualization.elements.get(i); - - //send the player a fake block change event - if (!element.location.getChunk().isLoaded()) continue; //cheap distance check - player.sendBlockChange(element.location, element.visualizedBlock); - } - - //remember the visualization applied to this player for later (so it can be inexpensively reverted) - playerData.currentVisualization = visualization; - - //schedule automatic visualization reversion in 60 seconds. - GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask( - GriefPrevention.instance, - new VisualizationReversionTask(player, playerData, visualization), - 20L * 60); //60 seconds - } -} +/* + 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.entity.Player; + +//applies a visualization for a player by sending him block change packets +class VisualizationApplicationTask implements Runnable +{ + private Visualization visualization; + private Player player; + private PlayerData playerData; + + public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization) + { + this.visualization = visualization; + this.playerData = playerData; + this.player = player; + } + + + @Override + public void run() + { + //for each element (=block) of the visualization + for (int i = 0; i < visualization.elements.size(); i++) + { + VisualizationElement element = visualization.elements.get(i); + + //send the player a fake block change event + if (!element.location.getChunk().isLoaded()) continue; //cheap distance check + player.sendBlockChange(element.location, element.visualizedBlock); + } + + //remember the visualization applied to this player for later (so it can be inexpensively reverted) + playerData.currentVisualization = visualization; + + //schedule automatic visualization reversion in 60 seconds. + GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask( + GriefPrevention.instance, + new VisualizationReversionTask(player, playerData, visualization), + 20L * 60); //60 seconds + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationElement.java b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationElement.java index 689515f..fcbfd43 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationElement.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationElement.java @@ -1,37 +1,37 @@ -/* - 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.block.data.BlockData; - -//represents a "fake" block sent to a player as part of a visualization -public class VisualizationElement -{ - public Location location; - public BlockData visualizedBlock; - public BlockData realBlock; - - public VisualizationElement(Location location, BlockData visualizedBlock, BlockData realBlock) - { - this.location = location; - this.visualizedBlock = visualizedBlock; - this.realBlock = realBlock; - } -} +/* + 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.block.data.BlockData; + +//represents a "fake" block sent to a player as part of a visualization +public class VisualizationElement +{ + public Location location; + public BlockData visualizedBlock; + public BlockData realBlock; + + public VisualizationElement(Location location, BlockData visualizedBlock, BlockData realBlock) + { + this.location = location; + this.visualizedBlock = visualizedBlock; + this.realBlock = realBlock; + } +} diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java index f4516ef..c2a8efb 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/VisualizationType.java @@ -1,29 +1,29 @@ -/* - 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; - -//just an enumeration of the visualization types, which determine what materials will be for the fake blocks -public enum VisualizationType -{ - Claim, - Subdivision, - ErrorClaim, - RestoreNature, - AdminClaim -} +/* + 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; + +//just an enumeration of the visualization types, which determine what materials will be for the fake blocks +public enum VisualizationType +{ + Claim, + Subdivision, + ErrorClaim, + RestoreNature, + AdminClaim +}