/* * _____ _ _ _____ _ * | __ \| | | | / ____| | | * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| * | | * |_| * PlotSquared plot management system for Minecraft * Copyright (C) 2020 IntellectualSites * * 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 . */ package com.plotsquared.bukkit.util; import com.plotsquared.bukkit.player.BukkitPlayer; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.location.Location; import com.plotsquared.core.permissions.Permission; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.flag.implementations.AnimalAttackFlag; import com.plotsquared.core.plot.flag.implementations.AnimalCapFlag; import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.EntityCapFlag; import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag; import com.plotsquared.core.plot.flag.implementations.HostileAttackFlag; import com.plotsquared.core.plot.flag.implementations.HostileCapFlag; import com.plotsquared.core.plot.flag.implementations.MiscBreakFlag; import com.plotsquared.core.plot.flag.implementations.MiscCapFlag; import com.plotsquared.core.plot.flag.implementations.MobCapFlag; import com.plotsquared.core.plot.flag.implementations.PveFlag; import com.plotsquared.core.plot.flag.implementations.PvpFlag; import com.plotsquared.core.plot.flag.implementations.TamedAttackFlag; import com.plotsquared.core.plot.flag.implementations.VehicleCapFlag; import com.plotsquared.core.util.EntityUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.entity.EntityCategories; import com.sk89q.worldedit.bukkit.BukkitAdapter; import net.kyori.adventure.text.minimessage.Template; import org.bukkit.entity.Arrow; import org.bukkit.entity.Creature; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.projectiles.BlockProjectileSource; import org.bukkit.projectiles.ProjectileSource; import java.util.Objects; public class BukkitEntityUtil { public static final com.sk89q.worldedit.world.entity.EntityType FAKE_ENTITY_TYPE = new com.sk89q.worldedit.world.entity.EntityType("plotsquared:fake"); public static boolean entityDamage(Entity damager, Entity victim) { return entityDamage(damager, victim, null); } public static boolean entityDamage(Entity damager, Entity victim, EntityDamageEvent.DamageCause cause) { Location dloc = BukkitUtil.adapt(damager.getLocation()); Location vloc = BukkitUtil.adapt(victim.getLocation()); PlotArea dArea = dloc.getPlotArea(); PlotArea vArea; if (dArea != null && dArea.contains(vloc.getX(), vloc.getZ())) { vArea = dArea; } else { vArea = vloc.getPlotArea(); } if (dArea == null && vArea == null) { return true; } Plot dplot; if (dArea != null) { dplot = dArea.getPlot(dloc); } else { dplot = null; } Plot vplot; if (vArea != null) { vplot = vArea.getPlot(vloc); } else { vplot = null; } Plot plot; String stub; boolean isPlot = true; if (dplot == null && vplot == null) { if (dArea == null) { return true; } plot = null; stub = "road"; isPlot = false; } else { // Prioritize plots for close to seamless pvp zones if (victim.getTicksLived() > damager.getTicksLived()) { if (dplot == null || !(victim instanceof Player)) { if (vplot == null) { plot = dplot; } else { plot = vplot; } } else { plot = dplot; } } else if (dplot == null || !(victim instanceof Player)) { if (vplot == null) { plot = dplot; } else { plot = vplot; } } else if (vplot == null) { plot = dplot; } else { plot = vplot; } if (plot.hasOwner()) { stub = "other"; } else { stub = "unowned"; } } boolean roadFlags = vArea != null ? vArea.isRoadFlags() : dArea.isRoadFlags(); PlotArea area = vArea != null ? vArea : dArea; Player player; if (damager instanceof Player) { // attacker is player player = (Player) damager; } else if (damager instanceof Projectile) { Projectile projectile = (Projectile) damager; ProjectileSource shooter = projectile.getShooter(); if (shooter instanceof Player) { // shooter is player player = (Player) shooter; } else { // shooter is not player if (shooter instanceof BlockProjectileSource) { Location sLoc = BukkitUtil .adapt(((BlockProjectileSource) shooter).getBlock().getLocation()); dplot = dArea.getPlot(sLoc); } player = null; } } else { // Attacker is not player player = null; } if (player != null) { BukkitPlayer plotPlayer = BukkitUtil.adapt(player); final com.sk89q.worldedit.world.entity.EntityType entityType; // Create a fake entity type if the type does not have a name if (victim.getType().getName() == null) { entityType = FAKE_ENTITY_TYPE; } else { entityType = BukkitAdapter.adapt(victim.getType()); } if (EntityCategories.HANGING.contains(entityType)) { // hanging if (plot != null && (plot.getFlag(HangingBreakFlag.class) || plot .isAdded(plotPlayer.getUUID()))) { if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { if (!Permissions .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", Permission.PERMISSION_ADMIN_BUILD_OTHER) ); return false; } } return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.destroy." + stub) ); return false; } } else if (victim.getType() == EntityType.ARMOR_STAND) { if (plot != null && (plot.getFlag(MiscBreakFlag.class) || plot .isAdded(plotPlayer.getUUID()))) { return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.destroy." + stub) ); if (plot != null) { plot.debug(player.getName() + " could not break armor stand because misc-break = false"); } return false; } } else if (EntityCategories.HOSTILE.contains(entityType)) { if (isPlot) { if (plot.getFlag(HostileAttackFlag.class) || plot.getFlag(PveFlag.class) || plot .isAdded(plotPlayer.getUUID())) { return true; } } else if (roadFlags && (area.getRoadFlag(HostileAttackFlag.class) || area .getFlag(PveFlag.class))) { return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pve." + stub) ); if (plot != null) { plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR hostile-attack = false"); } return false; } } else if (EntityCategories.TAMEABLE.contains(entityType)) { // victim is tameable if (isPlot) { if (plot.getFlag(TamedAttackFlag.class) || plot.getFlag(PveFlag.class) || plot .isAdded(plotPlayer.getUUID())) { return true; } } else if (roadFlags && (area.getRoadFlag(TamedAttackFlag.class) || area .getFlag(PveFlag.class))) { return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pve." + stub) ); if (plot != null) { plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR tamed-attack = false"); } return false; } } else if (EntityCategories.PLAYER.contains(entityType)) { if (isPlot) { if (!plot.getFlag(PvpFlag.class) && !Permissions .hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pvp." + stub) ); plot.debug(player.getName() + " could not attack " + entityType + " because pve = false"); return false; } else { return true; } } else if (roadFlags && area.getRoadFlag(PvpFlag.class)) { return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pvp." + stub) ); return false; } } else if (EntityCategories.ANIMAL.contains(entityType)) { // victim is animal if (isPlot) { if (plot.getFlag(AnimalAttackFlag.class) || plot.getFlag(PveFlag.class) || plot .isAdded(plotPlayer.getUUID())) { plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR animal-attack = false"); return true; } } else if (roadFlags && (area.getRoadFlag(AnimalAttackFlag.class) || area .getFlag(PveFlag.class))) { if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pve." + stub) ); return false; } } } else if (EntityCategories.VEHICLE .contains(entityType)) { // Vehicles are managed in vehicle destroy event return true; } else { // victim is something else if (isPlot) { if (plot.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID())) { return true; } } else if (roadFlags && area.getRoadFlag(PveFlag.class)) { return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { plotPlayer.sendMessage( TranslatableCaption.of("permission.no_permission_event"), Template.of("node", "plots.admin.pve." + stub) ); if (plot != null) { plot.debug(player.getName() + " could not attack " + entityType + " because pve = false"); } return false; } } return true; } else if (dplot != null && (!dplot.equals(vplot) || Objects .equals(dplot.getOwnerAbs(), vplot.getOwnerAbs()))) { return vplot != null && vplot.getFlag(PveFlag.class); } //disable the firework damage. too much of a headache to support at the moment. if (vplot != null) { if (EntityDamageEvent.DamageCause.ENTITY_EXPLOSION == cause && damager.getType() == EntityType.FIREWORK) { return false; } } if (vplot == null && roadFlags && area.getRoadFlag(PveFlag.class)) { return true; } return ((vplot != null && vplot.getFlag(PveFlag.class)) || !(damager instanceof Arrow && !(victim instanceof Creature))); } public static boolean checkEntity(Entity entity, Plot plot) { if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot.getArea() .getFlagContainer().getFlagMap().isEmpty()) { return false; } final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(entity.getType()); if (EntityCategories.PLAYER.contains(entityType)) { return false; } if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER .contains(entityType) || EntityCategories.HANGING.contains(entityType)) { return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, MiscCapFlag.MISC_CAP_UNLIMITED); } // Has to go go before vehicle as horses are both // animals and vehicles if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER .contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) { return EntityUtil .checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, MobCapFlag.MOB_CAP_UNLIMITED, AnimalCapFlag.ANIMAL_CAP_UNLIMITED); } if (EntityCategories.HOSTILE.contains(entityType)) { return EntityUtil .checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, MobCapFlag.MOB_CAP_UNLIMITED, HostileCapFlag.HOSTILE_CAP_UNLIMITED); } if (EntityCategories.VEHICLE.contains(entityType)) { return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, VehicleCapFlag.VEHICLE_CAP_UNLIMITED); } return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED); } }