This commit is contained in:
Ryan Hamshire 2012-11-14 17:33:22 -08:00
parent e09a6732ba
commit 7f600e7098
30 changed files with 1266 additions and 1087 deletions

View File

@ -2,7 +2,7 @@ name: GriefPrevention
main: me.ryanhamshire.GriefPrevention.GriefPrevention
softdepend: [Vault, Multiverse-Core, My Worlds, MystCraft, Transporter]
dev-url: http://dev.bukkit.org/server-mods/grief-prevention
version: 6.9
version: 7.0
commands:
abandonclaim:
description: Deletes a claim.
@ -89,12 +89,12 @@ commands:
description: Purchases additional claim blocks with server money. Doesn't work on servers without a Vault-compatible economy plugin.
usage: /BuyClaimBlocks <numberOfBlocks>
aliases: buyclaim
permission: griefprevention.claims
permission: griefprevention.buysellclaimblocks
sellclaimblocks:
description: Sells your claim blocks for server money. Doesn't work on servers without a Vault-compatible economy plugin.
usage: /SellClaimBlocks <numberOfBlocks>
aliases: sellclaim
permission: griefprevention.claims
permission: griefprevention.buysellclaimblocks
trapped:
description: Ejects you to nearby unclaimed land. Has a substantial cooldown period.
usage: /Trapped
@ -124,8 +124,7 @@ commands:
permission: griefprevention.deathblow
claimslist:
description: Lists information about a player's claim blocks and claims.
usage: /ClaimsList <player>
permission: griefprevention.adjustclaimblocks
usage: /ClaimsList or /ClaimsList <player>
permissions:
griefprevention.createclaims:
description: Grants permission to create claims.
@ -175,4 +174,7 @@ permissions:
default: op
griefprevention.claims:
description: Grants access to claim-related slash commands.
default: true
griefprevention.buysellclaimblocks:
description: Grants access to claim block buy/sell commands.
default: true

View File

@ -150,6 +150,9 @@ public class BlockEventHandler implements Listener
return;
}
//if a player is in pvp combat, he can't give away items
if(playerData.inPvpCombat()) return;
//NOTE: to eliminate accidental give-aways, first hit on a chest displays a confirmation message
//subsequent hits donate item to the chest
@ -266,7 +269,7 @@ public class BlockEventHandler implements Listener
//FEATURE: limit fire placement, to prevent PvP-by-fire
//if placed block is fire and pvp is off, apply rules for proximity to other players
if(block.getType() == Material.FIRE && !block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
if(block.getType() == Material.FIRE && !GriefPrevention.instance.config_pvp_enabledWorlds.contains(block.getWorld()) && !player.hasPermission("griefprevention.lava"))
{
List<Player> players = block.getWorld().getPlayers();
for(int i = 0; i < players.size(); i++)

View File

@ -82,7 +82,7 @@ public class Claim
//administrative claims are created and maintained by players with the griefprevention.adminclaims permission.
public boolean isAdminClaim()
{
return this.ownerName.isEmpty();
return (this.ownerName == null || this.ownerName.isEmpty());
}
//accessor for ID

View File

@ -1,6 +1,6 @@
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2011 Ryan Hamshire
Copyright (C) 2012 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

View File

@ -1,15 +1,33 @@
package me.ryanhamshire.GriefPrevention;
public class CustomizableMessage
{
public Messages id;
public String text;
public String notes;
public CustomizableMessage(Messages id, String text, String notes)
{
this.id = id;
this.text = text;
this.notes = notes;
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
public class CustomizableMessage
{
public Messages id;
public String text;
public String notes;
public CustomizableMessage(Messages id, String text, String notes)
{
this.id = id;
this.text = text;
this.notes = notes;
}
}

View File

@ -884,7 +884,7 @@ public abstract class DataStore
this.addDefault(defaults, Messages.AutomaticClaimNotification, "This chest and nearby blocks are protected from breakage and theft. The temporary gold and glowstone blocks mark the protected area. To toggle them on and off, right-click with a stick.", null);
this.addDefault(defaults, Messages.TrustCommandAdvertisement, "Use the /trust command to grant other players access.", null);
this.addDefault(defaults, Messages.GoldenShovelAdvertisement, "To claim more land, you need a golden shovel. When you equip one, you'll get more information.", null);
this.addDefault(defaults, Messages.UnprotectedChestWarning, "This chest is NOT protected. Consider expanding an existing claim or creating a new one.", null);
this.addDefault(defaults, Messages.UnprotectedChestWarning, "This chest is NOT protected. Consider using a golden shovel to expand an existing claim or to create a new one.", null);
this.addDefault(defaults, Messages.ThatPlayerPvPImmune, "You can't injure defenseless players.", null);
this.addDefault(defaults, Messages.CantFightWhileImmune, "You can't fight someone while you're protected from PvP.", null);
this.addDefault(defaults, Messages.NoDamageClaimedEntity, "That belongs to {0}.", "0: owner name");
@ -893,7 +893,7 @@ public abstract class DataStore
this.addDefault(defaults, Messages.CreativeBasicsDemoAdvertisement, "Land Claim Help: http://tinyurl.com/c7bajb8", null);
this.addDefault(defaults, Messages.SurvivalBasicsDemoAdvertisement, "Land Claim Help: http://tinyurl.com/6nkwegj", null);
this.addDefault(defaults, Messages.TrappedChatKeyword, "trapped", "When mentioned in chat, players get information about the /trapped command.");
this.addDefault(defaults, Messages.TrappedInstructions, "Are you trapped in someone's claim? Consider the /trapped command.", null);
this.addDefault(defaults, Messages.TrappedInstructions, "Are you trapped in someone's land claim? Try the /trapped command.", null);
this.addDefault(defaults, Messages.PvPNoDrop, "You can't drop items while in PvP combat.", null);
this.addDefault(defaults, Messages.SiegeNoTeleport, "You can't teleport out of a besieged area.", null);
this.addDefault(defaults, Messages.BesiegedNoTeleport, "You can't teleport into a besieged area.", null);
@ -952,7 +952,7 @@ public abstract class DataStore
this.addDefault(defaults, Messages.HowToClaimRegex, "(^|.*\\W)how\\W.*\\W(claim|protect|lock)(\\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.BuildingOutsideClaims, "Other players can undo your work here! Consider claiming this area to protect your work.", null);
this.addDefault(defaults, Messages.BuildingOutsideClaims, "Other players can undo your work here! Consider using a golden shovel to claim this area so that your work will be protected.", null);
this.addDefault(defaults, Messages.TrappedWontWorkHere, "Sorry, unable to find a safe location to teleport you to. Contact an admin, or consider /kill if you don't want to wait.", null);
this.addDefault(defaults, Messages.CommandBannedInPvP, "You can't use that command while in PvP combat.", null);
this.addDefault(defaults, Messages.UnclaimCleanupWarning, "The land you've unclaimed may be changed by other players or cleaned up by administrators. If you've built something there you want to keep, you should reclaim it.", null);
@ -961,6 +961,8 @@ public abstract class DataStore
this.addDefault(defaults, Messages.NoTNTDamageAboveSeaLevel, "Warning: TNT will not destroy blocks above sea level.", null);
this.addDefault(defaults, Messages.NoTNTDamageClaims, "Warning: TNT will not destroy claimed blocks.", null);
this.addDefault(defaults, Messages.IgnoreClaimsAdvertisement, "To override, use /IgnoreClaims.", null);
this.addDefault(defaults, Messages.NoPermissionForCommand, "You don't have permission to do that.", null);
this.addDefault(defaults, Messages.ClaimsListNoPermission, "You don't have permission to get information about another player's land claims.", null);
//load the config file
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));

View File

@ -1,75 +1,75 @@
/*
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.Location;
import org.bukkit.entity.Player;
//FEATURE: give players claim blocks for playing, as long as they're not away from their computer
//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing
class DeliverClaimBlocksTask implements Runnable
{
@Override
public void run()
{
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(int i = 0; i < players.length; i++)
{
Player player = players[i];
DataStore dataStore = GriefPrevention.instance.dataStore;
PlayerData playerData = dataStore.getPlayerData(player.getName());
Location lastLocation = playerData.lastAfkCheckLocation;
try //distance squared will throw an exception if the player has changed worlds
{
//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 is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued
//in that case, leave his blocks where they are
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue;
//add blocks
playerData.accruedClaimBlocks += accruedBlocks;
//respect limits
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
{
playerData.accruedClaimBlocks = GriefPrevention.instance.config_claims_maxAccruedBlocks;
}
//intentionally NOT saving data here to reduce overall secondary storage access frequency
//many other operations will cause this players data to save, including his eventual logout
//dataStore.savePlayerData(player.getName(), playerData);
}
}
catch(Exception e) { }
//remember current location for next time
playerData.lastAfkCheckLocation = player.getLocation();
}
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.Location;
import org.bukkit.entity.Player;
//FEATURE: give players claim blocks for playing, as long as they're not away from their computer
//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing
class DeliverClaimBlocksTask implements Runnable
{
@Override
public void run()
{
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(int i = 0; i < players.length; i++)
{
Player player = players[i];
DataStore dataStore = GriefPrevention.instance.dataStore;
PlayerData playerData = dataStore.getPlayerData(player.getName());
Location lastLocation = playerData.lastAfkCheckLocation;
try //distance squared will throw an exception if the player has changed worlds
{
//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 is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued
//in that case, leave his blocks where they are
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue;
//add blocks
playerData.accruedClaimBlocks += accruedBlocks;
//respect limits
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
{
playerData.accruedClaimBlocks = GriefPrevention.instance.config_claims_maxAccruedBlocks;
}
//intentionally NOT saving data here to reduce overall secondary storage access frequency
//many other operations will cause this players data to save, including his eventual logout
//dataStore.savePlayerData(player.getName(), playerData);
}
}
catch(Exception e) { }
//remember current location for next time
playerData.lastAfkCheckLocation = player.getLocation();
}
}
}

View File

@ -1,143 +1,143 @@
/*
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 java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
//FEATURE: creative mode worlds get a regular entity cleanup
//this main thread task revisits the location of a partially chopped tree from several minutes ago
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
class EntityCleanupTask implements Runnable
{
//where to start cleaning in the list of entities
private double percentageStart;
public EntityCleanupTask(double percentageStart)
{
this.percentageStart = percentageStart;
}
@Override
public void run()
{
ArrayList<World> worlds = GriefPrevention.instance.config_claims_enabledCreativeWorlds;
for(int i = 0; i < worlds.size(); i++)
{
World world = worlds.get(i);
List<Entity> entities = world.getEntities();
//starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities
int j = (int)(entities.size() * this.percentageStart);
int k = (int)(entities.size() * (this.percentageStart + .1));
Claim cachedClaim = null;
for(; j < entities.size() && j < k; j++)
{
Entity entity = entities.get(j);
boolean remove = false;
if(entity instanceof Boat) //boats must be occupied
{
Boat boat = (Boat)entity;
if(boat.isEmpty()) remove = true;
}
else if(entity instanceof Vehicle)
{
Vehicle vehicle = (Vehicle)entity;
//minecarts in motion must be occupied by a player
if(vehicle.getVelocity().lengthSquared() != 0)
{
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
{
remove = true;
}
}
//stationary carts must be on rails
else
{
Material material = world.getBlockAt(vehicle.getLocation()).getType();
if(material != Material.RAILS && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
{
remove = true;
}
}
}
//all non-player entities must be in claims
else if(!(entity instanceof Player))
{
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
if(claim != null)
{
cachedClaim = claim;
}
else
{
remove = true;
}
}
if(remove)
{
entity.remove();
}
}
}
//starting and stopping point. each execution of the task scans 5% of the server's claims
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
int j = (int)(claims.size() * this.percentageStart);
int k = (int)(claims.size() * (this.percentageStart + .05));
for(; j < claims.size() && j < k; j++)
{
Claim claim = claims.get(j);
//if it's a creative mode claim
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
{
//check its entity count and remove any extras
claim.allowMoreEntities();
}
}
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
double nextRunPercentageStart = this.percentageStart + .05;
if(nextRunPercentageStart > .99)
{
nextRunPercentageStart = 0;
System.gc(); //clean up every hour
}
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
//FEATURE: creative mode worlds get a regular entity cleanup
//this main thread task revisits the location of a partially chopped tree from several minutes ago
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
class EntityCleanupTask implements Runnable
{
//where to start cleaning in the list of entities
private double percentageStart;
public EntityCleanupTask(double percentageStart)
{
this.percentageStart = percentageStart;
}
@Override
public void run()
{
ArrayList<World> worlds = GriefPrevention.instance.config_claims_enabledCreativeWorlds;
for(int i = 0; i < worlds.size(); i++)
{
World world = worlds.get(i);
List<Entity> entities = world.getEntities();
//starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities
int j = (int)(entities.size() * this.percentageStart);
int k = (int)(entities.size() * (this.percentageStart + .1));
Claim cachedClaim = null;
for(; j < entities.size() && j < k; j++)
{
Entity entity = entities.get(j);
boolean remove = false;
if(entity instanceof Boat) //boats must be occupied
{
Boat boat = (Boat)entity;
if(boat.isEmpty()) remove = true;
}
else if(entity instanceof Vehicle)
{
Vehicle vehicle = (Vehicle)entity;
//minecarts in motion must be occupied by a player
if(vehicle.getVelocity().lengthSquared() != 0)
{
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
{
remove = true;
}
}
//stationary carts must be on rails
else
{
Material material = world.getBlockAt(vehicle.getLocation()).getType();
if(material != Material.RAILS && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
{
remove = true;
}
}
}
//all non-player entities must be in claims
else if(!(entity instanceof Player))
{
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
if(claim != null)
{
cachedClaim = claim;
}
else
{
remove = true;
}
}
if(remove)
{
entity.remove();
}
}
}
//starting and stopping point. each execution of the task scans 5% of the server's claims
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
int j = (int)(claims.size() * this.percentageStart);
int k = (int)(claims.size() * (this.percentageStart + .05));
for(; j < claims.size() && j < k; j++)
{
Claim claim = claims.get(j);
//if it's a creative mode claim
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
{
//check its entity count and remove any extras
claim.allowMoreEntities();
}
}
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
double nextRunPercentageStart = this.percentageStart + .05;
if(nextRunPercentageStart > .99)
{
nextRunPercentageStart = 0;
System.gc(); //clean up every hour
}
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
}
}

View File

@ -35,6 +35,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -361,7 +362,7 @@ class EntityEventHandler implements Listener
}
//if the attacker is a player and defender is a player (pvp combat)
if(attacker != null && event.getEntity() instanceof Player)
if(attacker != null && event.getEntity() instanceof Player && GriefPrevention.instance.config_pvp_enabledWorlds.contains(attacker.getWorld()))
{
//FEATURE: prevent pvp in the first minute after spawn, and prevent pvp when one or both players have no inventory
@ -425,10 +426,21 @@ class EntityEventHandler implements Listener
//if it's claimed
if(claim != null)
{
//if damaged by anything other than a player, cancel the event
//if damaged by anything other than a player (exception villagers injured by zombies in admin claims), cancel the event
//why exception? so admins can set up a village which can't be CHANGED by players, but must be "protected" by players.
if(attacker == null)
{
event.setCancelled(true);
//exception case
if(event.getEntity() instanceof Villager && damageSource instanceof Monster && claim.isAdminClaim())
{
return;
}
//all other cases
else
{
event.setCancelled(true);
}
}
//otherwise the player damaging the entity must have permission

View File

@ -1,66 +1,66 @@
/*
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.entity.Player;
//tells a player about how many claim blocks he has, etc
//implemented as a task so that it can be delayed
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
class EquipShovelProcessingTask implements Runnable
{
//player data
private Player player;
public EquipShovelProcessingTask(Player player)
{
this.player = player;
}
@Override
public void run()
{
//if he logged out, don't do anything
if(!player.isOnline()) return;
//if he's not holding the golden shovel anymore, do nothing
if(player.getItemInHand().getType() != GriefPrevention.instance.config_claims_modificationTool) return;
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
int remainingBlocks = playerData.getRemainingClaimBlocks();
//if in basic claims mode...
if(playerData.shovelMode == ShovelMode.Basic)
{
//tell him how many claim blocks he has available
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks));
//link to a video demo of land claiming, based on world type
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
{
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsDemoAdvertisement);
}
else
{
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsDemoAdvertisement);
}
}
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.entity.Player;
//tells a player about how many claim blocks he has, etc
//implemented as a task so that it can be delayed
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
class EquipShovelProcessingTask implements Runnable
{
//player data
private Player player;
public EquipShovelProcessingTask(Player player)
{
this.player = player;
}
@Override
public void run()
{
//if he logged out, don't do anything
if(!player.isOnline()) return;
//if he's not holding the golden shovel anymore, do nothing
if(player.getItemInHand().getType() != GriefPrevention.instance.config_claims_modificationTool) return;
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
int remainingBlocks = playerData.getRemainingClaimBlocks();
//if in basic claims mode...
if(playerData.shovelMode == ShovelMode.Basic)
{
//tell him how many claim blocks he has available
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks));
//link to a video demo of land claiming, based on world type
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
{
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsDemoAdvertisement);
}
else
{
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsDemoAdvertisement);
}
}
}
}

View File

@ -106,6 +106,7 @@ public class GriefPrevention extends JavaPlugin
public String config_spam_warningMessage; //message to show a player who is close to spam level
public String config_spam_allowedIpAddresses; //IP addresses which will not be censored
public ArrayList<World> config_pvp_enabledWorlds; //list of worlds where pvp anti-grief rules apply
public boolean config_pvp_protectFreshSpawns; //whether to make newly spawned players immune until they pick up an item
public boolean config_pvp_punishLogout; //whether to kill players who log out during PvP combat
public int config_pvp_combatTimeoutSeconds; //how long combat is considered to continue after the most recent damage
@ -238,6 +239,40 @@ public class GriefPrevention extends JavaPlugin
}
}
//default for pvp worlds list
ArrayList<String> defaultPvpWorldNames = new ArrayList<String>();
for(int i = 0; i < worlds.size(); i++)
{
World world = worlds.get(i);
if(world.getPVP())
{
defaultPvpWorldNames.add(world.getName());
}
}
//get pvp world names from the config file
List<String> pvpEnabledWorldNames = config.getStringList("GriefPrevention.PvP.Worlds");
if(pvpEnabledWorldNames == null || pvpEnabledWorldNames.size() == 0)
{
pvpEnabledWorldNames = defaultPvpWorldNames;
}
//validate that list
this.config_pvp_enabledWorlds = new ArrayList<World>();
for(int i = 0; i < pvpEnabledWorldNames.size(); i++)
{
String worldName = pvpEnabledWorldNames.get(i);
World world = this.getServer().getWorld(worldName);
if(world == null)
{
AddLogEntry("Error: PvP Configuration: There's no world named \"" + worldName + "\". Please update your config.yml.");
}
else
{
this.config_pvp_enabledWorlds.add(world);
}
}
//sea level
this.config_seaLevelOverride = new HashMap<String, Integer>();
for(int i = 0; i < worlds.size(); i++)
@ -525,6 +560,7 @@ public class GriefPrevention extends JavaPlugin
config.set("GriefPrevention.Spam.BanMessage", this.config_spam_banMessage);
config.set("GriefPrevention.Spam.AllowedIpAddresses", this.config_spam_allowedIpAddresses);
config.set("GriefPrevention.PvP.Worlds", pvpEnabledWorldNames);
config.set("GriefPrevention.PvP.ProtectFreshSpawns", this.config_pvp_protectFreshSpawns);
config.set("GriefPrevention.PvP.PunishLogout", this.config_pvp_punishLogout);
config.set("GriefPrevention.PvP.CombatTimeoutSeconds", this.config_pvp_combatTimeoutSeconds);
@ -1148,6 +1184,12 @@ public class GriefPrevention extends JavaPlugin
return true;
}
if(!player.hasPermission("griefprevention.buysellclaimblocks"))
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoPermissionForCommand);
return true;
}
//if purchase disabled, send error message
if(GriefPrevention.instance.config_economy_claimBlocksPurchaseCost == 0)
{
@ -1233,6 +1275,12 @@ public class GriefPrevention extends JavaPlugin
return true;
}
if(!player.hasPermission("griefprevention.buysellclaimblocks"))
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoPermissionForCommand);
return true;
}
//if disabled, error message
if(GriefPrevention.instance.config_economy_claimBlocksSellValue == 0)
{
@ -1404,21 +1452,40 @@ public class GriefPrevention extends JavaPlugin
return true;
}
//claimslist <player>
//claimslist or claimslist <player>
else if(cmd.getName().equalsIgnoreCase("claimslist"))
{
//requires exactly one parameter, the other player's name
if(args.length != 1) return false;
//at most one parameter
if(args.length > 1) return false;
//try to find that player
OfflinePlayer otherPlayer = this.resolvePlayer(args[0]);
if(otherPlayer == null)
//player whose claims will be listed
OfflinePlayer otherPlayer;
//if another player isn't specified, assume current player
if(args.length < 1)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
return true;
otherPlayer = player;
}
//load the player's data
//otherwise if no permission to delve into another player's claims data
else if(!player.hasPermission("griefprevention.deleteclaims"))
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.ClaimsListNoPermission);
return true;
}
//otherwise try to find the specified player
else
{
otherPlayer = this.resolvePlayer(args[0]);
if(otherPlayer == null)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
return true;
}
}
//load the target player's data
PlayerData playerData = this.dataStore.getPlayerData(otherPlayer.getName());
GriefPrevention.sendMessage(player, TextMode.Instr, " " + playerData.accruedClaimBlocks + "(+" + playerData.bonusClaimBlocks + ")=" + (playerData.accruedClaimBlocks + playerData.bonusClaimBlocks));
for(int i = 0; i < playerData.claims.size(); i++)
@ -1597,6 +1664,13 @@ public class GriefPrevention extends JavaPlugin
return true;
}
//if the player is in an administrative claim, he should contact an admin
if(claim.isAdminClaim())
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.TrappedWontWorkHere);
return true;
}
//check cooldown
long lastTrappedUsage = playerData.lastTrappedUsage.getTime();
long nextTrappedUsage = lastTrappedUsage + 1000 * 60 * 60 * this.config_claims_trappedCooldownHours;
@ -2003,7 +2077,7 @@ public class GriefPrevention extends JavaPlugin
public void checkPvpProtectionNeeded(Player player)
{
//if pvp is disabled, do nothing
if(!player.getWorld().getPVP()) return;
if(!this.config_pvp_enabledWorlds.contains(player.getWorld())) return;
//if player is in creative mode, do nothing
if(player.getGameMode() == GameMode.CREATIVE) return;

View File

@ -1,17 +1,35 @@
package me.ryanhamshire.GriefPrevention;
import java.net.InetAddress;
public class IpBanInfo
{
InetAddress address;
long expirationTimestamp;
String bannedAccountName;
IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName)
{
this.address = address;
this.expirationTimestamp = expirationTimestamp;
this.bannedAccountName = bannedAccountName;
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.net.InetAddress;
public class IpBanInfo
{
InetAddress address;
long expirationTimestamp;
String bannedAccountName;
IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName)
{
this.address = address;
this.expirationTimestamp = expirationTimestamp;
this.bannedAccountName = bannedAccountName;
}
}

View File

@ -1,56 +1,74 @@
package me.ryanhamshire.GriefPrevention;
import java.util.ArrayList;
//ordered list of material info objects, for fast searching
public class MaterialCollection
{
ArrayList<MaterialInfo> materials = new ArrayList<MaterialInfo>();
void Add(MaterialInfo material)
{
int i;
for(i = 0; i < this.materials.size() && this.materials.get(i).typeID <= material.typeID; i++);
this.materials.add(i, material);
}
boolean Contains(MaterialInfo material)
{
for(int i = 0; i < this.materials.size() ; i++)
{
MaterialInfo thisMaterial = this.materials.get(i);
if(material.typeID == thisMaterial.typeID && (thisMaterial.allDataValues || material.data == thisMaterial.data))
{
return true;
}
else if(thisMaterial.typeID > material.typeID)
{
return false;
}
}
return false;
}
@Override
public String toString()
{
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < this.materials.size(); i++)
{
stringBuilder.append(this.materials.get(i).toString() + " ");
}
return stringBuilder.toString();
}
public int size()
{
return this.materials.size();
}
public void clear()
{
this.materials.clear();
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.util.ArrayList;
//ordered list of material info objects, for fast searching
public class MaterialCollection
{
ArrayList<MaterialInfo> materials = new ArrayList<MaterialInfo>();
void Add(MaterialInfo material)
{
int i;
for(i = 0; i < this.materials.size() && this.materials.get(i).typeID <= material.typeID; i++);
this.materials.add(i, material);
}
boolean Contains(MaterialInfo material)
{
for(int i = 0; i < this.materials.size() ; i++)
{
MaterialInfo thisMaterial = this.materials.get(i);
if(material.typeID == thisMaterial.typeID && (thisMaterial.allDataValues || material.data == thisMaterial.data))
{
return true;
}
else if(thisMaterial.typeID > material.typeID)
{
return false;
}
}
return false;
}
@Override
public String toString()
{
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < this.materials.size(); i++)
{
stringBuilder.append(this.materials.get(i).toString() + " ");
}
return stringBuilder.toString();
}
public int size()
{
return this.materials.size();
}
public void clear()
{
this.materials.clear();
}
}

View File

@ -1,75 +1,93 @@
package me.ryanhamshire.GriefPrevention;
//represents a material or collection of materials
public class MaterialInfo
{
int typeID;
byte data;
boolean allDataValues;
String description;
public MaterialInfo(int typeID, byte data, String description)
{
this.typeID = typeID;
this.data = data;
this.allDataValues = false;
this.description = description;
}
public MaterialInfo(int typeID, String description)
{
this.typeID = typeID;
this.data = 0;
this.allDataValues = true;
this.description = description;
}
private MaterialInfo(int typeID, byte data, boolean allDataValues, String description)
{
this.typeID = typeID;
this.data = data;
this.allDataValues = allDataValues;
this.description = description;
}
@Override
public String toString()
{
String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues?"*":String.valueOf(this.data));
if(this.description != null) returnValue += ":" + this.description;
return returnValue;
}
public static MaterialInfo fromString(String string)
{
if(string == null || string.isEmpty()) return null;
String [] parts = string.split(":");
if(parts.length < 3) return null;
try
{
int typeID = Integer.parseInt(parts[0]);
byte data;
boolean allDataValues;
if(parts[1].equals("*"))
{
allDataValues = true;
data = 0;
}
else
{
allDataValues = false;
data = Byte.parseByte(parts[1]);
}
return new MaterialInfo(typeID, data, allDataValues, parts[2]);
}
catch(NumberFormatException exception)
{
return null;
}
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
//represents a material or collection of materials
public class MaterialInfo
{
int typeID;
byte data;
boolean allDataValues;
String description;
public MaterialInfo(int typeID, byte data, String description)
{
this.typeID = typeID;
this.data = data;
this.allDataValues = false;
this.description = description;
}
public MaterialInfo(int typeID, String description)
{
this.typeID = typeID;
this.data = 0;
this.allDataValues = true;
this.description = description;
}
private MaterialInfo(int typeID, byte data, boolean allDataValues, String description)
{
this.typeID = typeID;
this.data = data;
this.allDataValues = allDataValues;
this.description = description;
}
@Override
public String toString()
{
String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues?"*":String.valueOf(this.data));
if(this.description != null) returnValue += ":" + this.description;
return returnValue;
}
public static MaterialInfo fromString(String string)
{
if(string == null || string.isEmpty()) return null;
String [] parts = string.split(":");
if(parts.length < 3) return null;
try
{
int typeID = Integer.parseInt(parts[0]);
byte data;
boolean allDataValues;
if(parts[1].equals("*"))
{
allDataValues = true;
data = 0;
}
else
{
allDataValues = false;
data = Byte.parseByte(parts[1]);
}
return new MaterialInfo(typeID, data, allDataValues, parts[2]);
}
catch(NumberFormatException exception)
{
return null;
}
}
}

View File

@ -1,6 +1,24 @@
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
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, BuildingOutsideClaims, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement
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, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement, NoPermissionForCommand, ClaimsListNoPermission
}

View File

@ -125,23 +125,26 @@ class PlayerEventHandler implements Listener
//if the player has permission to spam, don't bother even examining the message
if(player.hasPermission("griefprevention.spam")) return false;
//remedy any CAPS SPAM without bothering to fault the player for it
boolean spam = false;
boolean muted = false;
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
//remedy any CAPS SPAM, exception for very short messages which could be emoticons like =D or XD
if(message.length() > 4 && this.stringsAreSimilar(message.toUpperCase(), message))
{
if(event instanceof AsyncPlayerChatEvent)
//exception for strings containing forward slash to avoid changing a case-sensitive URL
if(event instanceof AsyncPlayerChatEvent && !message.contains("/"))
{
((AsyncPlayerChatEvent)event).setMessage(message.toLowerCase());
playerData.spamCount++;
spam = true;
}
}
//where other types of spam are concerned, casing isn't significant
message = message.toLowerCase();
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
boolean spam = false;
boolean muted = false;
//check message content and timing
long millisecondsSinceLastMessage = (new Date()).getTime() - playerData.lastMessageTimestamp.getTime();
@ -363,7 +366,7 @@ class PlayerEventHandler implements Listener
//if in pvp, block any pvp-banned slash commands
PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getName());
if(playerData.inPvpCombat() && GriefPrevention.instance.config_pvp_blockedCommands.contains(command))
if((playerData.inPvpCombat() || playerData.siegeData != null) && GriefPrevention.instance.config_pvp_blockedCommands.contains(command))
{
event.setCancelled(true);
GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, Messages.CommandBannedInPvP);
@ -642,17 +645,10 @@ class PlayerEventHandler implements Listener
if(event.getCause() == TeleportCause.ENDER_PEARL) return;
Player player = event.getPlayer();
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
if(playerData.inPvpCombat())
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoTeleportPvPCombat);
event.setCancelled(true);
return;
}
Location source = event.getFrom();
Claim sourceClaim = this.dataStore.getClaimAt(source, false, null);
Claim sourceClaim = this.dataStore.getClaimAt(source, false, playerData.lastClaim);
if(sourceClaim != null && sourceClaim.siegeData != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeNoTeleport);
@ -875,7 +871,7 @@ class PlayerEventHandler implements Listener
}
//lava buckets can't be dumped near other players unless pvp is on
if(!block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
if(!GriefPrevention.instance.config_pvp_enabledWorlds.contains(block.getWorld()) && !player.hasPermission("griefprevention.lava"))
{
if(bucketEvent.getBucket() == Material.LAVA_BUCKET)
{

View File

@ -1,69 +1,69 @@
/*
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 java.util.Calendar;
import org.bukkit.Location;
import org.bukkit.entity.Player;
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
//related to the /trapped slash command
//this does run in the main thread, so it's okay to make non-thread-safe calls
class PlayerRescueTask implements Runnable
{
//original location where /trapped was used
private Location location;
//player data
private Player player;
public PlayerRescueTask(Player player, Location location)
{
this.player = player;
this.location = location;
}
@Override
public void run()
{
//if he logged out, don't do anything
if(!player.isOnline()) return;
//he no longer has a pending /trapped slash command, so he can try to use it again now
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
playerData.pendingTrapped = false;
//if the player moved three or more blocks from where he used /trapped, admonish him and don't save him
if(player.getLocation().distance(this.location) > 3)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved);
return;
}
//otherwise find a place to teleport him
Location destination = GriefPrevention.instance.ejectPlayer(this.player);
//log entry, in case admins want to investigate the "trap"
GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(destination) + ".");
//timestamp this successful save so that he can't use /trapped again for a while
playerData.lastTrappedUsage = Calendar.getInstance().getTime();
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.util.Calendar;
import org.bukkit.Location;
import org.bukkit.entity.Player;
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
//related to the /trapped slash command
//this does run in the main thread, so it's okay to make non-thread-safe calls
class PlayerRescueTask implements Runnable
{
//original location where /trapped was used
private Location location;
//player data
private Player player;
public PlayerRescueTask(Player player, Location location)
{
this.player = player;
this.location = location;
}
@Override
public void run()
{
//if he logged out, don't do anything
if(!player.isOnline()) return;
//he no longer has a pending /trapped slash command, so he can try to use it again now
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
playerData.pendingTrapped = false;
//if the player moved three or more blocks from where he used /trapped, admonish him and don't save him
if(player.getLocation().distance(this.location) > 3)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved);
return;
}
//otherwise find a place to teleport him
Location destination = GriefPrevention.instance.ejectPlayer(this.player);
//log entry, in case admins want to investigate the "trap"
GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(destination) + ".");
//timestamp this successful save so that he can't use /trapped again for a while
playerData.lastTrappedUsage = Calendar.getInstance().getTime();
}
}

View File

@ -1,6 +1,6 @@
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2011 Ryan Hamshire
Copyright (C) 2012 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

View File

@ -1,6 +1,6 @@
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2011 Ryan Hamshire
Copyright (C) 2012 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

View File

@ -1,56 +1,56 @@
/*
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.entity.Player;
//secures a claim after a siege looting window has closed
class SecureClaimTask implements Runnable
{
private SiegeData siegeData;
public SecureClaimTask(SiegeData siegeData)
{
this.siegeData = siegeData;
}
@Override
public void run()
{
//for each claim involved in this siege
for(int i = 0; i < this.siegeData.claims.size(); i++)
{
//lock the doors
Claim claim = this.siegeData.claims.get(i);
claim.doorsOpen = false;
//eject bad guys
Player [] onlinePlayers = GriefPrevention.instance.getServer().getOnlinePlayers();
for(int j = 0; j < onlinePlayers.length; j++)
{
Player player = onlinePlayers[j];
if(claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection);
GriefPrevention.instance.ejectPlayer(player);
}
}
}
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.entity.Player;
//secures a claim after a siege looting window has closed
class SecureClaimTask implements Runnable
{
private SiegeData siegeData;
public SecureClaimTask(SiegeData siegeData)
{
this.siegeData = siegeData;
}
@Override
public void run()
{
//for each claim involved in this siege
for(int i = 0; i < this.siegeData.claims.size(); i++)
{
//lock the doors
Claim claim = this.siegeData.claims.get(i);
claim.doorsOpen = false;
//eject bad guys
Player [] onlinePlayers = GriefPrevention.instance.getServer().getOnlinePlayers();
for(int j = 0; j < onlinePlayers.length; j++)
{
Player player = onlinePlayers[j];
if(claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null)
{
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection);
GriefPrevention.instance.ejectPlayer(player);
}
}
}
}
}

View File

@ -1,44 +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);
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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);
}
}

View File

@ -1,30 +1,30 @@
/*
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;
//enumeration for golden shovel modes
enum ShovelMode
{
Basic,
Admin,
Subdivide,
RestoreNature,
RestoreNatureAggressive,
RestoreNatureFill
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
//enumeration for golden shovel modes
enum ShovelMode
{
Basic,
Admin,
Subdivide,
RestoreNature,
RestoreNatureAggressive,
RestoreNatureFill
}

View File

@ -1,110 +1,110 @@
/*
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.entity.Player;
//checks to see whether or not a siege should end based on the locations of the players
//for example, defender escaped or attacker gave up and left
class SiegeCheckupTask implements Runnable
{
private SiegeData siegeData;
public SiegeCheckupTask(SiegeData siegeData)
{
this.siegeData = siegeData;
}
@Override
public void run()
{
DataStore dataStore = GriefPrevention.instance.dataStore;
Player defender = this.siegeData.defender;
Player attacker = this.siegeData.attacker;
//where is the defender?
Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null);
//if this is a new claim and he has some permission there, extend the siege to include it
if(defenderClaim != null)
{
String noAccessReason = defenderClaim.allowAccess(defender);
if(defenderClaim.canSiege(defender) && noAccessReason == null)
{
this.siegeData.claims.add(defenderClaim);
defenderClaim.siegeData = this.siegeData;
}
}
//determine who's close enough to the siege area to be considered "still here"
boolean attackerRemains = this.playerRemains(attacker);
boolean defenderRemains = this.playerRemains(defender);
//if they're both here, just plan to come check again later
if(attackerRemains && defenderRemains)
{
this.scheduleAnotherCheck();
}
//otherwise attacker wins if the defender runs away
else if(attackerRemains && !defenderRemains)
{
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
}
//or defender wins if the attacker leaves
else if(!attackerRemains && defenderRemains)
{
dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), false);
}
//if they both left, but are still close together, the battle continues (check again later)
else if(attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing
{
this.scheduleAnotherCheck();
}
//otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase)
else
{
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
}
}
//a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight
private boolean playerRemains(Player player)
{
for(int i = 0; i < this.siegeData.claims.size(); i++)
{
Claim claim = this.siegeData.claims.get(i);
if(claim.isNear(player.getLocation(), 25))
{
return true;
}
}
return false;
}
//schedules another checkup later
private void scheduleAnotherCheck()
{
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.entity.Player;
//checks to see whether or not a siege should end based on the locations of the players
//for example, defender escaped or attacker gave up and left
class SiegeCheckupTask implements Runnable
{
private SiegeData siegeData;
public SiegeCheckupTask(SiegeData siegeData)
{
this.siegeData = siegeData;
}
@Override
public void run()
{
DataStore dataStore = GriefPrevention.instance.dataStore;
Player defender = this.siegeData.defender;
Player attacker = this.siegeData.attacker;
//where is the defender?
Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null);
//if this is a new claim and he has some permission there, extend the siege to include it
if(defenderClaim != null)
{
String noAccessReason = defenderClaim.allowAccess(defender);
if(defenderClaim.canSiege(defender) && noAccessReason == null)
{
this.siegeData.claims.add(defenderClaim);
defenderClaim.siegeData = this.siegeData;
}
}
//determine who's close enough to the siege area to be considered "still here"
boolean attackerRemains = this.playerRemains(attacker);
boolean defenderRemains = this.playerRemains(defender);
//if they're both here, just plan to come check again later
if(attackerRemains && defenderRemains)
{
this.scheduleAnotherCheck();
}
//otherwise attacker wins if the defender runs away
else if(attackerRemains && !defenderRemains)
{
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
}
//or defender wins if the attacker leaves
else if(!attackerRemains && defenderRemains)
{
dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), false);
}
//if they both left, but are still close together, the battle continues (check again later)
else if(attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing
{
this.scheduleAnotherCheck();
}
//otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase)
else
{
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
}
}
//a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight
private boolean playerRemains(Player player)
{
for(int i = 0; i < this.siegeData.claims.size(); i++)
{
Claim claim = this.siegeData.claims.get(i);
if(claim.isNear(player.getLocation(), 25))
{
return true;
}
}
return false;
}
//schedules another checkup later
private void scheduleAnotherCheck()
{
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
}
}

View File

@ -1,40 +1,40 @@
/*
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 java.util.ArrayList;
import org.bukkit.entity.Player;
//information about an ongoing siege
public class SiegeData
{
public Player defender;
public Player attacker;
public ArrayList<Claim> claims;
public int checkupTaskID;
public SiegeData(Player attacker, Player defender, Claim claim)
{
this.defender = defender;
this.attacker = attacker;
this.claims = new ArrayList<Claim>();
this.claims.add(claim);
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.util.ArrayList;
import org.bukkit.entity.Player;
//information about an ongoing siege
public class SiegeData
{
public Player defender;
public Player attacker;
public ArrayList<Claim> claims;
public int checkupTaskID;
public SiegeData(Player attacker, Player defender, Claim claim)
{
this.defender = defender;
this.attacker = attacker;
this.claims = new ArrayList<Claim>();
this.claims.add(claim);
}
}

View File

@ -1,31 +1,31 @@
/*
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;
//just a few constants for chat color codes
class TextMode
{
final static ChatColor Info = ChatColor.BLUE;
final static ChatColor Instr = ChatColor.YELLOW;
final static ChatColor Warn = ChatColor.GOLD;
final static ChatColor Err = ChatColor.RED;
final static ChatColor Success = ChatColor.GREEN;
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
//just a few constants for chat color codes
class TextMode
{
final static ChatColor Info = ChatColor.BLUE;
final static ChatColor Instr = ChatColor.YELLOW;
final static ChatColor Warn = ChatColor.GOLD;
final static ChatColor Err = ChatColor.RED;
final static ChatColor Success = ChatColor.GREEN;
}

View File

@ -1,100 +1,100 @@
/*
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 java.util.ArrayList;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
//FEATURE: treetops left unnaturally hanging will be automatically cleaned up
//this main thread task revisits the location of a partially chopped tree from several minutes ago
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
class TreeCleanupTask implements Runnable
{
private Block originalChoppedBlock; //first block chopped in the tree
private Block originalRootBlock; //where the root of the tree used to be
private ArrayList<Block> originalTreeBlocks; //a list of other log blocks determined to be part of this tree
public TreeCleanupTask(Block originalChoppedBlock, Block originalRootBlock, ArrayList<Block> originalTreeBlocks)
{
this.originalChoppedBlock = originalChoppedBlock;
this.originalRootBlock = originalRootBlock;
this.originalTreeBlocks = originalTreeBlocks;
}
@Override
public void run()
{
//if this chunk is no longer loaded, load it and come back in a few seconds
Chunk chunk = this.originalChoppedBlock.getWorld().getChunkAt(this.originalChoppedBlock);
if(!chunk.isLoaded())
{
chunk.load();
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 100L);
return;
}
//if the block originally chopped has been replaced with anything but air, something has been built (or has grown here)
//in that case, don't do any cleanup
if(this.originalChoppedBlock.getWorld().getBlockAt(this.originalChoppedBlock.getLocation()).getType() != Material.AIR) return;
//scan the original tree block locations to see if any of them have been replaced
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
{
Location location = this.originalTreeBlocks.get(i).getLocation();
Block currentBlock = location.getBlock();
//if the block has been replaced, stop here, we won't do any cleanup
if(currentBlock.getType() != Material.LOG && currentBlock.getType() != Material.AIR)
{
return;
}
}
//otherwise scan again, this time removing any remaining log blocks
boolean logsRemaining = false;
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
{
Location location = this.originalTreeBlocks.get(i).getLocation();
Block currentBlock = location.getBlock();
if(currentBlock.getType() == Material.LOG)
{
logsRemaining = true;
currentBlock.setType(Material.AIR);
}
}
//if any were actually removed and we're set to automatically replant griefed trees, place a sapling where the root block was previously
if(logsRemaining && GriefPrevention.instance.config_trees_regrowGriefedTrees)
{
Block currentBlock = this.originalRootBlock.getLocation().getBlock();
//make sure there's grass or dirt underneath
if(currentBlock.getType() == Material.AIR && (currentBlock.getRelative(BlockFace.DOWN).getType() == Material.DIRT || currentBlock.getRelative(BlockFace.DOWN).getType() == Material.GRASS))
{
currentBlock.setType(Material.SAPLING);
currentBlock.setData(this.originalRootBlock.getData()); //makes the sapling type match the original tree type
}
}
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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 java.util.ArrayList;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
//FEATURE: treetops left unnaturally hanging will be automatically cleaned up
//this main thread task revisits the location of a partially chopped tree from several minutes ago
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
class TreeCleanupTask implements Runnable
{
private Block originalChoppedBlock; //first block chopped in the tree
private Block originalRootBlock; //where the root of the tree used to be
private ArrayList<Block> originalTreeBlocks; //a list of other log blocks determined to be part of this tree
public TreeCleanupTask(Block originalChoppedBlock, Block originalRootBlock, ArrayList<Block> originalTreeBlocks)
{
this.originalChoppedBlock = originalChoppedBlock;
this.originalRootBlock = originalRootBlock;
this.originalTreeBlocks = originalTreeBlocks;
}
@Override
public void run()
{
//if this chunk is no longer loaded, load it and come back in a few seconds
Chunk chunk = this.originalChoppedBlock.getWorld().getChunkAt(this.originalChoppedBlock);
if(!chunk.isLoaded())
{
chunk.load();
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 100L);
return;
}
//if the block originally chopped has been replaced with anything but air, something has been built (or has grown here)
//in that case, don't do any cleanup
if(this.originalChoppedBlock.getWorld().getBlockAt(this.originalChoppedBlock.getLocation()).getType() != Material.AIR) return;
//scan the original tree block locations to see if any of them have been replaced
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
{
Location location = this.originalTreeBlocks.get(i).getLocation();
Block currentBlock = location.getBlock();
//if the block has been replaced, stop here, we won't do any cleanup
if(currentBlock.getType() != Material.LOG && currentBlock.getType() != Material.AIR)
{
return;
}
}
//otherwise scan again, this time removing any remaining log blocks
boolean logsRemaining = false;
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
{
Location location = this.originalTreeBlocks.get(i).getLocation();
Block currentBlock = location.getBlock();
if(currentBlock.getType() == Material.LOG)
{
logsRemaining = true;
currentBlock.setType(Material.AIR);
}
}
//if any were actually removed and we're set to automatically replant griefed trees, place a sapling where the root block was previously
if(logsRemaining && GriefPrevention.instance.config_trees_regrowGriefedTrees)
{
Block currentBlock = this.originalRootBlock.getLocation().getBlock();
//make sure there's grass or dirt underneath
if(currentBlock.getType() == Material.AIR && (currentBlock.getRelative(BlockFace.DOWN).getType() == Material.DIRT || currentBlock.getRelative(BlockFace.DOWN).getType() == Material.GRASS))
{
currentBlock.setType(Material.SAPLING);
currentBlock.setData(this.originalRootBlock.getData()); //makes the sapling type match the original tree type
}
}
}
}

View File

@ -1,6 +1,6 @@
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2011 Ryan Hamshire
Copyright (C) 2012 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

View File

@ -1,52 +1,52 @@
/*
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.entity.Player;
//applies a visualization for a player by sending him block change packets
class VisualizationApplicationTask implements Runnable
{
private Visualization visualization;
private Player player;
private PlayerData playerData;
public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization)
{
this.visualization = visualization;
this.playerData = playerData;
this.player = player;
}
@Override
public void run()
{
//for each element (=block) of the visualization
for(int i = 0; i < visualization.elements.size(); i++)
{
VisualizationElement element = visualization.elements.get(i);
//send the player a fake block change event
player.sendBlockChange(element.location, element.visualizedMaterial, element.visualizedData);
}
//remember the visualization applied to this player for later (so it can be inexpensively reverted)
playerData.currentVisualization = visualization;
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.entity.Player;
//applies a visualization for a player by sending him block change packets
class VisualizationApplicationTask implements Runnable
{
private Visualization visualization;
private Player player;
private PlayerData playerData;
public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization)
{
this.visualization = visualization;
this.playerData = playerData;
this.player = player;
}
@Override
public void run()
{
//for each element (=block) of the visualization
for(int i = 0; i < visualization.elements.size(); i++)
{
VisualizationElement element = visualization.elements.get(i);
//send the player a fake block change event
player.sendBlockChange(element.location, element.visualizedMaterial, element.visualizedData);
}
//remember the visualization applied to this player for later (so it can be inexpensively reverted)
playerData.currentVisualization = visualization;
}
}

View File

@ -1,36 +1,36 @@
/*
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.Location;
import org.bukkit.Material;
//represents a "fake" block sent to a player as part of a visualization
public class VisualizationElement
{
public Location location;
public Material visualizedMaterial;
public byte visualizedData;
public VisualizationElement(Location location, Material visualizedMaterial, byte visualizedData)
{
this.location = location;
this.visualizedMaterial= visualizedMaterial;
this.visualizedData = visualizedData;
}
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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.Location;
import org.bukkit.Material;
//represents a "fake" block sent to a player as part of a visualization
public class VisualizationElement
{
public Location location;
public Material visualizedMaterial;
public byte visualizedData;
public VisualizationElement(Location location, Material visualizedMaterial, byte visualizedData)
{
this.location = location;
this.visualizedMaterial= visualizedMaterial;
this.visualizedData = visualizedData;
}
}

View File

@ -1,28 +1,28 @@
/*
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;
//just an enumeration of the visualization types, which determine what materials will be for the fake blocks
public enum VisualizationType
{
Claim,
Subdivision,
ErrorClaim,
RestoreNature
}
/*
GriefPrevention Server Plugin for Minecraft
Copyright (C) 2012 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;
//just an enumeration of the visualization types, which determine what materials will be for the fake blocks
public enum VisualizationType
{
Claim,
Subdivision,
ErrorClaim,
RestoreNature
}