diff --git a/server/src/main/java/dev/plex/listener/impl/ServerListener.java b/server/src/main/java/dev/plex/listener/impl/ServerListener.java index 78d6049..9b93804 100644 --- a/server/src/main/java/dev/plex/listener/impl/ServerListener.java +++ b/server/src/main/java/dev/plex/listener/impl/ServerListener.java @@ -1,47 +1,187 @@ package dev.plex.listener.impl; -import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import dev.plex.listener.PlexListener; -import dev.plex.util.PlexUtils; -import dev.plex.util.RandomUtil; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.block.data.Openable; +import org.bukkit.command.Command; +import org.bukkit.command.PluginIdentifiableCommand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.player.*; +import java.util.Arrays; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -public class ServerListener extends PlexListener +public class WorldListener extends PlexListener { - @EventHandler - public void onServerPing(PaperServerListPingEvent event) + private final List EDIT_COMMANDS = Arrays.asList("bigtree", "ebigtree", "largetree", "elargetree", "break", "ebreak", "antioch", "nuke", "editsign", "tree", "etree"); + + @EventHandler(priority = EventPriority.LOWEST) + public void onBlockPlace(BlockPlaceEvent event) { - String baseMotd = plugin.config.getString("server.motd"); - baseMotd = baseMotd.replace("\\n", "\n"); - baseMotd = baseMotd.replace("%servername%", plugin.config.getString("server.name")); - baseMotd = baseMotd.replace("%mcversion%", Bukkit.getBukkitVersion().split("-")[0]); - if (plugin.config.getBoolean("server.colorize_motd")) + if (!canModifyWorld(event.getPlayer(), true)) { - AtomicReference motd = new AtomicReference<>(Component.empty()); - for (final String word : baseMotd.split(" ")) - { - motd.set(motd.get().append(Component.text(word).color(RandomUtil.getRandomColor()))); - motd.set(motd.get().append(Component.space())); - } - event.motd(motd.get()); + event.setCancelled(true); } - else + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onBlockBreak(BlockBreakEvent event) + { + if (!canModifyWorld(event.getPlayer(), true)) { - event.motd(PlexUtils.mmDeserialize(baseMotd.trim())); + event.setCancelled(true); } - if (plugin.config.contains("server.sample")) + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onInteractWorld(PlayerInteractEvent event) + { + if (event.getInteractionPoint() != null && event.getInteractionPoint().getBlock().getBlockData() instanceof Openable) return; + if (!canModifyWorld(event.getPlayer(), true)) { - List samples = plugin.config.getStringList("server.sample"); - if (!samples.isEmpty()) + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onInteractWorld(PlayerInteractEntityEvent event) + { + if (!canModifyWorld(event.getPlayer(), true)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onInteractWorld(PlayerItemDamageEvent event) + { + if (!canModifyWorld(event.getPlayer(), true)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onInteractWorld(EntityDamageByEntityEvent event) + { + if (!(event.getDamager() instanceof Player player)) return; + if (!canModifyWorld(player, true)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onEntitySpawn(EntitySpawnEvent event) + { + if (event.getEntityType() != EntityType.SLIME) + { + return; + } + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) + { + // If the person has permission to modify the world, we don't need to block WorldEdit + if (canModifyWorld(event.getPlayer(), false)) + { + return; + } + + String message = event.getMessage(); + // Don't check the arguments + message = message.replaceAll("\\s.*", "").replaceFirst("/", ""); + Command command = Bukkit.getCommandMap().getCommand(message); + if (command != null) + { + // This does check for aliases + boolean isWeCommand = command instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) command).getPlugin().equals(Bukkit.getPluginManager().getPlugin("WorldEdit")); + boolean isFaweCommand = command instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) command).getPlugin().equals(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit")); + if (isWeCommand || isFaweCommand || EDIT_COMMANDS.contains(message.toLowerCase())) { - event.getPlayerSample().clear(); - event.getPlayerSample().addAll(samples.stream().map(string -> string.replace("&", "ยง")).map(Bukkit::createProfile).toList()); + String noEdit = plugin.config.getString("worlds." + world.getName().toLowerCase() + ".modification.message"); + event.getPlayer().sendMessage(MiniMessage.miniMessage().deserialize(noEdit)); + event.setCancelled(true); } } } + + @EventHandler(priority = EventPriority.LOWEST) + public void onWorldTeleport(PlayerTeleportEvent event) + { + if (!canEnterWorld(event.getPlayer(), event.getTo().getWorld())) + { + event.setCancelled(true); + } + } + + /** + * Check if a Player has the ability to modify the world they are in + * + * @param player The player who wants to modify the world + * @param showMessage Whether the message from the config.yml should be shown + * @return Returns true if the person has the ability to modify the world + */ + private boolean canModifyWorld(Player player, boolean showMessage) + { + World world = player.getWorld(); + String permission = plugin.config.getString("worlds." + world.getName().toLowerCase() + ".modification.permission"); + if (permission == null) + { + return true; + } + if (player.hasPermission(permission)) + { + return true; + } + + if (showMessage) + { + String noEdit = plugin.config.getString("worlds." + world.getName().toLowerCase() + ".modification.message"); + if (noEdit != null) + { + player.sendMessage(MiniMessage.miniMessage().deserialize(noEdit)); + } + } + return false; + } + + /** + * Check if a Player has the ability to enter the requested world + * + * @param player The player who wants to enter the world + * @return Returns true if the person has the ability to enter the world + */ + private boolean canEnterWorld(Player player, World destination) + { + String permission = plugin.config.getString("worlds." + destination.getName().toLowerCase() + ".entry.permission"); + if (permission == null) + { + return true; + } + if (player.hasPermission(permission)) + { + return true; + } + + String noEntry = plugin.config.getString("worlds." + destination.getName().toLowerCase() + ".entry.message"); + if (noEntry != null) + { + player.sendMessage(MiniMessage.miniMessage().deserialize(noEntry)); + } + return false; + } }