001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.bukkit.listener; 020 021import com.plotsquared.bukkit.util.BukkitEntityUtil; 022import com.plotsquared.bukkit.util.BukkitUtil; 023import com.plotsquared.core.PlotSquared; 024import com.plotsquared.core.configuration.Settings; 025import com.plotsquared.core.location.Location; 026import com.plotsquared.core.plot.Plot; 027import com.plotsquared.core.plot.PlotArea; 028import com.plotsquared.core.plot.flag.implementations.DoneFlag; 029import io.papermc.lib.PaperLib; 030import org.bukkit.Chunk; 031import org.bukkit.World; 032import org.bukkit.block.Block; 033import org.bukkit.entity.ArmorStand; 034import org.bukkit.entity.Entity; 035import org.bukkit.entity.EntityType; 036import org.bukkit.entity.Vehicle; 037import org.bukkit.event.EventHandler; 038import org.bukkit.event.EventPriority; 039import org.bukkit.event.Listener; 040import org.bukkit.event.entity.CreatureSpawnEvent; 041import org.bukkit.event.entity.EntitySpawnEvent; 042import org.bukkit.event.entity.EntityTeleportEvent; 043import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; 044import org.bukkit.event.vehicle.VehicleCreateEvent; 045import org.bukkit.event.vehicle.VehicleMoveEvent; 046import org.bukkit.event.vehicle.VehicleUpdateEvent; 047import org.bukkit.event.world.ChunkLoadEvent; 048import org.bukkit.metadata.FixedMetadataValue; 049import org.bukkit.metadata.MetadataValue; 050import org.bukkit.plugin.Plugin; 051import org.checkerframework.checker.nullness.qual.NonNull; 052 053import java.util.List; 054 055public class EntitySpawnListener implements Listener { 056 057 private static final String KEY = "P2"; 058 private static boolean ignoreTP = false; 059 private static boolean hasPlotArea = false; 060 private static String areaName = null; 061 062 public static void testNether(final Entity entity) { 063 @NonNull World world = entity.getWorld(); 064 if (world.getEnvironment() != World.Environment.NETHER && world.getEnvironment() != World.Environment.THE_END) { 065 return; 066 } 067 test(entity); 068 } 069 070 public static void testCreate(final Entity entity) { 071 @NonNull World world = entity.getWorld(); 072 if (!world.getName().equals(areaName)) { 073 areaName = world.getName(); 074 hasPlotArea = PlotSquared.get().getPlotAreaManager().hasPlotArea(areaName); 075 } 076 if (!hasPlotArea) { 077 return; 078 } 079 test(entity); 080 } 081 082 public static void test(Entity entity) { 083 @NonNull World world = entity.getWorld(); 084 List<MetadataValue> meta = entity.getMetadata(KEY); 085 if (meta.isEmpty()) { 086 if (PlotSquared.get().getPlotAreaManager().hasPlotArea(world.getName())) { 087 entity.setMetadata(KEY, new FixedMetadataValue((Plugin) PlotSquared.platform(), entity.getLocation())); 088 } 089 } else { 090 org.bukkit.Location origin = (org.bukkit.Location) meta.get(0).value(); 091 World originWorld = origin.getWorld(); 092 if (!originWorld.equals(world)) { 093 if (!ignoreTP) { 094 if (!world.getName().equalsIgnoreCase(originWorld + "_the_end")) { 095 if (entity.getType() == EntityType.PLAYER) { 096 return; 097 } 098 try { 099 ignoreTP = true; 100 PaperLib.teleportAsync(entity, origin); 101 } finally { 102 ignoreTP = false; 103 } 104 if (entity.getLocation().getWorld().equals(world)) { 105 entity.remove(); 106 } 107 } 108 } else { 109 if (entity.getType() == EntityType.PLAYER) { 110 return; 111 } 112 entity.remove(); 113 } 114 } 115 } 116 } 117 118 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 119 public void creatureSpawnEvent(EntitySpawnEvent event) { 120 Entity entity = event.getEntity(); 121 Location location = BukkitUtil.adapt(entity.getLocation()); 122 PlotArea area = location.getPlotArea(); 123 if (!location.isPlotArea()) { 124 return; 125 } 126 Plot plot = location.getOwnedPlotAbs(); 127 EntityType type = entity.getType(); 128 if (plot == null) { 129 if (type == EntityType.DROPPED_ITEM) { 130 if (Settings.Enabled_Components.KILL_ROAD_ITEMS) { 131 event.setCancelled(true); 132 } 133 return; 134 } 135 if (!area.isMobSpawning()) { 136 if (type == EntityType.PLAYER) { 137 return; 138 } 139 if (type.isAlive()) { 140 event.setCancelled(true); 141 } 142 } 143 if (!area.isMiscSpawnUnowned() && !type.isAlive()) { 144 event.setCancelled(true); 145 } 146 return; 147 } 148 if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { 149 event.setCancelled(true); 150 } 151 if (type == EntityType.ENDER_CRYSTAL) { 152 if (BukkitEntityUtil.checkEntity(entity, plot)) { 153 event.setCancelled(true); 154 } 155 return; 156 } 157 if (type == EntityType.SHULKER) { 158 if (!entity.hasMetadata("shulkerPlot")) { 159 entity.setMetadata("shulkerPlot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot.getId())); 160 } 161 } 162 } 163 164 @EventHandler 165 public void onChunkLoad(ChunkLoadEvent event) { 166 @NonNull Chunk chunk = event.getChunk(); 167 for (final Entity entity : chunk.getEntities()) { 168 testCreate(entity); 169 } 170 } 171 172 @EventHandler 173 public void onVehicle(VehicleUpdateEvent event) { 174 testNether(event.getVehicle()); 175 } 176 177 @EventHandler 178 public void onVehicle(VehicleCreateEvent event) { 179 testCreate(event.getVehicle()); 180 } 181 182 @EventHandler 183 public void onVehicle(VehicleBlockCollisionEvent event) { 184 testNether(event.getVehicle()); 185 } 186 187 @EventHandler 188 public void onTeleport(EntityTeleportEvent event) { 189 Entity entity = event.getEntity(); 190 Entity fromLocation = event.getEntity(); 191 Block toLocation = event.getTo().getBlock(); 192 final Location fromLocLocation = BukkitUtil.adapt(fromLocation.getLocation()); 193 final PlotArea fromArea = fromLocLocation.getPlotArea(); 194 Location toLocLocation = BukkitUtil.adapt(toLocation.getLocation()); 195 PlotArea toArea = toLocLocation.getPlotArea(); 196 197 if (toArea == null) { 198 if (fromLocation.getType() == EntityType.SHULKER && fromArea != null) { 199 event.setCancelled(true); 200 } 201 return; 202 } 203 Plot toPlot = toArea.getOwnedPlot(toLocLocation); 204 if (fromLocation.getType() == EntityType.SHULKER && fromArea != null) { 205 final Plot fromPlot = fromArea.getOwnedPlot(fromLocLocation); 206 207 if (fromPlot != null || toPlot != null) { 208 if ((fromPlot == null || !fromPlot.equals(toPlot)) && (toPlot == null || !toPlot.equals(fromPlot))) { 209 event.setCancelled(true); 210 return; 211 } 212 } 213 } 214 if (entity instanceof Vehicle || entity instanceof ArmorStand) { 215 testNether(event.getEntity()); 216 } 217 } 218 219 @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) 220 public void vehicleMove(VehicleMoveEvent event) { 221 testNether(event.getVehicle()); 222 } 223 224 @EventHandler 225 public void spawn(CreatureSpawnEvent event) { 226 if (event.getEntityType() == EntityType.ARMOR_STAND) { 227 testCreate(event.getEntity()); 228 } 229 } 230 231}