reformat code
- Lots of tabs to spaces going on - That's a lot of changes! #63
This commit is contained in:
parent
bc05440617
commit
40f554d386
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
@ -35,73 +35,73 @@ class AutoExtendClaimTask implements Runnable
|
||||||
private int getLowestBuiltY()
|
private int getLowestBuiltY()
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ class AutoExtendClaimTask implements Runnable
|
||||||
{
|
{
|
||||||
return y == 0 || y <= GriefPrevention.instance.config_claims_maxDepth;
|
return y == 0 || y <= GriefPrevention.instance.config_claims_maxDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
//runs in the main execution thread, where it can safely change claims and save those changes
|
//runs in the main execution thread, where it can safely change claims and save those changes
|
||||||
private class ExecuteExtendClaimTask implements Runnable
|
private class ExecuteExtendClaimTask implements Runnable
|
||||||
{
|
{
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,16 +24,16 @@ import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
//basically, just a few data points from a block conveniently encapsulated in a class
|
//basically, just a few data points from a block conveniently encapsulated in a class
|
||||||
//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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,25 +15,25 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
||||||
//sends a message to all online players
|
//sends a message to all online players
|
||||||
//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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,10 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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.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
|
|
@ -15,26 +15,26 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
||||||
//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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
@ -26,40 +26,40 @@ import java.util.UUID;
|
||||||
//asynchronously loads player data without caching it in the datastore, then
|
//asynchronously loads player data without caching it in the datastore, then
|
||||||
//passes those data to a claim cleanup task which might decide to delete a claim for inactivity
|
//passes those data to a claim cleanup task which might decide to delete a claim for inactivity
|
||||||
|
|
||||||
class CleanupUnusedClaimPreTask implements Runnable
|
class CleanupUnusedClaimPreTask implements Runnable
|
||||||
{
|
{
|
||||||
private UUID ownerID = null;
|
private UUID ownerID = null;
|
||||||
|
|
||||||
CleanupUnusedClaimPreTask(UUID uuid)
|
|
||||||
{
|
|
||||||
this.ownerID = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
//get the data
|
|
||||||
PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(ownerID);
|
|
||||||
OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(ownerID);
|
|
||||||
|
|
||||||
GriefPrevention.AddLogEntry("Looking for expired claims. Checking data for " + ownerID.toString(), CustomLogEntryTypes.Debug, true);
|
CleanupUnusedClaimPreTask(UUID uuid)
|
||||||
|
{
|
||||||
//expiration code uses last logout timestamp to decide whether to expire claims
|
this.ownerID = uuid;
|
||||||
//don't expire claims for online players
|
}
|
||||||
if(ownerInfo.isOnline())
|
|
||||||
{
|
@Override
|
||||||
GriefPrevention.AddLogEntry("Player is online. Ignoring.", CustomLogEntryTypes.Debug, true);
|
public void run()
|
||||||
return;
|
{
|
||||||
}
|
//get the data
|
||||||
if(ownerInfo.getLastPlayed() <= 0)
|
PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(ownerID);
|
||||||
{
|
OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(ownerID);
|
||||||
GriefPrevention.AddLogEntry("Player is new or not in the server's cached userdata. Ignoring. getLastPlayed = " + ownerInfo.getLastPlayed(), CustomLogEntryTypes.Debug, true);
|
|
||||||
return;
|
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
|
||||||
//skip claims belonging to exempted players based on block totals in config
|
//don't expire claims for online players
|
||||||
int bonusBlocks = ownerData.getBonusClaimBlocks();
|
if (ownerInfo.isOnline())
|
||||||
if(bonusBlocks >= GriefPrevention.instance.config_claims_expirationExemptionBonusBlocks || bonusBlocks + ownerData.getAccruedClaimBlocks() >= GriefPrevention.instance.config_claims_expirationExemptionTotalBlocks)
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Player is online. Ignoring.", CustomLogEntryTypes.Debug, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ownerInfo.getLastPlayed() <= 0)
|
||||||
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Player is new or not in the server's cached userdata. Ignoring. getLastPlayed = " + ownerInfo.getLastPlayed(), CustomLogEntryTypes.Debug, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip claims belonging to exempted players based on block totals in config
|
||||||
|
int bonusBlocks = ownerData.getBonusClaimBlocks();
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,134 +15,131 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
class CleanupUnusedClaimTask implements Runnable
|
||||||
import org.bukkit.OfflinePlayer;
|
{
|
||||||
|
|
||||||
import me.ryanhamshire.GriefPrevention.events.ClaimExpirationEvent;
|
|
||||||
|
|
||||||
class CleanupUnusedClaimTask implements Runnable
|
|
||||||
{
|
|
||||||
Claim claim;
|
Claim claim;
|
||||||
PlayerData ownerData;
|
PlayerData ownerData;
|
||||||
OfflinePlayer ownerInfo;
|
OfflinePlayer ownerInfo;
|
||||||
|
|
||||||
CleanupUnusedClaimTask(Claim claim, PlayerData ownerData, OfflinePlayer ownerInfo)
|
|
||||||
{
|
|
||||||
this.claim = claim;
|
|
||||||
this.ownerData = ownerData;
|
|
||||||
this.ownerInfo = ownerInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
CleanupUnusedClaimTask(Claim claim, PlayerData ownerData, OfflinePlayer ownerInfo)
|
||||||
//determine area of the default chest claim
|
{
|
||||||
int areaOfDefaultClaim = 0;
|
this.claim = claim;
|
||||||
if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius >= 0)
|
this.ownerData = ownerData;
|
||||||
{
|
this.ownerInfo = ownerInfo;
|
||||||
areaOfDefaultClaim = (int)Math.pow(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius * 2 + 1, 2);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
//if this claim is a chest claim and those are set to expire
|
public void run()
|
||||||
if(claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0)
|
{
|
||||||
{
|
|
||||||
|
|
||||||
|
//determine area of the default chest claim
|
||||||
|
int areaOfDefaultClaim = 0;
|
||||||
|
if (GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius >= 0)
|
||||||
|
{
|
||||||
|
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 (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(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
|
|
||||||
{
|
|
||||||
GriefPrevention.instance.restoreClaim(claim, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GriefPrevention.AddLogEntry(" " + claim.getOwnerName() + "'s new player claim expired.", CustomLogEntryTypes.AdminActivity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if configured to always remove claims after some inactivity period without exceptions...
|
|
||||||
else if(GriefPrevention.instance.config_claims_expirationDays > 0)
|
|
||||||
{
|
|
||||||
Calendar earliestPermissibleLastLogin = Calendar.getInstance();
|
|
||||||
earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays);
|
|
||||||
|
|
||||||
if(earliestPermissibleLastLogin.getTime().after(new Date(ownerInfo.getLastPlayed())))
|
|
||||||
{
|
|
||||||
if (expireEventCanceled())
|
|
||||||
return;
|
|
||||||
//make a copy of this player's claim list
|
|
||||||
Vector<Claim> claims = new Vector<Claim>();
|
|
||||||
for(int i = 0; i < ownerData.getClaims().size(); i++)
|
|
||||||
{
|
|
||||||
claims.add(ownerData.getClaims().get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete them
|
|
||||||
GriefPrevention.instance.dataStore.deleteClaimsForPlayer(claim.ownerID, true);
|
|
||||||
GriefPrevention.AddLogEntry(" All of " + claim.getOwnerName() + "'s claims have expired.", CustomLogEntryTypes.AdminActivity);
|
|
||||||
|
|
||||||
for(int i = 0; i < claims.size(); i++)
|
|
||||||
{
|
|
||||||
//if configured to do so, restore the land to natural
|
|
||||||
if(GriefPrevention.instance.creativeRulesApply(claims.get(i).getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
//otherwise scan the claim content
|
|
||||||
int minInvestment = 400;
|
|
||||||
|
|
||||||
long investmentScore = claim.getPlayerInvestmentScore();
|
|
||||||
|
|
||||||
if(investmentScore < minInvestment)
|
|
||||||
{
|
|
||||||
//if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed
|
|
||||||
Calendar sevenDaysAgo = Calendar.getInstance();
|
|
||||||
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays);
|
|
||||||
boolean claimExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed()));
|
|
||||||
if(claimExpired)
|
|
||||||
{
|
|
||||||
if (expireEventCanceled())
|
|
||||||
return;
|
|
||||||
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
|
|
||||||
GriefPrevention.AddLogEntry("Removed " + claim.getOwnerName() + "'s unused claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
|
|
||||||
|
|
||||||
//restore the claim area to natural state
|
|
||||||
GriefPrevention.instance.restoreClaim(claim, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean expireEventCanceled()
|
//if configured to do so, restore the land to natural
|
||||||
{
|
if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
|
||||||
//see if any other plugins don't want this claim deleted
|
{
|
||||||
ClaimExpirationEvent event = new ClaimExpirationEvent(this.claim);
|
GriefPrevention.instance.restoreClaim(claim, 0);
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
}
|
||||||
return event.isCancelled();
|
|
||||||
}
|
GriefPrevention.AddLogEntry(" " + claim.getOwnerName() + "'s new player claim expired.", CustomLogEntryTypes.AdminActivity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if configured to always remove claims after some inactivity period without exceptions...
|
||||||
|
else if (GriefPrevention.instance.config_claims_expirationDays > 0)
|
||||||
|
{
|
||||||
|
Calendar earliestPermissibleLastLogin = Calendar.getInstance();
|
||||||
|
earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays);
|
||||||
|
|
||||||
|
if (earliestPermissibleLastLogin.getTime().after(new Date(ownerInfo.getLastPlayed())))
|
||||||
|
{
|
||||||
|
if (expireEventCanceled())
|
||||||
|
return;
|
||||||
|
//make a copy of this player's claim list
|
||||||
|
Vector<Claim> claims = new Vector<Claim>();
|
||||||
|
for (int i = 0; i < ownerData.getClaims().size(); i++)
|
||||||
|
{
|
||||||
|
claims.add(ownerData.getClaims().get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete them
|
||||||
|
GriefPrevention.instance.dataStore.deleteClaimsForPlayer(claim.ownerID, true);
|
||||||
|
GriefPrevention.AddLogEntry(" All of " + claim.getOwnerName() + "'s claims have expired.", CustomLogEntryTypes.AdminActivity);
|
||||||
|
|
||||||
|
for (int i = 0; i < claims.size(); i++)
|
||||||
|
{
|
||||||
|
//if configured to do so, restore the land to natural
|
||||||
|
if (GriefPrevention.instance.creativeRulesApply(claims.get(i).getLesserBoundaryCorner()) || GriefPrevention.instance.config_claims_survivalAutoNatureRestoration)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
//otherwise scan the claim content
|
||||||
|
int minInvestment = 400;
|
||||||
|
|
||||||
|
long investmentScore = claim.getPlayerInvestmentScore();
|
||||||
|
|
||||||
|
if (investmentScore < minInvestment)
|
||||||
|
{
|
||||||
|
//if the owner has been gone at least a week, and if he has ONLY the new player claim, it will be removed
|
||||||
|
Calendar sevenDaysAgo = Calendar.getInstance();
|
||||||
|
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays);
|
||||||
|
boolean claimExpired = sevenDaysAgo.getTime().after(new Date(ownerInfo.getLastPlayed()));
|
||||||
|
if (claimExpired)
|
||||||
|
{
|
||||||
|
if (expireEventCanceled())
|
||||||
|
return;
|
||||||
|
GriefPrevention.instance.dataStore.deleteClaim(claim, true, true);
|
||||||
|
GriefPrevention.AddLogEntry("Removed " + claim.getOwnerName() + "'s unused claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()), CustomLogEntryTypes.AdminActivity);
|
||||||
|
|
||||||
|
//restore the claim area to natural state
|
||||||
|
GriefPrevention.instance.restoreClaim(claim, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@
|
||||||
|
|
||||||
package me.ryanhamshire.GriefPrevention;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,32 +29,28 @@ 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");
|
||||||
private final SimpleDateFormat filenameFormat = new SimpleDateFormat("yyyy_MM_dd");
|
private final SimpleDateFormat filenameFormat = new SimpleDateFormat("yyyy_MM_dd");
|
||||||
private final String logFolderPath = DataStore.dataLayerFolderPath + File.separator + "Logs";
|
private final String logFolderPath = DataStore.dataLayerFolderPath + File.separator + "Logs";
|
||||||
private final int secondsBetweenWrites = 300;
|
private final int secondsBetweenWrites = 300;
|
||||||
|
|
||||||
//stringbuilder is not thread safe, stringbuffer is
|
//stringbuilder is not thread safe, stringbuffer is
|
||||||
private StringBuffer queuedEntries = new StringBuffer();
|
private StringBuffer queuedEntries = new StringBuffer();
|
||||||
|
|
||||||
CustomLogger()
|
CustomLogger()
|
||||||
{
|
{
|
||||||
//ensure log folder exists
|
//ensure log folder exists
|
||||||
File logFolder = new File(this.logFolderPath);
|
File logFolder = new File(this.logFolderPath);
|
||||||
logFolder.mkdirs();
|
logFolder.mkdirs();
|
||||||
|
|
||||||
//delete any outdated log files immediately
|
//delete any outdated log files immediately
|
||||||
this.DeleteExpiredLogs();
|
this.DeleteExpiredLogs();
|
||||||
|
|
||||||
//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;
|
||||||
|
|
@ -60,33 +59,38 @@ class CustomLogger
|
||||||
scheduler.runTaskTimerAsynchronously(GriefPrevention.instance, new ExpiredLogRemover(), ticksPerDay, ticksPerDay);
|
scheduler.runTaskTimerAsynchronously(GriefPrevention.instance, new ExpiredLogRemover(), ticksPerDay, ticksPerDay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
entry = matcher.replaceAll("");
|
entry = matcher.replaceAll("");
|
||||||
String timestamp = this.timestampFormat.format(new Date());
|
String timestamp = this.timestampFormat.format(new Date());
|
||||||
this.queuedEntries.append(timestamp + " " + entry + "\n");
|
this.queuedEntries.append(timestamp + " " + entry + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
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,73 +99,73 @@ 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";
|
||||||
String filepath = this.logFolderPath + File.separator + filename;
|
String filepath = this.logFolderPath + File.separator + filename;
|
||||||
File logFile = new File(filepath);
|
File logFile = new File(filepath);
|
||||||
|
|
||||||
//dump content
|
//dump content
|
||||||
Files.append(this.queuedEntries.toString(), logFile, Charset.forName("UTF-8"));
|
Files.append(this.queuedEntries.toString(), logFile, Charset.forName("UTF-8"));
|
||||||
|
|
||||||
//in case of a failure to write the above due to exception,
|
//in case of a failure to write the above due to exception,
|
||||||
//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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteExpiredLogs()
|
private void DeleteExpiredLogs()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//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
|
||||||
{
|
{
|
||||||
int year = Integer.parseInt(dateParts[0]);
|
int year = Integer.parseInt(dateParts[0]);
|
||||||
int month = Integer.parseInt(dateParts[1]) - 1;
|
int month = Integer.parseInt(dateParts[1]) - 1;
|
||||||
int day = Integer.parseInt(dateParts[2]);
|
int day = Integer.parseInt(dateParts[2]);
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//transfers the internal buffer to a log file
|
//transfers the internal buffer to a log file
|
||||||
private class EntryWriter implements Runnable
|
private class EntryWriter implements Runnable
|
||||||
{
|
{
|
||||||
|
|
@ -171,7 +175,7 @@ class CustomLogger
|
||||||
WriteEntries();
|
WriteEntries();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExpiredLogRemover implements Runnable
|
private class ExpiredLogRemover implements Runnable
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,16 @@
|
||||||
|
|
||||||
package me.ryanhamshire.GriefPrevention;
|
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
File diff suppressed because it is too large
Load Diff
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -32,119 +32,116 @@ import java.util.List;
|
||||||
|
|
||||||
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
||||||
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
|
//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)
|
||||||
|
{
|
||||||
else if(entity instanceof Vehicle)
|
Vehicle vehicle = (Vehicle) entity;
|
||||||
{
|
|
||||||
Vehicle vehicle = (Vehicle)entity;
|
//minecarts in motion must be occupied by a player
|
||||||
|
if (vehicle.getVelocity().lengthSquared() != 0)
|
||||||
//minecarts in motion must be occupied by a player
|
{
|
||||||
if(vehicle.getVelocity().lengthSquared() != 0)
|
if (vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
|
||||||
{
|
{
|
||||||
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
|
remove = true;
|
||||||
{
|
}
|
||||||
remove = true;
|
}
|
||||||
}
|
|
||||||
}
|
//stationary carts must be on rails
|
||||||
|
else
|
||||||
//stationary carts must be on rails
|
{
|
||||||
else
|
Material material = world.getBlockAt(vehicle.getLocation()).getType();
|
||||||
{
|
if (material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
|
||||||
Material material = world.getBlockAt(vehicle.getLocation()).getType();
|
{
|
||||||
if(material != Material.RAIL && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
|
remove = true;
|
||||||
{
|
}
|
||||||
remove = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
//all non-player entities must be in claims
|
||||||
|
else if (!(entity instanceof Player))
|
||||||
//all non-player entities must be in claims
|
{
|
||||||
else if(!(entity instanceof Player))
|
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
|
||||||
{
|
if (claim != null)
|
||||||
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
|
{
|
||||||
if(claim != null)
|
cachedClaim = claim;
|
||||||
{
|
} else
|
||||||
cachedClaim = claim;
|
{
|
||||||
}
|
remove = true;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
remove = true;
|
|
||||||
}
|
if (remove)
|
||||||
}
|
{
|
||||||
|
GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true);
|
||||||
if(remove)
|
entity.remove();
|
||||||
{
|
}
|
||||||
GriefPrevention.AddLogEntry("Removing entity " + entity.getType().name() + " @ " + entity.getLocation(), CustomLogEntryTypes.Debug, true);
|
}
|
||||||
entity.remove();
|
}
|
||||||
}
|
|
||||||
}
|
//starting and stopping point. each execution of the task scans 5% of the server's claims
|
||||||
}
|
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
|
||||||
|
int j = (int) (claims.size() * this.percentageStart);
|
||||||
//starting and stopping point. each execution of the task scans 5% of the server's claims
|
int k = (int) (claims.size() * (this.percentageStart + .05));
|
||||||
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
|
for (; j < claims.size() && j < k; j++)
|
||||||
int j = (int)(claims.size() * this.percentageStart);
|
{
|
||||||
int k = (int)(claims.size() * (this.percentageStart + .05));
|
Claim claim = claims.get(j);
|
||||||
for(; j < claims.size() && j < k; j++)
|
|
||||||
{
|
//if it's a creative mode claim
|
||||||
Claim claim = claims.get(j);
|
if (GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||||
|
{
|
||||||
//if it's a creative mode claim
|
//check its entity count and remove any extras
|
||||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
claim.allowMoreEntities(true);
|
||||||
{
|
}
|
||||||
//check its entity count and remove any extras
|
}
|
||||||
claim.allowMoreEntities(true);
|
|
||||||
}
|
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
|
||||||
}
|
double nextRunPercentageStart = this.percentageStart + .05;
|
||||||
|
if (nextRunPercentageStart > .99)
|
||||||
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
|
{
|
||||||
double nextRunPercentageStart = this.percentageStart + .05;
|
nextRunPercentageStart = 0;
|
||||||
if(nextRunPercentageStart > .99)
|
}
|
||||||
{
|
|
||||||
nextRunPercentageStart = 0;
|
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
|
||||||
}
|
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
|
||||||
|
}
|
||||||
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
|
|
||||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,7 +15,7 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
@ -24,55 +24,55 @@ import org.bukkit.inventory.EquipmentSlot;
|
||||||
//tells a player about how many claim blocks he has, etc
|
//tells a player about how many claim blocks he has, etc
|
||||||
//implemented as a task so that it can be delayed
|
//implemented as a task so that it can be delayed
|
||||||
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
|
//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()));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,47 +31,49 @@ import java.util.stream.Collectors;
|
||||||
//...because the player has been gone a REALLY long time, and that expiration has been configured in config.yml
|
//...because the player has been gone a REALLY long time, and that expiration has been configured in config.yml
|
||||||
|
|
||||||
//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()
|
|
||||||
{
|
|
||||||
refreshUUIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
//don't do anything when there are no claims
|
|
||||||
if(claimOwnerUUIDs.isEmpty()) return;
|
|
||||||
|
|
||||||
//wrap search around to beginning
|
FindUnusedClaimsTask()
|
||||||
if(!claimOwnerIterator.hasNext())
|
{
|
||||||
{
|
refreshUUIDs();
|
||||||
refreshUUIDs();
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GriefPrevention.instance.getServer().getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claimOwnerIterator.next()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshUUIDs() {
|
@Override
|
||||||
// Fetch owner UUIDs from list of claims
|
public void run()
|
||||||
claimOwnerUUIDs = GriefPrevention.instance.dataStore.claims.stream().map(claim -> claim.ownerID)
|
{
|
||||||
.distinct().filter(Objects::nonNull).collect(Collectors.toList());
|
//don't do anything when there are no claims
|
||||||
|
if (claimOwnerUUIDs.isEmpty()) return;
|
||||||
|
|
||||||
if (!claimOwnerUUIDs.isEmpty()) {
|
//wrap search around to beginning
|
||||||
// Randomize order
|
if (!claimOwnerIterator.hasNext())
|
||||||
Collections.shuffle(claimOwnerUUIDs);
|
{
|
||||||
}
|
refreshUUIDs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GriefPrevention.AddLogEntry("The following UUIDs own a claim and will be checked for inactivity in the following order:", CustomLogEntryTypes.Debug, true);
|
GriefPrevention.instance.getServer().getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claimOwnerIterator.next()));
|
||||||
|
}
|
||||||
|
|
||||||
for (UUID uuid : claimOwnerUUIDs)
|
public void refreshUUIDs()
|
||||||
GriefPrevention.AddLogEntry(uuid.toString(), CustomLogEntryTypes.Debug, true);
|
{
|
||||||
|
// Fetch owner UUIDs from list of claims
|
||||||
|
claimOwnerUUIDs = GriefPrevention.instance.dataStore.claims.stream().map(claim -> claim.ownerID)
|
||||||
|
.distinct().filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
|
||||||
claimOwnerIterator = claimOwnerUUIDs.iterator();
|
if (!claimOwnerUUIDs.isEmpty())
|
||||||
}
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
for (UUID uuid : claimOwnerUUIDs)
|
||||||
|
GriefPrevention.AddLogEntry(uuid.toString(), CustomLogEntryTypes.Debug, true);
|
||||||
|
|
||||||
|
claimOwnerIterator = claimOwnerUUIDs.iterator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,51 +1,51 @@
|
||||||
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
|
||||||
{
|
{
|
||||||
private UUID playerToLoad;
|
private UUID playerToLoad;
|
||||||
private ConcurrentHashMap<UUID, Boolean> destinationMap;
|
private ConcurrentHashMap<UUID, Boolean> destinationMap;
|
||||||
|
|
||||||
IgnoreLoaderThread(UUID playerToLoad, ConcurrentHashMap<UUID, Boolean> destinationMap)
|
IgnoreLoaderThread(UUID playerToLoad, ConcurrentHashMap<UUID, Boolean> destinationMap)
|
||||||
{
|
{
|
||||||
this.playerToLoad = playerToLoad;
|
this.playerToLoad = playerToLoad;
|
||||||
this.destinationMap = destinationMap;
|
this.destinationMap = destinationMap;
|
||||||
this.setPriority(MIN_PRIORITY);
|
this.setPriority(MIN_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
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;
|
||||||
Exception latestException = null;
|
Exception latestException = null;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
needRetry = false;
|
needRetry = false;
|
||||||
|
|
||||||
//read the file content and immediately close it
|
//read the file content and immediately close it
|
||||||
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,28 +55,28 @@ 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;
|
||||||
retriesRemaining--;
|
retriesRemaining--;
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
{
|
|
||||||
this.materials.add(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean Contains(MaterialInfo material)
|
|
||||||
{
|
|
||||||
return this.materials.contains(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return materials.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size()
|
|
||||||
{
|
|
||||||
return this.materials.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear()
|
void Add(MaterialInfo material)
|
||||||
{
|
{
|
||||||
this.materials.clear();
|
this.materials.add(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean Contains(MaterialInfo material)
|
||||||
|
{
|
||||||
|
return this.materials.contains(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return materials.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return this.materials.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
this.materials.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
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;
|
||||||
public UUID owner;
|
public UUID owner;
|
||||||
long expirationTimestamp;
|
long expirationTimestamp;
|
||||||
ItemStack itemStack;
|
ItemStack itemStack;
|
||||||
|
|
||||||
public PendingItemProtection(Location location, UUID owner, long expirationTimestamp, ItemStack itemStack)
|
public PendingItemProtection(Location location, UUID owner, long expirationTimestamp, ItemStack itemStack)
|
||||||
{
|
{
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
private Vector<Claim> claims = null;
|
|
||||||
|
|
||||||
//how many claim blocks the player has earned via play time
|
|
||||||
private Integer accruedClaimBlocks = null;
|
|
||||||
|
|
||||||
//temporary holding area to avoid opening data files too early
|
|
||||||
private int newlyAccruedClaimBlocks = 0;
|
|
||||||
|
|
||||||
//where this player was the last time we checked on him for earning claim blocks
|
|
||||||
public Location lastAfkCheckLocation = null;
|
|
||||||
|
|
||||||
//how many claim blocks the player has been gifted by admins, or purchased via economy integration
|
|
||||||
private Integer bonusClaimBlocks = null;
|
|
||||||
|
|
||||||
//what "mode" the shovel is in determines what it will do when it's used
|
|
||||||
public ShovelMode shovelMode = ShovelMode.Basic;
|
|
||||||
|
|
||||||
//radius for restore nature fill mode
|
|
||||||
int fillRadius = 0;
|
|
||||||
|
|
||||||
//last place the player used the shovel, useful in creating and resizing claims,
|
|
||||||
//because the player must use the shovel twice in those instances
|
|
||||||
public Location lastShovelLocation = null;
|
|
||||||
|
|
||||||
//the claim this player is currently resizing
|
|
||||||
public Claim claimResizing = null;
|
|
||||||
|
|
||||||
//the claim this player is currently subdividing
|
|
||||||
public Claim claimSubdividing = null;
|
|
||||||
|
|
||||||
//whether or not the player has a pending /trapped rescue
|
|
||||||
public boolean pendingTrapped = false;
|
|
||||||
|
|
||||||
//whether this player was recently warned about building outside land claims
|
|
||||||
boolean warnedAboutBuildingOutsideClaims = false;
|
|
||||||
|
|
||||||
//timestamp when last siege ended (where this player was the defender)
|
|
||||||
long lastSiegeEndTimeStamp = 0;
|
|
||||||
|
|
||||||
//whether the player was kicked (set and used during logout)
|
|
||||||
boolean wasKicked = false;
|
|
||||||
|
|
||||||
//visualization
|
|
||||||
public Visualization currentVisualization = null;
|
|
||||||
|
|
||||||
//anti-camping pvp protection
|
|
||||||
public boolean pvpImmune = false;
|
|
||||||
public long lastSpawn = 0;
|
|
||||||
|
|
||||||
//ignore claims mode
|
|
||||||
public boolean ignoreClaims = false;
|
|
||||||
|
|
||||||
//the last claim this player was in, that we know of
|
|
||||||
public Claim lastClaim = null;
|
|
||||||
|
|
||||||
//siege
|
|
||||||
public SiegeData siegeData = null;
|
|
||||||
|
|
||||||
//pvp
|
|
||||||
public long lastPvpTimestamp = 0;
|
|
||||||
public String lastPvpPlayer = "";
|
|
||||||
|
|
||||||
//safety confirmation for deleting multi-subdivision claims
|
|
||||||
public boolean warnedAboutMajorDeletion = false;
|
|
||||||
|
|
||||||
public InetAddress ipAddress;
|
//the player's claims
|
||||||
|
private Vector<Claim> claims = null;
|
||||||
|
|
||||||
|
//how many claim blocks the player has earned via play time
|
||||||
|
private Integer accruedClaimBlocks = null;
|
||||||
|
|
||||||
|
//temporary holding area to avoid opening data files too early
|
||||||
|
private int newlyAccruedClaimBlocks = 0;
|
||||||
|
|
||||||
|
//where this player was the last time we checked on him for earning claim blocks
|
||||||
|
public Location lastAfkCheckLocation = null;
|
||||||
|
|
||||||
|
//how many claim blocks the player has been gifted by admins, or purchased via economy integration
|
||||||
|
private Integer bonusClaimBlocks = null;
|
||||||
|
|
||||||
|
//what "mode" the shovel is in determines what it will do when it's used
|
||||||
|
public ShovelMode shovelMode = ShovelMode.Basic;
|
||||||
|
|
||||||
|
//radius for restore nature fill mode
|
||||||
|
int fillRadius = 0;
|
||||||
|
|
||||||
|
//last place the player used the shovel, useful in creating and resizing claims,
|
||||||
|
//because the player must use the shovel twice in those instances
|
||||||
|
public Location lastShovelLocation = null;
|
||||||
|
|
||||||
|
//the claim this player is currently resizing
|
||||||
|
public Claim claimResizing = null;
|
||||||
|
|
||||||
|
//the claim this player is currently subdividing
|
||||||
|
public Claim claimSubdividing = null;
|
||||||
|
|
||||||
|
//whether or not the player has a pending /trapped rescue
|
||||||
|
public boolean pendingTrapped = false;
|
||||||
|
|
||||||
|
//whether this player was recently warned about building outside land claims
|
||||||
|
boolean warnedAboutBuildingOutsideClaims = false;
|
||||||
|
|
||||||
|
//timestamp when last siege ended (where this player was the defender)
|
||||||
|
long lastSiegeEndTimeStamp = 0;
|
||||||
|
|
||||||
|
//whether the player was kicked (set and used during logout)
|
||||||
|
boolean wasKicked = false;
|
||||||
|
|
||||||
|
//visualization
|
||||||
|
public Visualization currentVisualization = null;
|
||||||
|
|
||||||
|
//anti-camping pvp protection
|
||||||
|
public boolean pvpImmune = false;
|
||||||
|
public long lastSpawn = 0;
|
||||||
|
|
||||||
|
//ignore claims mode
|
||||||
|
public boolean ignoreClaims = false;
|
||||||
|
|
||||||
|
//the last claim this player was in, that we know of
|
||||||
|
public Claim lastClaim = null;
|
||||||
|
|
||||||
|
//siege
|
||||||
|
public SiegeData siegeData = null;
|
||||||
|
|
||||||
|
//pvp
|
||||||
|
public long lastPvpTimestamp = 0;
|
||||||
|
public String lastPvpPlayer = "";
|
||||||
|
|
||||||
|
//safety confirmation for deleting multi-subdivision claims
|
||||||
|
public boolean warnedAboutMajorDeletion = false;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,89 +205,87 @@ public class PlayerData
|
||||||
{
|
{
|
||||||
this.bonusClaimBlocks = bonusClaimBlocks;
|
this.bonusClaimBlocks = bonusClaimBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadDataFromSecondaryStorage()
|
private void loadDataFromSecondaryStorage()
|
||||||
{
|
{
|
||||||
//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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure player has claim blocks for his claims, and at least the minimum accrued
|
//ensure player has claim blocks for his claims, and at least the minimum accrued
|
||||||
this.loadDataFromSecondaryStorage();
|
this.loadDataFromSecondaryStorage();
|
||||||
|
|
||||||
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//try to fix it by adding to accrued blocks
|
//try to fix it by adding to accrued blocks
|
||||||
this.accruedClaimBlocks = totalClaimsArea; //Set accrued blocks to equal total claims
|
this.accruedClaimBlocks = totalClaimsArea; //Set accrued blocks to equal total claims
|
||||||
int accruedLimit = this.getAccruedClaimBlocksLimit();
|
int accruedLimit = this.getAccruedClaimBlocksLimit();
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -320,18 +310,18 @@ public class PlayerData
|
||||||
GriefPrevention.AddLogEntry("Remaining claim blocks to use: " + this.getRemainingClaimBlocks() + " (should be 0)", CustomLogEntryTypes.Debug, true);
|
GriefPrevention.AddLogEntry("Remaining claim blocks to use: " + this.getRemainingClaimBlocks() + " (should be 0)", CustomLogEntryTypes.Debug, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return claims;
|
return claims;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Limit can be changed by addons
|
//Limit can be changed by addons
|
||||||
public int getAccruedClaimBlocksLimit()
|
public int getAccruedClaimBlocksLimit()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,7 +15,7 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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.PlayerKickBanEvent;
|
import me.ryanhamshire.GriefPrevention.events.PlayerKickBanEvent;
|
||||||
|
|
@ -25,47 +25,46 @@ import org.bukkit.entity.Player;
|
||||||
//kicks or bans a player
|
//kicks or bans a player
|
||||||
//need a task for this because async threads (like the chat event handlers) can't kick or ban.
|
//need a task for this because async threads (like the chat event handlers) can't kick or ban.
|
||||||
//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.
|
|
||||||
private String reason;
|
|
||||||
|
|
||||||
//source of ban
|
|
||||||
private String source;
|
|
||||||
|
|
||||||
//whether to ban
|
|
||||||
private boolean ban;
|
|
||||||
|
|
||||||
public PlayerKickBanTask(Player player, String reason, String source, boolean ban)
|
|
||||||
{
|
|
||||||
this.player = player;
|
|
||||||
this.reason = reason;
|
|
||||||
this.source = source;
|
|
||||||
this.ban = ban;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
PlayerKickBanEvent kickBanEvent = new PlayerKickBanEvent(player, reason, source, ban);
|
|
||||||
Bukkit.getPluginManager().callEvent(kickBanEvent);
|
|
||||||
|
|
||||||
if (kickBanEvent.isCancelled())
|
//message to send player.
|
||||||
{
|
private String reason;
|
||||||
return; // cancelled by a plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.ban)
|
//source of ban
|
||||||
{
|
private String source;
|
||||||
//ban
|
|
||||||
GriefPrevention.banPlayer(this.player, this.reason, this.source);
|
//whether to ban
|
||||||
}
|
private boolean ban;
|
||||||
else if(this.player.isOnline())
|
|
||||||
{
|
public PlayerKickBanTask(Player player, String reason, String source, boolean ban)
|
||||||
this.player.kickPlayer(this.reason);
|
{
|
||||||
}
|
this.player = player;
|
||||||
}
|
this.reason = reason;
|
||||||
|
this.source = source;
|
||||||
|
this.ban = ban;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
PlayerKickBanEvent kickBanEvent = new PlayerKickBanEvent(player, reason, source, ban);
|
||||||
|
Bukkit.getPluginManager().callEvent(kickBanEvent);
|
||||||
|
|
||||||
|
if (kickBanEvent.isCancelled())
|
||||||
|
{
|
||||||
|
return; // cancelled by a plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.ban)
|
||||||
|
{
|
||||||
|
//ban
|
||||||
|
GriefPrevention.banPlayer(this.player, this.reason, this.source);
|
||||||
|
} else if (this.player.isOnline())
|
||||||
|
{
|
||||||
|
this.player.kickPlayer(this.reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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.Location;
|
import org.bukkit.Location;
|
||||||
|
|
@ -24,52 +24,51 @@ import org.bukkit.entity.Player;
|
||||||
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
|
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
|
||||||
//related to the /trapped slash command
|
//related to the /trapped slash command
|
||||||
//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) + ".");
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,41 +15,40 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
||||||
//sends a message to a player
|
//sends a message to a 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)
|
|
||||||
{
|
|
||||||
this.player = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public PvPImmunityValidationTask(Player player)
|
||||||
public void run()
|
{
|
||||||
{
|
this.player = player;
|
||||||
if(!player.isOnline()) return;
|
}
|
||||||
|
|
||||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
@Override
|
||||||
if(!playerData.pvpImmune) return;
|
public void run()
|
||||||
|
{
|
||||||
//check the player's inventory for anything
|
if (!player.isOnline()) return;
|
||||||
if(!GriefPrevention.isInventoryEmpty(player))
|
|
||||||
{
|
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
||||||
//if found, cancel invulnerability and notify
|
if (!playerData.pvpImmune) return;
|
||||||
playerData.pvpImmune = false;
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.PvPImmunityEnd);
|
//check the player's inventory for anything
|
||||||
}
|
if (!GriefPrevention.isInventoryEmpty(player))
|
||||||
else
|
{
|
||||||
{
|
//if found, cancel invulnerability and notify
|
||||||
//otherwise check again in one minute
|
playerData.pvpImmune = false;
|
||||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 1200L);
|
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.PvPImmunityEnd);
|
||||||
}
|
} else
|
||||||
}
|
{
|
||||||
|
//otherwise check again in one minute
|
||||||
|
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 1200L);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,8 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
package me.ryanhamshire.GriefPrevention;
|
||||||
|
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
|
@ -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
|
|
||||||
private int miny;
|
|
||||||
private Location lesserCorner;
|
|
||||||
private Location greaterCorner;
|
|
||||||
|
|
||||||
//player who should be notified about the result (will see a visualization when the restoration is complete)
|
|
||||||
private Player player;
|
|
||||||
|
|
||||||
public RestoreNatureExecutionTask(BlockSnapshot[][][] snapshots, int miny, Location lesserCorner, Location greaterCorner, Player player)
|
//boundaries for changes
|
||||||
{
|
private int miny;
|
||||||
this.snapshots = snapshots;
|
private Location lesserCorner;
|
||||||
this.miny = miny;
|
private Location greaterCorner;
|
||||||
this.lesserCorner = lesserCorner;
|
|
||||||
this.greaterCorner = greaterCorner;
|
//player who should be notified about the result (will see a visualization when the restoration is complete)
|
||||||
this.player = player;
|
private Player player;
|
||||||
}
|
|
||||||
|
public RestoreNatureExecutionTask(BlockSnapshot[][][] snapshots, int miny, Location lesserCorner, Location greaterCorner, Player player)
|
||||||
@SuppressWarnings("deprecation")
|
{
|
||||||
@Override
|
this.snapshots = snapshots;
|
||||||
public void run()
|
this.miny = miny;
|
||||||
{
|
this.lesserCorner = lesserCorner;
|
||||||
//apply changes to the world, but ONLY to unclaimed blocks
|
this.greaterCorner = greaterCorner;
|
||||||
//note that the edge of the results is not applied (the 1-block-wide band around the outside of the chunk)
|
this.player = player;
|
||||||
//those data were sent to the processing thread for referernce purposes, but aren't part of the area selected for restoration
|
}
|
||||||
Claim cachedClaim = null;
|
|
||||||
for(int x = 1; x < this.snapshots.length - 1; x++)
|
@SuppressWarnings("deprecation")
|
||||||
{
|
@Override
|
||||||
for(int z = 1; z < this.snapshots[0][0].length - 1; z++)
|
public void run()
|
||||||
{
|
{
|
||||||
for(int y = this.miny; y < this.snapshots[0].length; y++)
|
//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)
|
||||||
BlockSnapshot blockUpdate = this.snapshots[x][y][z];
|
//those data were sent to the processing thread for referernce purposes, but aren't part of the area selected for restoration
|
||||||
Block currentBlock = blockUpdate.location.getBlock();
|
Claim cachedClaim = null;
|
||||||
if(blockUpdate.typeId != currentBlock.getType()|| !blockUpdate.data.equals(currentBlock.getBlockData()))
|
for (int x = 1; x < this.snapshots.length - 1; x++)
|
||||||
{
|
{
|
||||||
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(blockUpdate.location, false, cachedClaim);
|
for (int z = 1; z < this.snapshots[0][0].length - 1; z++)
|
||||||
if(claim != null)
|
{
|
||||||
{
|
for (int y = this.miny; y < this.snapshots[0].length; y++)
|
||||||
cachedClaim = claim;
|
{
|
||||||
break;
|
BlockSnapshot blockUpdate = this.snapshots[x][y][z];
|
||||||
}
|
Block currentBlock = blockUpdate.location.getBlock();
|
||||||
|
if (blockUpdate.typeId != currentBlock.getType() || !blockUpdate.data.equals(currentBlock.getBlockData()))
|
||||||
try
|
{
|
||||||
{
|
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(blockUpdate.location, false, cachedClaim);
|
||||||
currentBlock.setType(blockUpdate.typeId, false);
|
if (claim != null)
|
||||||
// currentBlock.setBlockData(blockUpdate.data, false);
|
{
|
||||||
}
|
cachedClaim = claim;
|
||||||
catch(IllegalArgumentException e)
|
break;
|
||||||
{
|
}
|
||||||
//just don't update this block and continue trying to update other blocks
|
|
||||||
}
|
try
|
||||||
}
|
{
|
||||||
}
|
currentBlock.setType(blockUpdate.typeId, false);
|
||||||
}
|
// currentBlock.setBlockData(blockUpdate.data, false);
|
||||||
}
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
//clean up any entities in the chunk, ensure no players are suffocated
|
{
|
||||||
Chunk chunk = this.lesserCorner.getChunk();
|
//just don't update this block and continue trying to update other blocks
|
||||||
Entity [] entities = chunk.getEntities();
|
}
|
||||||
for(int i = 0; i < entities.length; i++)
|
}
|
||||||
{
|
}
|
||||||
Entity entity = entities[i];
|
}
|
||||||
if(!(entity instanceof Player || entity instanceof Animals))
|
}
|
||||||
{
|
|
||||||
//hanging entities (paintings, item frames) are protected when they're in land claims
|
//clean up any entities in the chunk, ensure no players are suffocated
|
||||||
if(!(entity instanceof Hanging) || GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, null) == null)
|
Chunk chunk = this.lesserCorner.getChunk();
|
||||||
{
|
Entity[] entities = chunk.getEntities();
|
||||||
//everything else is removed
|
for (int i = 0; i < entities.length; i++)
|
||||||
entity.remove();
|
{
|
||||||
}
|
Entity entity = entities[i];
|
||||||
}
|
if (!(entity instanceof Player || entity instanceof Animals))
|
||||||
|
{
|
||||||
//for players, always ensure there's air where the player is standing
|
//hanging entities (paintings, item frames) are protected when they're in land claims
|
||||||
else
|
if (!(entity instanceof Hanging) || GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, null) == null)
|
||||||
{
|
{
|
||||||
Block feetBlock = entity.getLocation().getBlock();
|
//everything else is removed
|
||||||
feetBlock.setType(Material.AIR);
|
entity.remove();
|
||||||
feetBlock.getRelative(BlockFace.UP).setType(Material.AIR);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//for players, always ensure there's air where the player is standing
|
||||||
//show visualization to player who started the restoration
|
else
|
||||||
if(player != null)
|
{
|
||||||
{
|
Block feetBlock = entity.getLocation().getBlock();
|
||||||
Claim claim = new Claim(lesserCorner, greaterCorner, null, new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), null);
|
feetBlock.setType(Material.AIR);
|
||||||
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
|
feetBlock.getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
Visualization.Apply(player, visualization);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//show visualization to player who started the restoration
|
||||||
|
if (player != 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.Apply(player, visualization);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,44 +15,44 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
package me.ryanhamshire.GriefPrevention;
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
|
@ -23,39 +23,39 @@ import org.bukkit.entity.Player;
|
||||||
|
|
||||||
//sends a message to a player
|
//sends a message to a 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)
|
|
||||||
{
|
|
||||||
this.player = player;
|
|
||||||
this.color = color;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public SendPlayerMessageTask(Player player, ChatColor color, String message)
|
||||||
public void run()
|
{
|
||||||
{
|
this.player = player;
|
||||||
if(player == null)
|
this.color = color;
|
||||||
{
|
this.message = message;
|
||||||
GriefPrevention.AddLogEntry(color + message);
|
}
|
||||||
return;
|
|
||||||
}
|
@Override
|
||||||
|
public void run()
|
||||||
//if the player is dead, save it for after his respawn
|
{
|
||||||
if(this.player.isDead())
|
if (player == null)
|
||||||
{
|
{
|
||||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId());
|
GriefPrevention.AddLogEntry(color + message);
|
||||||
playerData.messageOnRespawn = this.color + this.message;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise send it immediately
|
//if the player is dead, save it for after his respawn
|
||||||
else
|
if (this.player.isDead())
|
||||||
{
|
{
|
||||||
GriefPrevention.sendMessage(this.player, this.color, this.message);
|
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(this.player.getUniqueId());
|
||||||
}
|
playerData.messageOnRespawn = this.color + this.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//otherwise send it immediately
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(this.player, this.color, this.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,16 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,89 +22,89 @@ import org.bukkit.entity.Player;
|
||||||
|
|
||||||
//checks to see whether or not a siege should end based on the locations of the players
|
//checks to see whether or not a siege should end based on the locations of the players
|
||||||
//for example, defender escaped or attacker gave up and left
|
//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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,206 +9,204 @@ class SpamDetector
|
||||||
//last chat message shown and its timestamp, regardless of who sent it
|
//last chat message shown and its timestamp, regardless of who sent it
|
||||||
private String lastChatMessage = "";
|
private String lastChatMessage = "";
|
||||||
private long lastChatMessageTimestamp = 0;
|
private long lastChatMessageTimestamp = 0;
|
||||||
|
|
||||||
//number of identical chat messages in a row
|
//number of identical chat messages in a row
|
||||||
private int duplicateMessageCount = 0;
|
private int duplicateMessageCount = 0;
|
||||||
|
|
||||||
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpamAnalysisResult AnalyzeMessage(UUID chatterID, String message, long timestamp)
|
SpamAnalysisResult AnalyzeMessage(UUID chatterID, String message, long timestamp)
|
||||||
{
|
{
|
||||||
SpamAnalysisResult result = new SpamAnalysisResult();
|
SpamAnalysisResult result = new SpamAnalysisResult();
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean spam = false;
|
boolean spam = false;
|
||||||
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";
|
||||||
chatterData.spamLevel++;
|
chatterData.spamLevel++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//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;
|
||||||
this.duplicateMessageCount = 0;
|
this.duplicateMessageCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check message content and timing
|
//check message content and timing
|
||||||
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++;
|
||||||
spam = true;
|
spam = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//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;
|
||||||
result.muteReason = "repeat message";
|
result.muteReason = "repeat message";
|
||||||
}
|
}
|
||||||
|
|
||||||
//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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise if not a spam, reduce the spam level for this player
|
//otherwise if not a spam, reduce the spam level for this player
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
chatterData.spamLevel = 0;
|
chatterData.spamLevel = 0;
|
||||||
chatterData.spamWarned = false;
|
chatterData.spamWarned = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
chatterData.AddMessage(message, timestamp);
|
chatterData.AddMessage(message, timestamp);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if two strings are 75% identical, they're too close to follow each other in the chat
|
//if two strings are 75% identical, they're too close to follow each other in the chat
|
||||||
private boolean stringsAreSimilar(String message, String lastMessage)
|
private boolean stringsAreSimilar(String message, String lastMessage)
|
||||||
{
|
{
|
||||||
//ignore differences in only punctuation and whitespace
|
//ignore differences in only punctuation and whitespace
|
||||||
message = message.replaceAll("[^\\p{Alpha}]", "");
|
message = message.replaceAll("[^\\p{Alpha}]", "");
|
||||||
lastMessage = lastMessage.replaceAll("[^\\p{Alpha}]", "");
|
lastMessage = lastMessage.replaceAll("[^\\p{Alpha}]", "");
|
||||||
|
|
||||||
//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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -227,17 +225,17 @@ class ChatterData
|
||||||
public long lastMessageTimestamp; //last time the player sent a chat message or used a monitored slash command
|
public long lastMessageTimestamp; //last time the player sent a chat message or used a monitored slash command
|
||||||
public int spamLevel = 0; //number of consecutive "spams"
|
public int spamLevel = 0; //number of consecutive "spams"
|
||||||
public boolean spamWarned = false; //whether the player has received a warning recently
|
public boolean spamWarned = false; //whether the player has received a warning recently
|
||||||
|
|
||||||
//all recent message lengths and their total
|
//all recent message lengths and their total
|
||||||
private ConcurrentLinkedQueue<LengthTimestampPair> recentMessageLengths = new ConcurrentLinkedQueue<LengthTimestampPair>();
|
private ConcurrentLinkedQueue<LengthTimestampPair> recentMessageLengths = new ConcurrentLinkedQueue<LengthTimestampPair>();
|
||||||
private int recentTotalLength = 0;
|
private int recentTotalLength = 0;
|
||||||
|
|
||||||
public void AddMessage(String message, long timestamp)
|
public void AddMessage(String message, long timestamp)
|
||||||
{
|
{
|
||||||
int length = message.length();
|
int length = message.length();
|
||||||
this.recentMessageLengths.add(new LengthTimestampPair(length, timestamp));
|
this.recentMessageLengths.add(new LengthTimestampPair(length, timestamp));
|
||||||
this.recentTotalLength += length;
|
this.recentTotalLength += length;
|
||||||
|
|
||||||
this.lastMessage = message;
|
this.lastMessage = message;
|
||||||
this.lastMessageTimestamp = timestamp;
|
this.lastMessageTimestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
@ -245,13 +243,13 @@ 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;
|
||||||
oldestPair = this.recentMessageLengths.peek();
|
oldestPair = this.recentMessageLengths.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.recentTotalLength;
|
return this.recentTotalLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +258,7 @@ class LengthTimestampPair
|
||||||
{
|
{
|
||||||
public long timestamp;
|
public long timestamp;
|
||||||
public int length;
|
public int length;
|
||||||
|
|
||||||
public LengthTimestampPair(int length, long timestamp)
|
public LengthTimestampPair(int length, long timestamp)
|
||||||
{
|
{
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ package me.ryanhamshire.GriefPrevention;
|
||||||
import org.bukkit.ChatColor;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,93 +7,98 @@ import org.bukkit.OfflinePlayer;
|
||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.json.simple.parser.JSONParser;
|
import org.json.simple.parser.JSONParser;
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
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;
|
||||||
class UUIDFetcher {
|
import java.util.UUID;
|
||||||
|
|
||||||
|
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();
|
||||||
private final List<String> names;
|
private final List<String> names;
|
||||||
private final boolean rateLimiting;
|
private final boolean rateLimiting;
|
||||||
|
|
||||||
//cache for username -> uuid lookups
|
//cache for username -> uuid lookups
|
||||||
static HashMap<String, UUID> lookupCache;
|
static HashMap<String, UUID> lookupCache;
|
||||||
|
|
||||||
//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>();
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
||||||
correctedNames.put(player.getName().toLowerCase(), player.getName());
|
correctedNames.put(player.getName().toLowerCase(), player.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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)...");
|
||||||
|
|
||||||
for (int i = 0; i * PROFILES_PER_REQUEST < names.size(); i++)
|
for (int i = 0; i * PROFILES_PER_REQUEST < names.size(); i++)
|
||||||
{
|
{
|
||||||
boolean retry = false;
|
boolean retry = false;
|
||||||
|
|
@ -109,21 +114,21 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise, keep the batch size which has worked for previous iterations
|
//otherwise, keep the batch size which has worked for previous iterations
|
||||||
//but wait a little while before trying again.
|
//but wait a little while before trying again.
|
||||||
else
|
else
|
||||||
|
|
@ -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,18 +153,19 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//for offline mode, generate UUIDs for the rest
|
//for offline mode, generate UUIDs for the rest
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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));
|
||||||
|
|
@ -169,15 +175,17 @@ 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");
|
||||||
|
|
@ -187,20 +195,24 @@ class UUIDFetcher {
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
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);
|
||||||
|
|
@ -208,17 +220,17 @@ class UUIDFetcher {
|
||||||
long leastSignificant = byteBuffer.getLong();
|
long leastSignificant = byteBuffer.getLong();
|
||||||
return new UUID(mostSignificant, leastSignificant);
|
return new UUID(mostSignificant, leastSignificant);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
throw new IllegalArgumentException(name);
|
throw new IllegalArgumentException(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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,306 +28,300 @@ 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
|
|
||||||
public static void Apply(Player player, Visualization visualization)
|
|
||||||
{
|
|
||||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
|
||||||
|
|
||||||
//if he has any current visualization, clear it first
|
|
||||||
if(playerData.currentVisualization != null)
|
|
||||||
{
|
|
||||||
Visualization.Revert(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if he's online, create a task to send him the visualization
|
|
||||||
if(player.isOnline() && visualization.elements.size() > 0 && visualization.elements.get(0).location.getWorld().equals(player.getWorld()))
|
|
||||||
{
|
|
||||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new VisualizationApplicationTask(player, playerData, visualization), 1L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//reverts a visualization by sending another block change list, this time with the real world block values
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void Revert(Player player)
|
|
||||||
{
|
|
||||||
if(!player.isOnline()) return;
|
|
||||||
|
|
||||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
|
||||||
|
|
||||||
Visualization visualization = playerData.currentVisualization;
|
|
||||||
|
|
||||||
if(playerData.currentVisualization != null)
|
|
||||||
{
|
|
||||||
//locality
|
|
||||||
int minx = player.getLocation().getBlockX() - 100;
|
|
||||||
int minz = player.getLocation().getBlockZ() - 100;
|
|
||||||
int maxx = player.getLocation().getBlockX() + 100;
|
|
||||||
int maxz = player.getLocation().getBlockZ() + 100;
|
|
||||||
|
|
||||||
//remove any elements which are too far away
|
//sends a visualization to a player
|
||||||
visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz);
|
public static void Apply(Player player, Visualization visualization)
|
||||||
|
{
|
||||||
//send real block information for any remaining elements
|
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
||||||
for(int i = 0; i < visualization.elements.size(); i++)
|
|
||||||
{
|
|
||||||
VisualizationElement element = visualization.elements.get(i);
|
|
||||||
|
|
||||||
//check player still in world where visualization exists
|
//if he has any current visualization, clear it first
|
||||||
if(i == 0)
|
if (playerData.currentVisualization != null)
|
||||||
{
|
{
|
||||||
if(!player.getWorld().equals(element.location.getWorld())) return;
|
Visualization.Revert(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendBlockChange(element.location, element.realBlock);
|
//if he's online, create a task to send him the visualization
|
||||||
}
|
if (player.isOnline() && visualization.elements.size() > 0 && visualization.elements.get(0).location.getWorld().equals(player.getWorld()))
|
||||||
|
{
|
||||||
|
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new VisualizationApplicationTask(player, playerData, visualization), 1L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
playerData.currentVisualization = null;
|
//reverts a visualization by sending another block change list, this time with the real world block values
|
||||||
}
|
@SuppressWarnings("deprecation")
|
||||||
}
|
public static void Revert(Player player)
|
||||||
|
{
|
||||||
//convenience method to build a visualization from a claim
|
if (!player.isOnline()) return;
|
||||||
//visualizationType determines the style (gold blocks, silver, red, diamond, etc)
|
|
||||||
public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality)
|
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
||||||
{
|
|
||||||
//visualize only top level claims
|
Visualization visualization = playerData.currentVisualization;
|
||||||
if(claim.parent != null)
|
|
||||||
{
|
if (playerData.currentVisualization != null)
|
||||||
return FromClaim(claim.parent, height, visualizationType, locality);
|
{
|
||||||
}
|
//locality
|
||||||
|
int minx = player.getLocation().getBlockX() - 100;
|
||||||
Visualization visualization = new Visualization();
|
int minz = player.getLocation().getBlockZ() - 100;
|
||||||
|
int maxx = player.getLocation().getBlockX() + 100;
|
||||||
//add subdivisions first
|
int maxz = player.getLocation().getBlockZ() + 100;
|
||||||
for(int i = 0; i < claim.children.size(); i++)
|
|
||||||
{
|
//remove any elements which are too far away
|
||||||
Claim child = claim.children.get(i);
|
visualization.removeElementsOutOfRange(visualization.elements, minx, minz, maxx, maxz);
|
||||||
if(!child.inDataStore) continue;
|
|
||||||
visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality);
|
//send real block information for any remaining elements
|
||||||
}
|
for (int i = 0; i < visualization.elements.size(); i++)
|
||||||
|
{
|
||||||
//special visualization for administrative land claims
|
VisualizationElement element = visualization.elements.get(i);
|
||||||
if(claim.isAdminClaim() && visualizationType == VisualizationType.Claim)
|
|
||||||
|
//check player still in world where visualization exists
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
if (!player.getWorld().equals(element.location.getWorld())) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendBlockChange(element.location, element.realBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
playerData.currentVisualization = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//convenience method to build a visualization from a claim
|
||||||
|
//visualizationType determines the style (gold blocks, silver, red, diamond, etc)
|
||||||
|
public static Visualization FromClaim(Claim claim, int height, VisualizationType visualizationType, Location locality)
|
||||||
|
{
|
||||||
|
//visualize only top level claims
|
||||||
|
if (claim.parent != null)
|
||||||
|
{
|
||||||
|
return FromClaim(claim.parent, height, visualizationType, locality);
|
||||||
|
}
|
||||||
|
|
||||||
|
Visualization visualization = new Visualization();
|
||||||
|
|
||||||
|
//add subdivisions first
|
||||||
|
for (int i = 0; i < claim.children.size(); i++)
|
||||||
|
{
|
||||||
|
Claim child = claim.children.get(i);
|
||||||
|
if (!child.inDataStore) continue;
|
||||||
|
visualization.addClaimElements(child, height, VisualizationType.Subdivision, locality);
|
||||||
|
}
|
||||||
|
|
||||||
|
//special visualization for administrative land claims
|
||||||
|
if (claim.isAdminClaim() && visualizationType == VisualizationType.Claim)
|
||||||
{
|
{
|
||||||
visualizationType = VisualizationType.AdminClaim;
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
//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()
|
BlockData cornerBlockData;
|
||||||
switch (blockMaterial)
|
BlockData accentBlockData;
|
||||||
{
|
|
||||||
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))
|
ArrayList<VisualizationElement> newElements = new ArrayList<VisualizationElement>();
|
||||||
return true;
|
|
||||||
|
|
||||||
return (waterIsTransparent && block.getType() == Material.WATER) ||
|
if (visualizationType == VisualizationType.Claim)
|
||||||
block.getType().isTransparent();
|
{
|
||||||
}
|
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
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return visualization;
|
return visualization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,46 +15,46 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
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;
|
||||||
|
|
@ -25,28 +25,28 @@ import org.bukkit.entity.Player;
|
||||||
import java.util.Collections;
|
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
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
//don't do anything if the player's current visualization is different from the one scheduled to revert
|
|
||||||
if(playerData.currentVisualization != visualization) return;
|
|
||||||
|
|
||||||
// alert plugins of a visualization
|
@Override
|
||||||
Bukkit.getPluginManager().callEvent(new VisualizationEvent(player, Collections.<Claim>emptySet()));
|
public void run()
|
||||||
|
{
|
||||||
Visualization.Revert(player);
|
//don't do anything if the player's current visualization is different from the one scheduled to revert
|
||||||
}
|
if (playerData.currentVisualization != visualization) return;
|
||||||
|
|
||||||
|
// alert plugins of a visualization
|
||||||
|
Bukkit.getPluginManager().callEvent(new VisualizationEvent(player, Collections.<Claim>emptySet()));
|
||||||
|
|
||||||
|
Visualization.Revert(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@
|
||||||
package me.ryanhamshire.GriefPrevention;
|
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,24 +10,24 @@ import org.bukkit.inventory.meta.BookMeta;
|
||||||
public class WelcomeTask implements Runnable
|
public class WelcomeTask implements Runnable
|
||||||
{
|
{
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
public WelcomeTask(Player player)
|
public WelcomeTask(Player player)
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
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);
|
||||||
|
|
@ -35,43 +35,43 @@ public class WelcomeTask implements Runnable
|
||||||
DataStore datastore = GriefPrevention.instance.dataStore;
|
DataStore datastore = GriefPrevention.instance.dataStore;
|
||||||
meta.setAuthor(datastore.getMessage(Messages.BookAuthor));
|
meta.setAuthor(datastore.getMessage(Messages.BookAuthor));
|
||||||
meta.setTitle(datastore.getMessage(Messages.BookTitle));
|
meta.setTitle(datastore.getMessage(Messages.BookTitle));
|
||||||
|
|
||||||
StringBuilder page1 = new StringBuilder();
|
StringBuilder page1 = new StringBuilder();
|
||||||
String URL = datastore.getMessage(Messages.BookLink, DataStore.SURVIVAL_VIDEO_URL);
|
String URL = datastore.getMessage(Messages.BookLink, DataStore.SURVIVAL_VIDEO_URL);
|
||||||
String intro = datastore.getMessage(Messages.BookIntro);
|
String intro = datastore.getMessage(Messages.BookIntro);
|
||||||
|
|
||||||
page1.append(URL).append("\n\n");
|
page1.append(URL).append("\n\n");
|
||||||
page1.append(intro).append("\n\n");
|
page1.append(intro).append("\n\n");
|
||||||
String editToolName = GriefPrevention.instance.config_claims_modificationTool.name().replace('_', ' ').toLowerCase();
|
String editToolName = GriefPrevention.instance.config_claims_modificationTool.name().replace('_', ' ').toLowerCase();
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder page2 = new StringBuilder(datastore.getMessage(Messages.BookUsefulCommands)).append("\n\n");
|
StringBuilder page2 = new StringBuilder(datastore.getMessage(Messages.BookUsefulCommands)).append("\n\n");
|
||||||
page2.append("/Trust /UnTrust /TrustList\n");
|
page2.append("/Trust /UnTrust /TrustList\n");
|
||||||
page2.append("/ClaimsList\n");
|
page2.append("/ClaimsList\n");
|
||||||
page2.append("/AbandonClaim\n\n");
|
page2.append("/AbandonClaim\n\n");
|
||||||
page2.append("/Claim /ExtendClaim\n");
|
page2.append("/Claim /ExtendClaim\n");
|
||||||
|
|
||||||
page2.append("/IgnorePlayer\n\n");
|
page2.append("/IgnorePlayer\n\n");
|
||||||
|
|
||||||
page2.append("/SubdivideClaims\n");
|
page2.append("/SubdivideClaims\n");
|
||||||
page2.append("/AccessTrust\n");
|
page2.append("/AccessTrust\n");
|
||||||
page2.append("/ContainerTrust\n");
|
page2.append("/ContainerTrust\n");
|
||||||
page2.append("/PermissionTrust");
|
page2.append("/PermissionTrust");
|
||||||
|
|
||||||
meta.setPages(page1.toString(), page2.toString());
|
meta.setPages(page1.toString(), page2.toString());
|
||||||
|
|
||||||
ItemStack item = new ItemStack(Material.WRITTEN_BOOK);
|
ItemStack item = new ItemStack(Material.WRITTEN_BOOK);
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
player.getInventory().addItem(item);
|
player.getInventory().addItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,35 +6,35 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
class WordFinder
|
class WordFinder
|
||||||
{
|
{
|
||||||
private Pattern pattern;
|
private Pattern pattern;
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
this.pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,46 @@
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event gets called whenever a claim is going to be deleted. This event is
|
* This event gets called whenever a claim is going to be deleted. This event is
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the claim to be deleted.
|
* Gets the claim to be deleted.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Claim getClaim() {
|
public Claim getClaim()
|
||||||
|
{
|
||||||
return claim;
|
return claim;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HandlerList getHandlers() {
|
public HandlerList getHandlers()
|
||||||
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -11,7 +10,7 @@ public class ClaimExpirationEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private boolean cancelled = false;
|
private boolean cancelled = false;
|
||||||
|
|
||||||
public static HandlerList getHandlerList()
|
public static HandlerList getHandlerList()
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
|
|
@ -34,13 +33,13 @@ public class ClaimExpirationEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled()
|
public boolean isCancelled()
|
||||||
{
|
{
|
||||||
return this.cancelled;
|
return this.cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled)
|
public void setCancelled(boolean cancelled)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ public class PreventBlockBreakEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
private static final HandlerList handlers = new HandlerList();
|
private static final HandlerList handlers = new HandlerList();
|
||||||
private boolean cancelled = false;
|
private boolean cancelled = false;
|
||||||
private BlockBreakEvent innerEvent;
|
private BlockBreakEvent innerEvent;
|
||||||
|
|
||||||
public static HandlerList getHandlerList()
|
public static HandlerList getHandlerList()
|
||||||
{
|
{
|
||||||
|
|
@ -21,7 +21,7 @@ public class PreventBlockBreakEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
this.innerEvent = innerEvent;
|
this.innerEvent = innerEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockBreakEvent getInnerEvent()
|
public BlockBreakEvent getInnerEvent()
|
||||||
{
|
{
|
||||||
return this.innerEvent;
|
return this.innerEvent;
|
||||||
|
|
@ -32,13 +32,13 @@ public class PreventBlockBreakEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled()
|
public boolean isCancelled()
|
||||||
{
|
{
|
||||||
return this.cancelled;
|
return this.cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled)
|
public void setCancelled(boolean cancelled)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -34,13 +33,13 @@ public class PreventPvPEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled()
|
public boolean isCancelled()
|
||||||
{
|
{
|
||||||
return this.cancelled;
|
return this.cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled)
|
public void setCancelled(boolean cancelled)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -34,13 +33,13 @@ public class ProtectDeathDropsEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled()
|
public boolean isCancelled()
|
||||||
{
|
{
|
||||||
return this.cancelled;
|
return this.cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled)
|
public void setCancelled(boolean cancelled)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -46,13 +45,13 @@ public class SaveTrappedPlayerEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled()
|
public boolean isCancelled()
|
||||||
{
|
{
|
||||||
return this.cancelled;
|
return this.cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled)
|
public void setCancelled(boolean cancelled)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,110 +1,119 @@
|
||||||
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();
|
||||||
|
|
||||||
private final Player changer;
|
private final Player changer;
|
||||||
private final List<Claim> claims;
|
private final List<Claim> claims;
|
||||||
private final ClaimPermission claimPermission;
|
private final ClaimPermission claimPermission;
|
||||||
private final boolean given;
|
private final boolean given;
|
||||||
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,
|
|
||||||
String identifier) {
|
|
||||||
super();
|
|
||||||
this.changer = changer;
|
|
||||||
this.claims = claims;
|
|
||||||
this.claimPermission = claimPermission;
|
|
||||||
this.given = given;
|
|
||||||
this.identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TrustChangedEvent(Player changer, Claim claim, ClaimPermission claimPermission, boolean given, String identifier) {
|
public TrustChangedEvent(Player changer, List<Claim> claims, ClaimPermission claimPermission, boolean given,
|
||||||
this.changer = changer;
|
String identifier)
|
||||||
claims = new ArrayList<>();
|
{
|
||||||
claims.add(claim);
|
super();
|
||||||
this.claimPermission = claimPermission;
|
this.changer = changer;
|
||||||
this.given = given;
|
this.claims = claims;
|
||||||
this.identifier = identifier;
|
this.claimPermission = claimPermission;
|
||||||
}
|
this.given = given;
|
||||||
|
this.identifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public TrustChangedEvent(Player changer, Claim claim, ClaimPermission claimPermission, boolean given, String identifier)
|
||||||
public HandlerList getHandlers() {
|
{
|
||||||
return handlers;
|
this.changer = changer;
|
||||||
}
|
claims = new ArrayList<>();
|
||||||
|
claims.add(claim);
|
||||||
/**
|
this.claimPermission = claimPermission;
|
||||||
* Gets who made the change
|
this.given = given;
|
||||||
*
|
this.identifier = identifier;
|
||||||
* @return the changer
|
}
|
||||||
*/
|
|
||||||
public Player getChanger() {
|
|
||||||
return changer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the changed claims
|
public HandlerList getHandlers()
|
||||||
*
|
{
|
||||||
* @return the changed claims
|
return handlers;
|
||||||
*/
|
}
|
||||||
public List<Claim> getClaims() {
|
|
||||||
return claims;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the claim permission (null if the permission is being taken)
|
* Gets who made the change
|
||||||
*
|
*
|
||||||
* @return the claim permission
|
* @return the changer
|
||||||
*/
|
*/
|
||||||
public ClaimPermission getClaimPermission() {
|
public Player getChanger()
|
||||||
return claimPermission;
|
{
|
||||||
}
|
return changer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the trust is being given
|
* Gets the changed claims
|
||||||
*
|
*
|
||||||
* @return true if given, false if taken
|
* @return the changed claims
|
||||||
*/
|
*/
|
||||||
public boolean isGiven() {
|
public List<Claim> getClaims()
|
||||||
return given;
|
{
|
||||||
}
|
return claims;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the identifier of the receiver of this action
|
* Gets the claim permission (null if the permission is being taken)
|
||||||
* Can be: "public", "all", a UUID, a permission
|
*
|
||||||
*
|
* @return the claim permission
|
||||||
* @return the identifier
|
*/
|
||||||
*/
|
public ClaimPermission getClaimPermission()
|
||||||
public String getIdentifier() {
|
{
|
||||||
return identifier;
|
return claimPermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean isCancelled() {
|
* Checks if the trust is being given
|
||||||
return cancelled;
|
*
|
||||||
}
|
* @return true if given, false if taken
|
||||||
|
*/
|
||||||
|
public boolean isGiven()
|
||||||
|
{
|
||||||
|
return given;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void setCancelled(boolean cancelled) {
|
* Gets the identifier of the receiver of this action
|
||||||
this.cancelled = cancelled;
|
* Can be: "public", "all", a UUID, a permission
|
||||||
}
|
*
|
||||||
|
* @return the identifier
|
||||||
|
*/
|
||||||
|
public String getIdentifier()
|
||||||
|
{
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled()
|
||||||
|
{
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelled)
|
||||||
|
{
|
||||||
|
this.cancelled = cancelled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
*
|
* @author Ryan
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @author Ryan
|
* @author Ryan
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user