5.9
This commit is contained in:
parent
50f572fc2b
commit
452fd7f11a
|
|
@ -1,7 +1,8 @@
|
|||
name: GriefPrevention
|
||||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||
softdepend: [Vault, Multiverse-Core, My Worlds]
|
||||
version: 5.5
|
||||
dev-url: http://dev.bukkit.org/server-mods/grief-prevention
|
||||
version: 5.9
|
||||
commands:
|
||||
abandonclaim:
|
||||
description: Deletes a claim.
|
||||
|
|
@ -124,7 +125,7 @@ commands:
|
|||
claimslist:
|
||||
description: Lists information about a player's claim blocks and claims.
|
||||
usage: /ClaimsList <player>
|
||||
permission: griefprevention.adjustbonusclaimblocks
|
||||
permission: griefprevention.adjustclaimblocks
|
||||
permissions:
|
||||
griefprevention.createclaims:
|
||||
description: Grants permission to create claims.
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
|
|
@ -35,6 +36,7 @@ import org.bukkit.event.Listener;
|
|||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockBurnEvent;
|
||||
import org.bukkit.event.block.BlockDamageEvent;
|
||||
import org.bukkit.event.block.BlockDispenseEvent;
|
||||
import org.bukkit.event.block.BlockFromToEvent;
|
||||
import org.bukkit.event.block.BlockIgniteEvent;
|
||||
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
|
||||
|
|
@ -47,6 +49,7 @@ import org.bukkit.event.world.StructureGrowEvent;
|
|||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
//event handlers related to blocks
|
||||
public class BlockEventHandler implements Listener
|
||||
|
|
@ -54,10 +57,23 @@ public class BlockEventHandler implements Listener
|
|||
//convenience reference to singleton datastore
|
||||
private DataStore dataStore;
|
||||
|
||||
//boring typical constructor
|
||||
private ArrayList<Material> trashBlocks;
|
||||
|
||||
//constructor
|
||||
public BlockEventHandler(DataStore dataStore)
|
||||
{
|
||||
this.dataStore = dataStore;
|
||||
|
||||
//create the list of blocks which will not trigger a warning when they're placed outside of land claims
|
||||
this.trashBlocks = new ArrayList<Material>();
|
||||
this.trashBlocks.add(Material.COBBLESTONE);
|
||||
this.trashBlocks.add(Material.TORCH);
|
||||
this.trashBlocks.add(Material.DIRT);
|
||||
this.trashBlocks.add(Material.SAPLING);
|
||||
this.trashBlocks.add(Material.GRAVEL);
|
||||
this.trashBlocks.add(Material.SAND);
|
||||
this.trashBlocks.add(Material.TNT);
|
||||
this.trashBlocks.add(Material.WORKBENCH);
|
||||
}
|
||||
|
||||
//when a block is damaged...
|
||||
|
|
@ -251,6 +267,9 @@ public class BlockEventHandler implements Listener
|
|||
//extend the claim downward
|
||||
this.dataStore.extendClaim(claim, claim.getLesserBoundaryCorner().getBlockY() - GriefPrevention.instance.config_claims_claimsExtendIntoGroundDistance);
|
||||
}
|
||||
|
||||
//reset the counter for warning the player when he places outside his claims
|
||||
playerData.unclaimedBlockPlacementsUntilWarning = 1;
|
||||
}
|
||||
|
||||
//FEATURE: automatically create a claim when a player who has no claims places a chest
|
||||
|
|
@ -330,7 +349,23 @@ public class BlockEventHandler implements Listener
|
|||
placeEvent.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FEATURE: warn players when they're placing non-trash blocks outside of their claimed areas
|
||||
else if(GriefPrevention.instance.config_claims_warnOnBuildOutside && !this.trashBlocks.contains(block.getType()) && GriefPrevention.instance.claimsEnabledForWorld(block.getWorld()))
|
||||
{
|
||||
if(--playerData.unclaimedBlockPlacementsUntilWarning <= 0)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.BuildingOutsideClaims);
|
||||
playerData.unclaimedBlockPlacementsUntilWarning = 15;
|
||||
|
||||
if(playerData.lastClaim != null && playerData.lastClaim.allowBuild(player) == null)
|
||||
{
|
||||
Visualization visualization = Visualization.FromClaim(playerData.lastClaim, block.getY(), VisualizationType.Claim, player.getLocation());
|
||||
Visualization.Apply(player, visualization);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//blocks "pushing" other players' blocks around (pistons)
|
||||
|
|
@ -339,8 +374,21 @@ public class BlockEventHandler implements Listener
|
|||
{
|
||||
List<Block> blocks = event.getBlocks();
|
||||
|
||||
//if no blocks moving, then we don't care
|
||||
if(blocks.size() == 0) return;
|
||||
//if no blocks moving, then only check to make sure we're not pushing into a claim from outside
|
||||
//this avoids pistons breaking non-solids just inside a claim, like torches, doors, and touchplates
|
||||
if(blocks.size() == 0)
|
||||
{
|
||||
Block pistonBlock = event.getBlock();
|
||||
Block invadedBlock = pistonBlock.getRelative(event.getDirection());
|
||||
|
||||
if( this.dataStore.getClaimAt(pistonBlock.getLocation(), false, null) == null &&
|
||||
this.dataStore.getClaimAt(invadedBlock.getLocation(), false, null) != null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//who owns the piston, if anyone?
|
||||
String pistonClaimOwnerName = "_";
|
||||
|
|
@ -525,6 +573,50 @@ public class BlockEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
|
||||
//ensures dispensers can't be used to dispense a block(like water or lava) or item across a claim boundary
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onDispense(BlockDispenseEvent dispenseEvent)
|
||||
{
|
||||
//from where?
|
||||
Block fromBlock = dispenseEvent.getBlock();
|
||||
|
||||
//to where?
|
||||
Vector velocity = dispenseEvent.getVelocity();
|
||||
int xChange = 0;
|
||||
int zChange = 0;
|
||||
if(Math.abs(velocity.getX()) > Math.abs(velocity.getZ()))
|
||||
{
|
||||
if(velocity.getX() > 0) xChange = 1;
|
||||
else xChange = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(velocity.getZ() > 0) zChange = 1;
|
||||
else zChange = -1;
|
||||
}
|
||||
|
||||
Block toBlock = fromBlock.getRelative(xChange, 0, zChange);
|
||||
|
||||
Claim fromClaim = this.dataStore.getClaimAt(fromBlock.getLocation(), false, null);
|
||||
Claim toClaim = this.dataStore.getClaimAt(toBlock.getLocation(), false, fromClaim);
|
||||
|
||||
//into wilderness is NOT OK when surface buckets are limited
|
||||
if(GriefPrevention.instance.config_blockWildernessWaterBuckets && toClaim == null)
|
||||
{
|
||||
dispenseEvent.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//wilderness to wilderness is OK
|
||||
if(fromClaim == null && toClaim == null) return;
|
||||
|
||||
//within claim is OK
|
||||
if(fromClaim == toClaim) return;
|
||||
|
||||
//everything else is NOT OK
|
||||
dispenseEvent.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onTreeGrow (StructureGrowEvent growEvent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -128,13 +128,13 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//removes cached player data from memory
|
||||
void clearCachedPlayerData(String playerName)
|
||||
synchronized void clearCachedPlayerData(String playerName)
|
||||
{
|
||||
this.playerNameToPlayerDataMap.remove(playerName);
|
||||
}
|
||||
|
||||
//gets the number of bonus blocks a player has from his permissions
|
||||
int getGroupBonusBlocks(String playerName)
|
||||
synchronized int getGroupBonusBlocks(String playerName)
|
||||
{
|
||||
int bonusBlocks = 0;
|
||||
Set<String> keys = permissionToBonusBlocksMap.keySet();
|
||||
|
|
@ -153,7 +153,7 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//grants a group (players with a specific permission) bonus claim blocks as long as they're still members of the group
|
||||
public int adjustGroupBonusBlocks(String groupName, int amount)
|
||||
synchronized public int adjustGroupBonusBlocks(String groupName, int amount)
|
||||
{
|
||||
Integer currentValue = this.permissionToBonusBlocksMap.get(groupName);
|
||||
if(currentValue == null) currentValue = 0;
|
||||
|
|
@ -169,7 +169,7 @@ public abstract class DataStore
|
|||
|
||||
abstract void saveGroupBonusBlocks(String groupName, int amount);
|
||||
|
||||
public void changeClaimOwner(Claim claim, String newOwnerName) throws Exception
|
||||
synchronized public void changeClaimOwner(Claim claim, String newOwnerName) throws Exception
|
||||
{
|
||||
//if it's a subdivision, throw an exception
|
||||
if(claim.parent != null)
|
||||
|
|
@ -207,7 +207,7 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//adds a claim to the datastore, making it an effective claim
|
||||
void addClaim(Claim newClaim)
|
||||
synchronized void addClaim(Claim newClaim)
|
||||
{
|
||||
//subdivisions are easy
|
||||
if(newClaim.parent != null)
|
||||
|
|
@ -287,7 +287,7 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//saves any changes to a claim to secondary storage
|
||||
public void saveClaim(Claim claim)
|
||||
synchronized public void saveClaim(Claim claim)
|
||||
{
|
||||
//subdivisions don't save to their own files, but instead live in their parent claim's file
|
||||
//so any attempt to save a subdivision will save its parent (and thus the subdivision)
|
||||
|
|
@ -314,7 +314,7 @@ public abstract class DataStore
|
|||
|
||||
//retrieves player data from memory or secondary storage, as necessary
|
||||
//if the player has never been on the server before, this will return a fresh player data with default values
|
||||
public PlayerData getPlayerData(String playerName)
|
||||
synchronized public PlayerData getPlayerData(String playerName)
|
||||
{
|
||||
//first, look in memory
|
||||
PlayerData playerData = this.playerNameToPlayerDataMap.get(playerName);
|
||||
|
|
@ -346,7 +346,7 @@ public abstract class DataStore
|
|||
abstract PlayerData getPlayerDataFromStorage(String playerName);
|
||||
|
||||
//deletes a claim or subdivision
|
||||
public void deleteClaim(Claim claim)
|
||||
synchronized public void deleteClaim(Claim claim)
|
||||
{
|
||||
//subdivisions are simple - just remove them from their parent claim and save that claim
|
||||
if(claim.parent != null)
|
||||
|
|
@ -396,7 +396,7 @@ public abstract class DataStore
|
|||
//gets the claim at a specific location
|
||||
//ignoreHeight = TRUE means that a location UNDER an existing claim will return the claim
|
||||
//cachedClaim can be NULL, but will help performance if you have a reasonable guess about which claim the location is in
|
||||
public Claim getClaimAt(Location location, boolean ignoreHeight, Claim cachedClaim)
|
||||
synchronized public Claim getClaimAt(Location location, boolean ignoreHeight, Claim cachedClaim)
|
||||
{
|
||||
//check cachedClaim guess first. if it's in the datastore and the location is inside it, we're done
|
||||
if(cachedClaim != null && cachedClaim.inDataStore && cachedClaim.contains(location, ignoreHeight, true)) return cachedClaim;
|
||||
|
|
@ -443,7 +443,7 @@ public abstract 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, Long id)
|
||||
synchronized 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();
|
||||
|
||||
|
|
@ -541,7 +541,7 @@ public abstract class DataStore
|
|||
|
||||
//extends a claim to a new depth
|
||||
//respects the max depth config variable
|
||||
public void extendClaim(Claim claim, int newDepth)
|
||||
synchronized public void extendClaim(Claim claim, int newDepth)
|
||||
{
|
||||
if(newDepth < GriefPrevention.instance.config_claims_maxDepth) newDepth = GriefPrevention.instance.config_claims_maxDepth;
|
||||
|
||||
|
|
@ -567,7 +567,7 @@ public abstract class DataStore
|
|||
|
||||
//starts a siege on a claim
|
||||
//does NOT check siege cooldowns, see onCooldown() below
|
||||
public void startSiege(Player attacker, Player defender, Claim defenderClaim)
|
||||
synchronized public void startSiege(Player attacker, Player defender, Claim defenderClaim)
|
||||
{
|
||||
//fill-in the necessary SiegeData instance
|
||||
SiegeData siegeData = new SiegeData(attacker, defender, defenderClaim);
|
||||
|
|
@ -586,7 +586,7 @@ public abstract class DataStore
|
|||
|
||||
//ends a siege
|
||||
//either winnerName or loserName can be null, but not both
|
||||
public void endSiege(SiegeData siegeData, String winnerName, String loserName, boolean death)
|
||||
synchronized public void endSiege(SiegeData siegeData, String winnerName, String loserName, boolean death)
|
||||
{
|
||||
boolean grantAccess = false;
|
||||
|
||||
|
|
@ -704,7 +704,7 @@ public abstract class DataStore
|
|||
private HashMap<String, Long> siegeCooldownRemaining = new HashMap<String, Long>();
|
||||
|
||||
//whether or not a sieger can siege a particular victim or claim, considering only cooldowns
|
||||
public boolean onCooldown(Player attacker, Player defender, Claim defenderClaim)
|
||||
synchronized public boolean onCooldown(Player attacker, Player defender, Claim defenderClaim)
|
||||
{
|
||||
Long cooldownEnd = null;
|
||||
|
||||
|
|
@ -740,7 +740,7 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//extend a siege, if it's possible to do so
|
||||
void tryExtendSiege(Player player, Claim claim)
|
||||
synchronized void tryExtendSiege(Player player, Claim claim)
|
||||
{
|
||||
PlayerData playerData = this.getPlayerData(player.getName());
|
||||
|
||||
|
|
@ -762,7 +762,7 @@ public abstract class DataStore
|
|||
}
|
||||
|
||||
//deletes all claims owned by a player
|
||||
public void deleteClaimsForPlayer(String playerName, boolean deleteCreativeClaims)
|
||||
synchronized public void deleteClaimsForPlayer(String playerName, boolean deleteCreativeClaims)
|
||||
{
|
||||
//make a list of the player's claims
|
||||
ArrayList<Claim> claimsToDelete = new ArrayList<Claim>();
|
||||
|
|
@ -783,7 +783,7 @@ public abstract class DataStore
|
|||
|
||||
//tries to resize a claim
|
||||
//see CreateClaim() for details on return value
|
||||
public CreateClaimResult resizeClaim(Claim claim, int newx1, int newx2, int newy1, int newy2, int newz1, int newz2)
|
||||
synchronized public CreateClaimResult resizeClaim(Claim claim, int newx1, int newx2, int newy1, int newy2, int newz1, int newz2)
|
||||
{
|
||||
//remove old claim
|
||||
this.deleteClaim(claim);
|
||||
|
|
@ -993,7 +993,8 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.UntrustOwnerOnly, "Only {0} can revoke permissions here.", "0: claim owner's name");
|
||||
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.");
|
||||
this.addDefault(defaults, Messages.NoBuildOutsideClaims, "You can't build here unless you claim some land first.", null);
|
||||
this.addDefault(defaults, Messages.PlayerOfflineTime, " Last login: {0} days ago.", "0: number of full days since last login");
|
||||
this.addDefault(defaults, Messages.PlayerOfflineTime, " Last login: {0} days ago.", "0: number of full days since last login");
|
||||
this.addDefault(defaults, Messages.BuildingOutsideClaims, "Other players can undo your work here! Consider claiming this area to protect your work.", null);
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
@ -1044,7 +1045,7 @@ public abstract class DataStore
|
|||
defaults.put(id.name(), message);
|
||||
}
|
||||
|
||||
public String getMessage(Messages messageID, String... args)
|
||||
synchronized public String getMessage(Messages messageID, String... args)
|
||||
{
|
||||
String message = messages[messageID.ordinal()];
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ public class DatabaseDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void writeClaimToStorage(Claim claim) //see datastore.cs. this will ALWAYS be a top level claim
|
||||
synchronized void writeClaimToStorage(Claim claim) //see datastore.cs. this will ALWAYS be a top level claim
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -261,7 +261,7 @@ public class DatabaseDataStore extends DataStore
|
|||
}
|
||||
|
||||
//actually writes claim data to the database
|
||||
private void writeClaimData(Claim claim) throws SQLException
|
||||
synchronized private void writeClaimData(Claim claim) throws SQLException
|
||||
{
|
||||
String lesserCornerString = this.locationToString(claim.getLesserBoundaryCorner());
|
||||
String greaterCornerString = this.locationToString(claim.getGreaterBoundaryCorner());
|
||||
|
|
@ -342,7 +342,7 @@ public class DatabaseDataStore extends DataStore
|
|||
|
||||
//deletes a top level claim from the database
|
||||
@Override
|
||||
void deleteClaimFromSecondaryStorage(Claim claim)
|
||||
synchronized void deleteClaimFromSecondaryStorage(Claim claim)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -358,7 +358,7 @@ public class DatabaseDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
PlayerData getPlayerDataFromStorage(String playerName)
|
||||
synchronized PlayerData getPlayerDataFromStorage(String playerName)
|
||||
{
|
||||
PlayerData playerData = new PlayerData();
|
||||
playerData.playerName = playerName;
|
||||
|
|
@ -393,7 +393,7 @@ public class DatabaseDataStore extends DataStore
|
|||
|
||||
//saves changes to player data. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
@Override
|
||||
public void savePlayerData(String playerName, PlayerData playerData)
|
||||
synchronized public void savePlayerData(String playerName, PlayerData playerData)
|
||||
{
|
||||
//never save data for the "administrative" account. an empty string for player name indicates administrative account
|
||||
if(playerName.length() == 0) return;
|
||||
|
|
@ -415,13 +415,13 @@ public class DatabaseDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void incrementNextClaimID()
|
||||
synchronized void incrementNextClaimID()
|
||||
{
|
||||
this.setNextClaimID(this.nextClaimID + 1);
|
||||
}
|
||||
|
||||
//sets the next claim ID. used by incrementNextClaimID() above, and also while migrating data from a flat file data store
|
||||
void setNextClaimID(long nextID)
|
||||
synchronized void setNextClaimID(long nextID)
|
||||
{
|
||||
this.nextClaimID = nextID;
|
||||
|
||||
|
|
@ -440,7 +440,7 @@ public class DatabaseDataStore extends DataStore
|
|||
|
||||
//updates the database with a group's bonus blocks
|
||||
@Override
|
||||
void saveGroupBonusBlocks(String groupName, int currentValue)
|
||||
synchronized void saveGroupBonusBlocks(String groupName, int currentValue)
|
||||
{
|
||||
//group bonus blocks are stored in the player data table, with player name = $groupName
|
||||
String playerName = "$" + groupName;
|
||||
|
|
@ -451,7 +451,7 @@ public class DatabaseDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void close()
|
||||
synchronized void close()
|
||||
{
|
||||
if(this.databaseConnection != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.bukkit.World.Environment;
|
|||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.Enderman;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
|
@ -92,8 +93,8 @@ class EntityEventHandler implements Listener
|
|||
Location location = explodeEvent.getLocation();
|
||||
|
||||
//FEATURE: explosions don't destroy blocks when they explode near or above sea level in standard worlds
|
||||
|
||||
if(GriefPrevention.instance.config_blockSurfaceExplosions && location.getWorld().getEnvironment() == Environment.NORMAL)
|
||||
boolean isCreeper = (explodeEvent.getEntity() != null && explodeEvent.getEntity() instanceof Creeper);
|
||||
if( location.getWorld().getEnvironment() == Environment.NORMAL && ((isCreeper && GriefPrevention.instance.config_blockSurfaceCreeperExplosions) || (!isCreeper && GriefPrevention.instance.config_blockSurfaceOtherExplosions)))
|
||||
{
|
||||
for(int i = 0; i < blocks.size(); i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ public class FlatFileDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void writeClaimToStorage(Claim claim)
|
||||
synchronized void writeClaimToStorage(Claim claim)
|
||||
{
|
||||
String claimID = String.valueOf(claim.id);
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ public class FlatFileDataStore extends DataStore
|
|||
}
|
||||
|
||||
//actually writes claim data to an output stream
|
||||
private void writeClaimData(Claim claim, BufferedWriter outStream) throws IOException
|
||||
synchronized private void writeClaimData(Claim claim, BufferedWriter outStream) throws IOException
|
||||
{
|
||||
//first line is lesser boundary corner location
|
||||
outStream.write(this.locationToString(claim.getLesserBoundaryCorner()));
|
||||
|
|
@ -352,7 +352,7 @@ public class FlatFileDataStore extends DataStore
|
|||
|
||||
//deletes a top level claim from the file system
|
||||
@Override
|
||||
void deleteClaimFromSecondaryStorage(Claim claim)
|
||||
synchronized void deleteClaimFromSecondaryStorage(Claim claim)
|
||||
{
|
||||
String claimID = String.valueOf(claim.id);
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ public class FlatFileDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
PlayerData getPlayerDataFromStorage(String playerName)
|
||||
synchronized PlayerData getPlayerDataFromStorage(String playerName)
|
||||
{
|
||||
File playerFile = new File(playerDataFolderPath + File.separator + playerName);
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ public class FlatFileDataStore extends DataStore
|
|||
|
||||
//saves changes to player data. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
@Override
|
||||
public void savePlayerData(String playerName, PlayerData playerData)
|
||||
synchronized public void savePlayerData(String playerName, PlayerData playerData)
|
||||
{
|
||||
//never save data for the "administrative" account. an empty string for claim owner indicates administrative account
|
||||
if(playerName.length() == 0) return;
|
||||
|
|
@ -496,7 +496,7 @@ public class FlatFileDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void incrementNextClaimID()
|
||||
synchronized void incrementNextClaimID()
|
||||
{
|
||||
//increment in memory
|
||||
this.nextClaimID++;
|
||||
|
|
@ -529,7 +529,7 @@ public class FlatFileDataStore extends DataStore
|
|||
|
||||
//grants a group (players with a specific permission) bonus claim blocks as long as they're still members of the group
|
||||
@Override
|
||||
void saveGroupBonusBlocks(String groupName, int currentValue)
|
||||
synchronized void saveGroupBonusBlocks(String groupName, int currentValue)
|
||||
{
|
||||
//write changes to file to ensure they don't get lost
|
||||
BufferedWriter outStream = null;
|
||||
|
|
@ -562,7 +562,7 @@ public class FlatFileDataStore extends DataStore
|
|||
catch(IOException exception){}
|
||||
}
|
||||
|
||||
void migrateData(DatabaseDataStore databaseStore)
|
||||
synchronized void migrateData(DatabaseDataStore databaseStore)
|
||||
{
|
||||
//migrate claims
|
||||
for(int i = 0; i < this.claims.size(); i++)
|
||||
|
|
@ -629,5 +629,5 @@ public class FlatFileDataStore extends DataStore
|
|||
}
|
||||
|
||||
@Override
|
||||
void close() { }
|
||||
synchronized void close() { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ public class GriefPrevention extends JavaPlugin
|
|||
public boolean config_claims_preventTheft; //whether containers and crafting blocks are protectable
|
||||
public boolean config_claims_protectCreatures; //whether claimed animals may be injured by players without permission
|
||||
public boolean config_claims_preventButtonsSwitches; //whether buttons and switches are protectable
|
||||
public boolean config_claims_lockAllDoors; //whether wooden doors, trap doors, fence gates, etc require permission to use
|
||||
public boolean config_claims_lockWoodenDoors; //whether wooden doors should be locked by default (require /accesstrust)
|
||||
public boolean config_claims_lockTrapDoors; //whether trap doors should be locked by default (require /accesstrust)
|
||||
public boolean config_claims_lockFenceGates; //whether fence gates should be locked by default (require /accesstrust)
|
||||
|
||||
public int config_claims_initialBlocks; //the number of claim blocks a new player starts with
|
||||
public int config_claims_blocksAccruedPerHour; //how many additional blocks players get each hour of play (can be zero)
|
||||
|
|
@ -108,7 +110,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
public double config_economy_claimBlocksPurchaseCost; //cost to purchase a claim block. set to zero to disable purchase.
|
||||
public double config_economy_claimBlocksSellValue; //return on a sold claim block. set to zero to disable sale.
|
||||
|
||||
public boolean config_blockSurfaceExplosions; //whether creeper/TNT explosions near or above the surface destroy blocks
|
||||
public boolean config_blockSurfaceCreeperExplosions; //whether creeper explosions near or above the surface destroy blocks
|
||||
public boolean config_blockSurfaceOtherExplosions; //whether non-creeper explosions near or above the surface destroy blocks
|
||||
public boolean config_blockWildernessWaterBuckets; //whether players can dump water buckets outside their claims
|
||||
public boolean config_blockSkyTrees; //whether players can build trees on platforms in the sky
|
||||
|
||||
|
|
@ -128,6 +131,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
public List<Integer> config_mods_containerTrustIds; //list of block IDs which should require /containertrust for player interaction
|
||||
public List<String> config_mods_ignoreClaimsAccounts; //list of player names which ALWAYS ignore claims
|
||||
public List<Integer> config_mods_explodableIds; //list of block IDs which can be destroyed by explosions, even in claimed areas
|
||||
|
||||
public boolean config_claims_warnOnBuildOutside; //whether players should be warned when they're building in an unclaimed area
|
||||
|
||||
//reference to the economy plugin, if economy integration is enabled
|
||||
public static Economy economy = null;
|
||||
|
|
@ -225,7 +230,9 @@ public class GriefPrevention extends JavaPlugin
|
|||
this.config_claims_preventTheft = config.getBoolean("GriefPrevention.Claims.PreventTheft", true);
|
||||
this.config_claims_protectCreatures = config.getBoolean("GriefPrevention.Claims.ProtectCreatures", true);
|
||||
this.config_claims_preventButtonsSwitches = config.getBoolean("GriefPrevention.Claims.PreventButtonsSwitches", true);
|
||||
this.config_claims_lockAllDoors = config.getBoolean("GriefPrevention.Claims.LockAllDoors", false);
|
||||
this.config_claims_lockWoodenDoors = config.getBoolean("GriefPrevention.Claims.LockWoodenDoors", false);
|
||||
this.config_claims_lockTrapDoors = config.getBoolean("GriefPrevention.Claims.LockTrapDoors", false);
|
||||
this.config_claims_lockFenceGates = config.getBoolean("GriefPrevention.Claims.LockFenceGates", false);
|
||||
this.config_claims_initialBlocks = config.getInt("GriefPrevention.Claims.InitialBlocks", 100);
|
||||
this.config_claims_blocksAccruedPerHour = config.getInt("GriefPrevention.Claims.BlocksAccruedPerHour", 100);
|
||||
this.config_claims_maxAccruedBlocks = config.getInt("GriefPrevention.Claims.MaxAccruedBlocks", 80000);
|
||||
|
|
@ -237,6 +244,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
this.config_claims_expirationDays = config.getInt("GriefPrevention.Claims.IdleLimitDays", 0);
|
||||
this.config_claims_trappedCooldownHours = config.getInt("GriefPrevention.Claims.TrappedCommandCooldownHours", 8);
|
||||
this.config_claims_noBuildOutsideClaims = config.getBoolean("GriefPrevention.Claims.NoSurvivalBuildingOutsideClaims", false);
|
||||
this.config_claims_warnOnBuildOutside = config.getBoolean("GriefPrevention.Claims.WarnWhenBuildingOutsideClaims");
|
||||
|
||||
this.config_spam_enabled = config.getBoolean("GriefPrevention.Spam.Enabled", true);
|
||||
this.config_spam_loginCooldownMinutes = config.getInt("GriefPrevention.Spam.LoginCooldownMinutes", 2);
|
||||
|
|
@ -257,7 +265,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
this.config_economy_claimBlocksPurchaseCost = config.getDouble("GriefPrevention.Economy.ClaimBlocksPurchaseCost", 0);
|
||||
this.config_economy_claimBlocksSellValue = config.getDouble("GriefPrevention.Economy.ClaimBlocksSellValue", 0);
|
||||
|
||||
this.config_blockSurfaceExplosions = config.getBoolean("GriefPrevention.BlockSurfaceExplosions", true);
|
||||
this.config_blockSurfaceCreeperExplosions = config.getBoolean("GriefPrevention.BlockSurfaceCreeperExplosions", true);
|
||||
this.config_blockSurfaceOtherExplosions = config.getBoolean("GriefPrevention.BlockSurfaceOtherExplosions", true);
|
||||
this.config_blockWildernessWaterBuckets = config.getBoolean("GriefPrevention.LimitSurfaceWaterBuckets", true);
|
||||
this.config_blockSkyTrees = config.getBoolean("GriefPrevention.LimitSkyTrees", true);
|
||||
|
||||
|
|
@ -276,7 +285,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
this.config_mods_accessTrustIds = config.getIntegerList("GriefPrevention.Mods.BlockIdsRequiringAccessTrust");
|
||||
if(this.config_mods_accessTrustIds == null) this.config_mods_accessTrustIds = new ArrayList<Integer>();
|
||||
|
||||
this.config_mods_accessTrustIds = config.getIntegerList("GriefPrevention.Mods.BlockIdsRequiringContainerTrust");
|
||||
this.config_mods_containerTrustIds = config.getIntegerList("GriefPrevention.Mods.BlockIdsRequiringContainerTrust");
|
||||
if(this.config_mods_containerTrustIds == null) this.config_mods_containerTrustIds = new ArrayList<Integer>();
|
||||
|
||||
this.config_mods_ignoreClaimsAccounts = config.getStringList("GriefPrevention.Mods.PlayersIgnoringAllClaims");
|
||||
|
|
@ -395,7 +404,9 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Claims.PreventTheft", this.config_claims_preventTheft);
|
||||
config.set("GriefPrevention.Claims.ProtectCreatures", this.config_claims_protectCreatures);
|
||||
config.set("GriefPrevention.Claims.PreventButtonsSwitches", this.config_claims_preventButtonsSwitches);
|
||||
config.set("GriefPrevention.Claims.LockAllDoors", this.config_claims_lockAllDoors);
|
||||
config.set("GriefPrevention.Claims.LockWoodenDoors", this.config_claims_lockWoodenDoors);
|
||||
config.set("GriefPrevention.Claims.LockTrapDoors", this.config_claims_lockTrapDoors);
|
||||
config.set("GriefPrevention.Claims.LockFenceGates", this.config_claims_lockFenceGates);
|
||||
config.set("GriefPrevention.Claims.InitialBlocks", this.config_claims_initialBlocks);
|
||||
config.set("GriefPrevention.Claims.BlocksAccruedPerHour", this.config_claims_blocksAccruedPerHour);
|
||||
config.set("GriefPrevention.Claims.MaxAccruedBlocks", this.config_claims_maxAccruedBlocks);
|
||||
|
|
@ -408,7 +419,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Claims.TrappedCommandCooldownHours", this.config_claims_trappedCooldownHours);
|
||||
config.set("GriefPrevention.Claims.InvestigationTool", this.config_claims_investigationTool.name());
|
||||
config.set("GriefPrevention.Claims.ModificationTool", this.config_claims_modificationTool.name());
|
||||
config.set("GriefPrevention.Claims.NoSurvivalBuildingOutsideClaims", this.config_claims_noBuildOutsideClaims);
|
||||
config.set("GriefPrevention.Claims.NoSurvivalBuildingOutsideClaims", this.config_claims_noBuildOutsideClaims);
|
||||
config.set("GriefPrevention.Claims.WarnWhenBuildingOutsideClaims", this.config_claims_warnOnBuildOutside);
|
||||
|
||||
config.set("GriefPrevention.Spam.Enabled", this.config_spam_enabled);
|
||||
config.set("GriefPrevention.Spam.LoginCooldownMinutes", this.config_spam_loginCooldownMinutes);
|
||||
|
|
@ -429,7 +441,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Economy.ClaimBlocksPurchaseCost", this.config_economy_claimBlocksPurchaseCost);
|
||||
config.set("GriefPrevention.Economy.ClaimBlocksSellValue", this.config_economy_claimBlocksSellValue);
|
||||
|
||||
config.set("GriefPrevention.BlockSurfaceExplosions", this.config_blockSurfaceExplosions);
|
||||
config.set("GriefPrevention.BlockSurfaceCreeperExplosions", this.config_blockSurfaceCreeperExplosions);
|
||||
config.set("GriefPrevention.BlockSurfaceOtherExplosions", this.config_blockSurfaceOtherExplosions);
|
||||
config.set("GriefPrevention.LimitSurfaceWaterBuckets", this.config_blockWildernessWaterBuckets);
|
||||
config.set("GriefPrevention.LimitSkyTrees", this.config_blockSkyTrees);
|
||||
|
||||
|
|
@ -2117,9 +2130,15 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
//sends a color-coded message to a player
|
||||
static void sendMessage(Player player, ChatColor color, Messages messageID, String... args)
|
||||
{
|
||||
sendMessage(player, color, messageID, 0, args);
|
||||
}
|
||||
|
||||
//sends a color-coded message to a player
|
||||
static void sendMessage(Player player, ChatColor color, Messages messageID, long delayInTicks, String... args)
|
||||
{
|
||||
String message = GriefPrevention.instance.dataStore.getMessage(messageID, args);
|
||||
sendMessage(player, color, message);
|
||||
sendMessage(player, color, message, delayInTicks);
|
||||
}
|
||||
|
||||
//sends a color-coded message to a player
|
||||
|
|
@ -2135,6 +2154,19 @@ public class GriefPrevention extends JavaPlugin
|
|||
}
|
||||
}
|
||||
|
||||
static void sendMessage(Player player, ChatColor color, String message, long delayInTicks)
|
||||
{
|
||||
SendPlayerMessageTask task = new SendPlayerMessageTask(player, color, message);
|
||||
if(delayInTicks > 0)
|
||||
{
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleAsyncDelayedTask(GriefPrevention.instance, task, delayInTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
|
||||
//determines whether creative anti-grief rules apply at a location
|
||||
boolean creativeRulesApply(Location location)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ package me.ryanhamshire.GriefPrevention;
|
|||
|
||||
public enum Messages
|
||||
{
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionDemo, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, TrappedOnCooldown, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, TrustCommandAdvertisement, GoldenShovelAdvertisement, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsDemoAdvertisement, SurvivalBasicsDemoAdvertisement, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionDemo, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, TrappedOnCooldown, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, TrustCommandAdvertisement, GoldenShovelAdvertisement, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsDemoAdvertisement, SurvivalBasicsDemoAdvertisement, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime, BuildingOutsideClaims
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ public class PlayerData
|
|||
//last place the player damaged a chest
|
||||
public Location lastChestDamageLocation = null;
|
||||
|
||||
//number of blocks placed outside claims before next warning
|
||||
int unclaimedBlockPlacementsUntilWarning = 1;
|
||||
|
||||
//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
|
||||
|
|
|
|||
|
|
@ -74,11 +74,17 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
//when a player chats, monitor for spam
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
void onPlayerChat (PlayerChatEvent event)
|
||||
void onPlayerChat (AsyncPlayerChatEvent event)
|
||||
{
|
||||
Player player = event.getPlayer();
|
||||
String message = event.getMessage();
|
||||
|
||||
event.setCancelled(this.handlePlayerChat(player, message, event));
|
||||
}
|
||||
|
||||
//returns true if the message should be sent, false if it should be muted
|
||||
private boolean handlePlayerChat(Player player, String message, PlayerEvent event)
|
||||
{
|
||||
//FEATURE: automatically educate players about claiming land
|
||||
//watching for message format how*claim*, and will send a link to the basics video
|
||||
if(this.howToClaimPattern == null)
|
||||
|
|
@ -90,11 +96,11 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.CreativeBasicsDemoAdvertisement);
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.CreativeBasicsDemoAdvertisement, 10L);
|
||||
}
|
||||
else
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.SurvivalBasicsDemoAdvertisement);
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.SurvivalBasicsDemoAdvertisement, 10L);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,23 +108,26 @@ class PlayerEventHandler implements Listener
|
|||
//check for "trapped" or "stuck" to educate players about the /trapped command
|
||||
if(message.contains("trapped") || message.contains("stuck") || message.contains(this.dataStore.getMessage(Messages.TrappedChatKeyword)))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.TrappedInstructions);
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.TrappedInstructions, 10L);
|
||||
}
|
||||
|
||||
//FEATURE: monitor for chat and command spam
|
||||
|
||||
if(!GriefPrevention.instance.config_spam_enabled) return;
|
||||
if(!GriefPrevention.instance.config_spam_enabled) return false;
|
||||
|
||||
//if the player has permission to spam, don't bother even examining the message
|
||||
if(player.hasPermission("griefprevention.spam")) return;
|
||||
if(player.hasPermission("griefprevention.spam")) return false;
|
||||
|
||||
//remedy any CAPS SPAM without bothering to fault the player for it
|
||||
if(message.length() > 4 && message.toUpperCase().equals(message))
|
||||
if(message.length() > 4 && this.stringsAreSimilar(message.toUpperCase(), message))
|
||||
{
|
||||
event.setMessage(message.toLowerCase());
|
||||
if(event instanceof AsyncPlayerChatEvent)
|
||||
{
|
||||
((AsyncPlayerChatEvent)event).setMessage(message.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
//where spam is concerned, casing isn't significant
|
||||
//where other types of spam are concerned, casing isn't significant
|
||||
message = message.toLowerCase();
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
|
|
@ -137,8 +146,8 @@ class PlayerEventHandler implements Listener
|
|||
spam = true;
|
||||
}
|
||||
|
||||
//if it's very similar to the last message and less than 15 seconds have passed
|
||||
if(!muted && this.stringsAreSimilar(message, playerData.lastMessage) && millisecondsSinceLastMessage < 15000)
|
||||
//if it's very similar to the last message
|
||||
if(!muted && this.stringsAreSimilar(message, playerData.lastMessage))
|
||||
{
|
||||
playerData.spamCount++;
|
||||
spam = true;
|
||||
|
|
@ -146,10 +155,10 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//filter IP addresses
|
||||
if(!muted && !(event instanceof PlayerCommandPreprocessEvent))
|
||||
if(!muted)
|
||||
{
|
||||
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());
|
||||
Matcher matcher = ipAddressPattern.matcher(message);
|
||||
|
||||
//if it looks like an IP address
|
||||
while(matcher.find())
|
||||
|
|
@ -158,7 +167,7 @@ class PlayerEventHandler implements Listener
|
|||
if(!GriefPrevention.instance.config_spam_allowedIpAddresses.contains(matcher.group()))
|
||||
{
|
||||
//log entry
|
||||
GriefPrevention.AddLogEntry("Muted IP address from " + player.getName() + ": " + event.getMessage());
|
||||
GriefPrevention.AddLogEntry("Muted IP address from " + player.getName() + ": " + message);
|
||||
|
||||
//spam notation
|
||||
playerData.spamCount++;
|
||||
|
|
@ -201,7 +210,6 @@ class PlayerEventHandler implements Listener
|
|||
if(!muted && message.length() < 5 && millisecondsSinceLastMessage < 5000)
|
||||
{
|
||||
spam = true;
|
||||
if(playerData.spamCount > 4) muted = true;
|
||||
playerData.spamCount++;
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +243,7 @@ class PlayerEventHandler implements Listener
|
|||
muted = true;
|
||||
if(!playerData.spamWarned)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, GriefPrevention.instance.config_spam_warningMessage);
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, GriefPrevention.instance.config_spam_warningMessage, 10L);
|
||||
GriefPrevention.AddLogEntry("Warned " + player.getName() + " about spam penalties.");
|
||||
playerData.spamWarned = true;
|
||||
}
|
||||
|
|
@ -243,14 +251,15 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
if(muted)
|
||||
{
|
||||
//cancel the event and make a log entry
|
||||
//cancelling the event guarantees players don't receive the message
|
||||
event.setCancelled(true);
|
||||
//make a log entry
|
||||
GriefPrevention.AddLogEntry("Muted spam from " + player.getName() + ": " + message);
|
||||
|
||||
//send a fake message so the player doesn't realize he's muted
|
||||
//less information for spammers = less effective spam filter dodging
|
||||
player.sendMessage("<" + player.getName() + "> " + event.getMessage());
|
||||
player.sendMessage("<" + player.getName() + "> " + message);
|
||||
|
||||
//cancelling the event guarantees other players don't receive the message
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +272,9 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
//in any case, record the timestamp of this message and also its content for next time
|
||||
playerData.lastMessageTimestamp = new Date();
|
||||
playerData.lastMessage = message;
|
||||
playerData.lastMessage = message;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//if two strings are 75% identical, they're too close to follow each other in the chat
|
||||
|
|
@ -345,7 +356,10 @@ class PlayerEventHandler implements Listener
|
|||
if(!GriefPrevention.instance.config_spam_enabled) return;
|
||||
|
||||
//if the slash command used is in the list of monitored commands, treat it like a chat message (see above)
|
||||
if(GriefPrevention.instance.config_spam_monitorSlashCommands.contains(args[0])) this.onPlayerChat(event);
|
||||
if(GriefPrevention.instance.config_spam_monitorSlashCommands.contains(args[0]))
|
||||
{
|
||||
event.setCancelled(this.handlePlayerChat(event.getPlayer(), event.getMessage(), event));
|
||||
}
|
||||
}
|
||||
|
||||
//when a player attempts to join the server...
|
||||
|
|
@ -878,9 +892,11 @@ class PlayerEventHandler implements Listener
|
|||
//apply rules for containers and crafting blocks
|
||||
if( GriefPrevention.instance.config_claims_preventTheft && (
|
||||
event.getAction() == Action.RIGHT_CLICK_BLOCK && (
|
||||
clickedBlock.getState() instanceof InventoryHolder ||
|
||||
clickedBlockType == Material.BREWING_STAND ||
|
||||
clickedBlock.getState() instanceof InventoryHolder ||
|
||||
clickedBlockType == Material.WORKBENCH ||
|
||||
clickedBlockType == Material.ENDER_CHEST ||
|
||||
clickedBlockType == Material.DISPENSER ||
|
||||
clickedBlockType == Material.BREWING_STAND ||
|
||||
clickedBlockType == Material.JUKEBOX ||
|
||||
clickedBlockType == Material.ENCHANTMENT_TABLE ||
|
||||
GriefPrevention.instance.config_mods_containerTrustIds.contains(clickedBlock.getTypeId()))))
|
||||
|
|
@ -925,7 +941,9 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//otherwise apply rules for doors, if configured that way
|
||||
else if(GriefPrevention.instance.config_claims_lockAllDoors && (clickedBlockType == Material.WOOD_DOOR || clickedBlockType == Material.WOODEN_DOOR || clickedBlockType == Material.TRAP_DOOR || clickedBlockType == Material.FENCE_GATE))
|
||||
else if((GriefPrevention.instance.config_claims_lockWoodenDoors && clickedBlockType == Material.WOOD_DOOR) ||
|
||||
(GriefPrevention.instance.config_claims_lockTrapDoors && clickedBlockType == Material.TRAP_DOOR) ||
|
||||
(GriefPrevention.instance.config_claims_lockFenceGates && clickedBlockType == Material.FENCE_GATE))
|
||||
{
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
|
||||
if(claim != null)
|
||||
|
|
@ -1346,7 +1364,7 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//make sure player has enough blocks to make up the difference
|
||||
if(!playerData.claimResizing.isAdminClaim())
|
||||
if(!playerData.claimResizing.isAdminClaim() && player.getName().equals(playerData.claimResizing.getOwnerName()))
|
||||
{
|
||||
int newArea = newWidth * newHeight;
|
||||
int blocksRemainingAfter = playerData.getRemainingClaimBlocks() + playerData.claimResizing.getArea() - newArea;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//sends a message to a player
|
||||
//used to send delayed messages, for example help text triggered by a player's chat
|
||||
class SendPlayerMessageTask implements Runnable
|
||||
{
|
||||
private Player player;
|
||||
private ChatColor color;
|
||||
private String message;
|
||||
|
||||
public SendPlayerMessageTask(Player player, ChatColor color, String message)
|
||||
{
|
||||
this.player = player;
|
||||
this.color = color;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
GriefPrevention.sendMessage(this.player, this.color, this.message);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user