3.3.2
This commit is contained in:
parent
e68fd63194
commit
5037847814
16
plugin.yml
16
plugin.yml
|
|
@ -1,17 +1,20 @@
|
||||||
name: GriefPrevention
|
name: GriefPrevention
|
||||||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||||
softdepend: [Vault]
|
softdepend: [Vault]
|
||||||
version: 3.2
|
version: 3.3.2
|
||||||
commands:
|
commands:
|
||||||
abandonclaim:
|
abandonclaim:
|
||||||
description: Deletes a claim.
|
description: Deletes a claim.
|
||||||
usage: /abandonclaim
|
usage: /AbandonClaim
|
||||||
|
abandontoplevelclaim:
|
||||||
|
description: Deletes a claim and all its subdivisions.
|
||||||
|
usage: /AbandonTopLevelClaim
|
||||||
abandonallclaims:
|
abandonallclaims:
|
||||||
description: Deletes ALL your claims.
|
description: Deletes ALL your claims.
|
||||||
usage: /AbandonAllClaims
|
usage: /AbandonAllClaims
|
||||||
trust:
|
trust:
|
||||||
description: Grants a player full access to your claim(s).
|
description: Grants a player full access to your claim(s).
|
||||||
usage: /Trust <player> See also /UnTrust, /ContainerTrust, /AccessTrust, and /PermissionTrust.
|
usage: /Trust <player> Graants a player permission to build. See also /UnTrust, /ContainerTrust, /AccessTrust, and /PermissionTrust.
|
||||||
aliases: t
|
aliases: t
|
||||||
untrust:
|
untrust:
|
||||||
description: Revokes a player's access to your claim(s).
|
description: Revokes a player's access to your claim(s).
|
||||||
|
|
@ -19,15 +22,15 @@ commands:
|
||||||
aliases: ut
|
aliases: ut
|
||||||
containertrust:
|
containertrust:
|
||||||
description: Grants a player access to your containers.
|
description: Grants a player access to your containers.
|
||||||
usage: /ContainerTrust <player>
|
usage: /ContainerTrust <player>. Grants a player access to your inventory, bed, and buttons/levers.
|
||||||
aliases: ct
|
aliases: ct
|
||||||
accesstrust:
|
accesstrust:
|
||||||
description: Grants a player entry to your claim(s) and use of your bed.
|
description: Grants a player entry to your claim(s) and use of your bed.
|
||||||
usage: /AccessTrust <player>
|
usage: /AccessTrust <player>. Grants a player access to your bed, buttons, and levers.
|
||||||
aliases: at
|
aliases: at
|
||||||
permissiontrust:
|
permissiontrust:
|
||||||
description: Grants a player permission to grant his level of permission to others.
|
description: Grants a player permission to grant his level of permission to others.
|
||||||
usage: /PermissionTrust <player>
|
usage: /PermissionTrust <player>. Permits a player to share his permission level with others.
|
||||||
aliases: pt
|
aliases: pt
|
||||||
subdivideclaims:
|
subdivideclaims:
|
||||||
description: Switches the shovel tool to subdivision mode, used to subdivide your claims.
|
description: Switches the shovel tool to subdivision mode, used to subdivide your claims.
|
||||||
|
|
@ -100,6 +103,7 @@ permissions:
|
||||||
griefprevention.adjustclaimblocks: true
|
griefprevention.adjustclaimblocks: true
|
||||||
griefprevention.deleteclaims: true
|
griefprevention.deleteclaims: true
|
||||||
griefprevention.spam: true
|
griefprevention.spam: true
|
||||||
|
griefprevention.lava: true
|
||||||
griefprevention.restorenature:
|
griefprevention.restorenature:
|
||||||
description: Grants permission to use /RestoreNature.
|
description: Grants permission to use /RestoreNature.
|
||||||
default: op
|
default: op
|
||||||
|
|
|
||||||
|
|
@ -186,20 +186,18 @@ public class BlockEventHandler implements Listener
|
||||||
Player player = placeEvent.getPlayer();
|
Player player = placeEvent.getPlayer();
|
||||||
Block block = placeEvent.getBlock();
|
Block block = placeEvent.getBlock();
|
||||||
|
|
||||||
//FEATURE: limit fire placement, to prevent PvP-by-fire and general fiery messes
|
//FEATURE: limit fire placement, to prevent PvP-by-fire
|
||||||
|
|
||||||
//if placed block is fire and pvp is off, block it apply limitations based on the block it's placed on
|
//if placed block is fire and pvp is off, apply rules for proximity to other players
|
||||||
if(block.getType() == Material.FIRE && !block.getWorld().getPVP())
|
if(block.getType() == Material.FIRE && !block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
|
||||||
{
|
{
|
||||||
List<Player> players = block.getWorld().getPlayers();
|
List<Player> players = block.getWorld().getPlayers();
|
||||||
for(int i = 0; i < players.size(); i++)
|
for(int i = 0; i < players.size(); i++)
|
||||||
{
|
{
|
||||||
Player otherPlayer = players.get(i);
|
Player otherPlayer = players.get(i);
|
||||||
Location location = otherPlayer.getLocation();
|
Location location = otherPlayer.getLocation();
|
||||||
if(!otherPlayer.equals(player) && block.getY() <= location.getBlockY() - 1 && location.distanceSquared(block.getLocation()) < 9)
|
if(!otherPlayer.equals(player) && location.distanceSquared(block.getLocation()) < 9)
|
||||||
{
|
{
|
||||||
player.sendMessage(block.getY() + " " + otherPlayer.getLocation().getBlockY());
|
|
||||||
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, "You can't start a fire this close to " + otherPlayer.getName() + ".");
|
GriefPrevention.sendMessage(player, TextMode.Err, "You can't start a fire this close to " + otherPlayer.getName() + ".");
|
||||||
placeEvent.setCancelled(true);
|
placeEvent.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -349,25 +347,34 @@ public class BlockEventHandler implements Listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//blocks are ignited ONLY by flint and steel (not by being near lava, open flames, etc)
|
//blocks are ignited ONLY by flint and steel (not by being near lava, open flames, etc), unless configured otherwise
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onBlockIgnite (BlockIgniteEvent igniteEvent)
|
public void onBlockIgnite (BlockIgniteEvent igniteEvent)
|
||||||
{
|
{
|
||||||
if(igniteEvent.getCause() != IgniteCause.FLINT_AND_STEEL) igniteEvent.setCancelled(true);
|
if(igniteEvent.getCause() != IgniteCause.FLINT_AND_STEEL && !GriefPrevention.instance.config_fireSpreads) igniteEvent.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//fire doesn't spread, but other blocks still do (mushrooms and vines, for example)
|
//fire doesn't spread unless configured to, but other blocks still do (mushrooms and vines, for example)
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onBlockSpread (BlockSpreadEvent spreadEvent)
|
public void onBlockSpread (BlockSpreadEvent spreadEvent)
|
||||||
{
|
{
|
||||||
if(spreadEvent.getSource().getType() == Material.FIRE) spreadEvent.setCancelled(true);
|
if(spreadEvent.getSource().getType() == Material.FIRE && !GriefPrevention.instance.config_fireSpreads) spreadEvent.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//blocks are not destroyed by fire
|
//blocks are not destroyed by fire, unless configured to do so
|
||||||
@EventHandler(priority = EventPriority.HIGHEST)
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onBlockBurn (BlockBurnEvent burnEvent)
|
public void onBlockBurn (BlockBurnEvent burnEvent)
|
||||||
{
|
{
|
||||||
burnEvent.setCancelled(true);
|
if(!GriefPrevention.instance.config_fireDestroys)
|
||||||
|
{
|
||||||
|
burnEvent.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//never burn claimed blocks, regardless of settings
|
||||||
|
if(this.dataStore.getClaimAt(burnEvent.getBlock().getLocation(), false, null) != null)
|
||||||
|
{
|
||||||
|
burnEvent.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensures fluids don't flow into claims, unless out of another claim where the owner is trusted to build in the receiving claim
|
//ensures fluids don't flow into claims, unless out of another claim where the owner is trusted to build in the receiving claim
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,8 @@ public class Claim
|
||||||
//NOTE: if trying to understand this makes your head hurt, don't feel bad - it hurts mine too.
|
//NOTE: if trying to understand this makes your head hurt, don't feel bad - it hurts mine too.
|
||||||
//try drawing pictures to visualize test cases.
|
//try drawing pictures to visualize test cases.
|
||||||
|
|
||||||
|
if(!this.lesserBoundaryCorner.getWorld().equals(otherClaim.getLesserBoundaryCorner().getWorld())) return false;
|
||||||
|
|
||||||
//first, check the corners of this claim aren't inside any existing claims
|
//first, check the corners of this claim aren't inside any existing claims
|
||||||
if(otherClaim.contains(this.lesserBoundaryCorner, true, false)) return true;
|
if(otherClaim.contains(this.lesserBoundaryCorner, true, false)) return true;
|
||||||
if(otherClaim.contains(this.greaterBoundaryCorner, true, false)) return true;
|
if(otherClaim.contains(this.greaterBoundaryCorner, true, false)) return true;
|
||||||
|
|
|
||||||
|
|
@ -843,7 +843,7 @@ public class DataStore
|
||||||
//why isn't this a "repeating" task?
|
//why isn't this a "repeating" task?
|
||||||
//because depending on the status of the siege at the time the task runs, there may or may not be a reason to run the task again
|
//because depending on the status of the siege at the time the task runs, there may or may not be a reason to run the task again
|
||||||
SiegeCheckupTask task = new SiegeCheckupTask(siegeData);
|
SiegeCheckupTask task = new SiegeCheckupTask(siegeData);
|
||||||
siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60);
|
siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ends a siege
|
//ends a siege
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ class DeliverClaimBlocksTask implements Runnable
|
||||||
{
|
{
|
||||||
Player [] players = GriefPrevention.instance.getServer().getOnlinePlayers();
|
Player [] players = GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||||
|
|
||||||
|
//ensure players get at least 1 block (if accrual is totally disabled, this task won't even be scheduled)
|
||||||
|
int accruedBlocks = GriefPrevention.instance.config_claims_blocksAccruedPerHour / 12;
|
||||||
|
if(accruedBlocks == 0) accruedBlocks = 1;
|
||||||
|
|
||||||
//for each online player
|
//for each online player
|
||||||
for(int i = 0; i < players.length; i++)
|
for(int i = 0; i < players.length; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -43,8 +47,8 @@ class DeliverClaimBlocksTask implements Runnable
|
||||||
{
|
{
|
||||||
//if he's not in a vehicle and has moved at least three blocks since the last check
|
//if he's not in a vehicle and has moved at least three blocks since the last check
|
||||||
if(!player.isInsideVehicle() && (lastLocation == null || lastLocation.distanceSquared(player.getLocation()) >= 9))
|
if(!player.isInsideVehicle() && (lastLocation == null || lastLocation.distanceSquared(player.getLocation()) >= 9))
|
||||||
{
|
{
|
||||||
playerData.accruedClaimBlocks += GriefPrevention.instance.config_claims_blocksAccruedPerHour / 12;
|
playerData.accruedClaimBlocks += accruedBlocks;
|
||||||
|
|
||||||
//respect limits
|
//respect limits
|
||||||
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
|
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
|
||||||
|
|
|
||||||
|
|
@ -236,36 +236,39 @@ class EntityEventHandler implements Listener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FEATURE: prevent players who very recently participated in pvp combat from hiding inventory to protect it from looting
|
//FEATURE: prevent pvp in the first minute after spawn, and prevent pvp when one or both players have no inventory
|
||||||
//FEATURE: prevent players who are in pvp combat from logging out to avoid being defeated
|
|
||||||
Player defender = (Player)(event.getEntity());
|
Player defender = (Player)(event.getEntity());
|
||||||
|
|
||||||
PlayerData defenderData = this.dataStore.getPlayerData(((Player)event.getEntity()).getName());
|
PlayerData defenderData = this.dataStore.getPlayerData(((Player)event.getEntity()).getName());
|
||||||
PlayerData attackerData = this.dataStore.getPlayerData(attacker.getName());
|
PlayerData attackerData = this.dataStore.getPlayerData(attacker.getName());
|
||||||
|
|
||||||
long now = Calendar.getInstance().getTimeInMillis();
|
|
||||||
defenderData.lastPvpTimestamp = now;
|
|
||||||
defenderData.lastPvpPlayer = attacker.getName();
|
|
||||||
attackerData.lastPvpTimestamp = now;
|
|
||||||
attackerData.lastPvpPlayer = defender.getName();
|
|
||||||
|
|
||||||
//FEATURE: prevent pvp in the first minute after spawn, and prevent pvp when one or both players have no inventory
|
|
||||||
|
|
||||||
//otherwise if protecting spawning players
|
//otherwise if protecting spawning players
|
||||||
if(GriefPrevention.instance.config_pvp_protectFreshSpawns)
|
if(GriefPrevention.instance.config_pvp_protectFreshSpawns)
|
||||||
{
|
{
|
||||||
if(defenderData.pvpImmune)
|
if(defenderData.pvpImmune)
|
||||||
{
|
{
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
GriefPrevention.sendMessage(attacker, TextMode.Err, "You can't injure defenseless players.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(attackerData.pvpImmune)
|
if(attackerData.pvpImmune)
|
||||||
{
|
{
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
GriefPrevention.sendMessage(attacker, TextMode.Err, "You can't fight someone while you're protected from PvP.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FEATURE: prevent players who very recently participated in pvp combat from hiding inventory to protect it from looting
|
||||||
|
//FEATURE: prevent players who are in pvp combat from logging out to avoid being defeated
|
||||||
|
|
||||||
|
long now = Calendar.getInstance().getTimeInMillis();
|
||||||
|
defenderData.lastPvpTimestamp = now;
|
||||||
|
defenderData.lastPvpPlayer = attacker.getName();
|
||||||
|
attackerData.lastPvpTimestamp = now;
|
||||||
|
attackerData.lastPvpPlayer = defender.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
//FEATURE: protect claimed animals, boats, minecarts
|
//FEATURE: protect claimed animals, boats, minecarts
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ public class GriefPrevention extends JavaPlugin
|
||||||
|
|
||||||
public boolean config_creepersDontDestroySurface; //whether creeper explosions near or above the surface destroy blocks
|
public boolean config_creepersDontDestroySurface; //whether creeper explosions near or above the surface destroy blocks
|
||||||
|
|
||||||
|
public boolean config_fireSpreads; //whether fire spreads outside of claims
|
||||||
|
public boolean config_fireDestroys; //whether fire destroys blocks outside of claims
|
||||||
|
|
||||||
//reference to the economy plugin, if economy integration is enabled
|
//reference to the economy plugin, if economy integration is enabled
|
||||||
public static Economy economy = null;
|
public static Economy economy = null;
|
||||||
|
|
||||||
|
|
@ -183,6 +186,9 @@ public class GriefPrevention extends JavaPlugin
|
||||||
|
|
||||||
this.config_creepersDontDestroySurface = config.getBoolean("GriefPrevention.CreepersDontDestroySurface", true);
|
this.config_creepersDontDestroySurface = config.getBoolean("GriefPrevention.CreepersDontDestroySurface", true);
|
||||||
|
|
||||||
|
this.config_fireSpreads = config.getBoolean("GriefPrevention.FireSpreads", false);
|
||||||
|
this.config_fireDestroys = config.getBoolean("GriefPrevention.FireDestroys", false);
|
||||||
|
|
||||||
//default for claims worlds list
|
//default for claims worlds list
|
||||||
ArrayList<String> defaultSiegeWorldNames = new ArrayList<String>();
|
ArrayList<String> defaultSiegeWorldNames = new ArrayList<String>();
|
||||||
|
|
||||||
|
|
@ -218,6 +224,7 @@ public class GriefPrevention extends JavaPlugin
|
||||||
this.config_siege_blocks.add(Material.GRAVEL);
|
this.config_siege_blocks.add(Material.GRAVEL);
|
||||||
this.config_siege_blocks.add(Material.SAND);
|
this.config_siege_blocks.add(Material.SAND);
|
||||||
this.config_siege_blocks.add(Material.GLASS);
|
this.config_siege_blocks.add(Material.GLASS);
|
||||||
|
this.config_siege_blocks.add(Material.THIN_GLASS);
|
||||||
this.config_siege_blocks.add(Material.WOOD);
|
this.config_siege_blocks.add(Material.WOOD);
|
||||||
this.config_siege_blocks.add(Material.WOOL);
|
this.config_siege_blocks.add(Material.WOOL);
|
||||||
this.config_siege_blocks.add(Material.SNOW);
|
this.config_siege_blocks.add(Material.SNOW);
|
||||||
|
|
@ -286,7 +293,10 @@ public class GriefPrevention extends JavaPlugin
|
||||||
|
|
||||||
config.set("GriefPrevention.CreepersDontDestroySurface", this.config_creepersDontDestroySurface);
|
config.set("GriefPrevention.CreepersDontDestroySurface", this.config_creepersDontDestroySurface);
|
||||||
|
|
||||||
config.set("GriefPrevention.Siege.Enabled", siegeEnabledWorldNames);
|
config.set("GriefPrevention.FireSpreads", this.config_fireSpreads);
|
||||||
|
config.set("GriefPrevention.FireDestroys", this.config_fireDestroys);
|
||||||
|
|
||||||
|
config.set("GriefPrevention.Siege.Worlds", siegeEnabledWorldNames);
|
||||||
config.set("GriefPrevention.Siege.BreakableBlocks", breakableBlocksList);
|
config.set("GriefPrevention.Siege.BreakableBlocks", breakableBlocksList);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -311,8 +321,11 @@ public class GriefPrevention extends JavaPlugin
|
||||||
|
|
||||||
//unless claim block accrual is disabled, start the recurring per 5 minute event to give claim blocks to online players
|
//unless claim block accrual is disabled, start the recurring per 5 minute event to give claim blocks to online players
|
||||||
//20L ~ 1 second
|
//20L ~ 1 second
|
||||||
DeliverClaimBlocksTask task = new DeliverClaimBlocksTask();
|
if(this.config_claims_blocksAccruedPerHour > 0)
|
||||||
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, task, 20L * 60 * 5, 20L * 60 * 5);
|
{
|
||||||
|
DeliverClaimBlocksTask task = new DeliverClaimBlocksTask();
|
||||||
|
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, task, 20L * 60 * 5, 20L * 60 * 5);
|
||||||
|
}
|
||||||
|
|
||||||
//register for events
|
//register for events
|
||||||
PluginManager pluginManager = this.getServer().getPluginManager();
|
PluginManager pluginManager = this.getServer().getPluginManager();
|
||||||
|
|
@ -378,35 +391,14 @@ public class GriefPrevention extends JavaPlugin
|
||||||
//abandonclaim
|
//abandonclaim
|
||||||
if(cmd.getName().equalsIgnoreCase("abandonclaim") && player != null)
|
if(cmd.getName().equalsIgnoreCase("abandonclaim") && player != null)
|
||||||
{
|
{
|
||||||
//which claim is being abandoned?
|
this.abandonClaimHandler(player, false);
|
||||||
Claim claim = this.dataStore.getClaimAt(player.getLocation(), true /*ignore height*/, null);
|
}
|
||||||
if(claim == null)
|
|
||||||
{
|
//abandontoplevelclaim
|
||||||
GriefPrevention.sendMessage(player, TextMode.Instr, "Stand in the claim you want to delete, or consider /AbandonAllClaims.");
|
if(cmd.getName().equalsIgnoreCase("abandontoplevelclaim") && player != null)
|
||||||
}
|
{
|
||||||
|
return this.abandonClaimHandler(player, true);
|
||||||
//verify ownership
|
}
|
||||||
else if(claim.allowEdit(player) != null)
|
|
||||||
{
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, "This isn't your claim.");
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//delete it
|
|
||||||
this.dataStore.deleteClaim(claim);
|
|
||||||
|
|
||||||
//tell the player how many claim blocks he has left
|
|
||||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
|
||||||
int remainingBlocks = playerData.getRemainingClaimBlocks();
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Success, "Claim abandoned. You now have " + String.valueOf(remainingBlocks) + " available claim blocks.");
|
|
||||||
|
|
||||||
//revert any current visualization
|
|
||||||
Visualization.Revert(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ignoreclaims
|
//ignoreclaims
|
||||||
if(cmd.getName().equalsIgnoreCase("ignoreclaims") && player != null)
|
if(cmd.getName().equalsIgnoreCase("ignoreclaims") && player != null)
|
||||||
|
|
@ -1014,7 +1006,7 @@ public class GriefPrevention extends JavaPlugin
|
||||||
else if(cmd.getName().equalsIgnoreCase("siege") && player != null)
|
else if(cmd.getName().equalsIgnoreCase("siege") && player != null)
|
||||||
{
|
{
|
||||||
//error message for when siege mode is disabled
|
//error message for when siege mode is disabled
|
||||||
if(this.siegeEnabledForWorld(player.getWorld()))
|
if(!this.siegeEnabledForWorld(player.getWorld()))
|
||||||
{
|
{
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, "Siege is disabled here.");
|
GriefPrevention.sendMessage(player, TextMode.Err, "Siege is disabled here.");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1070,8 +1062,22 @@ public class GriefPrevention extends JavaPlugin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//victim must not be pvp immune
|
||||||
|
if(defenderData.pvpImmune)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, defender.getName() + " is defenseless. Go pick on somebody else.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Claim defenderClaim = this.dataStore.getClaimAt(defender.getLocation(), false, null);
|
Claim defenderClaim = this.dataStore.getClaimAt(defender.getLocation(), false, null);
|
||||||
|
|
||||||
|
//defender must have some level of permission there to be protected
|
||||||
|
if(defenderClaim == null || defenderClaim.allowAccess(defender) != null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, defender.getName() + " isn't protected there.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//attacker must be close to the claim he wants to siege
|
//attacker must be close to the claim he wants to siege
|
||||||
if(!defenderClaim.isNear(attacker.getLocation(), 25))
|
if(!defenderClaim.isNear(attacker.getLocation(), 25))
|
||||||
{
|
{
|
||||||
|
|
@ -1093,13 +1099,6 @@ public class GriefPrevention extends JavaPlugin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//defender must have some level of permission there to be protected
|
|
||||||
if(defenderClaim == null || defenderClaim.allowAccess(defender) != null)
|
|
||||||
{
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, defender.getName() + " isn't protected there.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//can't be on cooldown
|
//can't be on cooldown
|
||||||
if(dataStore.onCooldown(attacker, defender, defenderClaim))
|
if(dataStore.onCooldown(attacker, defender, defenderClaim))
|
||||||
{
|
{
|
||||||
|
|
@ -1111,13 +1110,53 @@ public class GriefPrevention extends JavaPlugin
|
||||||
dataStore.startSiege(attacker, defender, defenderClaim);
|
dataStore.startSiege(attacker, defender, defenderClaim);
|
||||||
|
|
||||||
//confirmation message for attacker, warning message for defender
|
//confirmation message for attacker, warning message for defender
|
||||||
GriefPrevention.sendMessage(player, TextMode.Warn, "You're under siege! If you log out now, you will die. You must defeat " + attacker.getName() + ", wait for him to give up, or escape.");
|
GriefPrevention.sendMessage(defender, TextMode.Warn, "You're under siege! If you log out now, you will die. You must defeat " + attacker.getName() + ", wait for him to give up, or escape.");
|
||||||
GriefPrevention.sendMessage(player, TextMode.Success, "The siege has begun! If you log out now, you will die. You must defeat " + defender.getName() + ", chase him away, or admit defeat and walk away.");
|
GriefPrevention.sendMessage(player, TextMode.Success, "The siege has begun! If you log out now, you will die. You must defeat " + defender.getName() + ", chase him away, or admit defeat and walk away.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean abandonClaimHandler(Player player, boolean deleteTopLevelClaim)
|
||||||
|
{
|
||||||
|
//which claim is being abandoned?
|
||||||
|
Claim claim = this.dataStore.getClaimAt(player.getLocation(), true /*ignore height*/, null);
|
||||||
|
if(claim == null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Instr, "Stand in the claim you want to delete, or consider /AbandonAllClaims.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//verify ownership
|
||||||
|
else if(claim.allowEdit(player) != null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "This isn't your claim.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//warn if has children and we're not explicitly deleting a top level claim
|
||||||
|
else if(claim.children.size() > 0 && !deleteTopLevelClaim)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Instr, "To delete a subdivision, stand inside it. Otherwise, use /AbandonTopLevelClaim to delete this claim and all subdivisions.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//delete it
|
||||||
|
this.dataStore.deleteClaim(claim);
|
||||||
|
|
||||||
|
//tell the player how many claim blocks he has left
|
||||||
|
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||||
|
int remainingBlocks = playerData.getRemainingClaimBlocks();
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Success, "Claim abandoned. You now have " + String.valueOf(remainingBlocks) + " available claim blocks.");
|
||||||
|
|
||||||
|
//revert any current visualization
|
||||||
|
Visualization.Revert(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//helper method keeps the trust commands consistent and eliminates duplicate code
|
//helper method keeps the trust commands consistent and eliminates duplicate code
|
||||||
private void handleTrustCommand(Player player, ClaimPermission permissionLevel, String recipientName)
|
private void handleTrustCommand(Player player, ClaimPermission permissionLevel, String recipientName)
|
||||||
{
|
{
|
||||||
|
|
@ -1314,8 +1353,7 @@ public class GriefPrevention extends JavaPlugin
|
||||||
playerData.pvpImmune = true;
|
playerData.pvpImmune = true;
|
||||||
|
|
||||||
//inform the player
|
//inform the player
|
||||||
GriefPrevention.sendMessage(player, TextMode.Info, "You have one minute of PvP protection, starting now.");
|
GriefPrevention.sendMessage(player, TextMode.Success, "You're protected from attack by other players as long as your inventory is empty.");
|
||||||
GriefPrevention.sendMessage(player, TextMode.Info, "After the minute, you can pick up items, but doing so will drop your PvP protection.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//checks whether players can create claims in a world
|
//checks whether players can create claims in a world
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.*;
|
import org.bukkit.event.player.*;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
|
@ -314,6 +315,36 @@ class PlayerEventHandler implements Listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//when a player teleports
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onPlayerTeleport(PlayerTeleportEvent event)
|
||||||
|
{
|
||||||
|
//FEATURE: prevent teleport abuse to win sieges
|
||||||
|
|
||||||
|
//these rules only apply to non-ender-pearl teleportation
|
||||||
|
if(event.getCause() == TeleportCause.ENDER_PEARL) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
Location source = event.getFrom();
|
||||||
|
Claim sourceClaim = this.dataStore.getClaimAt(source, false, null);
|
||||||
|
if(sourceClaim != null && sourceClaim.siegeData != null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "You can't teleport out of a besieged area.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location destination = event.getTo();
|
||||||
|
Claim destinationClaim = this.dataStore.getClaimAt(destination, false, null);
|
||||||
|
if(destinationClaim != null && destinationClaim.siegeData != null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "You can't teleport into a besieged area.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//when a player interacts with an entity...
|
//when a player interacts with an entity...
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
|
||||||
|
|
@ -397,10 +428,10 @@ class PlayerEventHandler implements Listener
|
||||||
PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getName());
|
PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getName());
|
||||||
if(playerData.pvpImmune)
|
if(playerData.pvpImmune)
|
||||||
{
|
{
|
||||||
//if it's been at least a minute since the last time he spawned, don't pick up the item
|
//if it's been less than 10 seconds since the last time he spawned, don't pick up the item
|
||||||
long now = Calendar.getInstance().getTimeInMillis();
|
long now = Calendar.getInstance().getTimeInMillis();
|
||||||
long elapsedSinceLastSpawn = now - playerData.lastSpawn;
|
long elapsedSinceLastSpawn = now - playerData.lastSpawn;
|
||||||
if(elapsedSinceLastSpawn < 60000)
|
if(elapsedSinceLastSpawn < 10000)
|
||||||
{
|
{
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -408,7 +439,7 @@ class PlayerEventHandler implements Listener
|
||||||
|
|
||||||
//otherwise take away his immunity. he may be armed now. at least, he's worth killing for some loot
|
//otherwise take away his immunity. he may be armed now. at least, he's worth killing for some loot
|
||||||
playerData.pvpImmune = false;
|
playerData.pvpImmune = false;
|
||||||
GriefPrevention.sendMessage(player, TextMode.Warn, "You're now vulnerable to damage from other players.");
|
GriefPrevention.sendMessage(player, TextMode.Warn, "Now you can fight with other players.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +512,7 @@ class PlayerEventHandler implements Listener
|
||||||
public void onPlayerBucketEmpty (PlayerBucketEmptyEvent bucketEvent)
|
public void onPlayerBucketEmpty (PlayerBucketEmptyEvent bucketEvent)
|
||||||
{
|
{
|
||||||
Player player = bucketEvent.getPlayer();
|
Player player = bucketEvent.getPlayer();
|
||||||
Block block = bucketEvent.getBlockClicked();
|
Block block = bucketEvent.getBlockClicked().getRelative(bucketEvent.getBlockFace());
|
||||||
int minLavaDistance = 10;
|
int minLavaDistance = 10;
|
||||||
|
|
||||||
//if the bucket is being used in a claim
|
//if the bucket is being used in a claim
|
||||||
|
|
@ -520,7 +551,7 @@ class PlayerEventHandler implements Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
//lava buckets can't be dumped near other players unless pvp is on
|
//lava buckets can't be dumped near other players unless pvp is on
|
||||||
if(!block.getWorld().getPVP())
|
if(!block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
|
||||||
{
|
{
|
||||||
if(bucketEvent.getBucket() == Material.LAVA_BUCKET)
|
if(bucketEvent.getBucket() == Material.LAVA_BUCKET)
|
||||||
{
|
{
|
||||||
|
|
@ -531,8 +562,6 @@ class PlayerEventHandler implements Listener
|
||||||
Location location = otherPlayer.getLocation();
|
Location location = otherPlayer.getLocation();
|
||||||
if(!otherPlayer.equals(player) && block.getY() >= location.getBlockY() - 1 && location.distanceSquared(block.getLocation()) < minLavaDistance * minLavaDistance)
|
if(!otherPlayer.equals(player) && block.getY() >= location.getBlockY() - 1 && location.distanceSquared(block.getLocation()) < minLavaDistance * minLavaDistance)
|
||||||
{
|
{
|
||||||
player.sendMessage(block.getY() + " " + otherPlayer.getLocation().getBlockY());
|
|
||||||
|
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, "You can't place lava this close to " + otherPlayer.getName() + ".");
|
GriefPrevention.sendMessage(player, TextMode.Err, "You can't place lava this close to " + otherPlayer.getName() + ".");
|
||||||
bucketEvent.setCancelled(true);
|
bucketEvent.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -611,6 +640,7 @@ class PlayerEventHandler implements Listener
|
||||||
event.getAction() == Action.RIGHT_CLICK_BLOCK && (
|
event.getAction() == Action.RIGHT_CLICK_BLOCK && (
|
||||||
clickedBlock.getState() instanceof InventoryHolder ||
|
clickedBlock.getState() instanceof InventoryHolder ||
|
||||||
clickedBlockType == Material.BREWING_STAND ||
|
clickedBlockType == Material.BREWING_STAND ||
|
||||||
|
clickedBlockType == Material.WORKBENCH ||
|
||||||
clickedBlockType == Material.JUKEBOX ||
|
clickedBlockType == Material.JUKEBOX ||
|
||||||
clickedBlockType == Material.ENCHANTMENT_TABLE)))
|
clickedBlockType == Material.ENCHANTMENT_TABLE)))
|
||||||
{
|
{
|
||||||
|
|
@ -639,12 +669,20 @@ class PlayerEventHandler implements Listener
|
||||||
if(noContainersReason != null)
|
if(noContainersReason != null)
|
||||||
{
|
{
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.sendMessage(noContainersReason);
|
GriefPrevention.sendMessage(player, TextMode.Err, noContainersReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if the event hasn't been cancelled, then the player is allowed to use the container
|
||||||
|
//so drop any pvp protection
|
||||||
|
if(playerData.pvpImmune)
|
||||||
|
{
|
||||||
|
playerData.pvpImmune = false;
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Warn, "Now you can fight with other players.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//apply rule for players trampling dirt (never allow it)
|
//apply rule for players trampling tilled soil back to dirt (never allow it)
|
||||||
//NOTE: that this event applies only to players. monsters and animals can still trample.
|
//NOTE: that this event applies only to players. monsters and animals can still trample.
|
||||||
else if(event.getAction() == Action.PHYSICAL && clickedBlockType == Material.SOIL)
|
else if(event.getAction() == Action.PHYSICAL && clickedBlockType == Material.SOIL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,6 @@ class SiegeCheckupTask implements Runnable
|
||||||
//schedules another checkup later
|
//schedules another checkup later
|
||||||
private void scheduleAnotherCheck()
|
private void scheduleAnotherCheck()
|
||||||
{
|
{
|
||||||
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 60);
|
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user