4.9
This commit is contained in:
parent
2e39b36f1b
commit
beec9c4e50
|
|
@ -1,7 +1,7 @@
|
|||
name: GriefPrevention
|
||||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||
softdepend: [Vault, Multiverse-Core]
|
||||
version: 4.7
|
||||
version: 4.9
|
||||
commands:
|
||||
abandonclaim:
|
||||
description: Deletes a claim.
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class BlockEventHandler implements Listener
|
|||
if(!GriefPrevention.instance.config_addItemsToClaimedChests) return;
|
||||
|
||||
Block block = event.getBlock();
|
||||
Player player = event.getPlayer();
|
||||
Player player = event.getPlayer();
|
||||
|
||||
//only care about player-damaged blocks
|
||||
if(player == null) return;
|
||||
|
|
@ -200,9 +200,7 @@ public class BlockEventHandler implements Listener
|
|||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
if(notEmpty && playerData.lastMessage != null && !playerData.lastMessage.equals(signMessage))
|
||||
{
|
||||
GriefPrevention.AddLogEntry("[Sign Placement] <" + player.getName() + "> " + lines.toString());
|
||||
GriefPrevention.AddLogEntry("Location: " + GriefPrevention.getfriendlyLocationString(event.getBlock().getLocation()));
|
||||
|
||||
GriefPrevention.AddLogEntry("[Sign Placement] <" + player.getName() + "> " + lines.toString() + " @ " + GriefPrevention.getfriendlyLocationString(event.getBlock().getLocation()));
|
||||
playerData.lastMessage = signMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -275,7 +273,7 @@ public class BlockEventHandler implements Listener
|
|||
//radius == 0 means protect ONLY the chest
|
||||
if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius == 0)
|
||||
{
|
||||
this.dataStore.createClaim(block.getWorld(), block.getX(), block.getX(), block.getY(), block.getY(), block.getZ(), block.getZ(), player.getName(), null);
|
||||
this.dataStore.createClaim(block.getWorld(), block.getX(), block.getX(), block.getY(), block.getY(), block.getZ(), block.getZ(), player.getName(), null, null);
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.ChestClaimConfirmation);
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +287,7 @@ public class BlockEventHandler implements Listener
|
|||
block.getY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance, block.getY(),
|
||||
block.getZ() - radius, block.getZ() + radius,
|
||||
player.getName(),
|
||||
null).succeeded)
|
||||
null, null).succeeded)
|
||||
{
|
||||
radius--;
|
||||
}
|
||||
|
|
@ -339,13 +337,17 @@ public class BlockEventHandler implements Listener
|
|||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onBlockPistonExtend (BlockPistonExtendEvent event)
|
||||
{
|
||||
List<Block> blocks = event.getBlocks();
|
||||
|
||||
//if no blocks moving, then we don't care
|
||||
if(blocks.size() == 0) return;
|
||||
|
||||
//who owns the piston, if anyone?
|
||||
String pistonClaimOwnerName = "_";
|
||||
Claim claim = this.dataStore.getClaimAt(event.getBlock().getLocation(), false, null);
|
||||
if(claim != null) pistonClaimOwnerName = claim.getOwnerName();
|
||||
|
||||
//which blocks are being pushed?
|
||||
List<Block> blocks = event.getBlocks();
|
||||
for(int i = 0; i < blocks.size(); i++)
|
||||
{
|
||||
//if ANY of the pushed blocks are owned by someone other than the piston owner, cancel the event
|
||||
|
|
@ -354,9 +356,69 @@ public class BlockEventHandler implements Listener
|
|||
if(claim != null && !claim.getOwnerName().equals(pistonClaimOwnerName))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
event.getBlock().getWorld().createExplosion(event.getBlock().getLocation(), 0);
|
||||
event.getBlock().getWorld().dropItem(event.getBlock().getLocation(), new ItemStack(event.getBlock().getType()));
|
||||
event.getBlock().setType(Material.AIR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//which direction? note we're ignoring vertical push
|
||||
int xchange = 0;
|
||||
int zchange = 0;
|
||||
|
||||
Block piston = event.getBlock();
|
||||
Block firstBlock = blocks.get(0);
|
||||
|
||||
if(firstBlock.getX() > piston.getX())
|
||||
{
|
||||
xchange = 1;
|
||||
}
|
||||
else if(firstBlock.getX() < piston.getX())
|
||||
{
|
||||
xchange = -1;
|
||||
}
|
||||
else if(firstBlock.getZ() > piston.getZ())
|
||||
{
|
||||
zchange = 1;
|
||||
}
|
||||
else if(firstBlock.getZ() < piston.getZ())
|
||||
{
|
||||
zchange = -1;
|
||||
}
|
||||
|
||||
//if horizontal movement
|
||||
if(xchange != 0 || zchange != 0)
|
||||
{
|
||||
for(int i = 0; i < blocks.size(); i++)
|
||||
{
|
||||
Block block = blocks.get(i);
|
||||
Claim originalClaim = this.dataStore.getClaimAt(block.getLocation(), false, null);
|
||||
String originalOwnerName = "";
|
||||
if(originalClaim != null)
|
||||
{
|
||||
originalOwnerName = originalClaim.getOwnerName();
|
||||
}
|
||||
|
||||
Claim newClaim = this.dataStore.getClaimAt(block.getLocation().add(xchange, 0, zchange), false, null);
|
||||
String newOwnerName = "";
|
||||
if(newClaim != null)
|
||||
{
|
||||
newOwnerName = newClaim.getOwnerName();
|
||||
}
|
||||
|
||||
//if pushing this block will change ownership, cancel the event and take away the piston (for performance reasons)
|
||||
if(!newOwnerName.equals(originalOwnerName))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
event.getBlock().getWorld().createExplosion(event.getBlock().getLocation(), 0);
|
||||
event.getBlock().getWorld().dropItem(event.getBlock().getLocation(), new ItemStack(event.getBlock().getType()));
|
||||
event.getBlock().setType(Material.AIR);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//blocks theft by pulling blocks out of a claim (again pistons)
|
||||
|
|
@ -469,11 +531,13 @@ public class BlockEventHandler implements Listener
|
|||
Location rootLocation = growEvent.getLocation();
|
||||
Claim rootClaim = this.dataStore.getClaimAt(rootLocation, false, null);
|
||||
|
||||
//who owns the root, if anyone?
|
||||
//who owns the spreading block, if anyone?
|
||||
OfflinePlayer fromOwner = null;
|
||||
if(rootClaim != null)
|
||||
{
|
||||
//tree growth in subdivisions is dependent on who owns the top level claim
|
||||
if(rootClaim.parent != null) rootClaim = rootClaim.parent;
|
||||
|
||||
//if an administrative claim, just let the tree grow where it wants
|
||||
if(rootClaim.isAdminClaim()) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ public class Claim
|
|||
//modification date. this comes from the file timestamp during load, and is updated with runtime changes
|
||||
public Date modifiedDate;
|
||||
|
||||
//id number. unique to this claim, never changes.
|
||||
Long id = null;
|
||||
|
||||
//ownername. for admin claims, this is the empty string
|
||||
//use getOwnerName() to get a friendly name (will be "an administrator" for admin claims)
|
||||
public String ownerName;
|
||||
|
|
@ -83,6 +86,12 @@ public class Claim
|
|||
return this.ownerName.isEmpty();
|
||||
}
|
||||
|
||||
//accessor for ID
|
||||
public Long getID()
|
||||
{
|
||||
return new Long(this.id);
|
||||
}
|
||||
|
||||
//basic constructor, just notes the creation time
|
||||
//see above declarations for other defaults
|
||||
Claim()
|
||||
|
|
@ -178,11 +187,14 @@ public class Claim
|
|||
}
|
||||
|
||||
//main constructor. note that only creating a claim instance does nothing - a claim must be added to the data store to be effective
|
||||
Claim(Location lesserBoundaryCorner, Location greaterBoundaryCorner, String ownerName, String [] builderNames, String [] containerNames, String [] accessorNames, String [] managerNames)
|
||||
Claim(Location lesserBoundaryCorner, Location greaterBoundaryCorner, String ownerName, String [] builderNames, String [] containerNames, String [] accessorNames, String [] managerNames, Long id)
|
||||
{
|
||||
//modification date
|
||||
this.modifiedDate = Calendar.getInstance().getTime();
|
||||
|
||||
//id
|
||||
this.id = id;
|
||||
|
||||
//store corners
|
||||
this.lesserBoundaryCorner = lesserBoundaryCorner;
|
||||
this.greaterBoundaryCorner = greaterBoundaryCorner;
|
||||
|
|
@ -253,7 +265,7 @@ public class Claim
|
|||
Claim claim = new Claim
|
||||
(new Location(this.lesserBoundaryCorner.getWorld(), this.lesserBoundaryCorner.getBlockX() - howNear, this.lesserBoundaryCorner.getBlockY(), this.lesserBoundaryCorner.getBlockZ() - howNear),
|
||||
new Location(this.greaterBoundaryCorner.getWorld(), this.greaterBoundaryCorner.getBlockX() + howNear, this.greaterBoundaryCorner.getBlockY(), this.greaterBoundaryCorner.getBlockZ() + howNear),
|
||||
"", new String[] {}, new String[] {}, new String[] {}, new String[] {});
|
||||
"", new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
||||
|
||||
return claim.contains(location, false, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,12 +45,16 @@ public class DataStore
|
|||
//in-memory cache for messages
|
||||
private String [] messages;
|
||||
|
||||
//next claim ID
|
||||
Long nextClaimID = (long)0;
|
||||
|
||||
//path information, for where stuff stored on disk is well... stored
|
||||
private final static String dataLayerFolderPath = "plugins" + File.separator + "GriefPreventionData";
|
||||
private final static String playerDataFolderPath = dataLayerFolderPath + File.separator + "PlayerData";
|
||||
private final static String claimDataFolderPath = dataLayerFolderPath + File.separator + "ClaimData";
|
||||
final static String configFilePath = dataLayerFolderPath + File.separator + "config.yml";
|
||||
final static String messagesFilePath = dataLayerFolderPath + File.separator + "messages.yml";
|
||||
final static String nextClaimIdFilePath = claimDataFolderPath + File.separator + "_nextClaimID";
|
||||
|
||||
//initialization!
|
||||
DataStore()
|
||||
|
|
@ -97,6 +101,32 @@ public class DataStore
|
|||
|
||||
//load claims data into memory
|
||||
File claimDataFolder = new File(claimDataFolderPath);
|
||||
|
||||
//load next claim number from file
|
||||
File nextClaimIdFile = new File(nextClaimIdFilePath);
|
||||
if(nextClaimIdFile.exists())
|
||||
{
|
||||
BufferedReader inStream = null;
|
||||
try
|
||||
{
|
||||
inStream = new BufferedReader(new FileReader(nextClaimIdFile.getAbsolutePath()));
|
||||
|
||||
//read the id
|
||||
String line = inStream.readLine();
|
||||
|
||||
//try to parse into a long value
|
||||
this.nextClaimID = Long.parseLong(line);
|
||||
}
|
||||
catch(Exception e){ }
|
||||
|
||||
try
|
||||
{
|
||||
if(inStream != null) inStream.close();
|
||||
}
|
||||
catch(IOException exception) {}
|
||||
}
|
||||
|
||||
//get a list of all the files in the claims data folder
|
||||
files = claimDataFolder.listFiles();
|
||||
|
||||
int loadedClaimCount = 0;
|
||||
|
|
@ -105,6 +135,28 @@ public class DataStore
|
|||
{
|
||||
if(files[i].isFile()) //avoids folders
|
||||
{
|
||||
//skip any file starting with an underscore, to avoid the _nextClaimID file.
|
||||
if(files[i].getName().startsWith("_")) continue;
|
||||
|
||||
//the filename is the claim ID. try to parse it
|
||||
long claimID;
|
||||
|
||||
try
|
||||
{
|
||||
claimID = Long.parseLong(files[i].getName());
|
||||
}
|
||||
|
||||
//because some older versions used a different file name pattern before claim IDs were introduced,
|
||||
//those files need to be "converted" by renaming them to a unique ID
|
||||
catch(Exception e)
|
||||
{
|
||||
claimID = this.nextClaimID;
|
||||
this.incrementNextClaimID();
|
||||
File newFile = new File(claimDataFolderPath + File.separator + String.valueOf(this.nextClaimID));
|
||||
files[i].renameTo(newFile);
|
||||
files[i] = newFile;
|
||||
}
|
||||
|
||||
BufferedReader inStream = null;
|
||||
try
|
||||
{
|
||||
|
|
@ -153,7 +205,7 @@ public class DataStore
|
|||
if(topLevelClaim == null)
|
||||
{
|
||||
//instantiate
|
||||
topLevelClaim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerName, builderNames, containerNames, accessorNames, managerNames);
|
||||
topLevelClaim = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, ownerName, builderNames, containerNames, accessorNames, managerNames, claimID);
|
||||
|
||||
//search for another claim overlapping this one
|
||||
Claim conflictClaim = this.getClaimAt(topLevelClaim.lesserBoundaryCorner, true, null);
|
||||
|
|
@ -184,7 +236,7 @@ public class DataStore
|
|||
//otherwise there's already a top level claim, so this must be a subdivision of that top level claim
|
||||
else
|
||||
{
|
||||
Claim subdivision = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, "--subdivision--", builderNames, containerNames, accessorNames, managerNames);
|
||||
Claim subdivision = new Claim(lesserBoundaryCorner, greaterBoundaryCorner, "--subdivision--", builderNames, containerNames, accessorNames, managerNames, null);
|
||||
|
||||
//make sure there are no other subdivisions overlapping this one
|
||||
|
||||
|
|
@ -487,7 +539,13 @@ public class DataStore
|
|||
}
|
||||
|
||||
//otherwise get a unique identifier for the claim which will be used to name the file on disk
|
||||
String claimID = this.getClaimID(claim);
|
||||
if(claim.id == null)
|
||||
{
|
||||
claim.id = this.nextClaimID;
|
||||
this.incrementNextClaimID();
|
||||
}
|
||||
|
||||
String claimID = String.valueOf(claim.id);
|
||||
|
||||
BufferedWriter outStream = null;
|
||||
|
||||
|
|
@ -521,13 +579,41 @@ public class DataStore
|
|||
catch(IOException exception) {}
|
||||
}
|
||||
|
||||
private void incrementNextClaimID()
|
||||
{
|
||||
this.nextClaimID++;
|
||||
|
||||
BufferedWriter outStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
//open the claim's file
|
||||
File nextClaimIdFile = new File(nextClaimIdFilePath);
|
||||
nextClaimIdFile.createNewFile();
|
||||
outStream = new BufferedWriter(new FileWriter(nextClaimIdFile));
|
||||
|
||||
outStream.write(String.valueOf(this.nextClaimID));
|
||||
}
|
||||
|
||||
//if any problem, log it
|
||||
catch(Exception e)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("Unexpected exception saving next claim ID: " + e.getMessage());
|
||||
}
|
||||
|
||||
//close the file
|
||||
try
|
||||
{
|
||||
if(outStream != null) outStream.close();
|
||||
}
|
||||
catch(IOException exception) {}
|
||||
}
|
||||
|
||||
//actually writes claim data to an output stream
|
||||
private void writeClaimData(Claim claim, BufferedWriter outStream) throws IOException
|
||||
{
|
||||
String claimID = this.getClaimID(claim);
|
||||
|
||||
//first line is lesser boundary corner location
|
||||
outStream.write(claimID);
|
||||
outStream.write(this.locationToString(claim.getLesserBoundaryCorner()));
|
||||
outStream.newLine();
|
||||
|
||||
//second line is greater boundary corner location
|
||||
|
|
@ -721,12 +807,12 @@ public class DataStore
|
|||
}
|
||||
|
||||
//otherwise, need to update the data store and ensure the claim's file is deleted
|
||||
String claimID = this.getClaimID(claim);
|
||||
String claimID = String.valueOf(claim.id);
|
||||
|
||||
//remove from memory
|
||||
for(int i = 0; i < this.claims.size(); i++)
|
||||
{
|
||||
if(this.getClaimID(this.claims.get(i)).equals(claimID))
|
||||
if(claims.get(i).id.equals(claim.id))
|
||||
{
|
||||
this.claims.remove(i);
|
||||
claim.inDataStore = false;
|
||||
|
|
@ -751,7 +837,7 @@ public class DataStore
|
|||
PlayerData ownerData = this.getPlayerData(claim.getOwnerName());
|
||||
for(int i = 0; i < ownerData.claims.size(); i++)
|
||||
{
|
||||
if(this.getClaimID(ownerData.claims.get(i)).equals(claimID))
|
||||
if(ownerData.claims.get(i).id.equals(claim.id))
|
||||
{
|
||||
ownerData.claims.remove(i);
|
||||
break;
|
||||
|
|
@ -811,7 +897,7 @@ public class DataStore
|
|||
//does NOT check a player has permission to create a claim, or enough claim blocks.
|
||||
//does NOT check minimum claim size constraints
|
||||
//does NOT visualize the new claim for any players
|
||||
public CreateClaimResult createClaim(World world, int x1, int x2, int y1, int y2, int z1, int z2, String ownerName, Claim parent)
|
||||
public CreateClaimResult createClaim(World world, int x1, int x2, int y1, int y2, int z1, int z2, String ownerName, Claim parent, Long id)
|
||||
{
|
||||
CreateClaimResult result = new CreateClaimResult();
|
||||
|
||||
|
|
@ -865,7 +951,8 @@ public class DataStore
|
|||
new String [] {},
|
||||
new String [] {},
|
||||
new String [] {},
|
||||
new String [] {});
|
||||
new String [] {},
|
||||
id);
|
||||
|
||||
newClaim.parent = parent;
|
||||
|
||||
|
|
@ -960,12 +1047,6 @@ public class DataStore
|
|||
catch(IOException exception){}
|
||||
}
|
||||
|
||||
//gets a unique identifier for a claim
|
||||
private String getClaimID(Claim claim)
|
||||
{
|
||||
return this.locationToString(claim.getLesserBoundaryCorner());
|
||||
}
|
||||
|
||||
//extends a claim to a new depth
|
||||
//respects the max depth config variable
|
||||
public void extendClaim(Claim claim, int newDepth)
|
||||
|
|
@ -1216,7 +1297,7 @@ public class DataStore
|
|||
this.deleteClaim(claim);
|
||||
|
||||
//try to create this new claim, ignoring the original when checking for overlap
|
||||
CreateClaimResult result = this.createClaim(claim.getLesserBoundaryCorner().getWorld(), newx1, newx2, newy1, newy2, newz1, newz2, claim.ownerName, claim.parent);
|
||||
CreateClaimResult result = this.createClaim(claim.getLesserBoundaryCorner().getWorld(), newx1, newx2, newy1, newy2, newz1, newz2, claim.ownerName, claim.parent, claim.id);
|
||||
|
||||
//if succeeded
|
||||
if(result.succeeded)
|
||||
|
|
@ -1418,7 +1499,7 @@ public class DataStore
|
|||
this.addDefault(defaults, Messages.AdjustGroupBlocksSuccess, "Adjusted bonus claim blocks for players with the {0} permission by {1}. New total: {2}.", "0: permission; 1: adjustment amount; 2: new total bonus");
|
||||
this.addDefault(defaults, Messages.InvalidPermissionID, "Please specify a player name, or a permission in [brackets].", null);
|
||||
this.addDefault(defaults, Messages.UntrustOwnerOnly, "Only {0} can revoke permissions here.", "0: claim owner's name");
|
||||
this.addDefault(defaults, Messages.HowToClaimRegex, "(^|.*\\W)how\\W.*\\Wclaim(\\W.*|$)", "This is a Java Regular Expression. Look it up before editing! It's used to tell players about the demo video when they ask how to claim land.");
|
||||
this.addDefault(defaults, Messages.HowToClaimRegex, "(^|.*\\W)how\\W.*\\W(claim|protect)(\\W.*|$)", "This is a Java Regular Expression. Look it up before editing! It's used to tell players about the demo video when they ask how to claim land.");
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ import org.bukkit.entity.Arrow;
|
|||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.Enderman;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
|
@ -45,11 +45,13 @@ 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.EntityInteractEvent;
|
||||
import org.bukkit.event.entity.ExpBottleEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.event.painting.PaintingBreakByEntityEvent;
|
||||
import org.bukkit.event.painting.PaintingBreakEvent;
|
||||
import org.bukkit.event.painting.PaintingPlaceEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDamageEvent;
|
||||
|
||||
//handles events related to entities
|
||||
class EntityEventHandler implements Listener
|
||||
|
|
@ -62,6 +64,26 @@ class EntityEventHandler implements Listener
|
|||
this.dataStore = dataStore;
|
||||
}
|
||||
|
||||
//don't allow endermen to change blocks
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityChangeBLock(EntityChangeBlockEvent event)
|
||||
{
|
||||
if(!GriefPrevention.instance.config_endermenMoveBlocks && event.getEntityType() == EntityType.ENDERMAN)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
//don't allow entities to trample crops
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityInteract(EntityInteractEvent event)
|
||||
{
|
||||
if(!GriefPrevention.instance.config_creaturesTrampleCrops && event.getBlock().getType() == Material.SOIL)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
//when an entity explodes...
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityExplode(EntityExplodeEvent explodeEvent)
|
||||
|
|
@ -147,10 +169,10 @@ class EntityEventHandler implements Listener
|
|||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, just apply the limit on total entities per claim
|
||||
|
||||
//otherwise, just apply the limit on total entities per claim (and no spawning in the wilderness!)
|
||||
Claim claim = this.dataStore.getClaimAt(event.getLocation(), false, null);
|
||||
if(claim != null && claim.allowMoreEntities() != null)
|
||||
if(claim == null || claim.allowMoreEntities() != null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
|
@ -363,8 +385,7 @@ class EntityEventHandler implements Listener
|
|||
if(event instanceof EntityDamageByEntityEvent)
|
||||
{
|
||||
//if the entity is an non-monster creature (remember monsters disqualified above), or a vehicle
|
||||
if ((subEvent.getEntity() instanceof Creature && GriefPrevention.instance.config_claims_protectCreatures) ||
|
||||
(subEvent.getEntity() instanceof Vehicle && GriefPrevention.instance.config_claims_preventTheft))
|
||||
if ((subEvent.getEntity() instanceof Creature && GriefPrevention.instance.config_claims_protectCreatures))
|
||||
{
|
||||
Claim cachedClaim = null;
|
||||
PlayerData playerData = null;
|
||||
|
|
@ -405,4 +426,75 @@ class EntityEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//when a vehicle is damaged
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onVehicleDamage (VehicleDamageEvent event)
|
||||
{
|
||||
//all of this is anti theft code
|
||||
if(!GriefPrevention.instance.config_claims_preventTheft) return;
|
||||
|
||||
//determine which player is attacking, if any
|
||||
Player attacker = null;
|
||||
Entity damageSource = event.getAttacker();
|
||||
if(damageSource instanceof Player)
|
||||
{
|
||||
attacker = (Player)damageSource;
|
||||
}
|
||||
else if(damageSource instanceof Arrow)
|
||||
{
|
||||
Arrow arrow = (Arrow)damageSource;
|
||||
if(arrow.getShooter() instanceof Player)
|
||||
{
|
||||
attacker = (Player)arrow.getShooter();
|
||||
}
|
||||
}
|
||||
else if(damageSource instanceof ThrownPotion)
|
||||
{
|
||||
ThrownPotion potion = (ThrownPotion)damageSource;
|
||||
if(potion.getShooter() instanceof Player)
|
||||
{
|
||||
attacker = (Player)potion.getShooter();
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: vehicles can be pushed around.
|
||||
//so unless precautions are taken by the owner, a resourceful thief might find ways to steal anyway
|
||||
Claim cachedClaim = null;
|
||||
PlayerData playerData = null;
|
||||
if(attacker != null)
|
||||
{
|
||||
playerData = this.dataStore.getPlayerData(attacker.getName());
|
||||
cachedClaim = playerData.lastClaim;
|
||||
}
|
||||
|
||||
Claim claim = this.dataStore.getClaimAt(event.getVehicle().getLocation(), false, cachedClaim);
|
||||
|
||||
//if it's claimed
|
||||
if(claim != null)
|
||||
{
|
||||
//if damaged by anything other than a player, cancel the event
|
||||
if(attacker == null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
//otherwise the player damaging the entity must have permission
|
||||
else
|
||||
{
|
||||
String noContainersReason = claim.allowContainers(attacker);
|
||||
if(noContainersReason != null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
GriefPrevention.sendMessage(attacker, TextMode.Err, Messages.NoDamageClaimedEntity, claim.getOwnerName());
|
||||
}
|
||||
|
||||
//cache claim for later
|
||||
if(playerData != null)
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
public int config_claims_trappedCooldownHours; //number of hours between uses of the /trapped command
|
||||
|
||||
public Material config_claims_investigationTool; //which material will be used to investigate claims with a right click
|
||||
|
||||
public ArrayList<World> config_siege_enabledWorlds; //whether or not /siege is enabled on this server
|
||||
public ArrayList<Material> config_siege_blocks; //which blocks will be breakable in siege mode
|
||||
|
||||
|
|
@ -114,6 +116,9 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
public boolean config_smartBan; //whether to ban accounts which very likely owned by a banned player
|
||||
|
||||
public boolean config_endermenMoveBlocks; //whether or not endermen may move blocks around
|
||||
public boolean config_creaturesTrampleCrops; //whether or not non-player entities may trample crops
|
||||
|
||||
//reference to the economy plugin, if economy integration is enabled
|
||||
public static Economy economy = null;
|
||||
|
||||
|
|
@ -252,6 +257,23 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
this.config_smartBan = config.getBoolean("GriefPrevention.SmartBan", true);
|
||||
|
||||
this.config_endermenMoveBlocks = config.getBoolean("GriefPrevention.EndermenMoveBlocks", false);
|
||||
this.config_creaturesTrampleCrops = config.getBoolean("GriefPrevention.CreaturesTrampleCrops", false);
|
||||
|
||||
//default for claim investigation tool
|
||||
String investigationToolMaterialName = Material.STICK.name();
|
||||
|
||||
//get investigation tool from config
|
||||
investigationToolMaterialName = config.getString("GriefPrevention.Claims.InvestigationTool", investigationToolMaterialName);
|
||||
|
||||
//validate investigation tool
|
||||
this.config_claims_investigationTool = Material.getMaterial(investigationToolMaterialName);
|
||||
if(this.config_claims_investigationTool == null)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("ERROR: Material " + investigationToolMaterialName + " not found. Defaulting to the stick. Please update your config.yml.");
|
||||
this.config_claims_investigationTool = Material.STICK;
|
||||
}
|
||||
|
||||
//default for siege worlds list
|
||||
ArrayList<String> defaultSiegeWorldNames = new ArrayList<String>();
|
||||
|
||||
|
|
@ -339,6 +361,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Claims.MaximumDepth", this.config_claims_maxDepth);
|
||||
config.set("GriefPrevention.Claims.IdleLimitDays", this.config_claims_expirationDays);
|
||||
config.set("GriefPrevention.Claims.TrappedCommandCooldownHours", this.config_claims_trappedCooldownHours);
|
||||
config.set("GriefPrevention.Claims.InvestigationTool", this.config_claims_investigationTool.name());
|
||||
|
||||
config.set("GriefPrevention.Spam.Enabled", this.config_spam_enabled);
|
||||
config.set("GriefPrevention.Spam.LoginCooldownMinutes", this.config_spam_loginCooldownMinutes);
|
||||
|
|
@ -367,13 +390,16 @@ 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.EavesdropEnabled", this.config_eavesdrop);
|
||||
config.set("GriefPrevention.SmartBan", this.config_smartBan);
|
||||
|
||||
config.set("GriefPrevention.Siege.Worlds", siegeEnabledWorldNames);
|
||||
config.set("GriefPrevention.Siege.BreakableBlocks", breakableBlocksList);
|
||||
|
||||
|
||||
config.set("GriefPrevention.EndermenMoveBlocks", this.config_endermenMoveBlocks);
|
||||
config.set("GriefPrevention.CreaturesTrampleCrops", this.config_creaturesTrampleCrops);
|
||||
|
||||
try
|
||||
{
|
||||
config.save(DataStore.configFilePath);
|
||||
|
|
@ -1655,6 +1681,9 @@ public class GriefPrevention extends JavaPlugin
|
|||
//if pvp is disabled, do nothing
|
||||
if(!player.getWorld().getPVP()) return;
|
||||
|
||||
//if player is in creative mode, do nothing
|
||||
if(player.getGameMode() == GameMode.CREATIVE) return;
|
||||
|
||||
//if anti spawn camping feature is not enabled, do nothing
|
||||
if(!this.config_pvp_protectFreshSpawns) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class PlayerData
|
|||
//spam
|
||||
public Date lastLogin; //when the player last logged into the server
|
||||
public String lastMessage = ""; //the player's last chat message, or slash command complete with parameters
|
||||
public Date lastMessageTimestamp = new Date(); //last time the player sent a chat message or used a monitored slash command
|
||||
public Date lastMessageTimestamp = new Date(); //last time the player sent a chat message or used a monitored slash command
|
||||
public int spamCount = 0; //number of consecutive "spams"
|
||||
public boolean spamWarned = false; //whether the player recently received a warning
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,14 @@ class PlayerEventHandler implements Listener
|
|||
boolean spam = false;
|
||||
boolean muted = false;
|
||||
|
||||
//single-character messages will not be sent
|
||||
if(message.length() == 1)
|
||||
{
|
||||
playerData.spamCount++;
|
||||
spam = true;
|
||||
muted = true;
|
||||
}
|
||||
|
||||
//check message content and timing
|
||||
long millisecondsSinceLastMessage = (new Date()).getTime() - playerData.lastMessageTimestamp.getTime();
|
||||
|
||||
|
|
@ -137,8 +145,8 @@ class PlayerEventHandler implements Listener
|
|||
spam = true;
|
||||
}
|
||||
|
||||
//if it's very similar to the last message
|
||||
if(!muted && this.stringsAreSimilar(message, playerData.lastMessage))
|
||||
//if it's very similar to the last message and less than 10 seconds have passed
|
||||
if(!muted && this.stringsAreSimilar(message, playerData.lastMessage) && millisecondsSinceLastMessage < 10000)
|
||||
{
|
||||
playerData.spamCount++;
|
||||
spam = true;
|
||||
|
|
@ -148,7 +156,7 @@ class PlayerEventHandler implements Listener
|
|||
//filter IP addresses
|
||||
if(!muted && !(event instanceof PlayerCommandPreprocessEvent))
|
||||
{
|
||||
Pattern ipAddressPattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
||||
Pattern ipAddressPattern = Pattern.compile("\\d{1,4}\\D{1,3}\\d{1,4}\\D{1,3}\\d{1,4}\\D{1,3}\\d{1,4}");
|
||||
Matcher matcher = ipAddressPattern.matcher(event.getMessage());
|
||||
|
||||
//if it looks like an IP address
|
||||
|
|
@ -515,6 +523,9 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
if(player.getHealth() > 0) player.setHealth(0); //might already be zero from above, this avoids a double death message
|
||||
}
|
||||
|
||||
//drop data about this player
|
||||
this.dataStore.clearCachedPlayerData(player.getName());
|
||||
}
|
||||
|
||||
//determines whether or not a login or logout notification should be silenced, depending on how many there have been in the last minute
|
||||
|
|
@ -993,8 +1004,8 @@ class PlayerEventHandler implements Listener
|
|||
return;
|
||||
}
|
||||
|
||||
//if it's stick or arrow, he's investigating a claim
|
||||
else if(materialInHand == Material.STICK)
|
||||
//if he's investigating a claim
|
||||
else if(materialInHand == GriefPrevention.instance.config_claims_investigationTool)
|
||||
{
|
||||
//air indicates too far away
|
||||
if(clickedBlockType == Material.AIR)
|
||||
|
|
@ -1316,7 +1327,7 @@ class PlayerEventHandler implements Listener
|
|||
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[]{});
|
||||
"", new String[]{}, new String[]{}, new String[]{}, new String[]{}, null);
|
||||
|
||||
//if the new claim is smaller
|
||||
if(!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
|
||||
|
|
@ -1423,7 +1434,8 @@ class PlayerEventHandler implements Listener
|
|||
playerData.lastShovelLocation.getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance, clickedBlock.getY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance,
|
||||
playerData.lastShovelLocation.getBlockZ(), clickedBlock.getZ(),
|
||||
"--subdivision--", //owner name is not used for subdivisions
|
||||
playerData.claimSubdividing);
|
||||
playerData.claimSubdividing,
|
||||
null);
|
||||
|
||||
//if it didn't succeed, tell the player why
|
||||
if(!result.succeeded)
|
||||
|
|
@ -1532,7 +1544,7 @@ class PlayerEventHandler implements Listener
|
|||
lastShovelLocation.getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance, clickedBlock.getY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance,
|
||||
lastShovelLocation.getBlockZ(), clickedBlock.getZ(),
|
||||
playerName,
|
||||
null);
|
||||
null, null);
|
||||
|
||||
//if it didn't succeed, tell the player why
|
||||
if(!result.succeeded)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class RestoreNatureExecutionTask implements Runnable
|
|||
}
|
||||
|
||||
//show visualization to player
|
||||
Claim claim = new Claim(lesserCorner, greaterCorner, "", new String[] {}, new String[] {}, new String[] {}, new String[] {});
|
||||
Claim claim = new Claim(lesserCorner, greaterCorner, "", new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
||||
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature);
|
||||
Visualization.Apply(player, visualization);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user