diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 9acc29415..199e0066e 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -29,6 +29,7 @@ import com.plotsquared.bukkit.generator.BukkitHybridUtils; import com.plotsquared.bukkit.generator.BukkitPlotGenerator; import com.plotsquared.bukkit.listener.ChunkListener; import com.plotsquared.bukkit.listener.EntitySpawnListener; +import com.plotsquared.bukkit.listener.PaperListener; import com.plotsquared.bukkit.listener.PlayerEvents; import com.plotsquared.bukkit.listener.SingleWorldListener; import com.plotsquared.bukkit.listener.WorldEvents; @@ -93,6 +94,7 @@ import com.plotsquared.core.util.uuid.UUIDWrapper; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.platform.Actor; +import io.papermc.lib.PaperLib; import lombok.Getter; import lombok.NonNull; import org.bstats.bukkit.Metrics; @@ -635,6 +637,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain final PlayerEvents main = new PlayerEvents(); getServer().getPluginManager().registerEvents(main, this); getServer().getPluginManager().registerEvents(new EntitySpawnListener(), this); + if (PaperLib.isPaper() && Settings.Paper_Components.ENTITY_PATHING + || Settings.Paper_Components.PRE_SPAWN_LISTENER) { + getServer().getPluginManager().registerEvents(new PaperListener(), this); + } PlotListener.startRunnable(); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java new file mode 100644 index 000000000..22f6890a6 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -0,0 +1,220 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.listener; + +import com.destroystokyo.paper.entity.Pathfinder; +import com.destroystokyo.paper.event.entity.EntityPathfindEvent; +import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent; +import com.destroystokyo.paper.event.entity.SlimePathfindEvent; +import com.plotsquared.bukkit.util.BukkitUtil; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.flag.implementations.DoneFlag; +import org.bukkit.Chunk; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; + +/** + * Events specific to Paper. Some toit nups here + */ +@SuppressWarnings("unused") +public class PaperListener implements Listener { + + private Chunk lastChunk; + + @EventHandler public void onEntityPathfind(EntityPathfindEvent event) { + if (!Settings.Paper_Components.ENTITY_PATHING) { + return; + } + Location toLoc = BukkitUtil.getLocation(event.getLoc()); + Location fromLoc = BukkitUtil.getLocation(event.getEntity().getLocation()); + PlotArea tarea = toLoc.getPlotArea(); + if (tarea == null) { + return; + } + PlotArea farea = fromLoc.getPlotArea(); + if (farea == null) { + return; + } + if (tarea != farea) { + event.setCancelled(true); + return; + } + Plot tplot = toLoc.getPlot(); + Plot fplot = fromLoc.getPlot(); + if (tplot == null ^ fplot == null) { + event.setCancelled(true); + return; + } + if (tplot == null || tplot == fplot) { + return; + } + if (fplot.isMerged() && fplot.getConnectedPlots().contains(fplot)) { + return; + } + event.setCancelled(true); + } + + @EventHandler public void onEntityPathfind(SlimePathfindEvent event) { + if (!Settings.Paper_Components.ENTITY_PATHING) { + return; + } + Pathfinder.PathResult path = event.getEntity().getPathfinder().getCurrentPath(); + + // Unsure why it would be null, but best to cancel just in case ? + if (path == null) { + event.setCancelled(true); + return; + } + org.bukkit.Location bukkitToLocation = path.getNextPoint(); + + // Unsure why it would be null, but best to cancel just in case ? + if (bukkitToLocation == null) { + event.setCancelled(true); + return; + } + + Location toLoc = BukkitUtil.getLocation(bukkitToLocation); + Location fromLoc = BukkitUtil.getLocation(event.getEntity().getLocation()); + PlotArea tarea = toLoc.getPlotArea(); + if (tarea == null) { + return; + } + PlotArea farea = fromLoc.getPlotArea(); + if (farea == null) { + return; + } + if (tarea != farea) { + event.setCancelled(true); + return; + } + Plot tplot = toLoc.getPlot(); + Plot fplot = fromLoc.getPlot(); + if (tplot == null ^ fplot == null) { + event.setCancelled(true); + return; + } + if (tplot == null || tplot == fplot) { + return; + } + if (fplot.isMerged() && fplot.getConnectedPlots().contains(fplot)) { + return; + } + event.setCancelled(true); + } + + @EventHandler public void onPreCreatureSpawnEvent(PreCreatureSpawnEvent event) { + if (!Settings.Paper_Components.PRE_SPAWN_LISTENER) { + return; + } + Location location = BukkitUtil.getLocation(event.getSpawnLocation()); + PlotArea area = location.getPlotArea(); + if (!location.isPlotArea()) { + return; + } + //If entities are spawning... the chunk should be loaded? + Entity[] entities = event.getSpawnLocation().getChunk().getEntities(); + if (entities.length > Settings.Chunk_Processor.MAX_ENTITIES) { + event.setCancelled(true); + return; + } + CreatureSpawnEvent.SpawnReason reason = event.getReason(); + switch (reason) { + case DISPENSE_EGG: + case EGG: + case OCELOT_BABY: + case SPAWNER_EGG: + if (!area.isSpawnEggs()) { + event.setCancelled(true); + return; + } + break; + case REINFORCEMENTS: + case NATURAL: + case MOUNT: + case PATROL: + case RAID: + case SHEARED: + case SHOULDER_ENTITY: + case SILVERFISH_BLOCK: + case TRAP: + case VILLAGE_DEFENSE: + case VILLAGE_INVASION: + case BEEHIVE: + case CHUNK_GEN: + if (!area.isMobSpawning()) { + event.setCancelled(true); + return; + } + case BREEDING: + if (!area.isSpawnBreeding()) { + event.setCancelled(true); + return; + } + break; + case BUILD_IRONGOLEM: + case BUILD_SNOWMAN: + case BUILD_WITHER: + case CUSTOM: + if (!area.isSpawnCustom() && event.getType() != EntityType.ARMOR_STAND) { + event.setCancelled(true); + return; + } + break; + case SPAWNER: + if (!area.isMobSpawnerSpawning()) { + event.setCancelled(true); + return; + } + break; + } + Plot plot = location.getOwnedPlotAbs(); + if (plot == null) { + if (!area.isMobSpawning()) { + EntityType type = event.getType(); + switch (type) { + case DROPPED_ITEM: + if (Settings.Enabled_Components.KILL_ROAD_ITEMS) { + event.setCancelled(true); + break; + } + case PLAYER: + return; + } + event.setCancelled(true); + } + return; + } + if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { + event.setCancelled(true); + } + } +} diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 37c008586..8249881d0 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -357,6 +357,13 @@ public class Settings extends Config { } + @Comment("Enable or disable parts of the plugin specific to using PaperSpigot") + public static final class Paper_Components { + @Comment("Prevent entities from leaving plots") public static boolean ENTITY_PATHING = true; + @Comment("Use paper's PreCreatureSpawnEvent") public static boolean PRE_SPAWN_LISTENER = true; + } + + @Comment({"Enable or disable parts of the plugin", "Note: A cache will use some memory if enabled"}) public static final class Enabled_Components { // Group the following values into a new config section