reformat code

- Lots of tabs to spaces going on
- That's a lot of changes!

#63
This commit is contained in:
RoboMWM 2020-06-08 21:57:55 -07:00
parent bc05440617
commit 40f554d386
63 changed files with 12745 additions and 12750 deletions

View File

@ -1,13 +1,13 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.ArrayList;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChunkSnapshot; import org.bukkit.ChunkSnapshot;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import java.util.ArrayList;
//automatically extends a claim downward based on block types detected //automatically extends a claim downward based on block types detected
class AutoExtendClaimTask implements Runnable class AutoExtendClaimTask implements Runnable
{ {
@ -26,7 +26,7 @@ class AutoExtendClaimTask implements Runnable
public void run() public void run()
{ {
int newY = this.getLowestBuiltY(); int newY = this.getLowestBuiltY();
if(newY < this.claim.getLesserBoundaryCorner().getBlockY()) if (newY < this.claim.getLesserBoundaryCorner().getBlockY())
{ {
Bukkit.getScheduler().runTask(GriefPrevention.instance, new ExecuteExtendClaimTask(claim, newY)); Bukkit.getScheduler().runTask(GriefPrevention.instance, new ExecuteExtendClaimTask(claim, newY));
} }
@ -36,67 +36,67 @@ class AutoExtendClaimTask implements Runnable
{ {
int y = this.claim.getLesserBoundaryCorner().getBlockY(); int y = this.claim.getLesserBoundaryCorner().getBlockY();
if(this.yTooSmall(y)) return y; if (this.yTooSmall(y)) return y;
try try
{ {
for(ChunkSnapshot chunk : this.chunks) for (ChunkSnapshot chunk : this.chunks)
{ {
Biome biome = chunk.getBiome(0, 0); Biome biome = chunk.getBiome(0, 0);
ArrayList<Material> playerBlockIDs = RestoreNatureProcessingTask.getPlayerBlocks(this.worldType, biome); ArrayList<Material> playerBlockIDs = RestoreNatureProcessingTask.getPlayerBlocks(this.worldType, biome);
boolean ychanged = true; boolean ychanged = true;
while(!this.yTooSmall(y) && ychanged) while (!this.yTooSmall(y) && ychanged)
{ {
ychanged = false; ychanged = false;
for(int x = 0; x < 16; x++) for (int x = 0; x < 16; x++)
{ {
for(int z = 0; z < 16; z++) for (int z = 0; z < 16; z++)
{ {
Material blockType = chunk.getBlockType(x, y, z); Material blockType = chunk.getBlockType(x, y, z);
while(!this.yTooSmall(y) && playerBlockIDs.contains(blockType)) while (!this.yTooSmall(y) && playerBlockIDs.contains(blockType))
{ {
ychanged = true; ychanged = true;
blockType = chunk.getBlockType(x, --y, z); blockType = chunk.getBlockType(x, --y, z);
} }
if(this.yTooSmall(y)) return y; if (this.yTooSmall(y)) return y;
} }
} }
} }
if(this.yTooSmall(y)) return y; if (this.yTooSmall(y)) return y;
} }
} }
catch (NoSuchMethodError e) catch (NoSuchMethodError e)
{ {
GriefPrevention.instance.getLogger().severe("You are running an outdated build of Craftbukkit/Spigot/Paper. Please update."); GriefPrevention.instance.getLogger().severe("You are running an outdated build of Craftbukkit/Spigot/Paper. Please update.");
for(ChunkSnapshot chunk : this.chunks) for (ChunkSnapshot chunk : this.chunks)
{ {
Biome biome = chunk.getBiome(0, 0); Biome biome = chunk.getBiome(0, 0);
ArrayList<Material> playerBlockIDs = RestoreNatureProcessingTask.getPlayerBlocks(this.worldType, biome); ArrayList<Material> playerBlockIDs = RestoreNatureProcessingTask.getPlayerBlocks(this.worldType, biome);
boolean ychanged = true; boolean ychanged = true;
while(!this.yTooSmall(y) && ychanged) while (!this.yTooSmall(y) && ychanged)
{ {
ychanged = false; ychanged = false;
for(int x = 0; x < 16; x++) for (int x = 0; x < 16; x++)
{ {
for(int z = 0; z < 16; z++) for (int z = 0; z < 16; z++)
{ {
Material blockType = chunk.getBlockType(x, y, z); Material blockType = chunk.getBlockType(x, y, z);
while(!this.yTooSmall(y) && playerBlockIDs.contains(blockType)) while (!this.yTooSmall(y) && playerBlockIDs.contains(blockType))
{ {
ychanged = true; ychanged = true;
blockType = chunk.getBlockType(x, --y, z); blockType = chunk.getBlockType(x, --y, z);
} }
if(this.yTooSmall(y)) return y; if (this.yTooSmall(y)) return y;
} }
} }
} }
if(this.yTooSmall(y)) return y; if (this.yTooSmall(y)) return y;
} }
} }

View File

@ -26,14 +26,14 @@ import org.bukkit.block.data.BlockData;
//this is used only by the RestoreNature code //this is used only by the RestoreNature code
public class BlockSnapshot public class BlockSnapshot
{ {
public Location location; public Location location;
public Material typeId; public Material typeId;
public BlockData data; public BlockData data;
public BlockSnapshot(Location location, Material typeId, BlockData data) public BlockSnapshot(Location location, Material typeId, BlockData data)
{ {
this.location = location; this.location = location;
this.typeId = typeId; this.typeId = typeId;
this.data = data; this.data = data;
} }
} }

View File

@ -24,16 +24,16 @@ import org.bukkit.Bukkit;
//used to send delayed messages, for example a quit message after the player has been gone a while //used to send delayed messages, for example a quit message after the player has been gone a while
class BroadcastMessageTask implements Runnable class BroadcastMessageTask implements Runnable
{ {
private String message; private String message;
public BroadcastMessageTask(String message) public BroadcastMessageTask(String message)
{ {
this.message = message; this.message = message;
} }
@Override @Override
public void run() public void run()
{ {
Bukkit.getServer().broadcastMessage(this.message); Bukkit.getServer().broadcastMessage(this.message);
} }
} }

View File

@ -19,9 +19,6 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
@ -31,30 +28,30 @@ import org.bukkit.scheduler.BukkitRunnable;
//if that happens, we detect the problem and send them back through the portal. //if that happens, we detect the problem and send them back through the portal.
class CheckForPortalTrapTask extends BukkitRunnable class CheckForPortalTrapTask extends BukkitRunnable
{ {
GriefPrevention instance; GriefPrevention instance;
//player who recently teleported via nether portal //player who recently teleported via nether portal
private Player player; private Player player;
//where to send the player back to if he hasn't left the portal frame //where to send the player back to if he hasn't left the portal frame
private Location returnLocation; private Location returnLocation;
public CheckForPortalTrapTask(Player player, GriefPrevention plugin, Location locationToReturn) public CheckForPortalTrapTask(Player player, GriefPrevention plugin, Location locationToReturn)
{ {
this.player = player; this.player = player;
this.instance = plugin; this.instance = plugin;
this.returnLocation = locationToReturn; this.returnLocation = locationToReturn;
player.setMetadata("GP_PORTALRESCUE", new FixedMetadataValue(instance, locationToReturn)); player.setMetadata("GP_PORTALRESCUE", new FixedMetadataValue(instance, locationToReturn));
} }
@Override @Override
public void run() public void run()
{ {
if(player.isOnline() && player.getPortalCooldown() >= 10 && player.hasMetadata("GP_PORTALRESCUE")) if (player.isOnline() && player.getPortalCooldown() >= 10 && player.hasMetadata("GP_PORTALRESCUE"))
{ {
instance.AddLogEntry("Rescued " + player.getName() + " from a nether portal.\nTeleported from " + player.getLocation().toString() + " to " + returnLocation.toString(), CustomLogEntryTypes.Debug); instance.AddLogEntry("Rescued " + player.getName() + " from a nether portal.\nTeleported from " + player.getLocation().toString() + " to " + returnLocation.toString(), CustomLogEntryTypes.Debug);
player.teleport(returnLocation); player.teleport(returnLocation);
player.removeMetadata("GP_PORTALRESCUE", instance); player.removeMetadata("GP_PORTALRESCUE", instance);
} }
instance.portalReturnTaskMap.remove(player.getUniqueId()); instance.portalReturnTaskMap.remove(player.getUniqueId());
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,20 @@ package me.ryanhamshire.GriefPrevention;
//basic enum stuff //basic enum stuff
public enum ClaimPermission public enum ClaimPermission
{ {
Build, Build,
Inventory, Inventory,
Access; Access;
/** /**
* Check if a ClaimPermission is granted by another ClaimPermission. * Check if a ClaimPermission is granted by another ClaimPermission.
* *
* @param other the ClaimPermission to compare against * @param other the ClaimPermission to compare against
* @return true if this ClaimPermission is equal or lesser than the provided ClaimPermission * @return true if this ClaimPermission is equal or lesser than the provided ClaimPermission
*/ */
public boolean isGrantedBy(ClaimPermission other) public boolean isGrantedBy(ClaimPermission other)
{ {
// As this uses declaration order to compare, if trust levels are reordered this method must be rewritten. // As this uses declaration order to compare, if trust levels are reordered this method must be rewritten.
return other != null && other.ordinal() <= this.ordinal(); return other != null && other.ordinal() <= this.ordinal();
} }
} }

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@ -28,38 +28,38 @@ import java.util.UUID;
class CleanupUnusedClaimPreTask implements Runnable class CleanupUnusedClaimPreTask implements Runnable
{ {
private UUID ownerID = null; private UUID ownerID = null;
CleanupUnusedClaimPreTask(UUID uuid) CleanupUnusedClaimPreTask(UUID uuid)
{ {
this.ownerID = uuid; this.ownerID = uuid;
} }
@Override @Override
public void run() public void run()
{ {
//get the data //get the data
PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(ownerID); PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(ownerID);
OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(ownerID); OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(ownerID);
GriefPrevention.AddLogEntry("Looking for expired claims. Checking data for " + ownerID.toString(), CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Looking for expired claims. Checking data for " + ownerID.toString(), CustomLogEntryTypes.Debug, true);
//expiration code uses last logout timestamp to decide whether to expire claims //expiration code uses last logout timestamp to decide whether to expire claims
//don't expire claims for online players //don't expire claims for online players
if(ownerInfo.isOnline()) if (ownerInfo.isOnline())
{ {
GriefPrevention.AddLogEntry("Player is online. Ignoring.", CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Player is online. Ignoring.", CustomLogEntryTypes.Debug, true);
return; return;
} }
if(ownerInfo.getLastPlayed() <= 0) if (ownerInfo.getLastPlayed() <= 0)
{ {
GriefPrevention.AddLogEntry("Player is new or not in the server's cached userdata. Ignoring. getLastPlayed = " + ownerInfo.getLastPlayed(), CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Player is new or not in the server's cached userdata. Ignoring. getLastPlayed = " + ownerInfo.getLastPlayed(), CustomLogEntryTypes.Debug, true);
return; return;
} }
//skip claims belonging to exempted players based on block totals in config //skip claims belonging to exempted players based on block totals in config
int bonusBlocks = ownerData.getBonusClaimBlocks(); int bonusBlocks = ownerData.getBonusClaimBlocks();
if(bonusBlocks >= GriefPrevention.instance.config_claims_expirationExemptionBonusBlocks || bonusBlocks + ownerData.getAccruedClaimBlocks() >= GriefPrevention.instance.config_claims_expirationExemptionTotalBlocks) if (bonusBlocks >= GriefPrevention.instance.config_claims_expirationExemptionBonusBlocks || bonusBlocks + ownerData.getAccruedClaimBlocks() >= GriefPrevention.instance.config_claims_expirationExemptionTotalBlocks)
{ {
GriefPrevention.AddLogEntry("Player exempt from claim expiration based on claim block counts vs. config file settings.", CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Player exempt from claim expiration based on claim block counts vs. config file settings.", CustomLogEntryTypes.Debug, true);
return; return;
@ -67,22 +67,22 @@ class CleanupUnusedClaimPreTask implements Runnable
Claim claimToExpire = null; Claim claimToExpire = null;
for (Claim claim : GriefPrevention.instance.dataStore.getClaims()) for (Claim claim : GriefPrevention.instance.dataStore.getClaims())
{ {
if (ownerID.equals(claim.ownerID)) if (ownerID.equals(claim.ownerID))
{ {
claimToExpire = claim; claimToExpire = claim;
break; break;
} }
} }
if (claimToExpire == null) if (claimToExpire == null)
{ {
GriefPrevention.AddLogEntry("Unable to find a claim to expire for " + ownerID.toString(), CustomLogEntryTypes.Debug, false); GriefPrevention.AddLogEntry("Unable to find a claim to expire for " + ownerID.toString(), CustomLogEntryTypes.Debug, false);
return; return;
} }
//pass it back to the main server thread, where it's safe to delete a claim if needed //pass it back to the main server thread, where it's safe to delete a claim if needed
Bukkit.getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new CleanupUnusedClaimTask(claimToExpire, ownerData, ownerInfo), 1L); Bukkit.getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new CleanupUnusedClaimTask(claimToExpire, ownerData, ownerInfo), 1L);
} }
} }

View File

@ -16,133 +16,130 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import me.ryanhamshire.GriefPrevention.events.ClaimExpirationEvent;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Vector; import java.util.Vector;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import me.ryanhamshire.GriefPrevention.events.ClaimExpirationEvent;
class CleanupUnusedClaimTask implements Runnable class CleanupUnusedClaimTask implements Runnable
{ {
Claim claim; Claim claim;
PlayerData ownerData; PlayerData ownerData;
OfflinePlayer ownerInfo; OfflinePlayer ownerInfo;
CleanupUnusedClaimTask(Claim claim, PlayerData ownerData, OfflinePlayer ownerInfo) CleanupUnusedClaimTask(Claim claim, PlayerData ownerData, OfflinePlayer ownerInfo)
{ {
this.claim = claim; this.claim = claim;
this.ownerData = ownerData; this.ownerData = ownerData;
this.ownerInfo = ownerInfo; this.ownerInfo = ownerInfo;
} }
@Override @Override
public void run() public void run()
{ {
//determine area of the default chest claim //determine area of the default chest claim
int areaOfDefaultClaim = 0; int areaOfDefaultClaim = 0;
if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius >= 0) if (GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius >= 0)
{ {
areaOfDefaultClaim = (int)Math.pow(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius * 2 + 1, 2); areaOfDefaultClaim = (int) Math.pow(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius * 2 + 1, 2);
} }
//if this claim is a chest claim and those are set to expire //if this claim is a chest claim and those are set to expire
if(claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0) if (claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0)
{ {
//if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed //if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed
Calendar sevenDaysAgo = Calendar.getInstance(); Calendar sevenDaysAgo = Calendar.getInstance();
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_chestClaimExpirationDays); sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_chestClaimExpirationDays);
boolean newPlayerClaimsExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed())); boolean newPlayerClaimsExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed()));
if(newPlayerClaimsExpired && ownerData.getClaims().size() == 1) if (newPlayerClaimsExpired && ownerData.getClaims().size() == 1)
{ {
if (expireEventCanceled()) if (expireEventCanceled())
return; return;
claim.removeSurfaceFluids(null); claim.removeSurfaceFluids(null);
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true); GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
//if configured to do so, restore the land to natural //if configured to do so, restore the land to natural
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration) if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
{ {
GriefPrevention.instance.restoreClaim(claim, 0); GriefPrevention.instance.restoreClaim(claim, 0);
} }
GriefPrevention.AddLogEntry(" " + claim.getOwnerName() + "'s new player claim expired.", CustomLogEntryTypes.AdminActivity); GriefPrevention.AddLogEntry(" " + claim.getOwnerName() + "'s new player claim expired.", CustomLogEntryTypes.AdminActivity);
} }
} }
//if configured to always remove claims after some inactivity period without exceptions... //if configured to always remove claims after some inactivity period without exceptions...
else if(GriefPrevention.instance.config_claims_expirationDays > 0) else if (GriefPrevention.instance.config_claims_expirationDays > 0)
{ {
Calendar earliestPermissibleLastLogin = Calendar.getInstance(); Calendar earliestPermissibleLastLogin = Calendar.getInstance();
earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays); earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays);
if(earliestPermissibleLastLogin.getTime().after(new Date(ownerInfo.getLastPlayed()))) if (earliestPermissibleLastLogin.getTime().after(new Date(ownerInfo.getLastPlayed())))
{ {
if (expireEventCanceled()) if (expireEventCanceled())
return; return;
//make a copy of this player's claim list //make a copy of this player's claim list
Vector<Claim> claims = new Vector<Claim>(); Vector<Claim> claims = new Vector<Claim>();
for(int i = 0; i < ownerData.getClaims().size(); i++) for (int i = 0; i < ownerData.getClaims().size(); i++)
{ {
claims.add(ownerData.getClaims().get(i)); claims.add(ownerData.getClaims().get(i));
} }
//delete them //delete them
GriefPrevention.instance.dataStore.deleteClaimsForPlayer(claim.ownerID, true); GriefPrevention.instance.dataStore.deleteClaimsForPlayer(claim.ownerID, true);
GriefPrevention.AddLogEntry(" All of " + claim.getOwnerName() + "'s claims have expired.", CustomLogEntryTypes.AdminActivity); GriefPrevention.AddLogEntry(" All of " + claim.getOwnerName() + "'s claims have expired.", CustomLogEntryTypes.AdminActivity);
for(int i = 0; i < claims.size(); i++) for (int i = 0; i < claims.size(); i++)
{ {
//if configured to do so, restore the land to natural //if configured to do so, restore the land to natural
if(GriefPrevention.instance.creativeRulesApply(claims.get(i).getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration) if (GriefPrevention.instance.creativeRulesApply(claims.get(i).getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
{ {
GriefPrevention.instance.restoreClaim(claims.get(i), 0); GriefPrevention.instance.restoreClaim(claims.get(i), 0);
} }
} }
} }
} } else if (GriefPrevention.instance.config_claims_unusedClaimExpirationDays > 0 && GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
{
//avoid scanning large claims and administrative claims
if (claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return;
else if(GriefPrevention.instance.config_claims_unusedClaimExpirationDays > 0 && GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner())) //otherwise scan the claim content
{ int minInvestment = 400;
//avoid scanning large claims and administrative claims
if(claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return;
//otherwise scan the claim content long investmentScore = claim.getPlayerInvestmentScore();
int minInvestment = 400;
long investmentScore = claim.getPlayerInvestmentScore(); if (investmentScore < minInvestment)
{
//if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed
Calendar sevenDaysAgo = Calendar.getInstance();
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays);
boolean claimExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed()));
if (claimExpired)
{
if (expireEventCanceled())
return;
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
GriefPrevention.AddLogEntry("Removed " + claim.getOwnerName() + "'s unused claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
if(investmentScore < minInvestment) //restore the claim area to natural state
{ GriefPrevention.instance.restoreClaim(claim, 0);
//if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed }
Calendar sevenDaysAgo = Calendar.getInstance(); }
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays); }
boolean claimExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed())); }
if(claimExpired)
{
if (expireEventCanceled())
return;
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
GriefPrevention.AddLogEntry("Removed " + claim.getOwnerName() + "'s unused claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
//restore the claim area to natural state public boolean expireEventCanceled()
GriefPrevention.instance.restoreClaim(claim, 0); {
} //see if any other plugins don't want this claim deleted
} ClaimExpirationEvent event = new ClaimExpirationEvent(this.claim);
} Bukkit.getPluginManager().callEvent(event);
} return event.isCancelled();
}
public boolean expireEventCanceled()
{
//see if any other plugins don't want this claim deleted
ClaimExpirationEvent event = new ClaimExpirationEvent(this.claim);
Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
}
} }

View File

@ -20,10 +20,10 @@ package me.ryanhamshire.GriefPrevention;
public class CreateClaimResult public class CreateClaimResult
{ {
//whether or not the creation succeeded (it would fail if the new claim overlapped another existing claim) //whether or not the creation succeeded (it would fail if the new claim overlapped another existing claim)
public boolean succeeded; public boolean succeeded;
//when succeeded, this is a reference to the new claim //when succeeded, this is a reference to the new claim
//when failed, this is a reference to the pre-existing, conflicting claim //when failed, this is a reference to the pre-existing, conflicting claim
public Claim claim; public Claim claim;
} }

View File

@ -18,6 +18,9 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import com.google.common.io.Files;
import org.bukkit.scheduler.BukkitScheduler;
import java.io.File; import java.io.File;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -26,10 +29,6 @@ import java.util.Date;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.bukkit.scheduler.BukkitScheduler;
import com.google.common.io.Files;
class CustomLogger class CustomLogger
{ {
private final SimpleDateFormat timestampFormat = new SimpleDateFormat("HH:mm"); private final SimpleDateFormat timestampFormat = new SimpleDateFormat("HH:mm");
@ -51,7 +50,7 @@ class CustomLogger
//unless disabled, schedule recurring tasks //unless disabled, schedule recurring tasks
int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep; int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep;
if(daysToKeepLogs > 0) if (daysToKeepLogs > 0)
{ {
BukkitScheduler scheduler = GriefPrevention.instance.getServer().getScheduler(); BukkitScheduler scheduler = GriefPrevention.instance.getServer().getScheduler();
final long ticksPerSecond = 20L; final long ticksPerSecond = 20L;
@ -62,14 +61,15 @@ class CustomLogger
} }
private static final Pattern inlineFormatterPattern = Pattern.compile("§."); private static final Pattern inlineFormatterPattern = Pattern.compile("§.");
void AddEntry(String entry, CustomLogEntryTypes entryType) void AddEntry(String entry, CustomLogEntryTypes entryType)
{ {
//if disabled, do nothing //if disabled, do nothing
int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep; int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep;
if(daysToKeepLogs == 0) return; if (daysToKeepLogs == 0) return;
//if entry type is not enabled, do nothing //if entry type is not enabled, do nothing
if(!this.isEnabledType(entryType)) return; if (!this.isEnabledType(entryType)) return;
//otherwise write to the in-memory buffer, after removing formatters //otherwise write to the in-memory buffer, after removing formatters
Matcher matcher = inlineFormatterPattern.matcher(entry); Matcher matcher = inlineFormatterPattern.matcher(entry);
@ -80,12 +80,16 @@ class CustomLogger
private boolean isEnabledType(CustomLogEntryTypes entryType) private boolean isEnabledType(CustomLogEntryTypes entryType)
{ {
if(entryType == CustomLogEntryTypes.Exception) return true; if (entryType == CustomLogEntryTypes.Exception) return true;
if(entryType == CustomLogEntryTypes.SocialActivity && !GriefPrevention.instance.config_logs_socialEnabled) return false; if (entryType == CustomLogEntryTypes.SocialActivity && !GriefPrevention.instance.config_logs_socialEnabled)
if(entryType == CustomLogEntryTypes.SuspiciousActivity && !GriefPrevention.instance.config_logs_suspiciousEnabled) return false; return false;
if(entryType == CustomLogEntryTypes.AdminActivity && !GriefPrevention.instance.config_logs_adminEnabled) return false; if (entryType == CustomLogEntryTypes.SuspiciousActivity && !GriefPrevention.instance.config_logs_suspiciousEnabled)
if(entryType == CustomLogEntryTypes.Debug && !GriefPrevention.instance.config_logs_debugEnabled) return false; return false;
if(entryType == CustomLogEntryTypes.MutedChat && !GriefPrevention.instance.config_logs_mutedChatEnabled) return false; if (entryType == CustomLogEntryTypes.AdminActivity && !GriefPrevention.instance.config_logs_adminEnabled)
return false;
if (entryType == CustomLogEntryTypes.Debug && !GriefPrevention.instance.config_logs_debugEnabled) return false;
if (entryType == CustomLogEntryTypes.MutedChat && !GriefPrevention.instance.config_logs_mutedChatEnabled)
return false;
return true; return true;
} }
@ -95,7 +99,7 @@ class CustomLogger
try try
{ {
//if nothing to write, stop here //if nothing to write, stop here
if(this.queuedEntries.length() == 0) return; if (this.queuedEntries.length() == 0) return;
//determine filename based on date //determine filename based on date
String filename = this.filenameFormat.format(new Date()) + ".log"; String filename = this.filenameFormat.format(new Date()) + ".log";
@ -109,7 +113,7 @@ class CustomLogger
//the unwritten entries will remain the buffer for the next write to retry //the unwritten entries will remain the buffer for the next write to retry
this.queuedEntries.setLength(0); this.queuedEntries.setLength(0);
} }
catch(Exception e) catch (Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
} }
@ -121,20 +125,20 @@ class CustomLogger
{ {
//get list of log files //get list of log files
File logFolder = new File(this.logFolderPath); File logFolder = new File(this.logFolderPath);
File [] files = logFolder.listFiles(); File[] files = logFolder.listFiles();
//delete any created before x days ago //delete any created before x days ago
int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep; int daysToKeepLogs = GriefPrevention.instance.config_logs_daysToKeep;
Calendar expirationBoundary = Calendar.getInstance(); Calendar expirationBoundary = Calendar.getInstance();
expirationBoundary.add(Calendar.DATE, -daysToKeepLogs); expirationBoundary.add(Calendar.DATE, -daysToKeepLogs);
for(int i = 0; i < files.length; i++) for (int i = 0; i < files.length; i++)
{ {
File file = files[i]; File file = files[i];
if(file.isDirectory()) continue; //skip any folders if (file.isDirectory()) continue; //skip any folders
String filename = file.getName().replace(".log", ""); String filename = file.getName().replace(".log", "");
String [] dateParts = filename.split("_"); //format is yyyy_MM_dd String[] dateParts = filename.split("_"); //format is yyyy_MM_dd
if(dateParts.length != 3) continue; if (dateParts.length != 3) continue;
try try
{ {
@ -144,19 +148,19 @@ class CustomLogger
Calendar filedate = Calendar.getInstance(); Calendar filedate = Calendar.getInstance();
filedate.set(year, month, day); filedate.set(year, month, day);
if(filedate.before(expirationBoundary)) if (filedate.before(expirationBoundary))
{ {
file.delete(); file.delete();
} }
} }
catch(NumberFormatException e) catch (NumberFormatException e)
{ {
//throw this away - effectively ignoring any files without the correct filename format //throw this away - effectively ignoring any files without the correct filename format
GriefPrevention.AddLogEntry("Ignoring an unexpected file in the abridged logs folder: " + file.getName(), CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Ignoring an unexpected file in the abridged logs folder: " + file.getName(), CustomLogEntryTypes.Debug, true);
} }
} }
} }
catch(Exception e) catch (Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -20,14 +20,14 @@ package me.ryanhamshire.GriefPrevention;
public class CustomizableMessage public class CustomizableMessage
{ {
public Messages id; public Messages id;
public String text; public String text;
public String notes; public String notes;
public CustomizableMessage(Messages id, String text, String notes) public CustomizableMessage(Messages id, String text, String notes)
{ {
this.id = id; this.id = id;
this.text = text; this.text = text;
this.notes = notes; this.notes = notes;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.Collection;
import me.ryanhamshire.GriefPrevention.events.AccrueClaimBlocksEvent; import me.ryanhamshire.GriefPrevention.events.AccrueClaimBlocksEvent;
import org.bukkit.entity.Player; 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 //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 //runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing
@ -43,13 +43,13 @@ class DeliverClaimBlocksTask implements Runnable
public void run() public void run()
{ {
//if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart //if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart
if(this.player == null) if (this.player == null)
{ {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Collection<Player> players = (Collection<Player>)GriefPrevention.instance.getServer().getOnlinePlayers(); Collection<Player> players = (Collection<Player>) GriefPrevention.instance.getServer().getOnlinePlayers();
long i = 0; long i = 0;
for(Player onlinePlayer : players) for (Player onlinePlayer : players)
{ {
DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance); DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance);
instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++); instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++);
@ -59,7 +59,7 @@ class DeliverClaimBlocksTask implements Runnable
} }
//deliver claim blocks to the specified player //deliver claim blocks to the specified player
if(!this.player.isOnline()) if (!this.player.isOnline())
{ {
return; //player is not online to receive claim blocks return; //player is not online to receive claim blocks
} }
@ -76,7 +76,7 @@ class DeliverClaimBlocksTask implements Runnable
isIdle = player.isInsideVehicle() || player.getLocation().getBlock().isLiquid() || isIdle = player.isInsideVehicle() || player.getLocation().getBlock().isLiquid() ||
!(playerData.lastAfkCheckLocation == null || playerData.lastAfkCheckLocation.distanceSquared(player.getLocation()) > idleThresholdSquared); !(playerData.lastAfkCheckLocation == null || playerData.lastAfkCheckLocation.distanceSquared(player.getLocation()) > idleThresholdSquared);
} }
catch(IllegalArgumentException ignore) //can't measure distance when to/from are different worlds catch (IllegalArgumentException ignore) //can't measure distance when to/from are different worlds
{ {
} }
@ -119,7 +119,7 @@ class DeliverClaimBlocksTask implements Runnable
//many other operations will cause this player's data to save, including his eventual logout //many other operations will cause this player's data to save, including his eventual logout
//dataStore.savePlayerData(player.getUniqueIdentifier(), playerData); //dataStore.savePlayerData(player.getUniqueIdentifier(), playerData);
} }
catch(Exception e) catch (Exception e)
{ {
GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":"); GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":");
e.printStackTrace(); e.printStackTrace();

View File

@ -34,117 +34,114 @@ import java.util.List;
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts //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 class EntityCleanupTask implements Runnable
{ {
//where to start cleaning in the list of entities //where to start cleaning in the list of entities
private double percentageStart; private double percentageStart;
public EntityCleanupTask(double percentageStart) public EntityCleanupTask(double percentageStart)
{ {
this.percentageStart = percentageStart; this.percentageStart = percentageStart;
} }
@Override @Override
public void run() public void run()
{ {
ArrayList<World> worlds = new ArrayList<World>(); ArrayList<World> worlds = new ArrayList<World>();
for(World world : GriefPrevention.instance.getServer().getWorlds()) for (World world : GriefPrevention.instance.getServer().getWorlds())
{ {
if(GriefPrevention.instance.config_claims_worldModes.get(world) == ClaimsMode.Creative) if (GriefPrevention.instance.config_claims_worldModes.get(world) == ClaimsMode.Creative)
{ {
worlds.add(world); worlds.add(world);
} }
} }
for(int i = 0; i < worlds.size(); i++) for (int i = 0; i < worlds.size(); i++)
{ {
World world = worlds.get(i); World world = worlds.get(i);
List<Entity> entities = world.getEntities(); List<Entity> entities = world.getEntities();
//starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities //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 j = (int) (entities.size() * this.percentageStart);
int k = (int)(entities.size() * (this.percentageStart + .1)); int k = (int) (entities.size() * (this.percentageStart + .1));
Claim cachedClaim = null; Claim cachedClaim = null;
for(; j < entities.size() && j < k; j++) for (; j < entities.size() && j < k; j++)
{ {
Entity entity = entities.get(j); Entity entity = entities.get(j);
boolean remove = false; boolean remove = false;
if(entity instanceof Boat) //boats must be occupied if (entity instanceof Boat) //boats must be occupied
{ {
Boat boat = (Boat)entity; Boat boat = (Boat) entity;
if(boat.isEmpty()) remove = true; if (boat.isEmpty()) remove = true;
} } else if (entity instanceof Vehicle)
{
Vehicle vehicle = (Vehicle) entity;
else if(entity instanceof Vehicle) //minecarts in motion must be occupied by a player
{ if (vehicle.getVelocity().lengthSquared() != 0)
Vehicle vehicle = (Vehicle)entity; {
if (vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
{
remove = true;
}
}
//minecarts in motion must be occupied by a player //stationary carts must be on rails
if(vehicle.getVelocity().lengthSquared() != 0) else
{ {
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player)) Material material = world.getBlockAt(vehicle.getLocation()).getType();
{ if (material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
remove = true; {
} remove = true;
} }
}
}
//stationary carts must be on rails //all non-player entities must be in claims
else else if (!(entity instanceof Player))
{ {
Material material = world.getBlockAt(vehicle.getLocation()).getType(); Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
if(material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL) if (claim != null)
{ {
remove = true; cachedClaim = claim;
} } else
} {
} remove = true;
}
}
//all non-player entities must be in claims if (remove)
else if(!(entity instanceof Player)) {
{ GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true);
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim); entity.remove();
if(claim != null) }
{ }
cachedClaim = claim; }
}
else
{
remove = true;
}
}
if(remove) //starting and stopping point. each execution of the task scans 5% of the server's claims
{ List<Claim> claims = GriefPrevention.instance.dataStore.claims;
GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true); int j = (int) (claims.size() * this.percentageStart);
entity.remove(); int k = (int) (claims.size() * (this.percentageStart + .05));
} for (; j < claims.size() && j < k; j++)
} {
} Claim claim = claims.get(j);
//starting and stopping point. each execution of the task scans 5% of the server's claims //if it's a creative mode claim
List<Claim> claims = GriefPrevention.instance.dataStore.claims; if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
int j = (int)(claims.size() * this.percentageStart); {
int k = (int)(claims.size() * (this.percentageStart + .05)); //check its entity count and remove any extras
for(; j < claims.size() && j < k; j++) claim.allowMoreEntities(true);
{ }
Claim claim = claims.get(j); }
//if it's a creative mode claim //schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner())) double nextRunPercentageStart = this.percentageStart + .05;
{ if (nextRunPercentageStart > .99)
//check its entity count and remove any extras {
claim.allowMoreEntities(true); nextRunPercentageStart = 0;
} }
}
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second) EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
double nextRunPercentageStart = this.percentageStart + .05; GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
if(nextRunPercentageStart > .99) }
{
nextRunPercentageStart = 0;
}
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
}
} }

View File

@ -26,53 +26,53 @@ import org.bukkit.inventory.EquipmentSlot;
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars //otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
class EquipShovelProcessingTask implements Runnable class EquipShovelProcessingTask implements Runnable
{ {
//player data //player data
private Player player; private Player player;
public EquipShovelProcessingTask(Player player) public EquipShovelProcessingTask(Player player)
{ {
this.player = player; this.player = player;
} }
@Override @Override
public void run() public void run()
{ {
//if he's not holding the golden shovel anymore, do nothing //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; if (GriefPrevention.instance.getItemInHand(player, EquipmentSlot.HAND).getType() != GriefPrevention.instance.config_claims_modificationTool)
return;
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
//reset any work he might have been doing //reset any work he might have been doing
playerData.lastShovelLocation = null; playerData.lastShovelLocation = null;
playerData.claimResizing = null; playerData.claimResizing = null;
//always reset to basic claims mode //always reset to basic claims mode
if(playerData.shovelMode != ShovelMode.Basic) if (playerData.shovelMode != ShovelMode.Basic)
{ {
playerData.shovelMode = ShovelMode.Basic; playerData.shovelMode = ShovelMode.Basic;
GriefPrevention.sendMessage(player, TextMode.Info, Messages.ShovelBasicClaimMode); GriefPrevention.sendMessage(player, TextMode.Info, Messages.ShovelBasicClaimMode);
} }
//tell him how many claim blocks he has available //tell him how many claim blocks he has available
int remainingBlocks = playerData.getRemainingClaimBlocks(); int remainingBlocks = playerData.getRemainingClaimBlocks();
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks)); GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks));
//link to a video demo of land claiming, based on world type //link to a video demo of land claiming, based on world type
if(GriefPrevention.instance.creativeRulesApply(player.getLocation())) if (GriefPrevention.instance.creativeRulesApply(player.getLocation()))
{ {
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL); GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsVideo2, DataStore.CREATIVE_VIDEO_URL);
} } else if (GriefPrevention.instance.claimsEnabledForWorld(player.getLocation().getWorld()))
else if(GriefPrevention.instance.claimsEnabledForWorld(player.getLocation().getWorld())) {
{ GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL);
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL); }
}
//if standing in a claim owned by the player, visualize it //if standing in a claim owned by the player, visualize it
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, playerData.lastClaim); Claim claim = GriefPrevention.instance.dataStore.getClaimAt(player.getLocation(), true, playerData.lastClaim);
if(claim != null && claim.allowEdit(player) == null) if (claim != null && claim.allowEdit(player) == null)
{ {
playerData.lastClaim = claim; playerData.lastClaim = claim;
Visualization.Apply(player, Visualization.FromClaim(claim, player.getEyeLocation().getBlockY(), VisualizationType.Claim, player.getLocation())); Visualization.Apply(player, Visualization.FromClaim(claim, player.getEyeLocation().getBlockY(), VisualizationType.Claim, player.getLocation()));
} }
} }
} }

View File

@ -33,45 +33,47 @@ import java.util.stream.Collectors;
//runs every 1 minute in the main thread //runs every 1 minute in the main thread
class FindUnusedClaimsTask implements Runnable class FindUnusedClaimsTask implements Runnable
{ {
private List<UUID> claimOwnerUUIDs; private List<UUID> claimOwnerUUIDs;
private Iterator<UUID> claimOwnerIterator; private Iterator<UUID> claimOwnerIterator;
FindUnusedClaimsTask() FindUnusedClaimsTask()
{ {
refreshUUIDs(); refreshUUIDs();
} }
@Override @Override
public void run() public void run()
{ {
//don't do anything when there are no claims //don't do anything when there are no claims
if(claimOwnerUUIDs.isEmpty()) return; if (claimOwnerUUIDs.isEmpty()) return;
//wrap search around to beginning //wrap search around to beginning
if(!claimOwnerIterator.hasNext()) if (!claimOwnerIterator.hasNext())
{ {
refreshUUIDs(); refreshUUIDs();
return; return;
} }
GriefPrevention.instance.getServer().getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claimOwnerIterator.next())); GriefPrevention.instance.getServer().getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claimOwnerIterator.next()));
} }
public void refreshUUIDs() { public void refreshUUIDs()
// Fetch owner UUIDs from list of claims {
claimOwnerUUIDs = GriefPrevention.instance.dataStore.claims.stream().map(claim -> claim.ownerID) // Fetch owner UUIDs from list of claims
.distinct().filter(Objects::nonNull).collect(Collectors.toList()); claimOwnerUUIDs = GriefPrevention.instance.dataStore.claims.stream().map(claim -> claim.ownerID)
.distinct().filter(Objects::nonNull).collect(Collectors.toList());
if (!claimOwnerUUIDs.isEmpty()) { if (!claimOwnerUUIDs.isEmpty())
// Randomize order {
Collections.shuffle(claimOwnerUUIDs); // Randomize order
} Collections.shuffle(claimOwnerUUIDs);
}
GriefPrevention.AddLogEntry("The following UUIDs own a claim and will be checked for inactivity in the following order:", CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("The following UUIDs own a claim and will be checked for inactivity in the following order:", CustomLogEntryTypes.Debug, true);
for (UUID uuid : claimOwnerUUIDs) for (UUID uuid : claimOwnerUUIDs)
GriefPrevention.AddLogEntry(uuid.toString(), CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry(uuid.toString(), CustomLogEntryTypes.Debug, true);
claimOwnerIterator = claimOwnerUUIDs.iterator(); claimOwnerIterator = claimOwnerUUIDs.iterator();
} }
} }

View File

@ -1,13 +1,13 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import com.google.common.io.Files;
import java.io.File; import java.io.File;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.google.common.io.Files;
//loads ignore data from file into a hash map //loads ignore data from file into a hash map
class IgnoreLoaderThread extends Thread class IgnoreLoaderThread extends Thread
{ {
@ -27,7 +27,7 @@ class IgnoreLoaderThread extends Thread
File ignoreFile = new File(DataStore.playerDataFolderPath + File.separator + this.playerToLoad + ".ignore"); File ignoreFile = new File(DataStore.playerDataFolderPath + File.separator + this.playerToLoad + ".ignore");
//if the file doesn't exist, there's nothing to do here //if the file doesn't exist, there's nothing to do here
if(!ignoreFile.exists()) return; if (!ignoreFile.exists()) return;
boolean needRetry = false; boolean needRetry = false;
int retriesRemaining = 5; int retriesRemaining = 5;
@ -42,10 +42,10 @@ class IgnoreLoaderThread extends Thread
List<String> lines = Files.readLines(ignoreFile, Charset.forName("UTF-8")); List<String> lines = Files.readLines(ignoreFile, Charset.forName("UTF-8"));
//each line is one ignore. asterisks indicate administrative ignores //each line is one ignore. asterisks indicate administrative ignores
for(String line : lines) for (String line : lines)
{ {
boolean adminIgnore = false; boolean adminIgnore = false;
if(line.startsWith("*")) if (line.startsWith("*"))
{ {
adminIgnore = true; adminIgnore = true;
line = line.substring(1); line = line.substring(1);
@ -55,12 +55,12 @@ class IgnoreLoaderThread extends Thread
UUID ignoredUUID = UUID.fromString(line); UUID ignoredUUID = UUID.fromString(line);
this.destinationMap.put(ignoredUUID, adminIgnore); this.destinationMap.put(ignoredUUID, adminIgnore);
} }
catch(IllegalArgumentException e){} //if a bad UUID, ignore the line catch (IllegalArgumentException e) {} //if a bad UUID, ignore the line
} }
} }
//if there's any problem with the file's content, retry up to 5 times with 5 milliseconds between //if there's any problem with the file's content, retry up to 5 times with 5 milliseconds between
catch(Exception e) catch (Exception e)
{ {
latestException = e; latestException = e;
needRetry = true; needRetry = true;
@ -69,14 +69,14 @@ class IgnoreLoaderThread extends Thread
try try
{ {
if(needRetry) Thread.sleep(5); if (needRetry) Thread.sleep(5);
} }
catch(InterruptedException exception) {} catch (InterruptedException exception) {}
}while(needRetry && retriesRemaining >= 0); } while (needRetry && retriesRemaining >= 0);
//if last attempt failed, log information about the problem //if last attempt failed, log information about the problem
if(needRetry) if (needRetry)
{ {
GriefPrevention.AddLogEntry("Retry attempts exhausted. Unable to load ignore data for player \"" + playerToLoad.toString() + "\": " + latestException.toString()); GriefPrevention.AddLogEntry("Retry attempts exhausted. Unable to load ignore data for player \"" + playerToLoad.toString() + "\": " + latestException.toString());
latestException.printStackTrace(); latestException.printStackTrace();

View File

@ -22,14 +22,14 @@ import java.net.InetAddress;
public class IpBanInfo public class IpBanInfo
{ {
InetAddress address; InetAddress address;
long expirationTimestamp; long expirationTimestamp;
String bannedAccountName; String bannedAccountName;
IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName) IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName)
{ {
this.address = address; this.address = address;
this.expirationTimestamp = expirationTimestamp; this.expirationTimestamp = expirationTimestamp;
this.bannedAccountName = bannedAccountName; this.bannedAccountName = bannedAccountName;
} }
} }

View File

@ -24,31 +24,31 @@ import java.util.Set;
//ordered list of material info objects, for fast searching //ordered list of material info objects, for fast searching
public class MaterialCollection public class MaterialCollection
{ {
Set<MaterialInfo> materials = new HashSet<MaterialInfo>(); Set<MaterialInfo> materials = new HashSet<MaterialInfo>();
void Add(MaterialInfo material) void Add(MaterialInfo material)
{ {
this.materials.add(material); this.materials.add(material);
} }
boolean Contains(MaterialInfo material) boolean Contains(MaterialInfo material)
{ {
return this.materials.contains(material); return this.materials.contains(material);
} }
@Override @Override
public String toString() public String toString()
{ {
return materials.toString(); return materials.toString();
} }
public int size() public int size()
{ {
return this.materials.size(); return this.materials.size();
} }
public void clear() public void clear()
{ {
this.materials.clear(); this.materials.clear();
} }
} }

View File

@ -24,73 +24,72 @@ import org.bukkit.Material;
public class MaterialInfo public class MaterialInfo
{ {
Material typeID; Material typeID;
byte data; byte data;
boolean allDataValues; boolean allDataValues;
String description; String description;
public MaterialInfo(Material typeID, byte data, String description) public MaterialInfo(Material typeID, byte data, String description)
{ {
this.typeID = typeID; this.typeID = typeID;
this.data = data; this.data = data;
this.allDataValues = false; this.allDataValues = false;
this.description = description; this.description = description;
} }
public MaterialInfo(Material typeID, String description) public MaterialInfo(Material typeID, String description)
{ {
this.typeID = typeID; this.typeID = typeID;
this.data = 0; this.data = 0;
this.allDataValues = true; this.allDataValues = true;
this.description = description; this.description = description;
} }
private MaterialInfo(Material typeID, byte data, boolean allDataValues, String description) private MaterialInfo(Material typeID, byte data, boolean allDataValues, String description)
{ {
this.typeID = typeID; this.typeID = typeID;
this.data = data; this.data = data;
this.allDataValues = allDataValues; this.allDataValues = allDataValues;
this.description = description; this.description = description;
} }
@Override @Override
public String toString() public String toString()
{ {
String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues?"*":String.valueOf(this.data)); String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues ? "*" : String.valueOf(this.data));
if(this.description != null) returnValue += ":" + this.description; if (this.description != null) returnValue += ":" + this.description;
return returnValue; return returnValue;
} }
public static MaterialInfo fromString(String string) public static MaterialInfo fromString(String string)
{ {
if(string == null || string.isEmpty()) return null; if (string == null || string.isEmpty()) return null;
String [] parts = string.split(":"); String[] parts = string.split(":");
if(parts.length < 3) return null; if (parts.length < 3) return null;
try try
{ {
Material typeID = Material.matchMaterial(parts[0]); Material typeID = Material.matchMaterial(parts[0]);
byte data; byte data;
boolean allDataValues; boolean allDataValues;
if(parts[1].equals("*")) if (parts[1].equals("*"))
{ {
allDataValues = true; allDataValues = true;
data = 0; data = 0;
} } else
else {
{ allDataValues = false;
allDataValues = false; data = Byte.parseByte(parts[1]);
data = Byte.parseByte(parts[1]); }
}
return new MaterialInfo(typeID, data, allDataValues, parts[2]); return new MaterialInfo(typeID, data, allDataValues, parts[2]);
} }
catch(NumberFormatException exception) catch (NumberFormatException exception)
{ {
return null; return null;
} }
} }
} }

View File

@ -1,9 +1,10 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.UUID;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.UUID;
class PendingItemProtection class PendingItemProtection
{ {
public Location location; public Location location;

View File

@ -17,184 +17,176 @@
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.UUID; import java.util.UUID;
import java.util.Vector; import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import me.ryanhamshire.GriefPrevention.Claim;
import me.ryanhamshire.GriefPrevention.GriefPrevention;
import me.ryanhamshire.GriefPrevention.ShovelMode;
import me.ryanhamshire.GriefPrevention.SiegeData;
import me.ryanhamshire.GriefPrevention.Visualization;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
//holds all of GriefPrevention's player-tied data //holds all of GriefPrevention's player-tied data
public class PlayerData public class PlayerData
{ {
//the player's ID //the player's ID
public UUID playerID; public UUID playerID;
//the player's claims //the player's claims
private Vector<Claim> claims = null; private Vector<Claim> claims = null;
//how many claim blocks the player has earned via play time //how many claim blocks the player has earned via play time
private Integer accruedClaimBlocks = null; private Integer accruedClaimBlocks = null;
//temporary holding area to avoid opening data files too early //temporary holding area to avoid opening data files too early
private int newlyAccruedClaimBlocks = 0; private int newlyAccruedClaimBlocks = 0;
//where this player was the last time we checked on him for earning claim blocks //where this player was the last time we checked on him for earning claim blocks
public Location lastAfkCheckLocation = null; public Location lastAfkCheckLocation = null;
//how many claim blocks the player has been gifted by admins, or purchased via economy integration //how many claim blocks the player has been gifted by admins, or purchased via economy integration
private Integer bonusClaimBlocks = null; private Integer bonusClaimBlocks = null;
//what "mode" the shovel is in determines what it will do when it's used //what "mode" the shovel is in determines what it will do when it's used
public ShovelMode shovelMode = ShovelMode.Basic; public ShovelMode shovelMode = ShovelMode.Basic;
//radius for restore nature fill mode //radius for restore nature fill mode
int fillRadius = 0; int fillRadius = 0;
//last place the player used the shovel, useful in creating and resizing claims, //last place the player used the shovel, useful in creating and resizing claims,
//because the player must use the shovel twice in those instances //because the player must use the shovel twice in those instances
public Location lastShovelLocation = null; public Location lastShovelLocation = null;
//the claim this player is currently resizing //the claim this player is currently resizing
public Claim claimResizing = null; public Claim claimResizing = null;
//the claim this player is currently subdividing //the claim this player is currently subdividing
public Claim claimSubdividing = null; public Claim claimSubdividing = null;
//whether or not the player has a pending /trapped rescue //whether or not the player has a pending /trapped rescue
public boolean pendingTrapped = false; public boolean pendingTrapped = false;
//whether this player was recently warned about building outside land claims //whether this player was recently warned about building outside land claims
boolean warnedAboutBuildingOutsideClaims = false; boolean warnedAboutBuildingOutsideClaims = false;
//timestamp when last siege ended (where this player was the defender) //timestamp when last siege ended (where this player was the defender)
long lastSiegeEndTimeStamp = 0; long lastSiegeEndTimeStamp = 0;
//whether the player was kicked (set and used during logout) //whether the player was kicked (set and used during logout)
boolean wasKicked = false; boolean wasKicked = false;
//visualization //visualization
public Visualization currentVisualization = null; public Visualization currentVisualization = null;
//anti-camping pvp protection //anti-camping pvp protection
public boolean pvpImmune = false; public boolean pvpImmune = false;
public long lastSpawn = 0; public long lastSpawn = 0;
//ignore claims mode //ignore claims mode
public boolean ignoreClaims = false; public boolean ignoreClaims = false;
//the last claim this player was in, that we know of //the last claim this player was in, that we know of
public Claim lastClaim = null; public Claim lastClaim = null;
//siege //siege
public SiegeData siegeData = null; public SiegeData siegeData = null;
//pvp //pvp
public long lastPvpTimestamp = 0; public long lastPvpTimestamp = 0;
public String lastPvpPlayer = ""; public String lastPvpPlayer = "";
//safety confirmation for deleting multi-subdivision claims //safety confirmation for deleting multi-subdivision claims
public boolean warnedAboutMajorDeletion = false; public boolean warnedAboutMajorDeletion = false;
public InetAddress ipAddress; public InetAddress ipAddress;
//for addons to set per-player claim limits. Any negative value will use config's value //for addons to set per-player claim limits. Any negative value will use config's value
private int AccruedClaimBlocksLimit = -1; private int AccruedClaimBlocksLimit = -1;
//whether or not this player has received a message about unlocking death drops since his last death //whether or not this player has received a message about unlocking death drops since his last death
boolean receivedDropUnlockAdvertisement = false; boolean receivedDropUnlockAdvertisement = false;
//whether or not this player's dropped items (on death) are unlocked for other players to pick up //whether or not this player's dropped items (on death) are unlocked for other players to pick up
boolean dropsAreUnlocked = false; boolean dropsAreUnlocked = false;
//message to send to player after he respawns //message to send to player after he respawns
String messageOnRespawn = null; String messageOnRespawn = null;
//player which a pet will be given to when it's right-clicked //player which a pet will be given to when it's right-clicked
OfflinePlayer petGiveawayRecipient = null; OfflinePlayer petGiveawayRecipient = null;
//timestamp for last "you're building outside your land claims" message //timestamp for last "you're building outside your land claims" message
Long buildWarningTimestamp = null; Long buildWarningTimestamp = null;
//spot where a player can't talk, used to mute new players until they've moved a little //spot where a player can't talk, used to mute new players until they've moved a little
//this is an anti-bot strategy. //this is an anti-bot strategy.
Location noChatLocation = null; Location noChatLocation = null;
//ignore list //ignore list
//true means invisible (admin-forced ignore), false means player-created ignore //true means invisible (admin-forced ignore), false means player-created ignore
public ConcurrentHashMap<UUID, Boolean> ignoredPlayers = new ConcurrentHashMap<UUID, Boolean>(); public ConcurrentHashMap<UUID, Boolean> ignoredPlayers = new ConcurrentHashMap<UUID, Boolean>();
public boolean ignoreListChanged = false; public boolean ignoreListChanged = false;
//profanity warning, once per play session //profanity warning, once per play session
boolean profanityWarned = false; boolean profanityWarned = false;
//whether or not this player is "in" pvp combat //whether or not this player is "in" pvp combat
public boolean inPvpCombat() public boolean inPvpCombat()
{ {
if(this.lastPvpTimestamp == 0) return false; if (this.lastPvpTimestamp == 0) return false;
long now = Calendar.getInstance().getTimeInMillis(); long now = Calendar.getInstance().getTimeInMillis();
long elapsed = now - this.lastPvpTimestamp; long elapsed = now - this.lastPvpTimestamp;
if(elapsed > GriefPrevention.instance.config_pvp_combatTimeoutSeconds * 1000) //X seconds if (elapsed > GriefPrevention.instance.config_pvp_combatTimeoutSeconds * 1000) //X seconds
{ {
this.lastPvpTimestamp = 0; this.lastPvpTimestamp = 0;
return false; return false;
} }
return true; return true;
} }
//the number of claim blocks a player has available for claiming land //the number of claim blocks a player has available for claiming land
public int getRemainingClaimBlocks() public int getRemainingClaimBlocks()
{ {
int remainingBlocks = this.getAccruedClaimBlocks() + this.getBonusClaimBlocks() + GriefPrevention.instance.dataStore.getGroupBonusBlocks(this.playerID); int remainingBlocks = this.getAccruedClaimBlocks() + this.getBonusClaimBlocks() + GriefPrevention.instance.dataStore.getGroupBonusBlocks(this.playerID);
for(int i = 0; i < this.getClaims().size(); i++) for (int i = 0; i < this.getClaims().size(); i++)
{ {
Claim claim = this.getClaims().get(i); Claim claim = this.getClaims().get(i);
remainingBlocks -= claim.getArea(); remainingBlocks -= claim.getArea();
} }
return remainingBlocks; return remainingBlocks;
} }
//don't load data from secondary storage until it's needed //don't load data from secondary storage until it's needed
public synchronized int getAccruedClaimBlocks() public synchronized int getAccruedClaimBlocks()
{ {
if(this.accruedClaimBlocks == null) this.loadDataFromSecondaryStorage(); if (this.accruedClaimBlocks == null) this.loadDataFromSecondaryStorage();
//update claim blocks with any he has accrued during his current play session //update claim blocks with any he has accrued during his current play session
if(this.newlyAccruedClaimBlocks > 0) if (this.newlyAccruedClaimBlocks > 0)
{ {
int accruedLimit = this.getAccruedClaimBlocksLimit(); int accruedLimit = this.getAccruedClaimBlocksLimit();
//if over the limit before adding blocks, leave it as-is, because the limit may have changed AFTER he accrued the blocks //if over the limit before adding blocks, leave it as-is, because the limit may have changed AFTER he accrued the blocks
if(this.accruedClaimBlocks < accruedLimit) if (this.accruedClaimBlocks < accruedLimit)
{ {
//move any in the holding area //move any in the holding area
int newTotal = this.accruedClaimBlocks + this.newlyAccruedClaimBlocks; int newTotal = this.accruedClaimBlocks + this.newlyAccruedClaimBlocks;
//respect limits //respect limits
this.accruedClaimBlocks = Math.min(newTotal, accruedLimit); this.accruedClaimBlocks = Math.min(newTotal, accruedLimit);
} }
this.newlyAccruedClaimBlocks = 0; this.newlyAccruedClaimBlocks = 0;
return this.accruedClaimBlocks; return this.accruedClaimBlocks;
} }
return accruedClaimBlocks; return accruedClaimBlocks;
} }
public void setAccruedClaimBlocks(Integer accruedClaimBlocks) public void setAccruedClaimBlocks(Integer accruedClaimBlocks)
@ -205,7 +197,7 @@ public class PlayerData
public int getBonusClaimBlocks() public int getBonusClaimBlocks()
{ {
if(this.bonusClaimBlocks == null) this.loadDataFromSecondaryStorage(); if (this.bonusClaimBlocks == null) this.loadDataFromSecondaryStorage();
return bonusClaimBlocks; return bonusClaimBlocks;
} }
@ -219,32 +211,30 @@ public class PlayerData
//reach out to secondary storage to get any data there //reach out to secondary storage to get any data there
PlayerData storageData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(this.playerID); PlayerData storageData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(this.playerID);
if(this.accruedClaimBlocks == null) if (this.accruedClaimBlocks == null)
{ {
if(storageData.accruedClaimBlocks != null) if (storageData.accruedClaimBlocks != null)
{ {
this.accruedClaimBlocks = storageData.accruedClaimBlocks; this.accruedClaimBlocks = storageData.accruedClaimBlocks;
//ensure at least minimum accrued are accrued (in case of settings changes to increase initial amount) //ensure at least minimum accrued are accrued (in case of settings changes to increase initial amount)
if(GriefPrevention.instance.config_advanced_fixNegativeClaimblockAmounts && (this.accruedClaimBlocks < GriefPrevention.instance.config_claims_initialBlocks)) if (GriefPrevention.instance.config_advanced_fixNegativeClaimblockAmounts && (this.accruedClaimBlocks < GriefPrevention.instance.config_claims_initialBlocks))
{ {
this.accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks; this.accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks;
} }
} } else
else
{ {
this.accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks; this.accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks;
} }
} }
if(this.bonusClaimBlocks == null) if (this.bonusClaimBlocks == null)
{ {
if(storageData.bonusClaimBlocks != null) if (storageData.bonusClaimBlocks != null)
{ {
this.bonusClaimBlocks = storageData.bonusClaimBlocks; this.bonusClaimBlocks = storageData.bonusClaimBlocks;
} } else
else
{ {
this.bonusClaimBlocks = 0; this.bonusClaimBlocks = 0;
} }
@ -253,22 +243,22 @@ public class PlayerData
public Vector<Claim> getClaims() public Vector<Claim> getClaims()
{ {
if(this.claims == null) if (this.claims == null)
{ {
this.claims = new Vector<Claim>(); this.claims = new Vector<Claim>();
//find all the claims belonging to this player and note them for future reference //find all the claims belonging to this player and note them for future reference
DataStore dataStore = GriefPrevention.instance.dataStore; DataStore dataStore = GriefPrevention.instance.dataStore;
int totalClaimsArea = 0; int totalClaimsArea = 0;
for(int i = 0; i < dataStore.claims.size(); i++) for (int i = 0; i < dataStore.claims.size(); i++)
{ {
Claim claim = dataStore.claims.get(i); Claim claim = dataStore.claims.get(i);
if(!claim.inDataStore) if (!claim.inDataStore)
{ {
dataStore.claims.remove(i--); dataStore.claims.remove(i--);
continue; continue;
} }
if(playerID.equals(claim.ownerID)) if (playerID.equals(claim.ownerID))
{ {
this.claims.add(claim); this.claims.add(claim);
totalClaimsArea += claim.getArea(); totalClaimsArea += claim.getArea();
@ -280,19 +270,19 @@ public class PlayerData
//if total claimed area is more than total blocks available //if total claimed area is more than total blocks available
int totalBlocks = this.accruedClaimBlocks + this.getBonusClaimBlocks() + GriefPrevention.instance.dataStore.getGroupBonusBlocks(this.playerID); int totalBlocks = this.accruedClaimBlocks + this.getBonusClaimBlocks() + GriefPrevention.instance.dataStore.getGroupBonusBlocks(this.playerID);
if(GriefPrevention.instance.config_advanced_fixNegativeClaimblockAmounts && totalBlocks < totalClaimsArea) if (GriefPrevention.instance.config_advanced_fixNegativeClaimblockAmounts && totalBlocks < totalClaimsArea)
{ {
OfflinePlayer player = GriefPrevention.instance.getServer().getOfflinePlayer(this.playerID); OfflinePlayer player = GriefPrevention.instance.getServer().getOfflinePlayer(this.playerID);
GriefPrevention.AddLogEntry(player.getName() + " has more claimed land than blocks available. Adding blocks to fix.", CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry(player.getName() + " has more claimed land than blocks available. Adding blocks to fix.", CustomLogEntryTypes.Debug, true);
GriefPrevention.AddLogEntry(player.getName() + " Accrued blocks: " + this.getAccruedClaimBlocks() + " Bonus blocks: " + this.getBonusClaimBlocks(), CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry(player.getName() + " Accrued blocks: " + this.getAccruedClaimBlocks() + " Bonus blocks: " + this.getBonusClaimBlocks(), CustomLogEntryTypes.Debug, true);
GriefPrevention.AddLogEntry("Total blocks: " + totalBlocks + " Total claimed area: " + totalClaimsArea, CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Total blocks: " + totalBlocks + " Total claimed area: " + totalClaimsArea, CustomLogEntryTypes.Debug, true);
for(Claim claim : this.claims) for (Claim claim : this.claims)
{ {
if(!claim.inDataStore) continue; if (!claim.inDataStore) continue;
GriefPrevention.AddLogEntry( GriefPrevention.AddLogEntry(
GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()) + " // " GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()) + " // "
+ GriefPrevention.getfriendlyLocationString(claim.getGreaterBoundaryCorner()) + " = " + GriefPrevention.getfriendlyLocationString(claim.getGreaterBoundaryCorner()) + " = "
+ claim.getArea() + claim.getArea()
, CustomLogEntryTypes.Debug, true); , CustomLogEntryTypes.Debug, true);
} }
@ -307,7 +297,7 @@ public class PlayerData
GriefPrevention.AddLogEntry("New total blocks: " + totalBlocks, CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("New total blocks: " + totalBlocks, CustomLogEntryTypes.Debug, true);
//if that didn't fix it, then make up the difference with bonus blocks //if that didn't fix it, then make up the difference with bonus blocks
if(totalBlocks < totalClaimsArea) if (totalBlocks < totalClaimsArea)
{ {
int bonusBlocksToAdd = totalClaimsArea - totalBlocks; int bonusBlocksToAdd = totalClaimsArea - totalBlocks;
this.bonusClaimBlocks += bonusBlocksToAdd; this.bonusClaimBlocks += bonusBlocksToAdd;
@ -321,9 +311,9 @@ public class PlayerData
} }
} }
for(int i = 0; i < this.claims.size(); i++) for (int i = 0; i < this.claims.size(); i++)
{ {
if(!claims.get(i).inDataStore) if (!claims.get(i).inDataStore)
{ {
claims.remove(i--); claims.remove(i--);
} }

View File

@ -27,45 +27,44 @@ import org.bukkit.entity.Player;
//but they CAN schedule a task to run in the main thread to do that job //but they CAN schedule a task to run in the main thread to do that job
class PlayerKickBanTask implements Runnable class PlayerKickBanTask implements Runnable
{ {
//player to kick or ban //player to kick or ban
private Player player; private Player player;
//message to send player. //message to send player.
private String reason; private String reason;
//source of ban //source of ban
private String source; private String source;
//whether to ban //whether to ban
private boolean ban; private boolean ban;
public PlayerKickBanTask(Player player, String reason, String source, boolean ban) public PlayerKickBanTask(Player player, String reason, String source, boolean ban)
{ {
this.player = player; this.player = player;
this.reason = reason; this.reason = reason;
this.source = source; this.source = source;
this.ban = ban; this.ban = ban;
} }
@Override @Override
public void run() public void run()
{ {
PlayerKickBanEvent kickBanEvent = new PlayerKickBanEvent(player, reason, source, ban); PlayerKickBanEvent kickBanEvent = new PlayerKickBanEvent(player, reason, source, ban);
Bukkit.getPluginManager().callEvent(kickBanEvent); Bukkit.getPluginManager().callEvent(kickBanEvent);
if (kickBanEvent.isCancelled()) if (kickBanEvent.isCancelled())
{ {
return; // cancelled by a plugin return; // cancelled by a plugin
} }
if(this.ban) if (this.ban)
{ {
//ban //ban
GriefPrevention.banPlayer(this.player, this.reason, this.source); GriefPrevention.banPlayer(this.player, this.reason, this.source);
} } else if (this.player.isOnline())
else if(this.player.isOnline()) {
{ this.player.kickPlayer(this.reason);
this.player.kickPlayer(this.reason); }
} }
}
} }

View File

@ -26,50 +26,49 @@ import org.bukkit.entity.Player;
//this does run in the main thread, so it's okay to make non-thread-safe calls //this does run in the main thread, so it's okay to make non-thread-safe calls
class PlayerRescueTask implements Runnable class PlayerRescueTask implements Runnable
{ {
//original location where /trapped was used //original location where /trapped was used
private Location location; private Location location;
//rescue destination, may be decided at instantiation or at execution //rescue destination, may be decided at instantiation or at execution
private Location destination; private Location destination;
//player data //player data
private Player player; private Player player;
public PlayerRescueTask(Player player, Location location, Location destination) public PlayerRescueTask(Player player, Location location, Location destination)
{ {
this.player = player; this.player = player;
this.location = location; this.location = location;
this.destination = destination; this.destination = destination;
} }
@Override @Override
public void run() public void run()
{ {
//if he logged out, don't do anything //if he logged out, don't do anything
if(!player.isOnline()) return; if (!player.isOnline()) return;
//he no longer has a pending /trapped slash command, so he can try to use it again now //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 playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
playerData.pendingTrapped = false; playerData.pendingTrapped = false;
//if the player moved three or more blocks from where he used /trapped, admonish him and don't save him //if the player moved three or more blocks from where he used /trapped, admonish him and don't save him
if(player.getLocation().distance(this.location) > 3) if (player.getLocation().distance(this.location) > 3)
{ {
GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved); GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved);
return; return;
} }
//otherwise find a place to teleport him //otherwise find a place to teleport him
if(this.destination == null) if (this.destination == null)
{ {
this.destination = GriefPrevention.instance.ejectPlayer(this.player); this.destination = GriefPrevention.instance.ejectPlayer(this.player);
} } else
else {
{ player.teleport(this.destination);
player.teleport(this.destination); }
}
//log entry, in case admins want to investigate the "trap" //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.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(this.destination) + ".");
} }
} }

View File

@ -24,32 +24,31 @@ import org.bukkit.entity.Player;
//used to send delayed messages, for example help text triggered by a player's chat //used to send delayed messages, for example help text triggered by a player's chat
class PvPImmunityValidationTask implements Runnable class PvPImmunityValidationTask implements Runnable
{ {
private Player player; private Player player;
public PvPImmunityValidationTask(Player player) public PvPImmunityValidationTask(Player player)
{ {
this.player = player; this.player = player;
} }
@Override @Override
public void run() public void run()
{ {
if(!player.isOnline()) return; if (!player.isOnline()) return;
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
if(!playerData.pvpImmune) return; if (!playerData.pvpImmune) return;
//check the player's inventory for anything //check the player's inventory for anything
if(!GriefPrevention.isInventoryEmpty(player)) if (!GriefPrevention.isInventoryEmpty(player))
{ {
//if found, cancel invulnerability and notify //if found, cancel invulnerability and notify
playerData.pvpImmune = false; playerData.pvpImmune = false;
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.PvPImmunityEnd); GriefPrevention.sendMessage(player, TextMode.Warn, Messages.PvPImmunityEnd);
} } else
else {
{ //otherwise check again in one minute
//otherwise check again in one minute GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 1200L);
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 1200L); }
} }
}
} }

View File

@ -18,8 +18,6 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.ArrayList;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -30,101 +28,103 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Hanging; import org.bukkit.entity.Hanging;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
//this main thread task takes the output from the RestoreNatureProcessingTask\ //this main thread task takes the output from the RestoreNatureProcessingTask\
//and updates the world accordingly //and updates the world accordingly
class RestoreNatureExecutionTask implements Runnable class RestoreNatureExecutionTask implements Runnable
{ {
//results from processing thread //results from processing thread
//will be applied to the world //will be applied to the world
private BlockSnapshot[][][] snapshots; private BlockSnapshot[][][] snapshots;
//boundaries for changes //boundaries for changes
private int miny; private int miny;
private Location lesserCorner; private Location lesserCorner;
private Location greaterCorner; private Location greaterCorner;
//player who should be notified about the result (will see a visualization when the restoration is complete) //player who should be notified about the result (will see a visualization when the restoration is complete)
private Player player; private Player player;
public RestoreNatureExecutionTask(BlockSnapshot[][][] snapshots, int miny, Location lesserCorner, Location greaterCorner, Player player) public RestoreNatureExecutionTask(BlockSnapshot[][][] snapshots, int miny, Location lesserCorner, Location greaterCorner, Player player)
{ {
this.snapshots = snapshots; this.snapshots = snapshots;
this.miny = miny; this.miny = miny;
this.lesserCorner = lesserCorner; this.lesserCorner = lesserCorner;
this.greaterCorner = greaterCorner; this.greaterCorner = greaterCorner;
this.player = player; this.player = player;
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
public void run() public void run()
{ {
//apply changes to the world, but ONLY to unclaimed blocks //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) //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 //those data were sent to the processing thread for referernce purposes, but aren't part of the area selected for restoration
Claim cachedClaim = null; Claim cachedClaim = null;
for(int x = 1; x < this.snapshots.length - 1; x++) for (int x = 1; x < this.snapshots.length - 1; x++)
{ {
for(int z = 1; z < this.snapshots[0][0].length - 1; z++) for (int z = 1; z < this.snapshots[0][0].length - 1; z++)
{ {
for(int y = this.miny; y < this.snapshots[0].length; y++) for (int y = this.miny; y < this.snapshots[0].length; y++)
{ {
BlockSnapshot blockUpdate = this.snapshots[x][y][z]; BlockSnapshot blockUpdate = this.snapshots[x][y][z];
Block currentBlock = blockUpdate.location.getBlock(); Block currentBlock = blockUpdate.location.getBlock();
if(blockUpdate.typeId != currentBlock.getType()|| !blockUpdate.data.equals(currentBlock.getBlockData())) if (blockUpdate.typeId != currentBlock.getType() || !blockUpdate.data.equals(currentBlock.getBlockData()))
{ {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(blockUpdate.location, false, cachedClaim); Claim claim = GriefPrevention.instance.dataStore.getClaimAt(blockUpdate.location, false, cachedClaim);
if(claim != null) if (claim != null)
{ {
cachedClaim = claim; cachedClaim = claim;
break; break;
} }
try try
{ {
currentBlock.setType(blockUpdate.typeId, false); currentBlock.setType(blockUpdate.typeId, false);
// currentBlock.setBlockData(blockUpdate.data, false); // currentBlock.setBlockData(blockUpdate.data, false);
} }
catch(IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
//just don't update this block and continue trying to update other blocks //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 //clean up any entities in the chunk, ensure no players are suffocated
Chunk chunk = this.lesserCorner.getChunk(); Chunk chunk = this.lesserCorner.getChunk();
Entity [] entities = chunk.getEntities(); Entity[] entities = chunk.getEntities();
for(int i = 0; i < entities.length; i++) for (int i = 0; i < entities.length; i++)
{ {
Entity entity = entities[i]; Entity entity = entities[i];
if(!(entity instanceof Player || entity instanceof Animals)) if (!(entity instanceof Player || entity instanceof Animals))
{ {
//hanging entities (paintings, item frames) are protected when they're in land claims //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) if (!(entity instanceof Hanging) || GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, null) == null)
{ {
//everything else is removed //everything else is removed
entity.remove(); entity.remove();
} }
} }
//for players, always ensure there's air where the player is standing //for players, always ensure there's air where the player is standing
else else
{ {
Block feetBlock = entity.getLocation().getBlock(); Block feetBlock = entity.getLocation().getBlock();
feetBlock.setType(Material.AIR); feetBlock.setType(Material.AIR);
feetBlock.getRelative(BlockFace.UP).setType(Material.AIR); feetBlock.getRelative(BlockFace.UP).setType(Material.AIR);
} }
} }
//show visualization to player who started the restoration //show visualization to player who started the restoration
if(player != null) if (player != null)
{ {
Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null); Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null);
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation()); Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
Visualization.Apply(player, visualization); Visualization.Apply(player, visualization);
} }
} }
} }

View File

@ -16,43 +16,43 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.Collection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.Collection;
//secures a claim after a siege looting window has closed //secures a claim after a siege looting window has closed
class SecureClaimTask implements Runnable class SecureClaimTask implements Runnable
{ {
private SiegeData siegeData; private SiegeData siegeData;
public SecureClaimTask(SiegeData siegeData) public SecureClaimTask(SiegeData siegeData)
{ {
this.siegeData = siegeData; this.siegeData = siegeData;
} }
@Override @Override
public void run() public void run()
{ {
//for each claim involved in this siege //for each claim involved in this siege
for(int i = 0; i < this.siegeData.claims.size(); i++) for (int i = 0; i < this.siegeData.claims.size(); i++)
{ {
//lock the doors //lock the doors
Claim claim = this.siegeData.claims.get(i); Claim claim = this.siegeData.claims.get(i);
claim.doorsOpen = false; claim.doorsOpen = false;
//eject bad guys //eject bad guys
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Collection<Player> onlinePlayers = (Collection<Player>)GriefPrevention.instance.getServer().getOnlinePlayers(); Collection<Player> onlinePlayers = (Collection<Player>) GriefPrevention.instance.getServer().getOnlinePlayers();
for(Player player : onlinePlayers) for (Player player : onlinePlayers)
{ {
if(claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null) if (claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null)
{ {
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection); GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection);
GriefPrevention.instance.ejectPlayer(player); GriefPrevention.instance.ejectPlayer(player);
} }
} }
} }
} }
} }

View File

@ -25,37 +25,37 @@ import org.bukkit.entity.Player;
//used to send delayed messages, for example help text triggered by a player's chat //used to send delayed messages, for example help text triggered by a player's chat
class SendPlayerMessageTask implements Runnable class SendPlayerMessageTask implements Runnable
{ {
private Player player; private Player player;
private ChatColor color; private ChatColor color;
private String message; private String message;
public SendPlayerMessageTask(Player player, ChatColor color, String message) public SendPlayerMessageTask(Player player, ChatColor color, String message)
{ {
this.player = player; this.player = player;
this.color = color; this.color = color;
this.message = message; this.message = message;
} }
@Override @Override
public void run() public void run()
{ {
if(player == null) if (player == null)
{ {
GriefPrevention.AddLogEntry(color + message); GriefPrevention.AddLogEntry(color + message);
return; return;
} }
//if the player is dead, save it for after his respawn //if the player is dead, save it for after his respawn
if(this.player.isDead()) if (this.player.isDead())
{ {
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId()); PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId());
playerData.messageOnRespawn = this.color + this.message; playerData.messageOnRespawn = this.color + this.message;
} }
//otherwise send it immediately //otherwise send it immediately
else else
{ {
GriefPrevention.sendMessage(this.player, this.color, this.message); GriefPrevention.sendMessage(this.player, this.color, this.message);
} }
} }
} }

View File

@ -16,15 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
//enumeration for golden shovel modes //enumeration for golden shovel modes
public enum ShovelMode public enum ShovelMode
{ {
Basic, Basic,
Admin, Admin,
Subdivide, Subdivide,
RestoreNature, RestoreNature,
RestoreNatureAggressive, RestoreNatureAggressive,
RestoreNatureFill RestoreNatureFill
} }

View File

@ -24,87 +24,87 @@ import org.bukkit.entity.Player;
//for example, defender escaped or attacker gave up and left //for example, defender escaped or attacker gave up and left
class SiegeCheckupTask implements Runnable class SiegeCheckupTask implements Runnable
{ {
private SiegeData siegeData; private SiegeData siegeData;
public SiegeCheckupTask(SiegeData siegeData) public SiegeCheckupTask(SiegeData siegeData)
{ {
this.siegeData = siegeData; this.siegeData = siegeData;
} }
@Override @Override
public void run() public void run()
{ {
DataStore dataStore = GriefPrevention.instance.dataStore; DataStore dataStore = GriefPrevention.instance.dataStore;
Player defender = this.siegeData.defender; Player defender = this.siegeData.defender;
Player attacker = this.siegeData.attacker; Player attacker = this.siegeData.attacker;
//where is the defender? //where is the defender?
Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null); 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 this is a new claim and he has some permission there, extend the siege to include it
if(defenderClaim != null) if (defenderClaim != null)
{ {
String noAccessReason = defenderClaim.allowAccess(defender); String noAccessReason = defenderClaim.allowAccess(defender);
if(defenderClaim.canSiege(defender) && noAccessReason == null) if (defenderClaim.canSiege(defender) && noAccessReason == null)
{ {
this.siegeData.claims.add(defenderClaim); this.siegeData.claims.add(defenderClaim);
defenderClaim.siegeData = this.siegeData; defenderClaim.siegeData = this.siegeData;
} }
} }
//determine who's close enough to the siege area to be considered "still here" //determine who's close enough to the siege area to be considered "still here"
boolean attackerRemains = this.playerRemains(attacker); boolean attackerRemains = this.playerRemains(attacker);
boolean defenderRemains = this.playerRemains(defender); boolean defenderRemains = this.playerRemains(defender);
//if they're both here, just plan to come check again later //if they're both here, just plan to come check again later
if(attackerRemains && defenderRemains) if (attackerRemains && defenderRemains)
{ {
this.scheduleAnotherCheck(); this.scheduleAnotherCheck();
} }
//otherwise attacker wins if the defender runs away //otherwise attacker wins if the defender runs away
else if(attackerRemains && !defenderRemains) else if (attackerRemains && !defenderRemains)
{ {
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null);
} }
//or defender wins if the attacker leaves //or defender wins if the attacker leaves
else if(!attackerRemains && defenderRemains) else if (!attackerRemains && defenderRemains)
{ {
dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), null); dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), null);
} }
//if they both left, but are still close together, the battle continues (check again later) //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 else if (attacker.getWorld().equals(defender.getWorld()) && attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing
{ {
this.scheduleAnotherCheck(); 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) //otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase)
else else
{ {
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), null); 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 //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) private boolean playerRemains(Player player)
{ {
for(int i = 0; i < this.siegeData.claims.size(); i++) for (int i = 0; i < this.siegeData.claims.size(); i++)
{ {
Claim claim = this.siegeData.claims.get(i); Claim claim = this.siegeData.claims.get(i);
if(claim.isNear(player.getLocation(), 25)) if (claim.isNear(player.getLocation(), 25))
{ {
return true; return true;
} }
} }
return false; return false;
} }
//schedules another checkup later //schedules another checkup later
private void scheduleAnotherCheck() private void scheduleAnotherCheck()
{ {
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30); this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
} }
} }

View File

@ -18,23 +18,23 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.ArrayList;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
//information about an ongoing siege //information about an ongoing siege
public class SiegeData public class SiegeData
{ {
public Player defender; public Player defender;
public Player attacker; public Player attacker;
public ArrayList<Claim> claims; public ArrayList<Claim> claims;
public int checkupTaskID; public int checkupTaskID;
public SiegeData(Player attacker, Player defender, Claim claim) public SiegeData(Player attacker, Player defender, Claim claim)
{ {
this.defender = defender; this.defender = defender;
this.attacker = attacker; this.attacker = attacker;
this.claims = new ArrayList<Claim>(); this.claims = new ArrayList<Claim>();
this.claims.add(claim); this.claims.add(claim);
} }
} }

View File

@ -15,10 +15,11 @@ class SpamDetector
//data for individual chatters //data for individual chatters
ConcurrentHashMap<UUID, ChatterData> dataStore = new ConcurrentHashMap<UUID, ChatterData>(); ConcurrentHashMap<UUID, ChatterData> dataStore = new ConcurrentHashMap<UUID, ChatterData>();
private ChatterData getChatterData(UUID chatterID) private ChatterData getChatterData(UUID chatterID)
{ {
ChatterData data = this.dataStore.get(chatterID); ChatterData data = this.dataStore.get(chatterID);
if(data == null) if (data == null)
{ {
data = new ChatterData(); data = new ChatterData();
this.dataStore.put(chatterID, data); this.dataStore.put(chatterID, data);
@ -33,7 +34,7 @@ class SpamDetector
result.finalMessage = message; result.finalMessage = message;
//remedy any CAPS SPAM, exception for very short messages which could be emoticons like =D or XD //remedy any CAPS SPAM, exception for very short messages which could be emoticons like =D or XD
if(message.length() > 4 && this.stringsAreSimilar(message.toUpperCase(), message)) if (message.length() > 4 && this.stringsAreSimilar(message.toUpperCase(), message))
{ {
message = message.toLowerCase(); message = message.toLowerCase();
result.finalMessage = message; result.finalMessage = message;
@ -43,7 +44,7 @@ class SpamDetector
ChatterData chatterData = this.getChatterData(chatterID); ChatterData chatterData = this.getChatterData(chatterID);
//mute if total volume of text from this player is too high //mute if total volume of text from this player is too high
if(message.length() > 50 && chatterData.getTotalRecentLength(timestamp) > 200) if (message.length() > 50 && chatterData.getTotalRecentLength(timestamp) > 200)
{ {
spam = true; spam = true;
result.muteReason = "too much chat sent in 10 seconds"; result.muteReason = "too much chat sent in 10 seconds";
@ -51,13 +52,12 @@ class SpamDetector
} }
//always mute an exact match to the last chat message //always mute an exact match to the last chat message
if(result.finalMessage.equals(this.lastChatMessage) && timestamp - this.lastChatMessageTimestamp < 2000) if (result.finalMessage.equals(this.lastChatMessage) && timestamp - this.lastChatMessageTimestamp < 2000)
{ {
chatterData.spamLevel += ++this.duplicateMessageCount; chatterData.spamLevel += ++this.duplicateMessageCount;
spam = true; spam = true;
result.muteReason = "repeat message"; result.muteReason = "repeat message";
} } else
else
{ {
this.lastChatMessage = message; this.lastChatMessage = message;
this.lastChatMessageTimestamp = timestamp; this.lastChatMessageTimestamp = timestamp;
@ -68,7 +68,7 @@ class SpamDetector
long millisecondsSinceLastMessage = timestamp - chatterData.lastMessageTimestamp; long millisecondsSinceLastMessage = timestamp - chatterData.lastMessageTimestamp;
//if the message came too close to the last one //if the message came too close to the last one
if(millisecondsSinceLastMessage < 1500) if (millisecondsSinceLastMessage < 1500)
{ {
//increment the spam counter //increment the spam counter
chatterData.spamLevel++; chatterData.spamLevel++;
@ -76,7 +76,7 @@ class SpamDetector
} }
//if it's exactly the same as the last message from the same player and within 30 seconds //if it's exactly the same as the last message from the same player and within 30 seconds
if(result.muteReason == null && millisecondsSinceLastMessage < 30000 && result.finalMessage.equalsIgnoreCase(chatterData.lastMessage)) if (result.muteReason == null && millisecondsSinceLastMessage < 30000 && result.finalMessage.equalsIgnoreCase(chatterData.lastMessage))
{ {
chatterData.spamLevel++; chatterData.spamLevel++;
spam = true; spam = true;
@ -84,68 +84,66 @@ class SpamDetector
} }
//if it's very similar to the last message from the same player and within 10 seconds of that message //if it's very similar to the last message from the same player and within 10 seconds of that message
if(result.muteReason == null && millisecondsSinceLastMessage < 10000 && this.stringsAreSimilar(message.toLowerCase(), chatterData.lastMessage.toLowerCase())) if (result.muteReason == null && millisecondsSinceLastMessage < 10000 && this.stringsAreSimilar(message.toLowerCase(), chatterData.lastMessage.toLowerCase()))
{ {
chatterData.spamLevel++; chatterData.spamLevel++;
spam = true; spam = true;
if(chatterData.spamLevel > 2) if (chatterData.spamLevel > 2)
{ {
result.muteReason = "similar message"; result.muteReason = "similar message";
} }
} }
//if the message was mostly non-alpha-numerics or doesn't include much whitespace, consider it a spam (probably ansi art or random text gibberish) //if the message was mostly non-alpha-numerics or doesn't include much whitespace, consider it a spam (probably ansi art or random text gibberish)
if(result.muteReason == null && message.length() > 5) if (result.muteReason == null && message.length() > 5)
{ {
int symbolsCount = 0; int symbolsCount = 0;
int whitespaceCount = 0; int whitespaceCount = 0;
for(int i = 0; i < message.length(); i++) for (int i = 0; i < message.length(); i++)
{ {
char character = message.charAt(i); char character = message.charAt(i);
if(!(Character.isLetterOrDigit(character))) if (!(Character.isLetterOrDigit(character)))
{ {
symbolsCount++; symbolsCount++;
} }
if(Character.isWhitespace(character)) if (Character.isWhitespace(character))
{ {
whitespaceCount++; whitespaceCount++;
} }
} }
if(symbolsCount > message.length() / 2 || (message.length() > 15 && whitespaceCount < message.length() / 10)) if (symbolsCount > message.length() / 2 || (message.length() > 15 && whitespaceCount < message.length() / 10))
{ {
spam = true; spam = true;
if(chatterData.spamLevel > 0) result.muteReason = "gibberish"; if (chatterData.spamLevel > 0) result.muteReason = "gibberish";
chatterData.spamLevel++; chatterData.spamLevel++;
} }
} }
//very short messages close together are spam //very short messages close together are spam
if(result.muteReason == null && message.length() < 5 && millisecondsSinceLastMessage < 3000) if (result.muteReason == null && message.length() < 5 && millisecondsSinceLastMessage < 3000)
{ {
spam = true; spam = true;
chatterData.spamLevel++; chatterData.spamLevel++;
} }
//if the message was determined to be a spam, consider taking action //if the message was determined to be a spam, consider taking action
if(spam) if (spam)
{ {
//anything above level 8 for a player which has received a warning... kick or if enabled, ban //anything above level 8 for a player which has received a warning... kick or if enabled, ban
if(chatterData.spamLevel > 8 && chatterData.spamWarned) if (chatterData.spamLevel > 8 && chatterData.spamWarned)
{ {
result.shouldBanChatter = true; result.shouldBanChatter = true;
} } else if (chatterData.spamLevel >= 4)
else if(chatterData.spamLevel >= 4)
{ {
if(!chatterData.spamWarned) if (!chatterData.spamWarned)
{ {
chatterData.spamWarned = true; chatterData.spamWarned = true;
result.shouldWarnChatter = true; result.shouldWarnChatter = true;
} }
if(result.muteReason == null) if (result.muteReason == null)
{ {
result.muteReason = "too-frequent text"; result.muteReason = "too-frequent text";
} }
@ -173,40 +171,40 @@ class SpamDetector
//determine which is shorter //determine which is shorter
String shorterString, longerString; String shorterString, longerString;
if(lastMessage.length() < message.length()) if (lastMessage.length() < message.length())
{ {
shorterString = lastMessage; shorterString = lastMessage;
longerString = message; longerString = message;
} } else
else
{ {
shorterString = message; shorterString = message;
longerString = lastMessage; longerString = lastMessage;
} }
if(shorterString.length() <= 5) return shorterString.equals(longerString); if (shorterString.length() <= 5) return shorterString.equals(longerString);
//set similarity tolerance //set similarity tolerance
int maxIdenticalCharacters = longerString.length() - longerString.length() / 4; int maxIdenticalCharacters = longerString.length() - longerString.length() / 4;
//trivial check on length //trivial check on length
if(shorterString.length() < maxIdenticalCharacters) return false; if (shorterString.length() < maxIdenticalCharacters) return false;
//compare forward //compare forward
int identicalCount = 0; int identicalCount = 0;
int i; int i;
for(i = 0; i < shorterString.length(); i++) for (i = 0; i < shorterString.length(); i++)
{ {
if(shorterString.charAt(i) == longerString.charAt(i)) identicalCount++; if (shorterString.charAt(i) == longerString.charAt(i)) identicalCount++;
if(identicalCount > maxIdenticalCharacters) return true; if (identicalCount > maxIdenticalCharacters) return true;
} }
//compare backward //compare backward
int j; int j;
for(j = 0; j < shorterString.length() - i; j++) for (j = 0; j < shorterString.length() - i; j++)
{ {
if(shorterString.charAt(shorterString.length() - j - 1) == longerString.charAt(longerString.length() - j - 1)) identicalCount++; if (shorterString.charAt(shorterString.length() - j - 1) == longerString.charAt(longerString.length() - j - 1))
if(identicalCount > maxIdenticalCharacters) return true; identicalCount++;
if (identicalCount > maxIdenticalCharacters) return true;
} }
return false; return false;
@ -245,7 +243,7 @@ class ChatterData
public int getTotalRecentLength(long timestamp) public int getTotalRecentLength(long timestamp)
{ {
LengthTimestampPair oldestPair = this.recentMessageLengths.peek(); LengthTimestampPair oldestPair = this.recentMessageLengths.peek();
while(oldestPair != null && timestamp - oldestPair.timestamp > 10000) while (oldestPair != null && timestamp - oldestPair.timestamp > 10000)
{ {
this.recentMessageLengths.poll(); this.recentMessageLengths.poll();
this.recentTotalLength -= oldestPair.length; this.recentTotalLength -= oldestPair.length;

View File

@ -23,9 +23,9 @@ import org.bukkit.ChatColor;
//just a few constants for chat color codes //just a few constants for chat color codes
public class TextMode public class TextMode
{ {
final static ChatColor Info = ChatColor.AQUA; final static ChatColor Info = ChatColor.AQUA;
final static ChatColor Instr = ChatColor.YELLOW; final static ChatColor Instr = ChatColor.YELLOW;
final static ChatColor Warn = ChatColor.GOLD; final static ChatColor Warn = ChatColor.GOLD;
final static ChatColor Err = ChatColor.RED; final static ChatColor Err = ChatColor.RED;
final static ChatColor Success = ChatColor.GREEN; final static ChatColor Success = ChatColor.GREEN;
} }

View File

@ -13,9 +13,12 @@ import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.HashMap;
import java.util.List;
import java.util.UUID;
class UUIDFetcher { class UUIDFetcher
{
private static int PROFILES_PER_REQUEST = 100; private static int PROFILES_PER_REQUEST = 100;
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
private final JSONParser jsonParser = new JSONParser(); private final JSONParser jsonParser = new JSONParser();
@ -28,23 +31,25 @@ class UUIDFetcher {
//record of username -> proper casing updates //record of username -> proper casing updates
static HashMap<String, String> correctedNames; static HashMap<String, String> correctedNames;
public UUIDFetcher(List<String> names, boolean rateLimiting) { public UUIDFetcher(List<String> names, boolean rateLimiting)
{
this.names = names; this.names = names;
this.rateLimiting = rateLimiting; this.rateLimiting = rateLimiting;
} }
public UUIDFetcher(List<String> names) { public UUIDFetcher(List<String> names)
{
this(names, true); this(names, true);
} }
public void call() throws Exception public void call() throws Exception
{ {
if(lookupCache == null) if (lookupCache == null)
{ {
lookupCache = new HashMap<String, UUID>(); lookupCache = new HashMap<String, UUID>();
} }
if(correctedNames == null) if (correctedNames == null)
{ {
correctedNames = new HashMap<String, String>(); correctedNames = new HashMap<String, String>();
} }
@ -52,10 +57,10 @@ class UUIDFetcher {
GriefPrevention.AddLogEntry("UUID conversion process started. Please be patient - this may take a while."); GriefPrevention.AddLogEntry("UUID conversion process started. Please be patient - this may take a while.");
GriefPrevention.AddLogEntry("Mining your local world data to save calls to Mojang..."); GriefPrevention.AddLogEntry("Mining your local world data to save calls to Mojang...");
OfflinePlayer [] players = GriefPrevention.instance.getServer().getOfflinePlayers(); OfflinePlayer[] players = GriefPrevention.instance.getServer().getOfflinePlayers();
for(OfflinePlayer player : players) for (OfflinePlayer player : players)
{ {
if(player.getName() != null && player.getUniqueId() != null) if (player.getName() != null && player.getUniqueId() != null)
{ {
lookupCache.put(player.getName(), player.getUniqueId()); lookupCache.put(player.getName(), player.getUniqueId());
lookupCache.put(player.getName().toLowerCase(), player.getUniqueId()); lookupCache.put(player.getName().toLowerCase(), player.getUniqueId());
@ -65,11 +70,11 @@ class UUIDFetcher {
//try to get correct casing from local data //try to get correct casing from local data
GriefPrevention.AddLogEntry("Checking local server data to get correct casing for player names..."); GriefPrevention.AddLogEntry("Checking local server data to get correct casing for player names...");
for(int i = 0; i < names.size(); i++) for (int i = 0; i < names.size(); i++)
{ {
String name = names.get(i); String name = names.get(i);
String correctCasingName = correctedNames.get(name); String correctCasingName = correctedNames.get(name);
if(correctCasingName != null && !name.equals(correctCasingName)) if (correctCasingName != null && !name.equals(correctCasingName))
{ {
GriefPrevention.AddLogEntry(name + " --> " + correctCasingName); GriefPrevention.AddLogEntry(name + " --> " + correctCasingName);
names.set(i, correctCasingName); names.set(i, correctCasingName);
@ -78,11 +83,11 @@ class UUIDFetcher {
//look for local uuid's first //look for local uuid's first
GriefPrevention.AddLogEntry("Checking local server data for UUIDs already seen..."); GriefPrevention.AddLogEntry("Checking local server data for UUIDs already seen...");
for(int i = 0; i < names.size(); i++) for (int i = 0; i < names.size(); i++)
{ {
String name = names.get(i); String name = names.get(i);
UUID uuid = lookupCache.get(name); UUID uuid = lookupCache.get(name);
if(uuid != null) if (uuid != null)
{ {
GriefPrevention.AddLogEntry(name + " --> " + uuid.toString()); GriefPrevention.AddLogEntry(name + " --> " + uuid.toString());
names.remove(i--); names.remove(i--);
@ -90,7 +95,7 @@ class UUIDFetcher {
} }
//for online mode, call Mojang to resolve the rest //for online mode, call Mojang to resolve the rest
if(GriefPrevention.instance.getServer().getOnlineMode()) if (GriefPrevention.instance.getServer().getOnlineMode())
{ {
GriefPrevention.AddLogEntry("Calling Mojang to get UUIDs for remaining unresolved players (this is the slowest step)..."); GriefPrevention.AddLogEntry("Calling Mojang to get UUIDs for remaining unresolved players (this is the slowest step)...");
@ -109,16 +114,16 @@ class UUIDFetcher {
{ {
array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
} }
catch(Exception e) catch (Exception e)
{ {
//in case of error 429 too many requests, pause and then retry later //in case of error 429 too many requests, pause and then retry later
if(e.getMessage().contains("429")) if (e.getMessage().contains("429"))
{ {
retry = true; retry = true;
//if this is the first time we're sending anything, the batch size must be too big //if this is the first time we're sending anything, the batch size must be too big
//try reducing it //try reducing it
if(i == 0 && PROFILES_PER_REQUEST > 1) if (i == 0 && PROFILES_PER_REQUEST > 1)
{ {
GriefPrevention.AddLogEntry("Batch size " + PROFILES_PER_REQUEST + " seems too large. Looking for a workable batch size..."); GriefPrevention.AddLogEntry("Batch size " + PROFILES_PER_REQUEST + " seems too large. Looking for a workable batch size...");
PROFILES_PER_REQUEST = Math.max(PROFILES_PER_REQUEST - 5, 1); PROFILES_PER_REQUEST = Math.max(PROFILES_PER_REQUEST - 5, 1);
@ -131,15 +136,15 @@ class UUIDFetcher {
GriefPrevention.AddLogEntry("Mojang says we're sending requests too fast. Will retry every 30 seconds until we succeed..."); GriefPrevention.AddLogEntry("Mojang says we're sending requests too fast. Will retry every 30 seconds until we succeed...");
Thread.sleep(30000); Thread.sleep(30000);
} }
} } else
else
{ {
throw e; throw e;
} }
} }
}while(retry); } while (retry);
for (Object profile : array) { for (Object profile : array)
{
JSONObject jsonProfile = (JSONObject) profile; JSONObject jsonProfile = (JSONObject) profile;
String id = (String) jsonProfile.get("id"); String id = (String) jsonProfile.get("id");
String name = (String) jsonProfile.get("name"); String name = (String) jsonProfile.get("name");
@ -148,7 +153,8 @@ class UUIDFetcher {
lookupCache.put(name, uuid); lookupCache.put(name, uuid);
lookupCache.put(name.toLowerCase(), uuid); lookupCache.put(name.toLowerCase(), uuid);
} }
if (rateLimiting) { if (rateLimiting)
{
Thread.sleep(200L); Thread.sleep(200L);
} }
} }
@ -159,7 +165,7 @@ class UUIDFetcher {
{ {
GriefPrevention.AddLogEntry("Generating offline mode UUIDs for remaining unresolved players..."); GriefPrevention.AddLogEntry("Generating offline mode UUIDs for remaining unresolved players...");
for(int i = 0; i < names.size(); i++) for (int i = 0; i < names.size(); i++)
{ {
String name = names.get(i); String name = names.get(i);
UUID uuid = java.util.UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)); UUID uuid = java.util.UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8));
@ -170,14 +176,16 @@ class UUIDFetcher {
} }
} }
private static void writeBody(HttpURLConnection connection, String body) throws Exception { private static void writeBody(HttpURLConnection connection, String body) throws Exception
{
OutputStream stream = connection.getOutputStream(); OutputStream stream = connection.getOutputStream();
stream.write(body.getBytes()); stream.write(body.getBytes());
stream.flush(); stream.flush();
stream.close(); stream.close();
} }
private static HttpURLConnection createConnection() throws Exception { private static HttpURLConnection createConnection() throws Exception
{
URL url = new URL(PROFILE_URL); URL url = new URL(PROFILE_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST"); connection.setRequestMethod("POST");
@ -188,19 +196,23 @@ class UUIDFetcher {
return connection; return connection;
} }
private static UUID getUUID(String id) { private static UUID getUUID(String id)
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +id.substring(20, 32)); {
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32));
} }
public static byte[] toBytes(UUID uuid) { public static byte[] toBytes(UUID uuid)
{
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
byteBuffer.putLong(uuid.getMostSignificantBits()); byteBuffer.putLong(uuid.getMostSignificantBits());
byteBuffer.putLong(uuid.getLeastSignificantBits()); byteBuffer.putLong(uuid.getLeastSignificantBits());
return byteBuffer.array(); return byteBuffer.array();
} }
public static UUID fromBytes(byte[] array) { public static UUID fromBytes(byte[] array)
if (array.length != 16) { {
if (array.length != 16)
{
throw new IllegalArgumentException("Illegal byte array length: " + array.length); throw new IllegalArgumentException("Illegal byte array length: " + array.length);
} }
ByteBuffer byteBuffer = ByteBuffer.wrap(array); ByteBuffer byteBuffer = ByteBuffer.wrap(array);
@ -212,7 +224,7 @@ class UUIDFetcher {
public static UUID getUUIDOf(String name) throws Exception public static UUID getUUIDOf(String name) throws Exception
{ {
UUID result = lookupCache.get(name); UUID result = lookupCache.get(name);
if(result == null) if (result == null)
{ {
//throw up our hands and report the problem in the logs //throw up our hands and report the problem in the logs
//this player will lose his land claim blocks, but claims will stay in place as admin claims //this player will lose his land claim blocks, but claims will stay in place as admin claims

View File

@ -18,8 +18,6 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import java.util.ArrayList;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Tag; import org.bukkit.Tag;
@ -30,302 +28,296 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Lightable; import org.bukkit.block.data.Lightable;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
//represents a visualization sent to a player //represents a visualization sent to a player
//FEATURE: to show players visually where claim boundaries are, we send them fake block change packets //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. //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 class Visualization
{ {
public ArrayList<VisualizationElement> elements = new ArrayList<VisualizationElement>(); public ArrayList<VisualizationElement> elements = new ArrayList<VisualizationElement>();
//sends a visualization to a player //sends a visualization to a player
public static void Apply(Player player, Visualization visualization) public static void Apply(Player player, Visualization visualization)
{ {
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
//if he has any current visualization, clear it first //if he has any current visualization, clear it first
if(playerData.currentVisualization != null) if (playerData.currentVisualization != null)
{ {
Visualization.Revert(player); Visualization.Revert(player);
} }
//if he's online, create a task to send him the visualization //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())) 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); 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 //reverts a visualization by sending another block change list, this time with the real world block values
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void Revert(Player player) public static void Revert(Player player)
{ {
if(!player.isOnline()) return; if (!player.isOnline()) return;
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
Visualization visualization = playerData.currentVisualization; Visualization visualization = playerData.currentVisualization;
if(playerData.currentVisualization != null) if (playerData.currentVisualization != null)
{ {
//locality //locality
int minx = player.getLocation().getBlockX() - 100; int minx = player.getLocation().getBlockX() - 100;
int minz = player.getLocation().getBlockZ() - 100; int minz = player.getLocation().getBlockZ() - 100;
int maxx = player.getLocation().getBlockX() + 100; int maxx = player.getLocation().getBlockX() + 100;
int maxz = player.getLocation().getBlockZ() + 100; int maxz = player.getLocation().getBlockZ() + 100;
//remove any elements which are too far away //remove any elements which are too far away
visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz); visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz);
//send real block information for any remaining elements //send real block information for any remaining elements
for(int i = 0; i < visualization.elements.size(); i++) for (int i = 0; i < visualization.elements.size(); i++)
{ {
VisualizationElement element = visualization.elements.get(i); VisualizationElement element = visualization.elements.get(i);
//check player still in world where visualization exists //check player still in world where visualization exists
if(i == 0) if (i == 0)
{ {
if(!player.getWorld().equals(element.location.getWorld())) return; if (!player.getWorld().equals(element.location.getWorld())) return;
} }
player.sendBlockChange(element.location, element.realBlock); player.sendBlockChange(element.location, element.realBlock);
} }
playerData.currentVisualization = null; playerData.currentVisualization = null;
} }
} }
//convenience method to build a visualization from a claim //convenience method to build a visualization from a claim
//visualizationType determines the style (gold blocks, silver, red, diamond, etc) //visualizationType determines the style (gold blocks, silver, red, diamond, etc)
public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality) public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality)
{ {
//visualize only top level claims //visualize only top level claims
if(claim.parent != null) if (claim.parent != null)
{ {
return FromClaim(claim.parent, height, visualizationType, locality); return FromClaim(claim.parent, height, visualizationType, locality);
} }
Visualization visualization = new Visualization(); Visualization visualization = new Visualization();
//add subdivisions first //add subdivisions first
for(int i = 0; i < claim.children.size(); i++) for (int i = 0; i < claim.children.size(); i++)
{ {
Claim child = claim.children.get(i); Claim child = claim.children.get(i);
if(!child.inDataStore) continue; if (!child.inDataStore) continue;
visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality); visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality);
} }
//special visualization for administrative land claims //special visualization for administrative land claims
if(claim.isAdminClaim() && visualizationType == VisualizationType.Claim) if (claim.isAdminClaim() && visualizationType == VisualizationType.Claim)
{ {
visualizationType = VisualizationType.AdminClaim; 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) //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); visualization.addClaimElements(claim, height, visualizationType, locality);
return visualization; 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
@SuppressWarnings("deprecation")
private void addClaimElements(Claim claim, int height, VisualizationType visualizationType, Location locality)
{
Location smallXsmallZ = claim.getLesserBoundaryCorner();
Location bigXbigZ = claim.getGreaterBoundaryCorner();
World world = smallXsmallZ.getWorld();
boolean waterIsTransparent = locality.getBlock().getType() == Material.WATER;
int smallx = smallXsmallZ.getBlockX();
int smallz = smallXsmallZ.getBlockZ();
int bigx = bigXbigZ.getBlockX();
int bigz = bigXbigZ.getBlockZ();
BlockData cornerBlockData;
BlockData accentBlockData;
ArrayList<VisualizationElement> newElements = new ArrayList<VisualizationElement>();
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();
}
//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;
final int STEP = 10;
//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
for(int i = 0; i < newElements.size(); i++)
{
VisualizationElement element = newElements.get(i);
if(!claim.contains(element.location, true, false))
{
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);
}
//removes any elements which are out of visualization range
private void removeElementsOutOfRange(ArrayList<VisualizationElement> 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 //adds a claim's visualization to the current visualization
private static Location getVisibleLocation(World world, int x, int y, int z, boolean waterIsTransparent) //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
Block block = world.getBlockAt(x, y, z); @SuppressWarnings("deprecation")
BlockFace direction = (isTransparent(block, waterIsTransparent)) ? BlockFace.DOWN : BlockFace.UP; private void addClaimElements(Claim claim, int height, VisualizationType visualizationType, Location locality)
{
Location smallXsmallZ = claim.getLesserBoundaryCorner();
Location bigXbigZ = claim.getGreaterBoundaryCorner();
World world = smallXsmallZ.getWorld();
boolean waterIsTransparent = locality.getBlock().getType() == Material.WATER;
while( block.getY() >= 1 && int smallx = smallXsmallZ.getBlockX();
block.getY() < world.getMaxHeight() - 1 && int smallz = smallXsmallZ.getBlockZ();
(!isTransparent(block.getRelative(BlockFace.UP), waterIsTransparent) || isTransparent(block, waterIsTransparent))) int bigx = bigXbigZ.getBlockX();
{ int bigz = bigXbigZ.getBlockZ();
block = block.getRelative(direction);
}
return block.getLocation(); BlockData cornerBlockData;
} BlockData accentBlockData;
//helper method for above. allows visualization blocks to sit underneath partly transparent blocks like grass and fence ArrayList<VisualizationElement> newElements = new ArrayList<VisualizationElement>();
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() if (visualizationType == VisualizationType.Claim)
switch (blockMaterial) {
{ cornerBlockData = Material.GLOWSTONE.createBlockData();
case AIR: accentBlockData = Material.GOLD_BLOCK.createBlockData();
case OAK_FENCE: } else if (visualizationType == VisualizationType.AdminClaim)
case ACACIA_FENCE: {
case BIRCH_FENCE: cornerBlockData = Material.GLOWSTONE.createBlockData();
case DARK_OAK_FENCE: accentBlockData = Material.PUMPKIN.createBlockData();
case JUNGLE_FENCE: } else if (visualizationType == VisualizationType.Subdivision)
case NETHER_BRICK_FENCE: {
case SPRUCE_FENCE: cornerBlockData = Material.IRON_BLOCK.createBlockData();
case OAK_FENCE_GATE: accentBlockData = Material.WHITE_WOOL.createBlockData();
case ACACIA_FENCE_GATE: } else if (visualizationType == VisualizationType.RestoreNature)
case BIRCH_FENCE_GATE: {
case DARK_OAK_FENCE_GATE: cornerBlockData = Material.DIAMOND_BLOCK.createBlockData();
case SPRUCE_FENCE_GATE: accentBlockData = Material.DIAMOND_BLOCK.createBlockData();
case JUNGLE_FENCE_GATE: } else
return true; {
} cornerBlockData = Material.REDSTONE_ORE.createBlockData();
((Lightable) cornerBlockData).setLit(true);
accentBlockData = Material.NETHERRACK.createBlockData();
}
if (Tag.SIGNS.isTagged(blockMaterial) || Tag.WALL_SIGNS.isTagged(blockMaterial)) //initialize visualization elements without Y values and real data
return true; //that will be added later for only the visualization elements within visualization range
return (waterIsTransparent && block.getType() == Material.WATER) || //locality
block.getType().isTransparent(); int minx = locality.getBlockX() - 75;
} int minz = locality.getBlockZ() - 75;
int maxx = locality.getBlockX() + 75;
int maxz = locality.getBlockZ() + 75;
final int STEP = 10;
//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
for (int i = 0; i < newElements.size(); i++)
{
VisualizationElement element = newElements.get(i);
if (!claim.contains(element.location, true, false))
{
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);
}
//removes any elements which are out of visualization range
private void removeElementsOutOfRange(ArrayList<VisualizationElement> 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<Claim> claims, int height, VisualizationType type, Location locality) public static Visualization fromClaims(Iterable<Claim> claims, int height, VisualizationType type, Location locality)
{ {
Visualization visualization = new Visualization(); Visualization visualization = new Visualization();
for(Claim claim : claims) for (Claim claim : claims)
{ {
visualization.addClaimElements(claim, height, type, locality); visualization.addClaimElements(claim, height, type, locality);
} }

View File

@ -16,45 +16,45 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
//applies a visualization for a player by sending him block change packets //applies a visualization for a player by sending him block change packets
class VisualizationApplicationTask implements Runnable class VisualizationApplicationTask implements Runnable
{ {
private Visualization visualization; private Visualization visualization;
private Player player; private Player player;
private PlayerData playerData; private PlayerData playerData;
public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization) public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization)
{ {
this.visualization = visualization; this.visualization = visualization;
this.playerData = playerData; this.playerData = playerData;
this.player = player; this.player = player;
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
public void run() public void run()
{ {
//for each element (=block) of the visualization //for each element (=block) of the visualization
for(int i = 0; i < visualization.elements.size(); i++) for (int i = 0; i < visualization.elements.size(); i++)
{ {
VisualizationElement element = visualization.elements.get(i); VisualizationElement element = visualization.elements.get(i);
//send the player a fake block change event //send the player a fake block change event
if(!element.location.getChunk().isLoaded()) continue; //cheap distance check if (!element.location.getChunk().isLoaded()) continue; //cheap distance check
player.sendBlockChange(element.location, element.visualizedBlock); player.sendBlockChange(element.location, element.visualizedBlock);
} }
//remember the visualization applied to this player for later (so it can be inexpensively reverted) //remember the visualization applied to this player for later (so it can be inexpensively reverted)
playerData.currentVisualization = visualization; playerData.currentVisualization = visualization;
//schedule automatic visualization reversion in 60 seconds. //schedule automatic visualization reversion in 60 seconds.
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask( GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(
GriefPrevention.instance, GriefPrevention.instance,
new VisualizationReversionTask(player, playerData, visualization), new VisualizationReversionTask(player, playerData, visualization),
20L * 60); //60 seconds 20L * 60); //60 seconds
} }
} }

View File

@ -17,21 +17,21 @@
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
//represents a "fake" block sent to a player as part of a visualization //represents a "fake" block sent to a player as part of a visualization
public class VisualizationElement public class VisualizationElement
{ {
public Location location; public Location location;
public BlockData visualizedBlock; public BlockData visualizedBlock;
public BlockData realBlock; public BlockData realBlock;
public VisualizationElement(Location location, BlockData visualizedBlock, BlockData realBlock) public VisualizationElement(Location location, BlockData visualizedBlock, BlockData realBlock)
{ {
this.location = location; this.location = location;
this.visualizedBlock = visualizedBlock; this.visualizedBlock = visualizedBlock;
this.realBlock = realBlock; this.realBlock = realBlock;
} }
} }

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import me.ryanhamshire.GriefPrevention.events.VisualizationEvent; import me.ryanhamshire.GriefPrevention.events.VisualizationEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -27,26 +27,26 @@ import java.util.Collections;
//applies a visualization for a player by sending him block change packets //applies a visualization for a player by sending him block change packets
class VisualizationReversionTask implements Runnable class VisualizationReversionTask implements Runnable
{ {
private Visualization visualization; private Visualization visualization;
private Player player; private Player player;
private PlayerData playerData; private PlayerData playerData;
public VisualizationReversionTask(Player player, PlayerData playerData, Visualization visualization) public VisualizationReversionTask(Player player, PlayerData playerData, Visualization visualization)
{ {
this.visualization = visualization; this.visualization = visualization;
this.playerData = playerData; this.playerData = playerData;
this.player = player; this.player = player;
} }
@Override @Override
public void run() public void run()
{ {
//don't do anything if the player's current visualization is different from the one scheduled to revert //don't do anything if the player's current visualization is different from the one scheduled to revert
if(playerData.currentVisualization != visualization) return; if (playerData.currentVisualization != visualization) return;
// alert plugins of a visualization // alert plugins of a visualization
Bukkit.getPluginManager().callEvent(new VisualizationEvent(player, Collections.<Claim>emptySet())); Bukkit.getPluginManager().callEvent(new VisualizationEvent(player, Collections.<Claim>emptySet()));
Visualization.Revert(player); Visualization.Revert(player);
} }
} }

View File

@ -21,9 +21,9 @@ package me.ryanhamshire.GriefPrevention;
//just an enumeration of the visualization types, which determine what materials will be for the fake blocks //just an enumeration of the visualization types, which determine what materials will be for the fake blocks
public enum VisualizationType public enum VisualizationType
{ {
Claim, Claim,
Subdivision, Subdivision,
ErrorClaim, ErrorClaim,
RestoreNature, RestoreNature,
AdminClaim AdminClaim
} }

View File

@ -20,14 +20,14 @@ public class WelcomeTask implements Runnable
public void run() public void run()
{ {
//abort if player has logged out since this task was scheduled //abort if player has logged out since this task was scheduled
if(!this.player.isOnline()) return; if (!this.player.isOnline()) return;
//offer advice and a helpful link //offer advice and a helpful link
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.AvoidGriefClaimLand); GriefPrevention.sendMessage(player, TextMode.Instr, Messages.AvoidGriefClaimLand);
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL); GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo2, DataStore.SURVIVAL_VIDEO_URL);
//give the player a reference book for later //give the player a reference book for later
if(GriefPrevention.instance.config_claims_supplyPlayerManual) if (GriefPrevention.instance.config_claims_supplyPlayerManual)
{ {
ItemFactory factory = Bukkit.getItemFactory(); ItemFactory factory = Bukkit.getItemFactory();
BookMeta meta = (BookMeta) factory.getItemMeta(Material.WRITTEN_BOOK); BookMeta meta = (BookMeta) factory.getItemMeta(Material.WRITTEN_BOOK);
@ -46,7 +46,7 @@ public class WelcomeTask implements Runnable
String infoToolName = GriefPrevention.instance.config_claims_investigationTool.name().replace('_', ' ').toLowerCase(); String infoToolName = GriefPrevention.instance.config_claims_investigationTool.name().replace('_', ' ').toLowerCase();
String configClaimTools = datastore.getMessage(Messages.BookTools, editToolName, infoToolName); String configClaimTools = datastore.getMessage(Messages.BookTools, editToolName, infoToolName);
page1.append(configClaimTools); page1.append(configClaimTools);
if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius < 0) if (GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius < 0)
{ {
page1.append(datastore.getMessage(Messages.BookDisabledChestClaims)); page1.append(datastore.getMessage(Messages.BookDisabledChestClaims));
} }

View File

@ -10,19 +10,19 @@ class WordFinder
WordFinder(List<String> wordsToFind) WordFinder(List<String> wordsToFind)
{ {
if(wordsToFind.size() == 0) return; if (wordsToFind.size() == 0) return;
StringBuilder patternBuilder = new StringBuilder(); StringBuilder patternBuilder = new StringBuilder();
for(String word : wordsToFind) for (String word : wordsToFind)
{ {
if(!word.isEmpty() && !word.trim().isEmpty()) if (!word.isEmpty() && !word.trim().isEmpty())
{ {
patternBuilder.append("|(([^\\w]|^)" + Pattern.quote(word) + "([^\\w]|$))"); patternBuilder.append("|(([^\\w]|^)" + Pattern.quote(word) + "([^\\w]|$))");
} }
} }
String patternString = patternBuilder.toString(); String patternString = patternBuilder.toString();
if(patternString.length() > 1) if (patternString.length() > 1)
{ {
//trim extraneous leading pipe (|) //trim extraneous leading pipe (|)
patternString = patternString.substring(1); patternString = patternString.substring(1);
@ -33,7 +33,7 @@ class WordFinder
boolean hasMatch(String input) boolean hasMatch(String input)
{ {
if(this.pattern == null) return false; if (this.pattern == null) return false;
Matcher matcher = this.pattern.matcher(input); Matcher matcher = this.pattern.matcher(input);
return matcher.find(); return matcher.find();

View File

@ -1,19 +1,18 @@
package me.ryanhamshire.GriefPrevention; package me.ryanhamshire.GriefPrevention;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.BukkitPlayer; import com.sk89q.worldguard.bukkit.BukkitPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.internal.permission.RegionPermissionModel; import com.sk89q.worldguard.internal.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.Location;
import org.bukkit.entity.Player;
class WorldGuardWrapper class WorldGuardWrapper
{ {
@ -21,7 +20,7 @@ class WorldGuardWrapper
public WorldGuardWrapper() throws ClassNotFoundException public WorldGuardWrapper() throws ClassNotFoundException
{ {
this.worldGuard = (WorldGuardPlugin)GriefPrevention.instance.getServer().getPluginManager().getPlugin("WorldGuard"); this.worldGuard = (WorldGuardPlugin) GriefPrevention.instance.getServer().getPluginManager().getPlugin("WorldGuard");
} }
public boolean canBuild(Location lesserCorner, Location greaterCorner, Player creatingPlayer) public boolean canBuild(Location lesserCorner, Location greaterCorner, Player creatingPlayer)
@ -31,11 +30,11 @@ class WorldGuardWrapper
BukkitPlayer localPlayer = new BukkitPlayer(this.worldGuard, creatingPlayer); BukkitPlayer localPlayer = new BukkitPlayer(this.worldGuard, creatingPlayer);
World world = WorldGuard.getInstance().getPlatform().getMatcher().getWorldByName(lesserCorner.getWorld().getName()); World world = WorldGuard.getInstance().getPlatform().getMatcher().getWorldByName(lesserCorner.getWorld().getName());
if(new RegionPermissionModel(localPlayer).mayIgnoreRegionProtection(world)) return true; if (new RegionPermissionModel(localPlayer).mayIgnoreRegionProtection(world)) return true;
RegionManager manager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(world); RegionManager manager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(world);
if(manager != null) if (manager != null)
{ {
ProtectedCuboidRegion tempRegion = new ProtectedCuboidRegion( ProtectedCuboidRegion tempRegion = new ProtectedCuboidRegion(
"GP_TEMP", "GP_TEMP",
@ -43,8 +42,10 @@ class WorldGuardWrapper
BlockVector3.at(greaterCorner.getX(), world.getMaxY(), greaterCorner.getZ())); BlockVector3.at(greaterCorner.getX(), world.getMaxY(), greaterCorner.getZ()));
ApplicableRegionSet overlaps = manager.getApplicableRegions(tempRegion); ApplicableRegionSet overlaps = manager.getApplicableRegions(tempRegion);
for (ProtectedRegion r : overlaps.getRegions()) { for (ProtectedRegion r : overlaps.getRegions())
if (!manager.getApplicableRegions(r).testState(localPlayer, Flags.BUILD)) { {
if (!manager.getApplicableRegions(r).testState(localPlayer, Flags.BUILD))
{
return false; return false;
} }
} }

View File

@ -14,11 +14,15 @@ public class AccrueClaimBlocksEvent extends Event
{ {
// Custom Event Requirements // Custom Event Requirements
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
public static HandlerList getHandlerList() {
public static HandlerList getHandlerList()
{
return handlers; return handlers;
} }
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
{
return handlers; return handlers;
} }
@ -30,7 +34,6 @@ public class AccrueClaimBlocksEvent extends Event
/** /**
* @param player Player receiving accruals * @param player Player receiving accruals
* @param blocksToAccrue Blocks to accrue * @param blocksToAccrue Blocks to accrue
*
* @deprecated Use {@link #AccrueClaimBlocksEvent(Player, int, boolean)} instead * @deprecated Use {@link #AccrueClaimBlocksEvent(Player, int, boolean)} instead
*/ */
public AccrueClaimBlocksEvent(Player player, int blocksToAccrue) public AccrueClaimBlocksEvent(Player player, int blocksToAccrue)
@ -67,7 +70,8 @@ public class AccrueClaimBlocksEvent extends Event
/** /**
* @return whether the player was detected as idle (used for idle accrual percentage) * @return whether the player was detected as idle (used for idle accrual percentage)
*/ */
public boolean isIdle() { public boolean isIdle()
{
return this.isIdle; return this.isIdle;
} }
@ -78,6 +82,7 @@ public class AccrueClaimBlocksEvent extends Event
/** /**
* Modify the amount of claim blocks to deliver to the player for this 10 minute interval * Modify the amount of claim blocks to deliver to the player for this 10 minute interval
*
* @param blocksToAccrue blocks to deliver * @param blocksToAccrue blocks to deliver
*/ */
public void setBlocksToAccrue(int blocksToAccrue) public void setBlocksToAccrue(int blocksToAccrue)
@ -87,6 +92,7 @@ public class AccrueClaimBlocksEvent extends Event
/** /**
* Similar to setBlocksToAccrue(int), but automatically converting from a per-hour rate value to a 10-minute rate value * Similar to setBlocksToAccrue(int), but automatically converting from a per-hour rate value to a 10-minute rate value
*
* @param blocksToAccruePerHour the per-hour rate of blocks to deliver * @param blocksToAccruePerHour the per-hour rate of blocks to deliver
*/ */

View File

@ -13,11 +13,13 @@ import org.bukkit.event.HandlerList;
* Created by Narimm on 5/08/2018. * Created by Narimm on 5/08/2018.
*/ */
public class ClaimCreatedEvent extends Event implements Cancellable { public class ClaimCreatedEvent extends Event implements Cancellable
{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
public static HandlerList getHandlerList() { public static HandlerList getHandlerList()
{
return handlers; return handlers;
} }
@ -27,23 +29,27 @@ public class ClaimCreatedEvent extends Event implements Cancellable {
private boolean cancelled = false; private boolean cancelled = false;
public ClaimCreatedEvent(Claim claim, CommandSender creator) { public ClaimCreatedEvent(Claim claim, CommandSender creator)
{
this.claim = claim; this.claim = claim;
this.creator = creator; this.creator = creator;
} }
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
{
return handlers; return handlers;
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled()
{
return cancelled; return cancelled;
} }
@Override @Override
public void setCancelled(boolean b) { public void setCancelled(boolean b)
{
this.cancelled = b; this.cancelled = b;
} }
@ -52,7 +58,8 @@ public class ClaimCreatedEvent extends Event implements Cancellable {
* *
* @return Claim * @return Claim
*/ */
public Claim getClaim() { public Claim getClaim()
{
return claim; return claim;
} }
@ -61,7 +68,8 @@ public class ClaimCreatedEvent extends Event implements Cancellable {
* *
* @return the CommandSender * @return the CommandSender
*/ */
public CommandSender getCreator() { public CommandSender getCreator()
{
return creator; return creator;
} }
} }

View File

@ -1,7 +1,6 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@ -10,20 +9,22 @@ import org.bukkit.event.HandlerList;
* not called when a claim is resized. * not called when a claim is resized.
* *
* @author Tux2 * @author Tux2
*
*/ */
public class ClaimDeletedEvent extends Event{ public class ClaimDeletedEvent extends Event
{
// Custom Event Requirements // Custom Event Requirements
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
public static HandlerList getHandlerList() { public static HandlerList getHandlerList()
{
return handlers; return handlers;
} }
private Claim claim; private Claim claim;
public ClaimDeletedEvent(Claim claim) { public ClaimDeletedEvent(Claim claim)
{
this.claim = claim; this.claim = claim;
} }
@ -32,12 +33,14 @@ public class ClaimDeletedEvent extends Event{
* *
* @return * @return
*/ */
public Claim getClaim() { public Claim getClaim()
{
return claim; return claim;
} }
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
{
return handlers; return handlers;
} }
} }

View File

@ -1,7 +1,6 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;

View File

@ -11,24 +11,28 @@ import org.bukkit.event.HandlerList;
* a claim has changed. The CommandSender can be null in the event that the modification is called by the plugin itself. * a claim has changed. The CommandSender can be null in the event that the modification is called by the plugin itself.
* Created by Narimm on 5/08/2018. * Created by Narimm on 5/08/2018.
*/ */
public class ClaimModifiedEvent extends Event { public class ClaimModifiedEvent extends Event
{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
public static HandlerList getHandlerList() { public static HandlerList getHandlerList()
{
return handlers; return handlers;
} }
private final Claim claim; private final Claim claim;
private CommandSender modifier; private CommandSender modifier;
public ClaimModifiedEvent(Claim claim, CommandSender modifier) { public ClaimModifiedEvent(Claim claim, CommandSender modifier)
{
this.claim = claim; this.claim = claim;
this.modifier = modifier; this.modifier = modifier;
} }
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
{
return handlers; return handlers;
} }
@ -37,7 +41,8 @@ public class ClaimModifiedEvent extends Event {
* *
* @return the claim * @return the claim
*/ */
public Claim getClaim() { public Claim getClaim()
{
return claim; return claim;
} }
@ -46,7 +51,8 @@ public class ClaimModifiedEvent extends Event {
* *
* @return the CommandSender or null * @return the CommandSender or null
*/ */
public CommandSender getModifier() { public CommandSender getModifier()
{
return modifier; return modifier;
} }
} }

View File

@ -34,8 +34,8 @@ public class PlayerKickBanEvent extends Event
/** /**
* @param player Player getting kicked and/or banned * @param player Player getting kicked and/or banned
* @param reason Reason message for kick/ban * @param reason Reason message for kick/ban
* @param source What caused the kick/ban * @param source What caused the kick/ban
* @param ban True if player is getting banned * @param ban True if player is getting banned
*/ */
public PlayerKickBanEvent(Player player, String reason, String source, boolean ban) public PlayerKickBanEvent(Player player, String reason, String source, boolean ban)
{ {

View File

@ -1,7 +1,6 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;

View File

@ -1,7 +1,6 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;

View File

@ -1,7 +1,6 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;

View File

@ -1,23 +1,22 @@
package me.ryanhamshire.GriefPrevention.events; package me.ryanhamshire.GriefPrevention.events;
import java.util.ArrayList; import me.ryanhamshire.GriefPrevention.Claim;
import java.util.List; import me.ryanhamshire.GriefPrevention.ClaimPermission;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import me.ryanhamshire.GriefPrevention.Claim; import java.util.ArrayList;
import me.ryanhamshire.GriefPrevention.ClaimPermission; import java.util.List;
/** /**
* This event is thrown when the trust is changed in one or more claims * This event is thrown when the trust is changed in one or more claims
* *
* @author roinujnosde * @author roinujnosde
*
*/ */
public class TrustChangedEvent extends Event implements Cancellable { public class TrustChangedEvent extends Event implements Cancellable
{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
@ -28,83 +27,93 @@ public class TrustChangedEvent extends Event implements Cancellable {
private final String identifier; private final String identifier;
private boolean cancelled; private boolean cancelled;
public TrustChangedEvent(Player changer, List<Claim> claims, ClaimPermission claimPermission, boolean given, public TrustChangedEvent(Player changer, List<Claim> claims, ClaimPermission claimPermission, boolean given,
String identifier) { String identifier)
super(); {
this.changer = changer; super();
this.claims = claims; this.changer = changer;
this.claimPermission = claimPermission; this.claims = claims;
this.given = given; this.claimPermission = claimPermission;
this.identifier = identifier; this.given = given;
} this.identifier = identifier;
}
public TrustChangedEvent(Player changer, Claim claim, ClaimPermission claimPermission, boolean given, String identifier) { public TrustChangedEvent(Player changer, Claim claim, ClaimPermission claimPermission, boolean given, String identifier)
this.changer = changer; {
claims = new ArrayList<>(); this.changer = changer;
claims.add(claim); claims = new ArrayList<>();
this.claimPermission = claimPermission; claims.add(claim);
this.given = given; this.claimPermission = claimPermission;
this.identifier = identifier; this.given = given;
} this.identifier = identifier;
}
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
return handlers; {
} return handlers;
}
/** /**
* Gets who made the change * Gets who made the change
* *
* @return the changer * @return the changer
*/ */
public Player getChanger() { public Player getChanger()
return changer; {
} return changer;
}
/** /**
* Gets the changed claims * Gets the changed claims
* *
* @return the changed claims * @return the changed claims
*/ */
public List<Claim> getClaims() { public List<Claim> getClaims()
return claims; {
} return claims;
}
/** /**
* Gets the claim permission (null if the permission is being taken) * Gets the claim permission (null if the permission is being taken)
* *
* @return the claim permission * @return the claim permission
*/ */
public ClaimPermission getClaimPermission() { public ClaimPermission getClaimPermission()
return claimPermission; {
} return claimPermission;
}
/** /**
* Checks if the trust is being given * Checks if the trust is being given
* *
* @return true if given, false if taken * @return true if given, false if taken
*/ */
public boolean isGiven() { public boolean isGiven()
return given; {
} return given;
}
/** /**
* Gets the identifier of the receiver of this action * Gets the identifier of the receiver of this action
* Can be: "public", "all", a UUID, a permission * Can be: "public", "all", a UUID, a permission
* *
* @return the identifier * @return the identifier
*/ */
public String getIdentifier() { public String getIdentifier()
return identifier; {
} return identifier;
}
@Override @Override
public boolean isCancelled() { public boolean isCancelled()
return cancelled; {
} return cancelled;
}
@Override @Override
public void setCancelled(boolean cancelled) { public void setCancelled(boolean cancelled)
this.cancelled = cancelled; {
} this.cancelled = cancelled;
}
} }

View File

@ -11,7 +11,8 @@ import java.util.Collections;
/** /**
* Called when GriefPrevention is sending claim visuals to a player * Called when GriefPrevention is sending claim visuals to a player
*/ */
public class VisualizationEvent extends PlayerEvent { public class VisualizationEvent extends PlayerEvent
{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
private final Collection<Claim> claims; private final Collection<Claim> claims;
private final boolean showSubdivides; private final boolean showSubdivides;
@ -22,7 +23,8 @@ public class VisualizationEvent extends PlayerEvent {
* @param player Player receiving visuals * @param player Player receiving visuals
* @param claim The claim being visualized (with subdivides), or null if visuals being removed * @param claim The claim being visualized (with subdivides), or null if visuals being removed
*/ */
public VisualizationEvent(Player player, Claim claim) { public VisualizationEvent(Player player, Claim claim)
{
super(player); super(player);
this.claims = Collections.singleton(claim); this.claims = Collections.singleton(claim);
this.showSubdivides = true; this.showSubdivides = true;
@ -34,7 +36,8 @@ public class VisualizationEvent extends PlayerEvent {
* @param player Player receiving visuals * @param player Player receiving visuals
* @param claims Claims being visualized (without subdivides) * @param claims Claims being visualized (without subdivides)
*/ */
public VisualizationEvent(Player player, Collection<Claim> claims) { public VisualizationEvent(Player player, Collection<Claim> claims)
{
super(player); super(player);
this.claims = claims; this.claims = claims;
this.showSubdivides = false; this.showSubdivides = false;
@ -45,7 +48,8 @@ public class VisualizationEvent extends PlayerEvent {
* *
* @return Claims being visualized * @return Claims being visualized
*/ */
public Collection<Claim> getClaims() { public Collection<Claim> getClaims()
{
return claims; return claims;
} }
@ -54,16 +58,19 @@ public class VisualizationEvent extends PlayerEvent {
* *
* @return True if subdivide claims are being shown * @return True if subdivide claims are being shown
*/ */
public boolean showSubdivides() { public boolean showSubdivides()
{
return showSubdivides; return showSubdivides;
} }
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers()
{
return handlers; return handlers;
} }
public static HandlerList getHandlerList() { public static HandlerList getHandlerList()
{
return handlers; return handlers;
} }
} }

View File

@ -1,5 +1,5 @@
/** /**
* * @author Ryan
*/ */
/** /**
* @author Ryan * @author Ryan

View File

@ -14,6 +14,7 @@ import java.util.concurrent.Callable;
public class MetricsHandler public class MetricsHandler
{ {
private Metrics metrics; private Metrics metrics;
public MetricsHandler(GriefPrevention plugin, String dataMode) public MetricsHandler(GriefPrevention plugin, String dataMode)
{ {
metrics = new Metrics(plugin); metrics = new Metrics(plugin);
@ -23,7 +24,7 @@ public class MetricsHandler
addSimplePie("custom_build", plugin.getDescription().getVersion().equals("15.2.2")); addSimplePie("custom_build", plugin.getDescription().getVersion().equals("15.2.2"));
addSimplePie("bukkit_impl", plugin.getServer().getVersion().split("-")[1]); addSimplePie("bukkit_impl", plugin.getServer().getVersion().split("-")[1]);
} }
catch (Throwable ignored){} catch (Throwable ignored) {}
//enums and etc. would be amazing. //enums and etc. would be amazing.