2011-07-18 22:06:02 +02:00
|
|
|
package com.massivecraft.factions.listeners;
|
2011-02-06 13:36:11 +01:00
|
|
|
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
import java.util.ArrayList;
|
2012-02-23 07:09:19 +01:00
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.LinkedHashSet;
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
import java.util.List;
|
2012-02-23 07:09:19 +01:00
|
|
|
import java.text.MessageFormat;
|
|
|
|
import java.util.Set;
|
2011-02-06 13:36:11 +01:00
|
|
|
|
2011-08-02 03:22:16 +02:00
|
|
|
import org.bukkit.Location;
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
import org.bukkit.block.Block;
|
2011-03-22 17:20:21 +01:00
|
|
|
import org.bukkit.entity.Creeper;
|
2012-02-20 23:59:18 +01:00
|
|
|
import org.bukkit.entity.Enderman;
|
2011-02-06 13:36:11 +01:00
|
|
|
import org.bukkit.entity.Entity;
|
2011-03-18 00:02:29 +01:00
|
|
|
import org.bukkit.entity.Fireball;
|
2012-02-23 07:09:19 +01:00
|
|
|
import org.bukkit.entity.LivingEntity;
|
2011-02-06 13:36:11 +01:00
|
|
|
import org.bukkit.entity.Player;
|
2011-09-08 10:20:55 +02:00
|
|
|
import org.bukkit.entity.Projectile;
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
import org.bukkit.entity.TNTPrimed;
|
2012-10-31 22:16:19 +01:00
|
|
|
import org.bukkit.entity.Wither;
|
2012-10-30 01:24:31 +01:00
|
|
|
import org.bukkit.entity.WitherSkull;
|
2012-01-28 11:37:55 +01:00
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.EventPriority;
|
|
|
|
import org.bukkit.event.Listener;
|
2011-03-23 17:39:56 +01:00
|
|
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
2012-02-20 23:59:18 +01:00
|
|
|
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
2012-02-23 07:09:19 +01:00
|
|
|
import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
2011-02-06 13:36:11 +01:00
|
|
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
2011-02-13 17:04:06 +01:00
|
|
|
import org.bukkit.event.entity.EntityDamageEvent;
|
2011-02-06 13:36:11 +01:00
|
|
|
import org.bukkit.event.entity.EntityDeathEvent;
|
2011-03-06 21:13:48 +01:00
|
|
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
2011-03-23 17:39:56 +01:00
|
|
|
import org.bukkit.event.entity.EntityTargetEvent;
|
2012-02-23 07:09:19 +01:00
|
|
|
import org.bukkit.event.entity.PotionSplashEvent;
|
2012-10-31 22:16:19 +01:00
|
|
|
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
|
|
|
import org.bukkit.event.hanging.HangingBreakEvent;
|
|
|
|
import org.bukkit.event.hanging.HangingPlaceEvent;
|
2012-02-23 07:09:19 +01:00
|
|
|
import org.bukkit.potion.PotionEffect;
|
|
|
|
import org.bukkit.potion.PotionEffectType;
|
2011-07-18 22:06:02 +02:00
|
|
|
|
|
|
|
import com.massivecraft.factions.Board;
|
|
|
|
import com.massivecraft.factions.Conf;
|
|
|
|
import com.massivecraft.factions.FLocation;
|
|
|
|
import com.massivecraft.factions.FPlayer;
|
2011-10-08 22:03:44 +02:00
|
|
|
import com.massivecraft.factions.FPlayers;
|
2011-07-18 22:06:02 +02:00
|
|
|
import com.massivecraft.factions.Faction;
|
2011-10-08 22:03:44 +02:00
|
|
|
import com.massivecraft.factions.P;
|
2011-07-18 22:06:02 +02:00
|
|
|
import com.massivecraft.factions.struct.Relation;
|
2011-10-08 22:03:44 +02:00
|
|
|
import com.massivecraft.factions.util.MiscUtil;
|
2011-02-06 13:36:11 +01:00
|
|
|
|
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
public class FactionsEntityListener implements Listener
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
|
|
|
public P p;
|
|
|
|
public FactionsEntityListener(P p)
|
|
|
|
{
|
|
|
|
this.p = p;
|
|
|
|
}
|
2012-01-15 18:41:13 +01:00
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2011-10-08 22:03:44 +02:00
|
|
|
public void onEntityDeath(EntityDeathEvent event)
|
|
|
|
{
|
2011-02-06 13:36:11 +01:00
|
|
|
Entity entity = event.getEntity();
|
2011-10-08 22:03:44 +02:00
|
|
|
if ( ! (entity instanceof Player))
|
|
|
|
{
|
2011-02-06 13:36:11 +01:00
|
|
|
return;
|
|
|
|
}
|
2011-05-29 23:28:29 +02:00
|
|
|
|
2011-02-06 13:36:11 +01:00
|
|
|
Player player = (Player) entity;
|
2011-10-08 22:03:44 +02:00
|
|
|
FPlayer fplayer = FPlayers.i.get(player);
|
2011-05-29 23:28:29 +02:00
|
|
|
Faction faction = Board.getFactionAt(new FLocation(player.getLocation()));
|
2011-10-08 22:03:44 +02:00
|
|
|
if (faction.isWarZone())
|
|
|
|
{
|
|
|
|
// war zones always override worldsNoPowerLoss either way, thus this layout
|
|
|
|
if (! Conf.warZonePowerLoss)
|
|
|
|
{
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<i>You didn't lose any power since you were in a war zone.");
|
2011-05-29 23:28:29 +02:00
|
|
|
return;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName()))
|
|
|
|
{
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<b>The world you are in has power loss normally disabled, but you still lost power since you were in a war zone.");
|
2011-05-29 23:28:29 +02:00
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
}
|
|
|
|
else if (faction.isNone() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName()))
|
|
|
|
{
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<i>You didn't lose any power since you were in the wilderness.");
|
2011-06-02 01:32:09 +02:00
|
|
|
return;
|
2011-10-08 22:03:44 +02:00
|
|
|
}
|
|
|
|
else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName()))
|
|
|
|
{
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<i>You didn't lose any power due to the world you died in.");
|
2011-05-29 23:28:29 +02:00
|
|
|
return;
|
2011-10-08 22:03:44 +02:00
|
|
|
}
|
|
|
|
else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful())
|
|
|
|
{
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<i>You didn't lose any power since you are in a peaceful faction.");
|
2011-08-05 10:50:47 +02:00
|
|
|
return;
|
2011-05-29 23:28:29 +02:00
|
|
|
}
|
2011-03-23 17:39:56 +01:00
|
|
|
fplayer.onDeath();
|
2011-10-21 18:14:04 +02:00
|
|
|
fplayer.msg("<i>Your power is now <h>"+fplayer.getPowerRounded()+" / "+fplayer.getPowerMaxRounded());
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|
2011-02-13 17:04:06 +01:00
|
|
|
|
2011-02-06 13:36:11 +01:00
|
|
|
/**
|
|
|
|
* Who can I hurt?
|
|
|
|
* I can never hurt members or allies.
|
|
|
|
* I can always hurt enemies.
|
|
|
|
* I can hurt neutrals as long as they are outside their own territory.
|
|
|
|
*/
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2011-10-21 18:14:04 +02:00
|
|
|
public void onEntityDamage(EntityDamageEvent event)
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (event.isCancelled()) return;
|
2011-02-06 13:36:11 +01:00
|
|
|
|
2011-10-21 18:14:04 +02:00
|
|
|
if (event instanceof EntityDamageByEntityEvent)
|
|
|
|
{
|
2011-07-29 13:39:20 +02:00
|
|
|
EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent)event;
|
2012-02-23 07:09:19 +01:00
|
|
|
if ( ! this.canDamagerHurtDamagee(sub, true))
|
2011-10-21 18:14:04 +02:00
|
|
|
{
|
2012-03-13 14:26:54 +01:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
2011-10-21 18:14:04 +02:00
|
|
|
}
|
|
|
|
else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity()))
|
|
|
|
{
|
2011-07-29 13:39:20 +02:00
|
|
|
// Players can not take any damage in a Safe Zone
|
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
2011-02-13 09:33:42 +01:00
|
|
|
}
|
2012-01-17 08:57:25 +01:00
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2011-03-06 21:13:48 +01:00
|
|
|
public void onEntityExplode(EntityExplodeEvent event)
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (event.isCancelled()) return;
|
2011-03-22 17:20:21 +01:00
|
|
|
|
2011-08-23 07:37:31 +02:00
|
|
|
Location loc = event.getLocation();
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
Entity boomer = event.getEntity();
|
2011-08-23 07:37:31 +02:00
|
|
|
Faction faction = Board.getFactionAt(new FLocation(loc));
|
2011-10-13 05:31:18 +02:00
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (faction.noExplosionsInTerritory())
|
|
|
|
{
|
2011-08-05 10:50:47 +02:00
|
|
|
// faction is peaceful and has explosions set to disabled
|
|
|
|
event.setCancelled(true);
|
2011-10-13 05:31:18 +02:00
|
|
|
return;
|
2011-08-05 10:50:47 +02:00
|
|
|
}
|
2011-10-13 05:31:18 +02:00
|
|
|
|
|
|
|
boolean online = faction.hasPlayersOnline();
|
|
|
|
|
|
|
|
if
|
2011-10-08 22:03:44 +02:00
|
|
|
(
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
boomer instanceof Creeper
|
2011-10-08 22:03:44 +02:00
|
|
|
&&
|
|
|
|
(
|
|
|
|
(faction.isNone() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()))
|
|
|
|
||
|
|
|
|
(faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline))
|
|
|
|
||
|
|
|
|
(faction.isWarZone() && Conf.warZoneBlockCreepers)
|
|
|
|
||
|
2011-05-29 23:28:29 +02:00
|
|
|
faction.isSafeZone()
|
2011-10-08 22:03:44 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
2011-05-29 23:28:29 +02:00
|
|
|
// creeper which needs prevention
|
2011-03-22 17:20:21 +01:00
|
|
|
event.setCancelled(true);
|
2011-10-08 22:03:44 +02:00
|
|
|
}
|
|
|
|
else if
|
|
|
|
(
|
2012-10-31 22:16:19 +01:00
|
|
|
(boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither)
|
2011-10-08 22:03:44 +02:00
|
|
|
&&
|
|
|
|
(
|
|
|
|
(faction.isNone() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()))
|
|
|
|
||
|
|
|
|
(faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline))
|
|
|
|
||
|
|
|
|
(faction.isWarZone() && Conf.warZoneBlockFireballs)
|
|
|
|
||
|
2011-05-29 23:28:29 +02:00
|
|
|
faction.isSafeZone()
|
2011-10-08 22:03:44 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
2011-05-29 23:28:29 +02:00
|
|
|
// ghast fireball which needs prevention
|
2011-03-22 17:20:21 +01:00
|
|
|
event.setCancelled(true);
|
2011-10-08 22:03:44 +02:00
|
|
|
}
|
2012-01-17 08:57:25 +01:00
|
|
|
else if
|
|
|
|
(
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
boomer instanceof TNTPrimed
|
|
|
|
&&
|
2011-10-08 22:03:44 +02:00
|
|
|
(
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
(faction.isNone() && Conf.wildernessBlockTNT && ! Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()))
|
|
|
|
||
|
|
|
|
(faction.isNormal() && ( online ? Conf.territoryBlockTNT : Conf.territoryBlockTNTWhenOffline ))
|
|
|
|
||
|
|
|
|
(faction.isWarZone() && Conf.warZoneBlockTNT)
|
|
|
|
||
|
|
|
|
(faction.isSafeZone() && Conf.safeZoneBlockTNT)
|
2012-01-17 08:57:25 +01:00
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
// TNT which needs prevention
|
2012-01-17 08:57:25 +01:00
|
|
|
event.setCancelled(true);
|
2011-03-18 00:02:29 +01:00
|
|
|
}
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
else if (boomer instanceof TNTPrimed && Conf.handleExploitTNTWaterlog)
|
|
|
|
{
|
|
|
|
// TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior, but...
|
|
|
|
// this change below provides workaround for waterwalling providing perfect protection,
|
|
|
|
// and makes cheap (non-obsidian) TNT cannons require minor maintenance between shots
|
|
|
|
Block center = loc.getBlock();
|
|
|
|
if (center.isLiquid())
|
|
|
|
{
|
|
|
|
// a single surrounding block in all 6 directions is broken if the material is weak enough
|
|
|
|
List<Block> targets = new ArrayList<Block>();
|
|
|
|
targets.add(center.getRelative(0, 0, 1));
|
|
|
|
targets.add(center.getRelative(0, 0, -1));
|
|
|
|
targets.add(center.getRelative(0, 1, 0));
|
|
|
|
targets.add(center.getRelative(0, -1, 0));
|
|
|
|
targets.add(center.getRelative(1, 0, 0));
|
|
|
|
targets.add(center.getRelative(-1, 0, 0));
|
|
|
|
for (Block target : targets)
|
|
|
|
{
|
|
|
|
int id = target.getTypeId();
|
2012-10-19 07:11:37 +02:00
|
|
|
// ignore air, bedrock, water, lava, obsidian, enchanting table, etc.... too bad we can't get a blast resistance value through Bukkit yet
|
|
|
|
if (id != 0 && (id < 7 || id > 11) && id != 49 && id != 90 && id != 116 && id != 119 && id != 120 && id != 130)
|
New setting "handleExploitTNTWaterlog" (default false/disabled) which, if enabled, will cause TNT which explodes in liquid to actually destroy a single adjacent block in all 6 directions. This will only apply to blocks which can be destroyed by TNT normally, specifically anything other than air, bedrock, water, lava, obsidian, and enchanting tables. The destruction of these blocks will be handled as if they had been mined, dropping the appropriate item.
TNT in water/lava doesn't normally destroy any surrounding blocks, which is usually desired behavior. That's the reason this setting is disabled by default. However, it is available because it provides a method to get through waterwalls with enough persistence, and it makes cheap (non-obsidian) TNT cannons require minor maintenance between shots. Both are useful things for my server.
2012-03-19 17:18:40 +01:00
|
|
|
target.breakNaturally();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-03-06 21:13:48 +01:00
|
|
|
}
|
2011-07-29 13:39:20 +02:00
|
|
|
|
2012-02-23 07:09:19 +01:00
|
|
|
// mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled
|
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
|
|
|
public void onEntityCombustByEntity(EntityCombustByEntityEvent event)
|
|
|
|
{
|
|
|
|
if (event.isCancelled()) return;
|
|
|
|
|
|
|
|
EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0);
|
|
|
|
if ( ! this.canDamagerHurtDamagee(sub, false))
|
|
|
|
event.setCancelled(true);
|
|
|
|
sub = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final Set<PotionEffectType> badPotionEffects = new LinkedHashSet<PotionEffectType>(Arrays.asList(
|
|
|
|
PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER,
|
|
|
|
PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS
|
|
|
|
));
|
|
|
|
|
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
|
|
|
public void onPotionSplashEvent(PotionSplashEvent event)
|
|
|
|
{
|
|
|
|
if (event.isCancelled()) return;
|
|
|
|
|
|
|
|
// see if the potion has a harmful effect
|
|
|
|
boolean badjuju = false;
|
|
|
|
for (PotionEffect effect : event.getPotion().getEffects())
|
|
|
|
{
|
|
|
|
if (badPotionEffects.contains(effect.getType()))
|
|
|
|
{
|
|
|
|
badjuju = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( ! badjuju) return;
|
|
|
|
|
2012-03-19 12:54:59 +01:00
|
|
|
Entity thrower = event.getPotion().getShooter();
|
2012-02-23 07:09:19 +01:00
|
|
|
|
|
|
|
// scan through affected entities to make sure they're all valid targets
|
|
|
|
Iterator<LivingEntity> iter = event.getAffectedEntities().iterator();
|
|
|
|
while (iter.hasNext())
|
|
|
|
{
|
|
|
|
LivingEntity target = iter.next();
|
|
|
|
EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0);
|
|
|
|
if ( ! this.canDamagerHurtDamagee(sub, true))
|
|
|
|
event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works
|
|
|
|
sub = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
public boolean isPlayerInSafeZone(Entity damagee)
|
|
|
|
{
|
|
|
|
if ( ! (damagee instanceof Player))
|
|
|
|
{
|
2011-07-29 13:39:20 +02:00
|
|
|
return false;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
if (Board.getFactionAt(new FLocation(damagee.getLocation())).isSafeZone())
|
|
|
|
{
|
2011-07-29 13:39:20 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub)
|
2012-02-23 07:09:19 +01:00
|
|
|
{
|
|
|
|
return canDamagerHurtDamagee(sub, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify)
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-03-07 04:13:27 +01:00
|
|
|
Entity damager = sub.getDamager();
|
|
|
|
Entity damagee = sub.getEntity();
|
|
|
|
int damage = sub.getDamage();
|
2011-02-06 13:36:11 +01:00
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if ( ! (damagee instanceof Player))
|
2011-02-13 09:33:42 +01:00
|
|
|
return true;
|
2012-01-17 09:56:22 +01:00
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
FPlayer defender = FPlayers.i.get((Player)damagee);
|
2011-03-23 17:39:56 +01:00
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (defender == null || defender.getPlayer() == null)
|
2011-05-12 07:52:17 +02:00
|
|
|
return true;
|
|
|
|
|
2011-08-02 03:22:16 +02:00
|
|
|
Location defenderLoc = defender.getPlayer().getLocation();
|
2011-08-05 10:50:47 +02:00
|
|
|
Faction defLocFaction = Board.getFactionAt(new FLocation(defenderLoc));
|
2011-09-08 10:20:55 +02:00
|
|
|
|
|
|
|
// for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source
|
2011-10-08 22:03:44 +02:00
|
|
|
if (damager instanceof Projectile)
|
2011-09-08 10:20:55 +02:00
|
|
|
damager = ((Projectile)damager).getShooter();
|
2012-01-17 09:56:22 +01:00
|
|
|
|
|
|
|
if (damager == damagee) // ender pearl usage and other self-inflicted damage
|
|
|
|
return true;
|
2011-09-08 10:20:55 +02:00
|
|
|
|
2011-08-05 10:50:47 +02:00
|
|
|
// Players can not take attack damage in a SafeZone, or possibly peaceful territory
|
|
|
|
if (defLocFaction.noPvPInTerritory()) {
|
2011-10-08 22:03:44 +02:00
|
|
|
if (damager instanceof Player)
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify)
|
|
|
|
{
|
|
|
|
FPlayer attacker = FPlayers.i.get((Player)damager);
|
|
|
|
attacker.msg("<i>You can't hurt other players in "+(defLocFaction.isSafeZone() ? "a SafeZone." : "peaceful territory."));
|
|
|
|
}
|
2011-08-05 10:50:47 +02:00
|
|
|
return false;
|
2011-03-23 17:39:56 +01:00
|
|
|
}
|
2011-08-05 10:50:47 +02:00
|
|
|
return !defLocFaction.noMonstersInTerritory();
|
2011-03-23 17:39:56 +01:00
|
|
|
}
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if ( ! (damager instanceof Player))
|
2011-03-23 17:39:56 +01:00
|
|
|
return true;
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
FPlayer attacker = FPlayers.i.get((Player)damager);
|
2011-05-12 07:52:17 +02:00
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (attacker == null || attacker.getPlayer() == null)
|
2011-05-12 07:52:17 +02:00
|
|
|
return true;
|
2012-03-11 19:36:07 +01:00
|
|
|
|
|
|
|
if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) return true;
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (attacker.hasLoginPvpDisabled())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt other players for " + Conf.noPVPDamageToOthersForXSecondsAfterLogin + " seconds after logging in.");
|
2011-06-23 03:10:42 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-10 14:38:14 +02:00
|
|
|
Faction locFaction = Board.getFactionAt(new FLocation(attacker));
|
|
|
|
|
2011-06-08 23:22:19 +02:00
|
|
|
// so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be?
|
2011-10-08 22:03:44 +02:00
|
|
|
if (locFaction.noPvPInTerritory())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt other players while you are in "+(locFaction.isSafeZone() ? "a SafeZone." : "peaceful territory."));
|
2011-06-08 23:22:19 +02:00
|
|
|
return false;
|
|
|
|
}
|
2012-02-07 22:04:20 +01:00
|
|
|
|
|
|
|
if (locFaction.isWarZone() && Conf.warZoneFriendlyFire)
|
2011-06-10 14:38:14 +02:00
|
|
|
return true;
|
2012-02-07 22:04:20 +01:00
|
|
|
|
|
|
|
if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName()))
|
|
|
|
return true;
|
|
|
|
|
2011-09-16 08:45:23 +02:00
|
|
|
Faction defendFaction = defender.getFaction();
|
|
|
|
Faction attackFaction = attacker.getFaction();
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (attackFaction.isNone() && Conf.disablePVPForFactionlessPlayers)
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt other players until you join a faction.");
|
2011-08-02 01:28:34 +02:00
|
|
|
return false;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (defendFaction.isNone())
|
|
|
|
{
|
|
|
|
if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand)
|
|
|
|
{
|
2011-09-16 08:45:23 +02:00
|
|
|
// Allow PVP vs. Factionless in attacker's faction territory
|
|
|
|
return true;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (Conf.disablePVPForFactionlessPlayers)
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt players who are not currently in a faction.");
|
2011-09-16 08:45:23 +02:00
|
|
|
return false;
|
|
|
|
}
|
2011-08-02 01:28:34 +02:00
|
|
|
}
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (defendFaction.isPeaceful())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt players who are in a peaceful faction.");
|
2011-08-05 10:50:47 +02:00
|
|
|
return false;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (attackFaction.isPeaceful())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt players while you are in a peaceful faction.");
|
2011-08-05 10:50:47 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-12 17:25:01 +02:00
|
|
|
Relation relation = defendFaction.getRelationTo(attackFaction);
|
2011-02-06 13:36:11 +01:00
|
|
|
|
2011-07-28 16:04:11 +02:00
|
|
|
// You can not hurt neutral factions
|
2011-10-08 22:03:44 +02:00
|
|
|
if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt neutral factions. Declare them as an enemy.");
|
2011-07-29 12:12:14 +02:00
|
|
|
return false;
|
2011-07-28 16:04:11 +02:00
|
|
|
}
|
|
|
|
|
2011-02-06 13:36:11 +01:00
|
|
|
// Players without faction may be hurt anywhere
|
2011-10-08 22:03:44 +02:00
|
|
|
if (!defender.hasFaction())
|
2011-02-13 09:33:42 +01:00
|
|
|
return true;
|
2011-02-06 13:36:11 +01:00
|
|
|
|
|
|
|
// You can never hurt faction members or allies
|
2011-10-08 22:03:44 +02:00
|
|
|
if (relation.isMember() || relation.isAlly())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify) attacker.msg("<i>You can't hurt %s<i>.", defender.describeTo(attacker));
|
2011-02-13 09:33:42 +01:00
|
|
|
return false;
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|
|
|
|
|
2011-08-05 10:50:47 +02:00
|
|
|
boolean ownTerritory = defender.isInOwnTerritory();
|
|
|
|
|
2011-02-06 13:36:11 +01:00
|
|
|
// You can not hurt neutrals in their own territory.
|
2011-10-08 22:03:44 +02:00
|
|
|
if (ownTerritory && relation.isNeutral())
|
|
|
|
{
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify)
|
|
|
|
{
|
|
|
|
attacker.msg("<i>You can't hurt %s<i> in their own territory unless you declare them as an enemy.", defender.describeTo(attacker));
|
|
|
|
defender.msg("%s<i> tried to hurt you.", attacker.describeTo(defender, true));
|
|
|
|
}
|
2011-02-13 09:33:42 +01:00
|
|
|
return false;
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Damage will be dealt. However check if the damage should be reduced.
|
2012-02-23 07:09:19 +01:00
|
|
|
if (damage > 0.0 && ownTerritory && Conf.territoryShieldFactor > 0)
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
int newDamage = (int)Math.ceil(damage * (1D - Conf.territoryShieldFactor));
|
2011-03-07 04:13:27 +01:00
|
|
|
sub.setDamage(newDamage);
|
2011-02-06 13:36:11 +01:00
|
|
|
|
|
|
|
// Send message
|
2012-02-23 07:09:19 +01:00
|
|
|
if (notify)
|
|
|
|
{
|
|
|
|
String perc = MessageFormat.format("{0,number,#%}", (Conf.territoryShieldFactor)); // TODO does this display correctly??
|
|
|
|
defender.msg("<i>Enemy damage reduced by <rose>%s<i>.", perc);
|
|
|
|
}
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|
|
|
|
|
2011-02-13 09:33:42 +01:00
|
|
|
return true;
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|
2011-03-23 17:39:56 +01:00
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2011-10-08 22:03:44 +02:00
|
|
|
public void onCreatureSpawn(CreatureSpawnEvent event)
|
|
|
|
{
|
|
|
|
if (event.isCancelled() || event.getLocation() == null)
|
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-13 14:43:55 +01:00
|
|
|
if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory())
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2011-10-08 22:03:44 +02:00
|
|
|
public void onEntityTarget(EntityTargetEvent event)
|
|
|
|
{
|
|
|
|
if (event.isCancelled()) return;
|
2011-03-23 17:39:56 +01:00
|
|
|
|
|
|
|
// if there is a target
|
|
|
|
Entity target = event.getTarget();
|
2011-10-08 22:03:44 +02:00
|
|
|
if (target == null)
|
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We are interested in blocking targeting for certain mobs:
|
2011-10-08 22:03:44 +02:00
|
|
|
if ( ! Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity())))
|
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// in case the target is in a safe zone.
|
2011-10-08 22:03:44 +02:00
|
|
|
if (Board.getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory())
|
|
|
|
{
|
2011-03-23 17:39:56 +01:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
|
|
|
}
|
2011-04-28 22:45:43 +02:00
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2012-10-31 22:16:19 +01:00
|
|
|
public void onPaintingBreak(HangingBreakEvent event)
|
2011-04-28 22:45:43 +02:00
|
|
|
{
|
2011-10-08 22:03:44 +02:00
|
|
|
if (event.isCancelled()) return;
|
|
|
|
|
2012-10-31 22:16:19 +01:00
|
|
|
if (! (event instanceof HangingBreakByEntityEvent))
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-04-28 22:45:43 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-31 22:16:19 +01:00
|
|
|
Entity breaker = ((HangingBreakByEntityEvent)event).getRemover();
|
2011-10-08 22:03:44 +02:00
|
|
|
if (! (breaker instanceof Player))
|
|
|
|
{
|
2011-04-28 22:45:43 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-31 22:16:19 +01:00
|
|
|
if ( ! FactionsBlockListener.playerCanBuildDestroyBlock((Player)breaker, event.getEntity().getLocation(), "remove paintings", false))
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-04-28 22:45:43 +02:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2012-10-31 22:16:19 +01:00
|
|
|
public void onPaintingPlace(HangingPlaceEvent event)
|
2011-04-28 22:45:43 +02:00
|
|
|
{
|
2011-10-08 22:03:44 +02:00
|
|
|
if (event.isCancelled()) return;
|
2011-04-28 22:45:43 +02:00
|
|
|
|
2011-10-13 05:31:18 +02:00
|
|
|
if ( ! FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false) )
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-04-28 22:45:43 +02:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:37:55 +01:00
|
|
|
@EventHandler(priority = EventPriority.NORMAL)
|
2012-02-20 23:59:18 +01:00
|
|
|
public void onEntityChangeBlock(EntityChangeBlockEvent event)
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
|
|
|
if (event.isCancelled()) return;
|
2011-09-22 13:22:01 +02:00
|
|
|
|
2012-02-20 23:59:18 +01:00
|
|
|
// for now, only interested in Enderman tomfoolery
|
|
|
|
if (!(event.getEntity() instanceof Enderman)) return;
|
2011-09-22 13:22:01 +02:00
|
|
|
|
2012-02-20 23:59:18 +01:00
|
|
|
if (stopEndermanBlockManipulation(event.getBlock().getLocation()))
|
2011-10-08 22:03:44 +02:00
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
event.setCancelled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
private boolean stopEndermanBlockManipulation(Location loc)
|
|
|
|
{
|
|
|
|
if (loc == null)
|
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// quick check to see if all Enderman deny options are enabled; if so, no need to check location
|
2011-10-08 22:03:44 +02:00
|
|
|
if
|
|
|
|
(
|
|
|
|
Conf.wildernessDenyEndermanBlocks
|
|
|
|
&&
|
|
|
|
Conf.territoryDenyEndermanBlocks
|
|
|
|
&&
|
|
|
|
Conf.territoryDenyEndermanBlocksWhenOffline
|
|
|
|
&&
|
|
|
|
Conf.safeZoneDenyEndermanBlocks
|
|
|
|
&&
|
|
|
|
Conf.warZoneDenyEndermanBlocks
|
|
|
|
)
|
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
FLocation fLoc = new FLocation(loc);
|
|
|
|
Faction claimFaction = Board.getFactionAt(fLoc);
|
|
|
|
|
2011-10-08 22:03:44 +02:00
|
|
|
if (claimFaction.isNone())
|
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
return Conf.wildernessDenyEndermanBlocks;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (claimFaction.isNormal())
|
|
|
|
{
|
2011-10-01 13:16:53 +02:00
|
|
|
return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline;
|
2011-09-22 13:22:01 +02:00
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (claimFaction.isSafeZone())
|
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
return Conf.safeZoneDenyEndermanBlocks;
|
|
|
|
}
|
2011-10-08 22:03:44 +02:00
|
|
|
else if (claimFaction.isWarZone())
|
|
|
|
{
|
2011-09-22 13:22:01 +02:00
|
|
|
return Conf.warZoneDenyEndermanBlocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2011-02-06 13:36:11 +01:00
|
|
|
}
|