Added pet protections. Tweaked drop protections.
This commit is contained in:
parent
2d94e6fdc7
commit
528fda95ff
|
|
@ -18,11 +18,14 @@
|
|||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.Block;
|
||||
|
|
@ -32,10 +35,12 @@ import org.bukkit.entity.Enderman;
|
|||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Explosive;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Villager;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
|
@ -58,6 +63,7 @@ import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
|
|||
import org.bukkit.event.hanging.HangingPlaceEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
//handles events related to entities
|
||||
class EntityEventHandler implements Listener
|
||||
|
|
@ -181,6 +187,49 @@ class EntityEventHandler implements Listener
|
|||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
//if item is on watch list, apply protection
|
||||
ArrayList<PendingItemProtection> watchList = GriefPrevention.instance.pendingItemWatchList;
|
||||
Item newItem = event.getEntity();
|
||||
Long now = null;
|
||||
for(int i = 0; i < watchList.size(); i++)
|
||||
{
|
||||
PendingItemProtection pendingProtection = watchList.get(i);
|
||||
//ignore and remove any expired pending protections
|
||||
if(now == null) now = System.currentTimeMillis();
|
||||
if(pendingProtection.expirationTimestamp < now)
|
||||
{
|
||||
watchList.remove(i--);
|
||||
continue;
|
||||
}
|
||||
//skip if item stack doesn't match
|
||||
if(pendingProtection.itemStack.getAmount() != newItem.getItemStack().getAmount() ||
|
||||
pendingProtection.itemStack.getType() != newItem.getItemStack().getType())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//skip if new item location isn't near the expected spawn area
|
||||
Location spawn = event.getLocation();
|
||||
Location expected = pendingProtection.location;
|
||||
if(!spawn.getWorld().equals(expected.getWorld()) ||
|
||||
spawn.getX() < expected.getX() - 5 ||
|
||||
spawn.getX() > expected.getX() + 5 ||
|
||||
spawn.getZ() < expected.getZ() - 5 ||
|
||||
spawn.getZ() > expected.getZ() + 5 ||
|
||||
spawn.getY() < expected.getY() - 15 ||
|
||||
spawn.getY() > expected.getY() + 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//otherwise, mark item with protection information
|
||||
newItem.setMetadata("GP_ITEMOWNER", new FixedMetadataValue(GriefPrevention.instance, pendingProtection.owner));
|
||||
|
||||
//and remove pending protection data
|
||||
watchList.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//when an experience bottle explodes...
|
||||
|
|
@ -219,36 +268,11 @@ class EntityEventHandler implements Listener
|
|||
}
|
||||
|
||||
//when an entity dies...
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onEntityDeath(EntityDeathEvent event)
|
||||
{
|
||||
LivingEntity entity = event.getEntity();
|
||||
|
||||
//FEATURE: lock dropped items to player who dropped them
|
||||
|
||||
if(entity instanceof Player)
|
||||
{
|
||||
Player player = (Player)entity;
|
||||
World world = entity.getWorld();
|
||||
|
||||
//decide whether or not to apply this feature to this situation (depends on the world wher it happens)
|
||||
boolean isPvPWorld = GriefPrevention.instance.config_pvp_enabledWorlds.contains(world);
|
||||
if((isPvPWorld && GriefPrevention.instance.config_lockDeathDropsInPvpWorlds) ||
|
||||
(!isPvPWorld && GriefPrevention.instance.config_lockDeathDropsInNonPvpWorlds))
|
||||
{
|
||||
//mark the dropped stacks with player's UUID
|
||||
List<ItemStack> drops = event.getDrops();
|
||||
for(ItemStack stack : drops)
|
||||
{
|
||||
GriefPrevention.instance.itemStackOwnerMap.put(stack, new ItemStackOwnerInfo(player.getUniqueId(), player.getLocation()));
|
||||
}
|
||||
|
||||
//allow the player to receive a message about how to unlock any drops
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
playerData.receivedDropUnlockAdvertisement = false;
|
||||
}
|
||||
}
|
||||
|
||||
//don't do the rest in worlds where claims are not enabled
|
||||
if(!GriefPrevention.instance.claimsEnabledForWorld(entity.getWorld())) return;
|
||||
|
||||
|
|
@ -276,6 +300,31 @@ class EntityEventHandler implements Listener
|
|||
//end it, with the dieing player being the loser
|
||||
this.dataStore.endSiege(playerData.siegeData, null, player.getName(), true /*ended due to death*/);
|
||||
}
|
||||
|
||||
//FEATURE: lock dropped items to player who dropped them
|
||||
|
||||
World world = entity.getWorld();
|
||||
|
||||
//decide whether or not to apply this feature to this situation (depends on the world where it happens)
|
||||
boolean isPvPWorld = GriefPrevention.instance.config_pvp_enabledWorlds.contains(world);
|
||||
if((isPvPWorld && GriefPrevention.instance.config_lockDeathDropsInPvpWorlds) ||
|
||||
(!isPvPWorld && GriefPrevention.instance.config_lockDeathDropsInNonPvpWorlds))
|
||||
{
|
||||
//remember information about these drops so that they can be marked when they spawn as items
|
||||
long expirationTime = System.currentTimeMillis() + 3000; //now + 3 seconds
|
||||
Location deathLocation = player.getLocation();
|
||||
UUID playerID = player.getUniqueId();
|
||||
List<ItemStack> drops = event.getDrops();
|
||||
for(ItemStack stack : drops)
|
||||
{
|
||||
GriefPrevention.instance.pendingItemWatchList.add(
|
||||
new PendingItemProtection(deathLocation, playerID, expirationTime, stack));
|
||||
}
|
||||
|
||||
//allow the player to receive a message about how to unlock any drops
|
||||
playerData.dropsAreUnlocked = false;
|
||||
playerData.receivedDropUnlockAdvertisement = false;
|
||||
}
|
||||
}
|
||||
|
||||
//when an entity picks up an item
|
||||
|
|
@ -527,7 +576,34 @@ class EntityEventHandler implements Listener
|
|||
//if the entity is an non-monster creature (remember monsters disqualified above), or a vehicle
|
||||
if ((subEvent.getEntity() instanceof Creature && GriefPrevention.instance.config_claims_protectCreatures))
|
||||
{
|
||||
Claim cachedClaim = null;
|
||||
//if entity is tameable and has an owner, apply special rules
|
||||
if(subEvent.getEntity() instanceof Tameable)
|
||||
{
|
||||
Tameable tameable = (Tameable)subEvent.getEntity();
|
||||
if(tameable.isTamed() && tameable.getOwner() != null)
|
||||
{
|
||||
UUID ownerID = tameable.getOwner().getUniqueId();
|
||||
|
||||
//if the player interacting is the owner, always allow
|
||||
if(attacker.getUniqueId().equals(ownerID)) return;
|
||||
|
||||
//otherwise disallow in non-pvp worlds
|
||||
if(!GriefPrevention.instance.config_pvp_enabledWorlds.contains(subEvent.getEntity().getLocation().getWorld()))
|
||||
{
|
||||
OfflinePlayer owner = GriefPrevention.instance.getServer().getOfflinePlayer(ownerID);
|
||||
String ownerName = owner.getName();
|
||||
if(ownerName == null) ownerName = "someone";
|
||||
String message = GriefPrevention.instance.dataStore.getMessage(Messages.NoDamageClaimedEntity, ownerName);
|
||||
if(attacker.hasPermission("griefprevention.ignoreclaims"))
|
||||
message += " " + GriefPrevention.instance.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
|
||||
GriefPrevention.sendMessage(attacker, TextMode.Err, message);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Claim cachedClaim = null;
|
||||
PlayerData playerData = null;
|
||||
|
||||
//if not a player or an explosive, allow
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import org.bukkit.block.Block;
|
|||
import org.bukkit.command.*;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
|
@ -60,9 +61,6 @@ public class GriefPrevention extends JavaPlugin
|
|||
//this handles data storage, like player and region data
|
||||
public DataStore dataStore;
|
||||
|
||||
//this remembers which item stacks dropped in the world belong to which players
|
||||
ConcurrentHashMap<ItemStack, ItemStackOwnerInfo> itemStackOwnerMap = new ConcurrentHashMap<ItemStack, ItemStackOwnerInfo>();
|
||||
|
||||
//configuration variables, loaded/saved from a config.yml
|
||||
|
||||
//claim mode for each world
|
||||
|
|
@ -2292,8 +2290,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
playerData.pvpImmune = true;
|
||||
|
||||
//inform the player
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.PvPImmunityStart);
|
||||
//inform the player after he finishes respawning
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.PvPImmunityStart, 5L);
|
||||
}
|
||||
|
||||
//checks whether players siege in a world
|
||||
|
|
@ -2558,4 +2556,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
return overrideValue;
|
||||
}
|
||||
}
|
||||
|
||||
//this tracks item stacks expected to drop which will need protection
|
||||
ArrayList<PendingItemProtection> pendingItemWatchList = new ArrayList<PendingItemProtection>();
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Location;
|
||||
|
||||
//tracks an item stack's owner. ownership is limited to a locality due to problems with hash overlaps overprotecting item stacks
|
||||
class ItemStackOwnerInfo
|
||||
{
|
||||
public UUID ownerID;
|
||||
public Location locality;
|
||||
|
||||
public ItemStackOwnerInfo(UUID ownerID, Location location)
|
||||
{
|
||||
this.ownerID = ownerID;
|
||||
this.locality = location;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
class PendingItemProtection
|
||||
{
|
||||
public Location location;
|
||||
public UUID owner;
|
||||
long expirationTimestamp;
|
||||
ItemStack itemStack;
|
||||
|
||||
public PendingItemProtection(Location location, UUID owner, long expirationTimestamp, ItemStack itemStack)
|
||||
{
|
||||
this.location = location;
|
||||
this.owner = owner;
|
||||
this.expirationTimestamp = expirationTimestamp;
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,9 @@ import org.bukkit.entity.Entity;
|
|||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Hanging;
|
||||
import org.bukkit.entity.Horse;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.entity.minecart.PoweredMinecart;
|
||||
import org.bukkit.entity.minecart.StorageMinecart;
|
||||
|
|
@ -58,6 +60,7 @@ import org.bukkit.event.player.PlayerLoginEvent.Result;
|
|||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
|
||||
class PlayerEventHandler implements Listener
|
||||
|
|
@ -596,7 +599,6 @@ class PlayerEventHandler implements Listener
|
|||
Player player = event.getPlayer();
|
||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getUniqueId());
|
||||
playerData.lastSpawn = Calendar.getInstance().getTimeInMillis();
|
||||
GriefPrevention.instance.checkPvpProtectionNeeded(player);
|
||||
|
||||
//also send him any messaged from grief prevention he would have received while dead
|
||||
if(playerData.messageOnRespawn != null)
|
||||
|
|
@ -604,6 +606,8 @@ class PlayerEventHandler implements Listener
|
|||
GriefPrevention.sendMessage(player, ChatColor.RESET /*color is alrady embedded in message in this case*/, playerData.messageOnRespawn, 40L);
|
||||
playerData.messageOnRespawn = null;
|
||||
}
|
||||
|
||||
GriefPrevention.instance.checkPvpProtectionNeeded(player);
|
||||
}
|
||||
|
||||
//when a player dies...
|
||||
|
|
@ -806,7 +810,10 @@ class PlayerEventHandler implements Listener
|
|||
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event)
|
||||
{
|
||||
//treat it the same as interacting with an entity in general
|
||||
this.onPlayerInteractEntity((PlayerInteractEntityEvent)event);
|
||||
if(event.getRightClicked().getType() == EntityType.ARMOR_STAND)
|
||||
{
|
||||
this.onPlayerInteractEntity((PlayerInteractEntityEvent)event);
|
||||
}
|
||||
}
|
||||
|
||||
//when a player interacts with an entity...
|
||||
|
|
@ -835,6 +842,9 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
|
||||
//always allow interactions when player is in ignore claims mode
|
||||
if(playerData.ignoreClaims) return;
|
||||
|
||||
//don't allow container access during pvp combat
|
||||
if((entity instanceof StorageMinecart || entity instanceof PoweredMinecart))
|
||||
{
|
||||
|
|
@ -853,6 +863,30 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
|
||||
//if entity is tameable and has an owner, apply special rules
|
||||
if(entity instanceof Tameable && !GriefPrevention.instance.config_pvp_enabledWorlds.contains(entity.getLocation().getWorld()))
|
||||
{
|
||||
Tameable tameable = (Tameable)entity;
|
||||
if(tameable.isTamed() && tameable.getOwner() != null)
|
||||
{
|
||||
UUID ownerID = tameable.getOwner().getUniqueId();
|
||||
|
||||
//if the player interacting is the owner, always allow
|
||||
if(player.getUniqueId().equals(ownerID)) return;
|
||||
|
||||
//otherwise disallow
|
||||
OfflinePlayer owner = GriefPrevention.instance.getServer().getOfflinePlayer(ownerID);
|
||||
String ownerName = owner.getName();
|
||||
if(ownerName == null) ownerName = "someone";
|
||||
String message = GriefPrevention.instance.dataStore.getMessage(Messages.NoDamageClaimedEntity, ownerName);
|
||||
if(player.hasPermission("griefprevention.ignoreclaims"))
|
||||
message += " " + GriefPrevention.instance.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, message);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//if the entity is a vehicle and we're preventing theft in claims
|
||||
if(GriefPrevention.instance.config_claims_preventTheft && entity instanceof Vehicle)
|
||||
{
|
||||
|
|
@ -868,6 +902,7 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, noContainersReason);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -879,6 +914,7 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
player.sendMessage(noAccessReason);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -898,6 +934,7 @@ class PlayerEventHandler implements Listener
|
|||
message += " " + GriefPrevention.instance.dataStore.getMessage(Messages.IgnoreClaimsAdvertisement);
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, message);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -928,25 +965,21 @@ class PlayerEventHandler implements Listener
|
|||
//FEATURE: lock dropped items to player who dropped them
|
||||
|
||||
//who owns this stack?
|
||||
ItemStack stack = event.getItem().getItemStack();
|
||||
ItemStackOwnerInfo ownerInfo = GriefPrevention.instance.itemStackOwnerMap.get(stack);
|
||||
if(ownerInfo != null)
|
||||
Item item = event.getItem();
|
||||
List<MetadataValue> data = item.getMetadata("GP_ITEMOWNER");
|
||||
if(data != null && data.size() > 0)
|
||||
{
|
||||
UUID ownerID = (UUID)data.get(0).value();
|
||||
|
||||
//has that player unlocked his drops?
|
||||
OfflinePlayer owner = GriefPrevention.instance.getServer().getOfflinePlayer(ownerInfo.ownerID);
|
||||
String ownerName = GriefPrevention.lookupPlayerName(ownerInfo.ownerID);
|
||||
OfflinePlayer owner = GriefPrevention.instance.getServer().getOfflinePlayer(ownerID);
|
||||
String ownerName = GriefPrevention.lookupPlayerName(ownerID);
|
||||
if(owner.isOnline() && !player.equals(owner))
|
||||
{
|
||||
PlayerData playerData = this.dataStore.getPlayerData(ownerInfo.ownerID);
|
||||
Location location = event.getItem().getLocation();
|
||||
PlayerData playerData = this.dataStore.getPlayerData(ownerID);
|
||||
|
||||
//if locked and in locality of protection, don't allow pickup
|
||||
if(!playerData.dropsAreUnlocked
|
||||
&& location.getX() > ownerInfo.locality.getX() - 10
|
||||
&& location.getX() < ownerInfo.locality.getX() + 10
|
||||
&& location.getZ() < ownerInfo.locality.getZ() + 10
|
||||
&& location.getZ() > ownerInfo.locality.getZ() - 10
|
||||
&& location.getY() < ownerInfo.locality.getY() + 5)
|
||||
//if locked, don't allow pickup
|
||||
if(!playerData.dropsAreUnlocked)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
|
||||
|
|
@ -959,12 +992,6 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if allowed to pick up, remove from ownership map
|
||||
if(!event.isCancelled())
|
||||
{
|
||||
GriefPrevention.instance.itemStackOwnerMap.remove(stack);
|
||||
}
|
||||
}
|
||||
|
||||
//the rest of this code is specific to pvp worlds
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user