This commit is contained in:
Ryan Hamshire 2012-05-22 20:31:42 -07:00
parent 136bf91c8a
commit 540746ad4b
7 changed files with 415 additions and 88 deletions

View File

@ -1,7 +1,7 @@
name: GriefPrevention
main: me.ryanhamshire.GriefPrevention.GriefPrevention
softdepend: [Vault, Multiverse-Core]
version: 3.6
version: 3.8
commands:
abandonclaim:
description: Deletes a claim.
@ -108,6 +108,7 @@ permissions:
griefprevention.deleteclaims: true
griefprevention.spam: true
griefprevention.lava: true
griefprevention.eavesdrop: true
griefprevention.restorenature:
description: Grants permission to use /RestoreNature.
default: op
@ -128,4 +129,7 @@ permissions:
default: op
griefprevention.lava:
description: Grants permission to place lava near the surface and outside of claims.
default: op
griefprevention.eavesdrop:
description: Allows a player to see whispered chat messages (/tell).
default: op

View File

@ -144,34 +144,27 @@ public class BlockEventHandler implements Listener
{
Player player = breakEvent.getPlayer();
Block block = breakEvent.getBlock();
//make sure the player is allowed to break at the location
String noBuildReason = GriefPrevention.instance.allowBreak(player, block.getLocation());
if(noBuildReason != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
breakEvent.setCancelled(true);
return;
}
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
Claim claim = this.dataStore.getClaimAt(block.getLocation(), true, playerData.lastClaim);
//if there's a claim here
if(claim != null)
{
//cache the claim for later reference
playerData.lastClaim = claim;
//check permissions
String noBuildReason = claim.allowBreak(player, block.getType());
//if permission to break and breaking UNDER the claim
//if breaking UNDER the claim
if(block.getY() < claim.lesserBoundaryCorner.getBlockY())
{
if(noBuildReason == null)
{
//extend the claim downward beyond the breakage point
this.dataStore.extendClaim(claim, claim.getLesserBoundaryCorner().getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance);
}
}
//otherwise if not allowed to break blocks here, tell the player why
else if(noBuildReason != null)
{
breakEvent.setCancelled(true);
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
return;
//extend the claim downward beyond the breakage point
this.dataStore.extendClaim(claim, claim.getLesserBoundaryCorner().getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance);
}
}
@ -210,30 +203,26 @@ public class BlockEventHandler implements Listener
}
}
//make sure the player is allowed to build at the location
String noBuildReason = GriefPrevention.instance.allowBuild(player, block.getLocation());
if(noBuildReason != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
placeEvent.setCancelled(true);
return;
}
//if the block is being placed within an existing claim
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
Claim claim = this.dataStore.getClaimAt(block.getLocation(), true, playerData.lastClaim);
if(claim != null)
{
playerData.lastClaim = claim;
String noBuildReason = claim.allowBuild(player);
//if the player has permission for the claim and he's placing UNDER the claim
if(block.getY() < claim.lesserBoundaryCorner.getBlockY())
{
if(noBuildReason == null)
{
//extend the claim downward
this.dataStore.extendClaim(claim, claim.getLesserBoundaryCorner().getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance);
}
//extend the claim downward
this.dataStore.extendClaim(claim, claim.getLesserBoundaryCorner().getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance);
}
//otherwise if he doesn't have permission, tell him why
else if(noBuildReason != null)
{
placeEvent.setCancelled(true);
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
}
}
//FEATURE: automatically create a claim when a player who has no claims places a chest
@ -304,7 +293,7 @@ public class BlockEventHandler implements Listener
//blocks "pushing" other players' blocks around (pistons)
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onBlockPistonExtend (BlockPistonExtendEvent event)
public void onBlockPistonExtend (BlockPistonExtendEvent event)
{
//who owns the piston, if anyone?
String pistonClaimOwnerName = "_";
@ -390,6 +379,13 @@ public class BlockEventHandler implements Listener
Block toBlock = spreadEvent.getToBlock();
Claim toClaim = this.dataStore.getClaimAt(toBlock.getLocation(), false, null);
//if in a creative world, block any spread into the wilderness
if(GriefPrevention.instance.creativeRulesApply(toBlock.getLocation()) && toClaim == null)
{
spreadEvent.setCancelled(true);
return;
}
//if spreading into a claim
if(toClaim != null)
{

View File

@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.Map;
import org.bukkit.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
//represents a player claim
@ -182,6 +183,9 @@ public class Claim
//all of these return NULL when a player has permission, or a String error message when the player doesn't have permission
public String allowEdit(Player player)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//special cases...
//admin claims need adminclaims permission only.
@ -219,6 +223,9 @@ public class Claim
//build permission check
public String allowBuild(Player player)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//when a player tries to build in a claim, if he's under siege, the siege may extend to include the new claim
GriefPrevention.instance.dataStore.tryExtendSiege(player, this);
@ -263,6 +270,9 @@ public class Claim
//break permission check
public String allowBreak(Player player, Material material)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//if under siege, some blocks will be breakable
if(this.siegeData != null)
{
@ -301,6 +311,9 @@ public class Claim
//access permission check
public String allowAccess(Player player)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//everyone always has access to admin claims
if(this.isAdminClaim()) return null;
@ -329,6 +342,9 @@ public class Claim
//inventory permission check
public String allowContainers(Player player)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//trying to access inventory in a claim may extend an existing siege to include this claim
GriefPrevention.instance.dataStore.tryExtendSiege(player, this);
@ -363,6 +379,9 @@ public class Claim
//grant permission check, relatively simple
public String allowGrantPermission(Player player)
{
//if we don't know who's asking, always say no (i've been told some mods can make this happen somehow)
if(player == null) return "";
//anyone who can modify the claim, or who's explicitly in the managers (/PermissionTrust) list can do this
if(this.allowEdit(player) == null || this.managers.contains(player.getName())) return null;
@ -543,6 +562,40 @@ public class Claim
return false;
}
//whether more entities may be added to a claim
public String allowMoreEntities()
{
if(this.parent != null) return this.parent.allowMoreEntities();
//this rule only applies to creative mode worlds
if(!GriefPrevention.instance.creativeRulesApply(this.getLesserBoundaryCorner())) return null;
//determine maximum allowable entity count, based on claim size
int maxEntities = this.getArea() / 50;
if(maxEntities == 0) return "This claim isn't big enough for that. Try enlarging it.";
//count current entities (ignoring players)
Chunk lesserChunk = this.getLesserBoundaryCorner().getChunk();
Chunk greaterChunk = this.getGreaterBoundaryCorner().getChunk();
int totalEntities = 0;
for(int x = lesserChunk.getX(); x <= greaterChunk.getX(); x++)
for(int z = lesserChunk.getZ(); z <= greaterChunk.getZ(); z++)
{
Chunk chunk = lesserChunk.getWorld().getChunkAt(x, z);
Entity [] entities = chunk.getEntities();
for(int i = 0; i < entities.length; i++)
{
Entity entity = entities[i];
if(!(entity instanceof Player) && this.contains(entity.getLocation(), false, false)) totalEntities++;
}
}
if(totalEntities > maxEntities) return "This claim has too many entities already. Try enlarging the claim or removing some animals, monsters, or minecarts.";
return null;
}
//implements a strict ordering of claims, used to keep the claims collection sorted for faster searching
boolean greaterThan(Claim otherClaim)
{

View File

@ -140,6 +140,9 @@ public class DataStore
else
{
Claim subdivision = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, "--subdivision--", builderNames, containerNames, accessorNames, managerNames);
//make sure there are no other subdivisions overlapping this one
subdivision.modifiedDate = new Date(files[i].lastModified());
subdivision.parent = topLevelClaim;
topLevelClaim.children.add(subdivision);
@ -509,8 +512,10 @@ public class DataStore
//convert that to a number and store it
playerData.bonusClaimBlocks = Integer.parseInt(bonusBlocksString);
//fourth line is a double-semicolon-delimited list of claims
String claimsString = inStream.readLine();
//fourth line is a double-semicolon-delimited list of claims, which is currently ignored
//String claimsString = inStream.readLine();
inStream.readLine();
/*
if(claimsString != null && claimsString.length() > 0)
{
String [] claimsStrings = claimsString.split(";;");
@ -522,7 +527,7 @@ public class DataStore
String claimID = claimsStrings[i];
if(claimID != null)
{
Claim claim = this.getClaimAt(this.locationFromString(claimID), true /*ignore height*/, null);
Claim claim = this.getClaimAt(this.locationFromString(claimID), true, null);
//if the referenced claim exists, add it to the player data instance for later reference
if(claim != null)
@ -544,6 +549,17 @@ public class DataStore
this.savePlayerData(playerName, playerData);
}
}
*/
//find all the claims belonging to this player and note them for future reference
for(int i = 0; i < this.claims.size(); i++)
{
Claim claim = this.claims.get(i);
if(claim.ownerName.equals(playerName))
{
playerData.claims.add(claim);
}
}
inStream.close();
}
@ -1044,14 +1060,14 @@ public class DataStore
}
//deletes all claims owned by a player
public void deleteClaimsForPlayer(String playerName)
public void deleteClaimsForPlayer(String playerName, boolean deleteCreativeClaims)
{
//make a list of the player's claims
ArrayList<Claim> claimsToDelete = new ArrayList<Claim>();
for(int i = 0; i < this.claims.size(); i++)
{
Claim claim = this.claims.get(i);
if(claim.ownerName.equals(playerName))
if(claim.ownerName.equals(playerName) && (deleteCreativeClaims || !GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner())))
claimsToDelete.add(claim);
}

View File

@ -35,11 +35,14 @@ import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.painting.PaintingBreakByEntityEvent;
import org.bukkit.event.painting.PaintingBreakEvent;
import org.bukkit.event.painting.PaintingPlaceEvent;
@ -73,6 +76,12 @@ class EntityEventHandler implements Listener
}
}
//special rule for creative worlds: explosions don't destroy anything
if(GriefPrevention.instance.creativeRulesApply(entity.getLocation()))
{
blocks.clear();
}
//FEATURE: creating an explosion near a claim doesn't damage any of the claimed blocks
Claim claim = null;
@ -96,14 +105,59 @@ class EntityEventHandler implements Listener
}
}
//when an item spawns...
@EventHandler
public void onItemSpawn(ItemSpawnEvent event)
{
//if in a creative world, cancel the event (don't drop items on the ground)
if(GriefPrevention.instance.creativeRulesApply(event.getLocation()))
{
event.setCancelled(true);
}
}
//when a creature spawns...
@EventHandler
public void onEntitySpawn(CreatureSpawnEvent event)
{
LivingEntity entity = event.getEntity();
//these rules apply only to creative worlds
if(!GriefPrevention.instance.creativeRulesApply(entity.getLocation())) return;
//chicken eggs and breeding could potentially make a mess in the wilderness, once griefers get involved
SpawnReason reason = event.getSpawnReason();
if(reason == SpawnReason.EGG || reason == SpawnReason.BREEDING)
{
event.setCancelled(true);
return;
}
//otherwise, just apply the limit on total entities per claim
Claim claim = this.dataStore.getClaimAt(event.getLocation(), false, null);
if(claim != null && claim.allowMoreEntities() != null)
{
event.setCancelled(true);
return;
}
}
//when an entity dies...
@EventHandler
public void onEntityDeath(EntityDeathEvent event)
{
LivingEntity entity = event.getEntity();
//special rule for creative worlds: killed entities don't drop items or experience orbs
if(GriefPrevention.instance.creativeRulesApply(entity.getLocation()))
{
event.setDroppedExp(0);
event.getDrops().clear();
}
//FEATURE: when a player is involved in a siege (attacker or defender role)
//his death will end the siege
LivingEntity entity = event.getEntity();
if(!(entity instanceof Player)) return; //only tracking players
Player player = (Player)entity;
@ -153,10 +207,6 @@ class EntityEventHandler implements Listener
PaintingBreakByEntityEvent entityEvent = (PaintingBreakByEntityEvent)event;
//which claim is the painting in?
Claim claim = this.dataStore.getClaimAt(event.getPainting().getLocation(), false, null);
if(claim == null) return;
//who is removing it?
Entity remover = entityEvent.getRemover();
@ -166,15 +216,19 @@ class EntityEventHandler implements Listener
event.setCancelled(true);
return;
}
//make sure the player has build permission here
Claim claim = this.dataStore.getClaimAt(event.getPainting().getLocation(), false, null);
if(claim == null) return;
//if the player doesn't have build permission, don't allow the breakage
Player playerRemover = (Player)entityEvent.getRemover();
String noBuildReason = claim.allowBuild(playerRemover);
String noBuildReason = GriefPrevention.instance.allowBuild(playerRemover, event.getPainting().getLocation());
if(noBuildReason != null)
{
event.setCancelled(true);
GriefPrevention.sendMessage(playerRemover, TextMode.Err, noBuildReason);
}
}
}
//when a painting is placed...
@ -183,17 +237,13 @@ class EntityEventHandler implements Listener
{
//FEATURE: similar to above, placing a painting requires build permission in the claim
//which claim is the painting in?
Claim claim = this.dataStore.getClaimAt(event.getBlock().getLocation(), false, null);
if(claim == null) return;
//if the player doesn't have permission, don't allow the placement
String noBuildReason = claim.allowBuild(event.getPlayer());
//if the player doesn't have permission, don't allow the placement
String noBuildReason = GriefPrevention.instance.allowBuild(event.getPlayer(), event.getPainting().getLocation());
if(noBuildReason != null)
{
event.setCancelled(true);
GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, noBuildReason);
}
}
}
//when an entity is damaged

View File

@ -30,6 +30,7 @@ import net.milkbowl.vault.economy.Economy;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
@ -59,6 +60,7 @@ public class GriefPrevention extends JavaPlugin
//configuration variables, loaded/saved from a config.yml
public ArrayList<World> config_claims_enabledWorlds; //list of worlds where players can create GriefPrevention claims
public ArrayList<World> config_claims_enabledCreativeWorlds; //list of worlds where additional creative mode anti-grief rules apply
public boolean config_claims_preventTheft; //whether containers and crafting blocks are protectable
public boolean config_claims_preventButtonsSwitches; //whether buttons and switches are protectable
@ -103,6 +105,7 @@ public class GriefPrevention extends JavaPlugin
public boolean config_fireDestroys; //whether fire destroys blocks outside of claims
public boolean config_addItemsToClaimedChests; //whether players may add items to claimed chests by left-clicking them
public boolean config_eavesdrop; //whether whispered messages will be visible to administrators
//reference to the economy plugin, if economy integration is enabled
public static Economy economy = null;
@ -159,6 +162,41 @@ public class GriefPrevention extends JavaPlugin
}
}
//default creative claim world names
List<String> defaultCreativeWorldNames = new ArrayList<String>();
//if default game mode for the server is creative, creative rules will apply to all worlds unless the config specifies otherwise
if(this.getServer().getDefaultGameMode() == GameMode.CREATIVE)
{
for(int i = 0; i < defaultClaimsWorldNames.size(); i++)
{
defaultCreativeWorldNames.add(defaultClaimsWorldNames.get(i));
}
}
//get creative world names from the config file
List<String> creativeClaimsEnabledWorldNames = config.getStringList("GriefPrevention.Claims.CreativeRulesWorlds");
if(creativeClaimsEnabledWorldNames == null || creativeClaimsEnabledWorldNames.size() == 0)
{
creativeClaimsEnabledWorldNames = defaultCreativeWorldNames;
}
//validate that list
this.config_claims_enabledCreativeWorlds = new ArrayList<World>();
for(int i = 0; i < creativeClaimsEnabledWorldNames.size(); i++)
{
String worldName = creativeClaimsEnabledWorldNames.get(i);
World world = this.getServer().getWorld(worldName);
if(world == null)
{
AddLogEntry("Error: Claims Configuration: There's no world named \"" + worldName + "\". Please update your config.yml.");
}
else
{
this.config_claims_enabledCreativeWorlds.add(world);
}
}
this.config_claims_preventTheft = config.getBoolean("GriefPrevention.Claims.PreventTheft", true);
this.config_claims_preventButtonsSwitches = config.getBoolean("GriefPrevention.Claims.PreventButtonsSwitches", true);
this.config_claims_initialBlocks = config.getInt("GriefPrevention.Claims.InitialBlocks", 100);
@ -196,8 +234,9 @@ public class GriefPrevention extends JavaPlugin
this.config_fireDestroys = config.getBoolean("GriefPrevention.FireDestroys", false);
this.config_addItemsToClaimedChests = config.getBoolean("GriefPrevention.AddItemsToClaimedChests", true);
this.config_eavesdrop = config.getBoolean("GriefPrevention.EavesdropEnabled", false);
//default for claims worlds list
//default for siege worlds list
ArrayList<String> defaultSiegeWorldNames = new ArrayList<String>();
//get siege world names from the config file
@ -270,6 +309,7 @@ public class GriefPrevention extends JavaPlugin
}
config.set("GriefPrevention.Claims.Worlds", claimsEnabledWorldNames);
config.set("GriefPrevention.Claims.CreativeRulesWorlds", creativeClaimsEnabledWorldNames);
config.set("GriefPrevention.Claims.PreventTheft", this.config_claims_preventTheft);
config.set("GriefPrevention.Claims.PreventButtonsSwitches", this.config_claims_preventButtonsSwitches);
config.set("GriefPrevention.Claims.InitialBlocks", this.config_claims_initialBlocks);
@ -307,6 +347,7 @@ public class GriefPrevention extends JavaPlugin
config.set("GriefPrevention.FireDestroys", this.config_fireDestroys);
config.set("GriefPrevention.AddItemsToClaimedChests", this.config_addItemsToClaimedChests);
config.set("GriefPrevention.EavesdropEnabled", this.config_eavesdrop);
config.set("GriefPrevention.Siege.Worlds", siegeEnabledWorldNames);
config.set("GriefPrevention.Siege.BreakableBlocks", breakableBlocksList);
@ -403,7 +444,7 @@ public class GriefPrevention extends JavaPlugin
//abandonclaim
if(cmd.getName().equalsIgnoreCase("abandonclaim") && player != null)
{
this.abandonClaimHandler(player, false);
return this.abandonClaimHandler(player, false);
}
//abandontoplevelclaim
@ -435,6 +476,14 @@ public class GriefPrevention extends JavaPlugin
//abandonallclaims
else if(cmd.getName().equalsIgnoreCase("abandonallclaims") && player != null)
{
if(args.length != 0) return false;
if(creativeRulesApply(player.getLocation()))
{
GriefPrevention.sendMessage(player, TextMode.Err, "Creative mode claims can't be abandoned.");
return true;
}
//count claims
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
int originalClaimCount = playerData.claims.size();
@ -447,11 +496,11 @@ public class GriefPrevention extends JavaPlugin
}
//delete them
this.dataStore.deleteClaimsForPlayer(player.getName());
this.dataStore.deleteClaimsForPlayer(player.getName(), false);
//inform the player
int remainingBlocks = playerData.getRemainingClaimBlocks();
GriefPrevention.sendMessage(player, TextMode.Success, originalClaimCount + " claims abandoned. You now have " + String.valueOf(remainingBlocks) + " available claim blocks.");
GriefPrevention.sendMessage(player, TextMode.Success, "Claims abandoned. You now have " + String.valueOf(remainingBlocks) + " available claim blocks.");
//revert any current visualization
Visualization.Revert(player);
@ -960,7 +1009,7 @@ public class GriefPrevention extends JavaPlugin
}
//delete all that player's claims
this.dataStore.deleteClaimsForPlayer(otherPlayer.getName());
this.dataStore.deleteClaimsForPlayer(otherPlayer.getName(), true);
GriefPrevention.sendMessage(player, TextMode.Success, "Deleted all of " + otherPlayer.getName() + "'s claims.");
@ -980,7 +1029,7 @@ public class GriefPrevention extends JavaPlugin
}
//delete all admin claims
this.dataStore.deleteClaimsForPlayer(""); //empty string for owner name indicates an administrative claim
this.dataStore.deleteClaimsForPlayer("", true); //empty string for owner name indicates an administrative claim
GriefPrevention.sendMessage(player, TextMode.Success, "Deleted all administrative claims.");
@ -1194,7 +1243,12 @@ public class GriefPrevention extends JavaPlugin
if(claim == null)
{
GriefPrevention.sendMessage(player, TextMode.Instr, "Stand in the claim you want to delete, or consider /AbandonAllClaims.");
}
}
else if(this.creativeRulesApply(player.getLocation()))
{
GriefPrevention.sendMessage(player, TextMode.Err, "Creative-mode claims can't be abandoned.");
}
//verify ownership
else if(claim.allowEdit(player) != null)
@ -1673,4 +1727,72 @@ public class GriefPrevention extends JavaPlugin
{
player.sendMessage(color + message);
}
//determines whether creative anti-grief rules apply at a location
boolean creativeRulesApply(Location location)
{
return this.config_claims_enabledCreativeWorlds.contains(location.getWorld());
}
public String allowBuild(Player player, Location location)
{
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
Claim claim = this.dataStore.getClaimAt(location, false, playerData.lastClaim);
//wilderness rules
if(claim == null)
{
//no building in the wilderness in creative mode
if(this.creativeRulesApply(location))
{
//exception: administrators in ignore claims mode
if(playerData.ignoreClaims) return null;
return "You can't build here. Use the golden shovel to claim some land first.";
}
//but it's fine in survival mode
else
{
//cache the claim for later reference
playerData.lastClaim = claim;
return null;
}
}
//if not in the wilderness, then apply claim rules (permissions, etc)
return claim.allowBuild(player);
}
public String allowBreak(Player player, Location location)
{
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
Claim claim = this.dataStore.getClaimAt(location, false, playerData.lastClaim);
//wilderness rules
if(claim == null)
{
//no building in the wilderness in creative mode
if(this.creativeRulesApply(location))
{
//exception: administrators in ignore claims mode
if(playerData.ignoreClaims) return null;
return "You can't build here. Use the golden shovel to claim some land first.";
}
//but it's fine in survival mode
else
{
//cache the claim for later reference
playerData.lastClaim = claim;
return null;
}
}
//if not in the wilderness, then apply claim rules (permissions, etc)
return claim.allowBreak(player, location.getBlock().getType());
}
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
@ -111,7 +112,7 @@ class PlayerEventHandler implements Listener
long millisecondsSinceLastMessage = (new Date()).getTime() - playerData.lastMessageTimestamp.getTime();
//if the message came too close to the last one
if(millisecondsSinceLastMessage < 3000)
if(millisecondsSinceLastMessage < 2000)
{
//increment the spam counter
playerData.spamCount++;
@ -122,6 +123,7 @@ class PlayerEventHandler implements Listener
if(message.equals(playerData.lastMessage))
{
playerData.spamCount++;
event.setCancelled(true);
spam = true;
}
@ -164,7 +166,11 @@ class PlayerEventHandler implements Listener
//kick
player.kickPlayer(GriefPrevention.instance.config_spam_banMessage);
}
}
else
{
player.kickPlayer("");
}
}
//cancel any messages while at or above the third spam level and issue warnings
@ -197,6 +203,31 @@ class PlayerEventHandler implements Listener
//if the slash command used is in the list of monitored commands, treat it like a chat message (see above)
String [] args = event.getMessage().split(" ");
if(GriefPrevention.instance.config_spam_monitorSlashCommands.contains(args[0])) this.onPlayerChat(event);
if(GriefPrevention.instance.config_eavesdrop && args[0].equalsIgnoreCase("/tell") && !event.getPlayer().hasPermission("griefprevention.eavesdrop") && args.length > 2)
{
StringBuilder logMessageBuilder = new StringBuilder();
logMessageBuilder.append("[").append(event.getPlayer().getName()).append(" > ").append(args[1]).append("] ");
for(int i = 2; i < args.length; i++)
{
logMessageBuilder.append(args[i]).append(" ");
}
String logMessage = logMessageBuilder.toString();
GriefPrevention.AddLogEntry(logMessage.toString());
Player [] players = GriefPrevention.instance.getServer().getOnlinePlayers();
for(int i = 0; i < players.length; i++)
{
Player player = players[i];
if(player.hasPermission("griefprevention.eavesdrop") && !player.getName().equalsIgnoreCase(args[1]))
{
player.sendMessage(ChatColor.GRAY + logMessage);
}
}
}
}
//when a player attempts to join the server...
@ -300,6 +331,14 @@ class PlayerEventHandler implements Listener
public void onPlayerDropItem(PlayerDropItemEvent event)
{
Player player = event.getPlayer();
//in creative worlds, dropping items is blocked
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
{
event.setCancelled(true);
return;
}
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
//FEATURE: players under siege or in PvP combat, can't throw items on the ground to hide
@ -494,18 +533,19 @@ class PlayerEventHandler implements Listener
Block block = bucketEvent.getBlockClicked().getRelative(bucketEvent.getBlockFace());
int minLavaDistance = 10;
//make sure the player is allowed to build at the location
String noBuildReason = GriefPrevention.instance.allowBuild(player, block.getLocation());
if(noBuildReason != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
bucketEvent.setCancelled(true);
return;
}
//if the bucket is being used in a claim
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, null);
if(claim != null)
{
//the player must have build permission to use it
if(claim.allowBuild(player) != null)
{
bucketEvent.setCancelled(true);
GriefPrevention.sendMessage(player, TextMode.Err, "You don't have " + claim.getOwnerName() + "'s permission to use your bucket here.");
return;
}
//the claim must be at least an hour old
long now = Calendar.getInstance().getTimeInMillis();
long lastModified = claim.modifiedDate.getTime();
@ -526,6 +566,7 @@ class PlayerEventHandler implements Listener
{
GriefPrevention.sendMessage(player, TextMode.Err, "You may only dump lava inside your claim(s) or underground.");
bucketEvent.setCancelled(true);
return;
}
}
@ -557,15 +598,14 @@ class PlayerEventHandler implements Listener
Player player = bucketEvent.getPlayer();
Block block = bucketEvent.getBlockClicked();
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, null);
if(claim != null)
//make sure the player is allowed to build at the location
String noBuildReason = GriefPrevention.instance.allowBuild(player, block.getLocation());
if(noBuildReason != null)
{
if(claim.allowBuild(player) != null)
{
bucketEvent.setCancelled(true);
GriefPrevention.sendMessage(player, TextMode.Err, "You don't have permission to use your bucket here.");
}
}
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
bucketEvent.setCancelled(true);
return;
}
}
//when a player interacts with the world
@ -681,14 +721,39 @@ class PlayerEventHandler implements Listener
//if it's bonemeal, check for build permission (ink sac == bone meal, must be a Bukkit bug?)
if(materialInHand == Material.INK_SACK)
{
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
String noBuildReason = GriefPrevention.instance.allowBuild(player, clickedBlock.getLocation());
if(noBuildReason != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
event.setCancelled(true);
}
return;
}
//if it's a spawn egg or minecart and this is a creative world, apply special rules
else if((materialInHand == Material.MONSTER_EGG || materialInHand == Material.MINECART || materialInHand == Material.POWERED_MINECART || materialInHand == Material.STORAGE_MINECART) && GriefPrevention.instance.creativeRulesApply(clickedBlock.getLocation()))
{
//player needs build permission at this location
String noBuildReason = GriefPrevention.instance.allowBuild(player, clickedBlock.getLocation());
if(noBuildReason != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
event.setCancelled(true);
return;
}
//enforce limit on total number of entities in this claim
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
if(claim == null) return;
String noBuildReason = claim.allowBuild(player);
if(claim != null && noBuildReason != null)
String noEntitiesReason = claim.allowMoreEntities();
if(noEntitiesReason != null)
{
player.sendMessage(noBuildReason);
event.setCancelled(true);
GriefPrevention.sendMessage(player, TextMode.Err, noEntitiesReason);
event.setCancelled(true);
return;
}
return;
@ -885,7 +950,7 @@ class PlayerEventHandler implements Listener
{
int newArea = newWidth * newHeight;
int blocksRemainingAfter = playerData.getRemainingClaimBlocks() + playerData.claimResizing.getArea() - newArea;
if(blocksRemainingAfter < 0)
{
GriefPrevention.sendMessage(player, TextMode.Err, "You don't have enough blocks for this size. You need " + Math.abs(blocksRemainingAfter) + " more.");
@ -894,7 +959,28 @@ class PlayerEventHandler implements Listener
}
}
//ask the datastore to try and resize the claim
//in creative mode, top-level claims can't be moved or resized smaller.
//to check this, verifying the old claim's corners are inside the new claim's boundaries.
if(!player.hasPermission("griefprevention.deleteclaims") && GriefPrevention.instance.creativeRulesApply(player.getLocation()) && playerData.claimResizing.parent == null)
{
Claim oldClaim = playerData.claimResizing;
//temporary claim instance, just for checking contains()
Claim newClaim = new Claim(
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx1, newy1, newz1),
new Location(oldClaim.getLesserBoundaryCorner().getWorld(), newx2, newy2, newz2),
"", new String[]{}, new String[]{}, new String[]{}, new String[]{});
//both greater and lesser boundary corners of the old claim must be inside the new claim
if(!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
{
//otherwise, show an error message and stop here
GriefPrevention.sendMessage(player, TextMode.Err, "You can't un-claim creative mode land. You can only make this claim larger or create additional claims.");
return;
}
}
//ask the datastore to try and resize the claim, this checks for conflicts with other claims
CreateClaimResult result = GriefPrevention.instance.dataStore.resizeClaim(playerData.claimResizing, newx1, newx2, newy1, newy2, newz1, newz2);
if(result.succeeded)