package fr.mrmicky.worldeditselectionvisualizer.selection; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.Polygonal2DRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; import fr.mrmicky.worldeditselectionvisualizer.WorldEditSelectionVisualizer; import fr.mrmicky.worldeditselectionvisualizer.compat.RegionAdapter; import fr.mrmicky.worldeditselectionvisualizer.config.GlobalSelectionConfig; import fr.mrmicky.worldeditselectionvisualizer.event.SelectionChangeEvent; import fr.mrmicky.worldeditselectionvisualizer.math.Vector3d; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.ShapeProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.ConvexPolyhedralProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.CuboidProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.CylinderProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.EllipsoidProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.FawePolyhedralProcessor; import fr.mrmicky.worldeditselectionvisualizer.selection.shape.type.Polygonal2DProcessor; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; public class WorldEditHelper extends BukkitRunnable { private final Map<Class<? extends Region>, ShapeProcessor<?>> shapeProcessors = new HashMap<>(); private final WorldEditSelectionVisualizer plugin; private final WorldEditPlugin worldEditPlugin; public WorldEditHelper(WorldEditSelectionVisualizer plugin) { this.plugin = plugin; registerShapeProcessors(); worldEditPlugin = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); if (worldEditPlugin == null) { throw new IllegalStateException("WorldEditPlugin not found"); } runTaskTimer(plugin, 20, plugin.getConfig().getInt("selection-update-interval")); } @Override public void run() { for (Player player : Bukkit.getOnlinePlayers()) { updatePlayerVisualizations(plugin.getPlayerInfos(player)); } } public void updatePlayerVisualizations(PlayerVisualizerInfos playerInfo) { for (SelectionType type : SelectionType.values()) { updatePlayerVisualization(playerInfo, type); } } public void updatePlayerVisualization(PlayerVisualizerInfos playerInfo, SelectionType type) { Player player = playerInfo.getPlayer(); LocalSession session; try { session = worldEditPlugin.getSession(player); } catch (Exception e) { // sometimes after a reload getSession create errors with WorldEdit, this prevent error spam return; } PlayerSelection playerSelection = playerInfo.getSelection(type).orElse(null); if (playerSelection == null || session == null) { return; } Vector3d origin = Vector3d.ZERO; Region region; if (type == SelectionType.CLIPBOARD) { ClipboardHolder clipboardHolder = getClipboardHolder(session); if (clipboardHolder == null) { playerSelection.resetSelection(); return; } Clipboard clipboard = clipboardHolder.getClipboard(); Transform transform = clipboardHolder.getTransform(); origin = plugin.getCompatibilityHelper().adaptClipboard(clipboard).getOrigin(); region = clipboard.getRegion().clone(); if (!transform.isIdentity()) { region = plugin.getCompatibilityHelper().adaptRegion(region).transform(transform, origin); } } else { region = getSelectedRegion(session); } if (region == null) { playerSelection.resetSelection(); return; } if (type == SelectionType.SELECTION && (region.getWorld() == null || !region.getWorld().getName().equals(player.getWorld().getName()))) { playerSelection.resetSelection(); return; } RegionAdapter regionAdapter = plugin.getCompatibilityHelper().adaptRegion(region); RegionInfos regionInfos = regionAdapter.getRegionsInfos(); if (regionInfos.equals(playerSelection.getLastSelectedRegion())) { SelectionPoints points = playerSelection.getSelectionPoints(); if (points == null || points.origin().equals(origin)) { return; } } if (!player.hasPermission("wesv.use")) { playerSelection.resetSelection(regionInfos); return; } GlobalSelectionConfig config = plugin.getSelectionConfig(type); if (region.getArea() > config.getMaxSelectionSize()) { if (!playerSelection.isLastSelectionTooLarge()) { String message = plugin.getMessage("selection-too-large").replace("%blocks%", Integer.toString(config.getMaxSelectionSize())); plugin.getCompatibilityHelper().sendActionBar(player, message); } playerSelection.resetSelection(regionInfos); playerSelection.setLastSelectionTooLarge(true); return; } plugin.updateHoldingSelectionItem(playerInfo); Bukkit.getPluginManager().callEvent(new SelectionChangeEvent(player, region)); ShapeProcessor<?> shapeProcessor = shapeProcessors.get(region.getClass()); if (shapeProcessor != null) { playerSelection.updateSelection(shapeProcessor.processSelection(regionAdapter, config, origin), regionInfos, config.getFadeDelay()); } else { // Unsupported selection type playerSelection.resetSelection(regionInfos); } } @Nullable private Region getSelectedRegion(@Nullable LocalSession session) { if (session != null && session.getSelectionWorld() != null) { RegionSelector selector = session.getRegionSelector(session.getSelectionWorld()); if (selector.isDefined()) { try { return selector.getRegion(); } catch (IncompleteRegionException e) { plugin.getLogger().warning("Region still incomplete"); } } } return null; } @Nullable private ClipboardHolder getClipboardHolder(@Nullable LocalSession session) { if (session != null) { try { return session.getClipboard(); } catch (EmptyClipboardException e) { // ignore, clipboard is empty } } return null; } private void registerShapeProcessors() { shapeProcessors.put(CuboidRegion.class, new CuboidProcessor(plugin)); shapeProcessors.put(Polygonal2DRegion.class, new Polygonal2DProcessor(plugin)); shapeProcessors.put(EllipsoidRegion.class, new EllipsoidProcessor(plugin)); shapeProcessors.put(CylinderRegion.class, new CylinderProcessor(plugin)); shapeProcessors.put(ConvexPolyhedralRegion.class, new ConvexPolyhedralProcessor(plugin)); if (plugin.getCompatibilityHelper().isUsingFawe()) { shapeProcessors.put(FawePolyhedralProcessor.getRegionClass(), new FawePolyhedralProcessor(plugin)); } } }