3.8
This commit is contained in:
parent
136bf91c8a
commit
540746ad4b
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user