Saber-Factions/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java

711 lines
31 KiB
Java
Raw Normal View History

2011-07-18 22:06:02 +02:00
package com.massivecraft.factions.listeners;
2011-02-06 13:36:11 +01:00
2014-04-04 20:55:21 +02:00
import com.massivecraft.factions.*;
import com.massivecraft.factions.event.PowerLossEvent;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.util.MiscUtil;
2015-01-23 20:25:14 +01:00
import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.TravelAgent;
import org.bukkit.block.Block;
2014-04-04 20:55:21 +02:00
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
2014-04-04 20:55:21 +02:00
import org.bukkit.event.entity.*;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
2014-04-06 00:00:33 +02:00
import org.bukkit.projectiles.ProjectileSource;
2011-07-18 22:06:02 +02:00
2014-04-04 20:55:21 +02:00
import java.util.*;
public class FactionsEntityListener implements Listener {
2018-07-12 18:11:07 +02:00
private static final Set<PotionEffectType> badPotionEffects = new LinkedHashSet<>(Arrays.asList(PotionEffectType.BLINDNESS, PotionEffectType.CONFUSION, PotionEffectType.HARM, PotionEffectType.HUNGER, PotionEffectType.POISON, PotionEffectType.SLOW, PotionEffectType.SLOW_DIGGING, PotionEffectType.WEAKNESS, PotionEffectType.WITHER));
2014-04-04 20:55:21 +02:00
public P p;
public FactionsEntityListener(P p) {
this.p = p;
}
@EventHandler(priority = EventPriority.NORMAL)
public void onEntityDeath(EntityDeathEvent event) {
2014-07-01 22:10:18 +02:00
Entity entity = event.getEntity();
if (!(entity instanceof Player)) {
2014-04-04 20:55:21 +02:00
return;
}
2014-07-01 22:10:18 +02:00
Player player = (Player) entity;
FPlayer fplayer = FPlayers.getInstance().getByPlayer(player);
Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation()));
2014-04-04 20:55:21 +02:00
PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer);
// Check for no power loss conditions
if (faction.isWarZone()) {
// war zones always override worldsNoPowerLoss either way, thus this layout
if (!Conf.warZonePowerLoss) {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WARZONE.toString());
2014-04-04 20:55:21 +02:00
powerLossEvent.setCancelled(true);
2014-07-01 22:10:18 +02:00
}
if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_LOSS_WARZONE.toString());
2014-04-04 20:55:21 +02:00
}
} else if (faction.isWilderness() && !Conf.wildernessPowerLoss && !Conf.worldsNoWildernessProtection.contains(player.getWorld().getName())) {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WILDERNESS.toString());
2014-04-04 20:55:21 +02:00
powerLossEvent.setCancelled(true);
2014-07-01 21:52:40 +02:00
} else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_WORLD.toString());
2014-04-04 20:55:21 +02:00
powerLossEvent.setCancelled(true);
2014-07-01 21:52:40 +02:00
} else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_NOLOSS_PEACEFUL.toString());
2014-04-04 20:55:21 +02:00
powerLossEvent.setCancelled(true);
2014-07-01 21:52:40 +02:00
} else {
2015-01-23 20:25:14 +01:00
powerLossEvent.setMessage(TL.PLAYER_POWER_NOW.toString());
2014-04-04 20:55:21 +02:00
}
// call Event
Bukkit.getPluginManager().callEvent(powerLossEvent);
// Call player onDeath if the event is not cancelled
if (!powerLossEvent.isCancelled()) {
fplayer.onDeath();
}
// Send the message from the powerLossEvent
2014-07-01 22:10:18 +02:00
final String msg = powerLossEvent.getMessage();
if (msg != null && !msg.isEmpty()) {
2014-04-04 20:55:21 +02:00
fplayer.msg(msg, fplayer.getPowerRounded(), fplayer.getPowerMaxRounded());
}
}
/**
* 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.
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onEntityDamage(EntityDamageEvent event) {
if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent sub = (EntityDamageByEntityEvent) event;
if (!this.canDamagerHurtDamagee(sub, true)) {
event.setCancelled(true);
}
2015-05-13 05:16:47 +02:00
// event is not cancelled by factions
Entity damagee = sub.getEntity();
Entity damager = sub.getDamager();
if (damagee instanceof Player) {
if (damager instanceof Player) {
FPlayer fdamager = FPlayers.getInstance().getByPlayer((Player) damager);
FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee);
if ((fdamagee.getRelationTo(fdamager) == Relation.ALLY) ||
(fdamagee.getRelationTo(fdamager) == Relation.TRUCE) ||
(fdamagee.getFaction() == fdamager.getFaction())) {
return;
}
} else {
// this triggers if damagee is a player and damager is mob ( so like if a skeleton hits u )
if (damager instanceof Projectile) {
// this will trigger if the damager is a projectile
if (((Projectile) damager).getShooter() instanceof Player) {
Player damagerPlayer = (Player) ((Projectile) damager).getShooter();
FPlayer fdamager = FPlayers.getInstance().getByPlayer(damagerPlayer);
FPlayer fdamagee = FPlayers.getInstance().getByPlayer((Player) damagee);
Relation relation = fdamager.getRelationTo(fdamagee);
if (relation == Relation.ALLY || relation == Relation.TRUCE ||
fdamager.getFaction() == fdamagee.getFaction()) {
// this should disable the fly so
return;
}
} else {
// this should trigger if the attacker shootin the arrow is a mob
return;
}
}
}
} else {
//this one should trigger if something other than a player takes damage
if (damager instanceof Player) {
// now itll only go here if the damage is dealt by a player
return;
// we cancel it so fly isnt removed when you hit a mob etc
}
}
2015-05-13 05:16:47 +02:00
if (damagee != null && damagee instanceof Player) {
cancelFStuckTeleport((Player) damagee);
2018-03-04 23:13:32 +01:00
cancelFFly((Player) damagee);
FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damagee);
2018-07-12 18:11:07 +02:00
if (fplayer.isInspectMode()) {
fplayer.setInspectMode(false);
fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG);
}
2015-05-13 05:16:47 +02:00
}
if (damager instanceof Player) {
cancelFStuckTeleport((Player) damager);
2018-03-04 23:13:32 +01:00
cancelFFly((Player) damager);
FPlayer fplayer = FPlayers.getInstance().getByPlayer((Player) damager);
2018-07-12 18:11:07 +02:00
if (fplayer.isInspectMode()) {
fplayer.setInspectMode(false);
fplayer.msg(TL.COMMAND_INSPECT_DISABLED_MSG);
}
2015-05-13 05:16:47 +02:00
}
2014-07-01 21:52:40 +02:00
} else if (Conf.safeZonePreventAllDamageToPlayers && isPlayerInSafeZone(event.getEntity())) {
2014-04-04 20:55:21 +02:00
// Players can not take any damage in a Safe Zone
event.setCancelled(true);
2018-03-05 02:27:48 +01:00
} else if (event.getCause() == EntityDamageEvent.DamageCause.FALL && event.getEntity() instanceof Player) {
Player player = (Player) event.getEntity();
FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player);
if (fPlayer != null && !fPlayer.shouldTakeFallDamage()) {
event.setCancelled(true); // Falling after /f fly
}
2014-04-04 20:55:21 +02:00
}
2015-05-13 05:16:47 +02:00
// entity took generic damage?
Entity entity = event.getEntity();
if (entity instanceof Player) {
2015-05-25 06:42:31 +02:00
Player player = (Player) entity;
FPlayer me = FPlayers.getInstance().getByPlayer(player);
cancelFStuckTeleport(player);
if (me.isWarmingUp()) {
me.clearWarmup();
me.msg(TL.WARMUPS_CANCELLED);
}
2015-05-13 05:16:47 +02:00
}
}
2018-03-04 23:13:32 +01:00
private void cancelFFly(Player player) {
if (player == null) {
return;
}
FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player);
if (fPlayer.isFlying()) {
fPlayer.setFFlying(false, true);
}
}
2015-05-13 05:16:47 +02:00
public void cancelFStuckTeleport(Player player) {
2015-05-13 06:17:22 +02:00
if (player == null) {
return;
}
2015-05-13 05:16:47 +02:00
UUID uuid = player.getUniqueId();
if (P.p.getStuckMap().containsKey(uuid)) {
FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED);
P.p.getStuckMap().remove(uuid);
}
2014-04-04 20:55:21 +02:00
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onEntityExplode(EntityExplodeEvent event) {
Entity boomer = event.getEntity();
// Before we need to check the location where the block is placed
if (!this.checkExplosionForBlock(boomer, event.getLocation().getBlock())) {
event.setCancelled(true);
return;
}
// Loop the blocklist to run checks on each aimed block
Iterator<Block> blockList = event.blockList().iterator();
while (blockList.hasNext()) {
Block block = blockList.next();
if (!this.checkExplosionForBlock(boomer, block)) {
// The block don't have to explode
blockList.remove();
}
}
// Cancel the event if no block will explode
if (event.blockList().isEmpty()) {
event.setCancelled(true);
// Or handle the exploit of TNT in water/lava
} else if ((boomer instanceof TNTPrimed || boomer instanceof ExplosiveMinecart) && 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 = event.getLocation().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<>();
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.getType().getId();
// 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) {
target.breakNaturally();
}
}
}
}
2018-05-11 18:09:11 +02:00
}
2018-05-11 19:27:21 +02:00
private boolean checkExplosionForBlock(Entity boomer, Block block) {
2018-05-11 18:09:11 +02:00
Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation()));
2014-04-04 20:55:21 +02:00
if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) {
2014-04-04 20:55:21 +02:00
// faction is peaceful and has explosions set to disabled
2018-05-11 18:09:11 +02:00
return false;
2014-04-04 20:55:21 +02:00
}
boolean online = faction.hasPlayersOnline();
2018-05-11 18:09:11 +02:00
if (boomer instanceof Creeper && ((faction.isWilderness() && Conf.wildernessBlockCreepers && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) ||
(faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) ||
(faction.isWarZone() && Conf.warZoneBlockCreepers) ||
faction.isSafeZone())) {
2014-04-04 20:55:21 +02:00
// creeper which needs prevention
2018-05-11 18:09:11 +02:00
return false;
2014-07-01 21:52:40 +02:00
} else if (
2014-04-04 20:55:21 +02:00
// it's a bit crude just using fireball protection for Wither boss too, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever
2018-05-11 18:09:11 +02:00
(boomer instanceof Fireball || boomer instanceof WitherSkull || boomer instanceof Wither) && ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) ||
(faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) ||
(faction.isWarZone() && Conf.warZoneBlockFireballs) ||
faction.isSafeZone())) {
2014-04-04 20:55:21 +02:00
// ghast fireball which needs prevention
2018-05-11 18:09:11 +02:00
return false;
} else
return (!(boomer instanceof TNTPrimed) && !(boomer instanceof ExplosiveMinecart)) || ((!faction.isWilderness() || !Conf.wildernessBlockTNT || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) &&
(!faction.isNormal() || (online ? !Conf.territoryBlockTNT : !Conf.territoryBlockTNTWhenOffline)) &&
(!faction.isWarZone() || !Conf.warZoneBlockTNT) &&
(!faction.isSafeZone() || !Conf.safeZoneBlockTNT));
2018-05-11 18:09:11 +02:00
// No condition retained, destroy the block!
}
2014-04-04 20:55:21 +02: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, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onEntityCombustByEntity(EntityCombustByEntityEvent event) {
EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d);
2014-07-01 22:10:18 +02:00
if (!this.canDamagerHurtDamagee(sub, false)) {
event.setCancelled(true);
}
2014-04-04 20:55:21 +02:00
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onPotionSplashEvent(PotionSplashEvent event) {
// see if the potion has a harmful effect
2014-07-01 22:10:18 +02:00
boolean badjuju = false;
for (PotionEffect effect : event.getPotion().getEffects()) {
2014-04-04 20:55:21 +02:00
if (badPotionEffects.contains(effect.getType())) {
2014-07-01 22:10:18 +02:00
badjuju = true;
break;
2014-04-04 20:55:21 +02:00
}
2014-07-01 22:10:18 +02:00
}
if (!badjuju) {
return;
}
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
ProjectileSource thrower = event.getPotion().getShooter();
if (!(thrower instanceof Entity)) {
2014-04-06 00:00:33 +02:00
return;
}
2014-04-04 20:55:21 +02:00
2014-11-06 01:36:47 +01:00
if (thrower instanceof Player) {
Player player = (Player) thrower;
FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player);
2014-11-06 01:36:47 +01:00
if (badjuju && fPlayer.getFaction().isPeaceful()) {
event.setCancelled(true);
return;
}
}
2014-04-04 20:55:21 +02:00
// scan through affected entities to make sure they're all valid targets
2017-12-19 11:18:13 +01:00
for (LivingEntity target : event.getAffectedEntities()) {
2014-04-06 00:00:33 +02:00
EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0);
2014-07-01 21:49:42 +02:00
if (!this.canDamagerHurtDamagee(sub, true)) {
2014-04-04 20:55:21 +02:00
event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works
2014-07-01 22:10:18 +02:00
}
2014-04-04 20:55:21 +02:00
}
}
public boolean isPlayerInSafeZone(Entity damagee) {
if (!(damagee instanceof Player)) {
return false;
2014-07-01 22:10:18 +02:00
}
2017-12-19 11:18:13 +01:00
return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone();
2014-04-04 20:55:21 +02:00
}
public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub) {
return canDamagerHurtDamagee(sub, true);
}
public boolean canDamagerHurtDamagee(EntityDamageByEntityEvent sub, boolean notify) {
2014-07-01 22:10:18 +02:00
Entity damager = sub.getDamager();
Entity damagee = sub.getEntity();
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
if (!(damagee instanceof Player)) {
return true;
}
2014-04-04 20:55:21 +02:00
FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee);
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
if (defender == null || defender.getPlayer() == null) {
return true;
}
2014-04-04 20:55:21 +02:00
Location defenderLoc = defender.getPlayer().getLocation();
Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc));
2014-04-04 20:55:21 +02:00
// for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source
2014-04-06 00:00:33 +02:00
if (damager instanceof Projectile) {
Projectile projectile = (Projectile) damager;
if (!(projectile.getShooter() instanceof Entity)) {
return true;
}
damager = (Entity) projectile.getShooter();
2014-04-06 00:00:33 +02:00
}
2014-04-04 20:55:21 +02:00
2014-06-17 07:54:50 +02:00
if (damager == damagee) // ender pearl usage and other self-inflicted damage
2014-07-01 22:10:18 +02:00
{
return true;
}
2014-04-04 20:55:21 +02:00
// Players can not take attack damage in a SafeZone, or possibly peaceful territory
if (defLocFaction.noPvPInTerritory()) {
if (damager instanceof Player) {
if (notify) {
FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager);
2015-01-27 16:46:56 +01:00
attacker.msg(TL.PLAYER_CANTHURT, (defLocFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString()));
2014-07-01 22:10:18 +02:00
}
return false;
}
return !defLocFaction.noMonstersInTerritory();
2014-04-04 20:55:21 +02:00
}
2014-07-01 22:10:18 +02:00
if (!(damager instanceof Player)) {
return true;
}
2014-04-04 20:55:21 +02:00
FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager);
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
if (attacker == null || attacker.getPlayer() == null) {
return true;
}
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) {
return true;
}
2014-04-04 20:55:21 +02:00
if (attacker.hasLoginPvpDisabled()) {
2014-07-01 21:49:42 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_LOGIN, Conf.noPVPDamageToOthersForXSecondsAfterLogin);
2014-07-01 22:10:18 +02:00
}
return false;
2014-04-04 20:55:21 +02:00
}
Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker));
2014-04-04 20:55:21 +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?
if (locFaction.noPvPInTerritory()) {
2014-07-01 21:49:42 +02:00
if (notify) {
2015-01-27 16:46:56 +01:00
attacker.msg(TL.PLAYER_CANTHURT, (locFaction.isSafeZone() ? TL.REGION_SAFEZONE.toString() : TL.REGION_PEACEFUL.toString()));
2014-07-01 22:10:18 +02:00
}
return false;
2014-04-04 20:55:21 +02:00
}
2014-07-01 22:10:18 +02:00
if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) {
return true;
}
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) {
return true;
}
2014-04-04 20:55:21 +02:00
2014-07-01 22:10:18 +02:00
Faction defendFaction = defender.getFaction();
Faction attackFaction = attacker.getFaction();
2014-04-04 20:55:21 +02:00
if (attackFaction.isWilderness() && Conf.disablePVPForFactionlessPlayers) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_REQUIREFACTION);
2014-07-01 22:10:18 +02:00
}
return false;
} else if (defendFaction.isWilderness()) {
2014-04-04 20:55:21 +02:00
if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) {
// Allow PVP vs. Factionless in attacker's faction territory
return true;
2014-07-01 21:52:40 +02:00
} else if (Conf.disablePVPForFactionlessPlayers) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_FACTIONLESS);
2014-07-01 22:10:18 +02:00
}
2014-04-04 20:55:21 +02:00
return false;
}
}
if (defendFaction.isPeaceful()) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_PEACEFUL);
2014-07-01 22:10:18 +02:00
}
return false;
2014-07-01 21:52:40 +02:00
} else if (attackFaction.isPeaceful()) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_PEACEFUL);
2014-07-01 22:10:18 +02:00
}
2014-04-04 20:55:21 +02:00
return false;
}
Relation relation = defendFaction.getRelationTo(attackFaction);
// You can not hurt neutral factions
if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_NEUTRAL);
2014-07-01 22:10:18 +02:00
}
return false;
2014-04-04 20:55:21 +02:00
}
// Players without faction may be hurt anywhere
2014-07-01 22:10:18 +02:00
if (!defender.hasFaction()) {
return true;
}
2014-04-04 20:55:21 +02:00
// You can never hurt faction members or allies
if (relation.isMember() || relation.isAlly()) {
2014-07-01 22:10:18 +02:00
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_CANTHURT, defender.describeTo(attacker));
2014-07-01 22:10:18 +02:00
}
return false;
2014-04-04 20:55:21 +02:00
}
boolean ownTerritory = defender.isInOwnTerritory();
// You can not hurt neutrals in their own territory.
if (ownTerritory && relation.isNeutral()) {
if (notify) {
2015-01-23 20:25:14 +01:00
attacker.msg(TL.PLAYER_PVP_NEUTRALFAIL, defender.describeTo(attacker));
defender.msg(TL.PLAYER_PVP_TRIED, attacker.describeTo(defender, true));
2014-07-01 22:10:18 +02:00
}
return false;
2014-04-04 20:55:21 +02:00
}
// Damage will be dealt. However check if the damage should be reduced.
/*
2014-04-04 20:55:21 +02:00
if (damage > 0.0 && ownTerritory && Conf.territoryShieldFactor > 0) {
double newDamage = Math.ceil(damage * (1D - Conf.territoryShieldFactor));
2014-07-01 22:10:18 +02:00
sub.setDamage(newDamage);
2014-04-04 20:55:21 +02:00
// Send message
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);
}
} */
2014-04-04 20:55:21 +02:00
return true;
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onCreatureSpawn(CreatureSpawnEvent event) {
if (event.getLocation() == null) {
2014-04-04 20:55:21 +02:00
return;
}
if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) {
2014-04-04 20:55:21 +02:00
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onEntityTarget(EntityTargetEvent event) {
// if there is a target
2014-07-01 22:10:18 +02:00
Entity target = event.getTarget();
if (target == null) {
2014-04-04 20:55:21 +02:00
return;
}
// We are interested in blocking targeting for certain mobs:
if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) {
return;
}
// in case the target is in a safe zone.
if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) {
2014-04-04 20:55:21 +02:00
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onPaintingBreak(HangingBreakEvent event) {
2014-07-01 22:10:18 +02:00
if (event.getCause() == RemoveCause.EXPLOSION) {
Location loc = event.getEntity().getLocation();
Faction faction = Board.getInstance().getFactionAt(new FLocation(loc));
2014-04-04 20:55:21 +02:00
if (faction.noExplosionsInTerritory()) {
// faction is peaceful and has explosions set to disabled
2014-07-01 22:10:18 +02:00
event.setCancelled(true);
return;
2014-04-04 20:55:21 +02:00
}
boolean online = faction.hasPlayersOnline();
if ((faction.isWilderness() && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName()) && (Conf.wildernessBlockCreepers || Conf.wildernessBlockFireballs || Conf.wildernessBlockTNT)) ||
(faction.isNormal() && (online ? (Conf.territoryBlockCreepers || Conf.territoryBlockFireballs || Conf.territoryBlockTNT) : (Conf.territoryBlockCreepersWhenOffline || Conf.territoryBlockFireballsWhenOffline || Conf.territoryBlockTNTWhenOffline))) ||
(faction.isWarZone() && (Conf.warZoneBlockCreepers || Conf.warZoneBlockFireballs || Conf.warZoneBlockTNT)) ||
faction.isSafeZone()) {
2014-04-04 20:55:21 +02:00
// explosion which needs prevention
event.setCancelled(true);
}
}
if (!(event instanceof HangingBreakByEntityEvent)) {
return;
}
2014-07-01 22:10:18 +02:00
Entity breaker = ((HangingBreakByEntityEvent) event).getRemover();
if (!(breaker instanceof Player)) {
2014-04-04 20:55:21 +02:00
return;
}
if (!FactionsBlockListener.playerCanBuildDestroyBlock((Player) breaker, event.getEntity().getLocation(), "remove paintings", false)) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onPaintingPlace(HangingPlaceEvent event) {
if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "place paintings", false)) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
2014-04-04 20:55:21 +02:00
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
Entity entity = event.getEntity();
// for now, only interested in Enderman and Wither boss tomfoolery
2014-07-01 22:10:18 +02:00
if (!(entity instanceof Enderman) && !(entity instanceof Wither)) {
return;
}
2014-04-04 20:55:21 +02:00
Location loc = event.getBlock().getLocation();
if (entity instanceof Enderman) {
2014-07-01 22:10:18 +02:00
if (stopEndermanBlockManipulation(loc)) {
event.setCancelled(true);
}
2014-07-01 21:52:40 +02:00
} else if (entity instanceof Wither) {
Faction faction = Board.getInstance().getFactionAt(new FLocation(loc));
2014-04-04 20:55:21 +02:00
// it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever
if ((faction.isWilderness() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) ||
(faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) ||
(faction.isWarZone() && Conf.warZoneBlockFireballs) ||
faction.isSafeZone()) {
2014-07-01 22:10:18 +02:00
event.setCancelled(true);
}
2014-04-04 20:55:21 +02:00
}
}
@EventHandler
public void onTravel(PlayerPortalEvent event) {
if (!P.p.getConfig().getBoolean("portals.limit", false)) {
return; // Don't do anything if they don't want us to.
}
TravelAgent agent = event.getPortalTravelAgent();
// If they aren't able to find a portal, it'll try to create one.
if (event.useTravelAgent() && agent.getCanCreatePortal() && agent.findPortal(event.getTo()) == null) {
FLocation loc = new FLocation(event.getTo());
Faction faction = Board.getInstance().getFactionAt(loc);
if (faction.isWilderness()) {
return; // We don't care about wilderness.
} else if (!faction.isNormal() && !event.getPlayer().isOp()) {
// Don't let non ops make portals in safezone or warzone.
event.setCancelled(true);
return;
}
FPlayer fp = FPlayers.getInstance().getByPlayer(event.getPlayer());
String mininumRelation = P.p.getConfig().getString("portals.minimum-relation", "MEMBER"); // Defaults to Neutral if typed wrong.
if (!fp.getFaction().getRelationTo(faction).isAtLeast(Relation.fromString(mininumRelation))) {
event.setCancelled(true);
}
}
}
2018-03-26 23:43:15 +02:00
@EventHandler
public void onHit(EntityDamageByEntityEvent e) {
if (e.getDamager() instanceof Player) {
if (e.getEntity() instanceof Player) {
Player victim = (Player) e.getEntity();
Player attacker = (Player) e.getDamager();
FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim);
FPlayer fattacker = FPlayers.getInstance().getByPlayer(attacker);
if (fattacker.getRelationTo(fvictim) == Relation.TRUCE) {
fattacker.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fattacker));
e.setCancelled(true);
}
}
}
}
@EventHandler
2018-07-12 18:11:07 +02:00
public void onBowHit(EntityDamageByEntityEvent e) {
if (e.getDamager() instanceof Projectile) {
if (e.getEntity() instanceof Player) {
Projectile arrow = ((Projectile) e.getDamager());
if (arrow.getShooter() instanceof Player) {
Player damager = (Player) ((Projectile) e.getDamager()).getShooter();
Player victim = (Player) e.getEntity();
FPlayer fdamager = FPlayers.getInstance().getByPlayer(damager);
FPlayer fvictim = FPlayers.getInstance().getByPlayer(victim);
if (fvictim.getRelationTo(fdamager) == Relation.TRUCE) {
fdamager.msg(TL.PLAYER_PVP_CANTHURT, fvictim.describeTo(fdamager));
e.setCancelled(true);
}
if (fvictim.getRelationTo(fdamager) == Relation.ENEMY) {
if (fvictim.isFlying()) {
fvictim.setFFlying(false, true);
}
2018-03-26 23:43:15 +02:00
}
}
}
}
}
2014-04-04 20:55:21 +02:00
private boolean stopEndermanBlockManipulation(Location loc) {
if (loc == null) {
return false;
}
// quick check to see if all Enderman deny options are enabled; if so, no need to check location
2014-07-01 21:52:40 +02:00
if (Conf.wildernessDenyEndermanBlocks &&
Conf.territoryDenyEndermanBlocks &&
Conf.territoryDenyEndermanBlocksWhenOffline &&
Conf.safeZoneDenyEndermanBlocks &&
Conf.warZoneDenyEndermanBlocks) {
2014-04-04 20:55:21 +02:00
return true;
}
2014-07-01 22:10:18 +02:00
FLocation fLoc = new FLocation(loc);
Faction claimFaction = Board.getInstance().getFactionAt(fLoc);
2014-04-04 20:55:21 +02:00
if (claimFaction.isWilderness()) {
2014-04-04 20:55:21 +02:00
return Conf.wildernessDenyEndermanBlocks;
2014-07-01 21:52:40 +02:00
} else if (claimFaction.isNormal()) {
2014-04-04 20:55:21 +02:00
return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline;
2014-07-01 21:52:40 +02:00
} else if (claimFaction.isSafeZone()) {
2014-04-04 20:55:21 +02:00
return Conf.safeZoneDenyEndermanBlocks;
2014-07-01 21:52:40 +02:00
} else if (claimFaction.isWarZone()) {
2014-04-04 20:55:21 +02:00
return Conf.warZoneDenyEndermanBlocks;
}
return false;
}
}