From 3daab62714f200562d884b0fb03e86d009ac701c Mon Sep 17 00:00:00 2001 From: "Blue (Lukas Rieger)" Date: Fri, 17 Jan 2020 00:21:46 +0100 Subject: [PATCH] Move commands to common and start implementing spigot plugin --- .../bluemap/bukkit/BukkitCommandSource.java | 31 ++ .../{Commands.java => BukkitCommands.java} | 16 +- .../bluemap/bukkit/BukkitPlugin.java | 12 +- .../resources/bluemap-bukkit-defaults.conf | 10 + .../src/main/resources/bluemap-bukkit.conf | 171 +++++++++ BlueMapBukkit/src/main/resources/plugin.yml | 3 +- .../bluemap/common/plugin/Commands.java | 298 +++++++++++++++ .../bluemap/common/plugin/Plugin.java | 7 + .../plugin/serverinterface/CommandSource.java | 15 + .../bluemap/common/plugin/text/Text.java | 31 +- .../bluecolored/bluemap/sponge/Commands.java | 341 ------------------ .../bluemap/sponge/SpongeCommandSource.java | 46 +++ .../bluemap/sponge/SpongeCommands.java | 170 +++++++++ .../bluemap/sponge/SpongePlugin.java | 10 +- 14 files changed, 783 insertions(+), 378 deletions(-) create mode 100644 BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommandSource.java rename BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/{Commands.java => BukkitCommands.java} (51%) create mode 100644 BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf create mode 100644 BlueMapBukkit/src/main/resources/bluemap-bukkit.conf create mode 100644 BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Commands.java create mode 100644 BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/serverinterface/CommandSource.java delete mode 100644 BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java create mode 100644 BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommandSource.java create mode 100644 BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommandSource.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommandSource.java new file mode 100644 index 00000000..6b68c6e3 --- /dev/null +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommandSource.java @@ -0,0 +1,31 @@ +package de.bluecolored.bluemap.bukkit; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import de.bluecolored.bluemap.common.plugin.serverinterface.CommandSource; +import de.bluecolored.bluemap.common.plugin.text.Text; + +public class BukkitCommandSource implements CommandSource { + + private CommandSender delegate; + + public BukkitCommandSource(CommandSender delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(Text text) { + if (delegate instanceof Player) { + Player player = (Player) delegate; + + //kinda hacky but works + Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " " + text.toJSONString()); + return; + } + + delegate.sendMessage(text.toFormattingCodedString('§')); + } + +} diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/Commands.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java similarity index 51% rename from BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/Commands.java rename to BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java index 6d261925..ca94fe58 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/Commands.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java @@ -4,21 +4,19 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; -import de.bluecolored.bluemap.common.plugin.Plugin; +import de.bluecolored.bluemap.common.plugin.Commands; -public class Commands implements CommandExecutor { - - private BukkitPlugin plugin; - private Plugin bluemap; +public class BukkitCommands implements CommandExecutor { - public Commands(BukkitPlugin plugin) { - this.plugin = plugin; - this.bluemap = plugin.getBlueMap(); + private Commands commands; + + public BukkitCommands(Commands commands) { + this.commands = commands; } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - + commands.executeRootCommand(new BukkitCommandSource(sender)); return true; } diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java index ec7a0cbb..41421fe8 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java @@ -17,14 +17,14 @@ public class BukkitPlugin extends JavaPlugin implements ServerInterface { private Plugin bluemap; private EventForwarder eventForwarder; - private Commands commands; + private BukkitCommands commands; public BukkitPlugin() { Logger.global = new JavaLogger(getLogger()); this.eventForwarder = new EventForwarder(); - this.commands = new Commands(this); this.bluemap = new Plugin("bukkit", this); + this.commands = new BukkitCommands(bluemap.getCommands()); } @Override @@ -64,16 +64,18 @@ public void unregisterAllListeners() { @Override public UUID getUUIDForWorld(File worldFolder) throws IOException { + worldFolder = worldFolder.getCanonicalFile(); for (World world : getServer().getWorlds()) { - if (worldFolder.equals(world.getWorldFolder())) return world.getUID(); + Logger.global.logInfo("Found world-folder: " + world.getWorldFolder().getCanonicalPath()); + if (worldFolder.equals(world.getWorldFolder().getCanonicalFile())) return world.getUID(); } - throw new IOException("There is no world with this folder loaded!"); + throw new IOException("There is no world with this folder loaded: " + worldFolder.getCanonicalPath()); } @Override public File getConfigFolder() { - return getConfigFolder(); + return getDataFolder(); } public Plugin getBlueMap() { diff --git a/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf b/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf new file mode 100644 index 00000000..d8404ad8 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf @@ -0,0 +1,10 @@ +accept-download: false +metrics: true +renderThreadCount: -2 +data: "bluemap" +webroot: "bluemap/web" +webserver { + enabled: true + port: 8100 + maxConnectionCount: 100 +} diff --git a/BlueMapBukkit/src/main/resources/bluemap-bukkit.conf b/BlueMapBukkit/src/main/resources/bluemap-bukkit.conf new file mode 100644 index 00000000..34d64029 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/bluemap-bukkit.conf @@ -0,0 +1,171 @@ +## ## +## BlueMap ## +## ## +## by Blue (Lukas Rieger) ## +## http://bluecolored.de/ ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"CLI","version":"%version%"} +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +data: "bluemap" + +# The webroot of the website that displays the map. +webroot: "bluemap/web" + +# Unncomment this to override the path where bluemap stores the data-files. +# Default is "/data" +#webdata: "path/to/data/folder" + +webserver { + # With this setting you can disable the integrated web-server. + # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. + # Default is enabled + enabled: true + + # The IP-Adress that the webserver binds to. + # If this setting is commented out, bluemap tries to find the default ip-adress of your system. + # If you only want to access it locally use "localhost". + #ip: "localhost" + #ip: "127.0.0.1" + + # The port that the webserver listenes to. + # Default is 8100 + port: 8100 + + # Max number of simultaneous connections that the webserver allows + # Default is 100 + maxConnectionCount: 100 +} + +# This is an array with multiple configured maps. +# You can define multiple maps, for different worlds with different render-settings here +maps: [ + + { + # The id of this map + # Should only contain word-charactes: [a-zA-Z0-9_] + id: "world" + + # The name of this map + # This defines the display name of this map, you can change this at any time + # Default is the id of this map + name: "World" + + # The path to the save-folder of the world to render + world: "world" + + # If this is false, BlueMap tries to omit all blocks that are not visible from above-ground. + # More specific: Block-Faces that have a sunlight/skylight value of 0 are removed. + # This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible. + # Default is false + renderCaves: false + + # AmbientOcclusion adds soft shadows into corners, which gives the map a much better look. + # This has only a small impact on render-time and has no impact on the web-performance of the map. + # The value defines the strength of the shading, a value of 0 disables ambientOcclusion. + # Default is 0.25 + ambientOcclusion: 0.25 + + # Lighting uses the light-data in minecraft to shade each block-face. + # If this is enabled, caves and inside buildings without torches will be darker. + # The value defines the strength of the shading and a value of 0 disables lighting (every block will be fully lit). + # Default is 0.8 + lighting: 0.8 + + # With the below values you can limit the map-render. + # This can be used to ignore the nethers ceiling or render only a certain part of a world. + # Default is no min or max value (= infinite bounds) + #minX: -4000 + #maxX: 4000 + #minZ: -4000 + #maxZ: 4000 + #minY: 50 + #maxY: 126 + + # Using this, BlueMap pretends that every Block out of the defined render-bounds is AIR, + # this means you can see the blocks where the world is cut (instead of having a see-through/xray view). + # This has only an effect if you set some render-bounds above. + # Default is enabled + renderEdges: true + + # HIRES is the high-resolution render of the map. Where you see every block. + hires { + # Defines the size of one map-tile in blocks. + # If you change this value, the lowres values might need adjustment as well! + # Default is 32 + tileSize: 32 + + # The View-Distance for hires tiles on the web-map (the value is the radius in tiles) + # Default is 4.5 + viewDistance: 4.5 + } + + # LOWRES is the low-resolution render of the map. Thats the model that you see if you zoom far out to get an overview. + lowres { + # Defines resolution of the lowres model. E.g. If the hires.tileSize is 32, a value of 4 means that every 8*8 blocks will be summarized by one point on the lowres map. + # Calculation: 32 / 4 = 8 + # You can only use values that result in an integer if you use the above calculation! + # Default is 4 + pointsPerHiresTile: 4 + + # Defines the size of one lowres-map-tile in points. + # Default is 50 + pointsPerLowresTile: 50 + + # The View-Distance for lowres tiles on the web-map (the value is the radius in tiles) + # Default is 7 + viewDistance: 7 + } + } + + # Here another example for the End-Map + # Things we don't want to change from default we can just omit + { + id: "end" + name: "End" + world: "world/DIM1" + + # In the end is no sky-light, so we need to enable this or we won't see anything. + renderCaves: true + + # Same here, we don't want a dark map. But not completely disabled, so we see the effect of e.g torches. + lighting: 0.4 + } + + # Here another example for the Nether-Map + { + id: "nether" + name: "Nether" + world: "world/DIM-1" + + renderCaves: true + lighting: 0.6 + + # We slice the whole world at y:90 so every block above 90 will be air. + # This way we don't render the nethers ceiling. + maxY: 90 + renderEdges: true + } + +] diff --git a/BlueMapBukkit/src/main/resources/plugin.yml b/BlueMapBukkit/src/main/resources/plugin.yml index 7a3565e9..71cfbf31 100644 --- a/BlueMapBukkit/src/main/resources/plugin.yml +++ b/BlueMapBukkit/src/main/resources/plugin.yml @@ -1,7 +1,8 @@ name: BlueMap main: de.bluecolored.bluemap.bukkit.BukkitPlugin -version: 0.1.0 +version: 0.2.1 author: Blue (TBlueF / Lukas Rieger) authors: [Blue (TBlueF / Lukas Rieger)] website: "https://github.com/BlueMap-Minecraft" commands: + bluemap: \ No newline at end of file diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Commands.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Commands.java new file mode 100644 index 00000000..82d1b576 --- /dev/null +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Commands.java @@ -0,0 +1,298 @@ +package de.bluecolored.bluemap.common.plugin; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.lang3.time.DurationFormatUtils; + +import com.flowpowered.math.GenericMath; +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; + +import de.bluecolored.bluemap.common.MapType; +import de.bluecolored.bluemap.common.RenderManager; +import de.bluecolored.bluemap.common.RenderTask; +import de.bluecolored.bluemap.common.plugin.serverinterface.CommandSource; +import de.bluecolored.bluemap.common.plugin.text.Text; +import de.bluecolored.bluemap.common.plugin.text.TextColor; +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.mca.Chunk; +import de.bluecolored.bluemap.core.mca.ChunkAnvil112; +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.render.hires.HiresModelManager; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.World; + +/** + * Commands: + * + *
    + *
  • /bluemap
  • + *
  • /bluemap reload
  • + *
  • /bluemap pause
  • + *
  • /bluemap resume
  • + *
  • /bluemap render [world]
  • + *
  • /bluemap render prioritize [task-uuid]
  • + *
  • /bluemap render remove [task-uuid]
  • + *
  • /bluemap debug
  • + *
+ */ +public class Commands { + + private Plugin bluemap; + + public Commands(Plugin bluemap) { + this.bluemap = bluemap; + } + + /** + * Command: /bluemap + */ + public void executeRootCommand(CommandSource source) { + if (!checkLoaded(source)) return; + + source.sendMessages(createStatusMessage()); + } + + /** + * Command: /bluemap debug + */ + public boolean executeDebugCommand(CommandSource source, UUID worldUuid, Vector3i playerPosition) { + if (!checkLoaded(source)) return false; + + World world = bluemap.getWorld(worldUuid); + + if (world == null) { + source.sendMessage(Text.of(TextColor.RED, "This world is not loaded with BlueMap! Maybe it is not configured?")); + return false; + } + + Block block = world.getBlock(playerPosition); + Block blockBelow = world.getBlock(playerPosition.add(0, -1, 0)); + + String blockIdMeta = ""; + String blockBelowIdMeta = ""; + + if (world instanceof MCAWorld) { + try { + Chunk chunk = ((MCAWorld) world).getChunk(MCAWorld.blockToChunk(playerPosition)); + if (chunk instanceof ChunkAnvil112) { + blockIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(playerPosition) + ")"; + blockBelowIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(playerPosition.add(0, -1, 0)) + ")"; + } + } catch (IOException ex) { + Logger.global.logError("Failed to read chunk for debug!", ex); + } + } + + source.sendMessages(Lists.newArrayList( + Text.of(TextColor.GOLD, "Block at you: ", TextColor.WHITE, block, TextColor.GRAY, blockIdMeta), + Text.of(TextColor.GOLD, "Block below you: ", TextColor.WHITE, blockBelow, TextColor.GRAY, blockBelowIdMeta) + )); + + return true; + } + + /** + * Command: /bluemap reload + */ + public void executeReloadCommand(CommandSource source) { + source.sendMessage(Text.of(TextColor.GOLD, "Reloading BlueMap...")); + + new Thread(() -> { + try { + bluemap.reload(); + + if (bluemap.isLoaded()) { + source.sendMessage(Text.of(TextColor.GREEN, "BlueMap reloaded!")); + } else { + source.sendMessage(Text.of(TextColor.RED, "Could not load BlueMap! See the console for details!")); + } + + } catch (Exception ex) { + Logger.global.logError("Failed to reload BlueMap!", ex); + + source.sendMessage(Text.of(TextColor.RED, "There was an error reloading BlueMap! See the console for details!")); + } + }).start(); + + } + + /** + * Command: /bluemap pause + */ + public boolean executePauseCommand(CommandSource source) { + if (!checkLoaded(source)) return false; + + if (bluemap.getRenderManager().isRunning()) { + bluemap.getRenderManager().stop(); + source.sendMessage(Text.of(TextColor.GREEN, "BlueMap rendering paused!")); + return true; + } else { + source.sendMessage(Text.of(TextColor.RED, "BlueMap rendering are already paused!")); + return false; + } + } + + /** + * Command: /bluemap resume + */ + public boolean executeResumeCommand(CommandSource source) { + if (!checkLoaded(source)) return false; + + if (!bluemap.getRenderManager().isRunning()) { + bluemap.getRenderManager().start(); + source.sendMessage(Text.of(TextColor.GREEN, "BlueMap renders resumed!")); + return true; + } else { + source.sendMessage(Text.of(TextColor.RED, "BlueMap renders are already running!")); + return false; + } + } + + /** + * Command: /bluemap render [world] + */ + public boolean executeRenderWorldCommand(CommandSource source, UUID worldUuid) { + if (!checkLoaded(source)) return false; + + World world = bluemap.getWorld(worldUuid); + + if (world == null) { + source.sendMessage(Text.of(TextColor.RED, "This world is not loaded with BlueMap! Maybe it is not configured?")); + return false; + } + + world.invalidateChunkCache(); + + new Thread(() -> { + createWorldRenderTask(source, world); + }).start(); + + return true; + } + + /** + * Command: /bluemap render prioritize [task-uuid] + */ + public void executePrioritizeRenderTaskCommand(CommandSource source, UUID taskUUID) { + if (!checkLoaded(source)) return; + + for (RenderTask task : bluemap.getRenderManager().getRenderTasks()) { + if (task.getUuid().equals(taskUUID)) { + bluemap.getRenderManager().prioritizeRenderTask(task); + break; + } + } + + source.sendMessages(createStatusMessage()); + } + + /** + * Command: /bluemap render remove [task-uuid] + */ + public void executeRemoveRenderTaskCommand(CommandSource source, UUID taskUUID) { + if (!checkLoaded(source)) return; + + for (RenderTask task : bluemap.getRenderManager().getRenderTasks()) { + if (task.getUuid().equals(taskUUID)) { + bluemap.getRenderManager().removeRenderTask(task); + break; + } + } + + source.sendMessages(createStatusMessage()); + } + + private List createStatusMessage(){ + List lines = new ArrayList<>(); + + RenderManager renderer = bluemap.getRenderManager(); + + lines.add(Text.of()); + lines.add(Text.of(TextColor.BLUE, "Tile-Updates:")); + + if (renderer.isRunning()) { + lines.add(Text.of(TextColor.WHITE, " Render-Threads are ", Text.of(TextColor.GREEN, "running").setHoverText(Text.of("click to pause rendering")).setClickCommand("/bluemap pause"), TextColor.GRAY, "!")); + } else { + lines.add(Text.of(TextColor.WHITE, " Render-Threads are ", Text.of(TextColor.RED, "paused").setHoverText(Text.of("click to resume rendering")).setClickCommand("/bluemap resume"), TextColor.GRAY, "!")); + } + + lines.add(Text.of(TextColor.WHITE, " Scheduled tile-updates: ", Text.of(TextColor.GOLD, renderer.getQueueSize()).setHoverText(Text.of("tiles waiting for a free render-thread")), TextColor.GRAY, " + " , Text.of(TextColor.GRAY, bluemap.getUpdateHandler().getUpdateBufferCount()).setHoverText(Text.of("tiles waiting for world-save")))); + + RenderTask[] tasks = renderer.getRenderTasks(); + if (tasks.length > 0) { + RenderTask task = tasks[0]; + + long time = task.getActiveTime(); + String durationString = DurationFormatUtils.formatDurationWords(time, true, true); + double pct = (double)task.getRenderedTileCount() / (double)(task.getRenderedTileCount() + task.getRemainingTileCount()); + + long ert = (long)((time / pct) * (1d - pct)); + String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true); + + double tps = task.getRenderedTileCount() / (time / 1000.0); + + lines.add(Text.of(TextColor.BLUE, "Current task:")); + lines.add(Text.of(" ", createCancelTaskText(task), TextColor.WHITE, " Task ", TextColor.GOLD, task.getName(), TextColor.WHITE, " for map ", Text.of(TextColor.GOLD, task.getMapType().getName()).setHoverText(Text.of(TextColor.WHITE, "World: ", TextColor.GOLD, task.getMapType().getWorld().getName())))); + lines.add(Text.of(TextColor.WHITE, " rendered ", TextColor.GOLD, task.getRenderedTileCount(), TextColor.WHITE, " tiles ", TextColor.GRAY, "(" + (Math.round(pct * 1000)/10.0) + "% | " + GenericMath.round(tps, 1) + "t/s)", TextColor.WHITE, " in ", TextColor.GOLD, durationString)); + lines.add(Text.of(TextColor.WHITE, " with ", TextColor.GOLD, task.getRemainingTileCount(), TextColor.WHITE, " tiles to go. ETA: ", TextColor.GOLD, ertDurationString)); + } + + if (tasks.length > 1) { + lines.add(Text.of(TextColor.BLUE, "Waiting tasks:")); + for (int i = 1; i < tasks.length; i++) { + RenderTask task = tasks[i]; + lines.add(Text.of(" ", createCancelTaskText(task), createPrioritizeTaskText(task), TextColor.WHITE, " Task ", TextColor.GOLD, task.getName(), TextColor.WHITE, " for map ", Text.of(TextColor.GOLD, task.getMapType().getName()).setHoverText(Text.of(TextColor.WHITE, "World: ", TextColor.GOLD, task.getMapType().getWorld().getName())), TextColor.GRAY, " (" + task.getRemainingTileCount() + " tiles)")); + } + } + + return lines; + } + + private Text createCancelTaskText(RenderTask task) { + return Text.of(TextColor.RED, "[X]").setHoverText(Text.of(TextColor.GRAY, "click to remove this render-task")).setClickCommand("/bluemap render remove " + task.getUuid()); + } + + private Text createPrioritizeTaskText(RenderTask task) { + return Text.of(TextColor.GREEN, "[^]").setHoverText(Text.of(TextColor.GRAY, "click to prioritize this render-task")).setClickCommand("/bluemap render prioritize " + task.getUuid()); + } + + private void createWorldRenderTask(CommandSource source, World world) { + source.sendMessage(Text.of(TextColor.GOLD, "Collecting chunks to render...")); + Collection chunks = world.getChunkList(); + source.sendMessage(Text.of(TextColor.GREEN, chunks.size() + " chunks found!")); + + for (MapType map : bluemap.getMapTypes()) { + if (!map.getWorld().getUUID().equals(world.getUUID())) continue; + + source.sendMessage(Text.of(TextColor.GOLD, "Collecting tiles for map '" + map.getId() + "'")); + + HiresModelManager hmm = map.getTileRenderer().getHiresModelManager(); + Collection tiles = hmm.getTilesForChunks(chunks); + + RenderTask task = new RenderTask("world-render", map); + task.addTiles(tiles); + task.optimizeQueue(); + bluemap.getRenderManager().addRenderTask(task); + + source.sendMessage(Text.of(TextColor.GREEN, tiles.size() + " tiles found! Task created.")); + } + + source.sendMessage(Text.of(TextColor.GREEN, "All render tasks created! Use /bluemap to view the progress!")); + } + + private boolean checkLoaded(CommandSource source) { + if (!bluemap.isLoaded()) { + source.sendMessage(Text.of(TextColor.RED, "BlueMap is not loaded!", TextColor.GRAY, "(Try /bluemap reload)")); + return false; + } + + return true; + } + +} diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index ff74856b..4a2e4064 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -56,6 +56,7 @@ public class Plugin { private String implementationType; private ServerInterface serverInterface; + private Commands commands; private MainConfig config; private ResourcePack resourcePack; @@ -74,7 +75,9 @@ public class Plugin { public Plugin(String implementationType, ServerInterface serverInterface) { this.implementationType = implementationType.toLowerCase(); + this.serverInterface = serverInterface; + this.commands = new Commands(this); this.maps = new HashMap<>(); this.worlds = new HashMap<>(); @@ -321,6 +324,10 @@ public ServerInterface getServerInterface() { return serverInterface; } + public Commands getCommands() { + return commands; + } + public MainConfig getMainConfig() { return config; } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/serverinterface/CommandSource.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/serverinterface/CommandSource.java new file mode 100644 index 00000000..f59900ca --- /dev/null +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/serverinterface/CommandSource.java @@ -0,0 +1,15 @@ +package de.bluecolored.bluemap.common.plugin.serverinterface; + +import de.bluecolored.bluemap.common.plugin.text.Text; + +public interface CommandSource { + + void sendMessage(Text text); + + default void sendMessages(Iterable textLines) { + for (Text text : textLines) { + sendMessage(text); + } + } + +} diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/text/Text.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/text/Text.java index ebc3dea9..e7d54ac2 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/text/Text.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/text/Text.java @@ -14,25 +14,29 @@ public class Text { private String clickCommand; private List children = new ArrayList<>(); - public void setHoverText(Text hoverText) { + public Text setHoverText(Text hoverText) { this.hoverText = hoverText; + + return this; } - public void setClickCommand(String clickCommand) { + public Text setClickCommand(String clickCommand) { this.clickCommand = clickCommand; + + return this; } - public void addChild(Text child) { + public Text addChild(Text child) { children.add(child); + + return this; } public String toJSONString() { StringBuilder sb = new StringBuilder(); sb.append("{"); - if (!content.isEmpty()) { - sb.append(quote("text")).append(":").append(quote(content)).append(','); - } + sb.append(quote("text")).append(":").append(quote(content)).append(','); if (color != null) { sb.append(quote("color")).append(":").append(quote(color.getId())).append(','); @@ -46,23 +50,23 @@ public String toJSONString() { sb.append(quote("hoverEvent")).append(":{"); sb.append(quote("action")).append(":").append(quote("show_text")).append(','); sb.append(quote("value")).append(":").append(quote(hoverText.toFormattingCodedString('§'))); - sb.append("}"); + sb.append("},"); } if (clickCommand != null) { sb.append(quote("clickEvent")).append(":{"); sb.append(quote("action")).append(":").append(quote("run_command")).append(','); sb.append(quote("value")).append(":").append(quote(clickCommand)); - sb.append("}"); + sb.append("},"); } if (!children.isEmpty()) { - sb.append(quote("")).append(":["); + sb.append(quote("extra")).append(":["); for (Text child : children) { sb.append(child.toJSONString()).append(','); } sb.deleteCharAt(sb.length() - 1); //delete last , - sb.append("]"); + sb.append("],"); } if (sb.charAt(sb.length() - 1) == ',') sb.deleteCharAt(sb.length() - 1); //delete last , @@ -87,7 +91,8 @@ public String toFormattingCodedString(char escapeChar) { } for (Text child : children) { - sb.append(escapeChar).append('r').append(child.withParentFormat(this).toFormattingCodedString(escapeChar)); + if (sb.length() > 0) sb.append(escapeChar).append('r'); + sb.append(child.withParentFormat(this).toFormattingCodedString(escapeChar)); } return sb.toString(); @@ -126,7 +131,7 @@ private String quote(String value) { private String escape(String value) { value = value.replace("\\", "\\\\"); value = value.replace("\"", "\\\""); - value = value.replace("§", "\\u00a76"); + value = value.replace("§", "\\u00a7"); value = value.replace("\n", "\\n"); return value; } @@ -194,7 +199,7 @@ public static Text of(Object... objects) { } if (text.children.isEmpty()) return text; - if (text.children.size() == 1) return text.children.get(1); + if (text.children.size() == 1) return text.children.get(0); return text; } diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java deleted file mode 100644 index b067cb8f..00000000 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java +++ /dev/null @@ -1,341 +0,0 @@ -package de.bluecolored.bluemap.sponge; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -import org.apache.commons.lang3.time.DurationFormatUtils; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.CommandResult; -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.command.args.GenericArguments; -import org.spongepowered.api.command.spec.CommandSpec; -import org.spongepowered.api.text.Text; -import org.spongepowered.api.text.action.TextActions; -import org.spongepowered.api.text.format.TextColors; -import org.spongepowered.api.world.Locatable; -import org.spongepowered.api.world.Location; -import org.spongepowered.api.world.storage.WorldProperties; - -import com.flowpowered.math.GenericMath; -import com.flowpowered.math.vector.Vector2i; -import com.google.common.collect.Lists; - -import de.bluecolored.bluemap.common.MapType; -import de.bluecolored.bluemap.common.RenderManager; -import de.bluecolored.bluemap.common.RenderTask; -import de.bluecolored.bluemap.common.plugin.Plugin; -import de.bluecolored.bluemap.core.logger.Logger; -import de.bluecolored.bluemap.core.mca.Chunk; -import de.bluecolored.bluemap.core.mca.ChunkAnvil112; -import de.bluecolored.bluemap.core.mca.MCAWorld; -import de.bluecolored.bluemap.core.render.hires.HiresModelManager; -import de.bluecolored.bluemap.core.world.Block; -import de.bluecolored.bluemap.core.world.World; - -public class Commands { - - private SpongePlugin plugin; - private Plugin bluemap; - - public Commands(SpongePlugin plugin) { - this.plugin = plugin; - this.bluemap = plugin.getBlueMap(); - } - - public CommandSpec createRootCommand() { - - CommandSpec debugCommand = CommandSpec.builder() - .permission("bluemap.debug") - .description(Text.of("Prints some debug info")) - .extendedDescription(Text.of("Prints some information about how bluemap sees the blocks at and below your position")) - .executor((source, args) -> { - if (source instanceof Locatable) { - Location loc = ((Locatable) source).getLocation(); - UUID worldUuid = loc.getExtent().getUniqueId(); - World world = bluemap.getWorld(worldUuid); - Block block = world.getBlock(loc.getBlockPosition()); - Block blockBelow = world.getBlock(loc.getBlockPosition().add(0, -1, 0)); - - String blockIdMeta = ""; - String blockBelowIdMeta = ""; - - if (world instanceof MCAWorld) { - try { - Chunk chunk = ((MCAWorld) world).getChunk(MCAWorld.blockToChunk(loc.getBlockPosition())); - if (chunk instanceof ChunkAnvil112) { - blockIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(loc.getBlockPosition()) + ")"; - blockBelowIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(loc.getBlockPosition().add(0, -1, 0)) + ")"; - } - } catch (IOException ex) { - Logger.global.logError("Failed to read chunk for debug!", ex); - } - } - - source.sendMessages(Lists.newArrayList( - Text.of(TextColors.GOLD, "Block at you: ", TextColors.RESET, block, TextColors.GRAY, blockIdMeta), - Text.of(TextColors.GOLD, "Block below you: ", TextColors.RESET, blockBelow, TextColors.GRAY, blockBelowIdMeta) - )); - } - - return CommandResult.success(); - }) - .build(); - - return CommandSpec.builder() - .description(Text.of("Displays BlueMaps render status")) - .permission("bluemap.status") - .childArgumentParseExceptionFallback(false) - .child(createReloadCommand(), "reload") - .child(createPauseRenderCommand(), "pause") - .child(createResumeRenderCommand(), "resume") - .child(createRenderCommand(), "render") - .child(debugCommand, "debug") - .executor((source, args) -> { - source.sendMessages(createStatusMessage()); - return CommandResult.success(); - }) - .build(); - } - - public CommandSpec createStandaloneReloadCommand() { - return CommandSpec.builder() - .description(Text.of("BlueMaps root command")) - .childArgumentParseExceptionFallback(false) - .child(createReloadCommand(), "reload") - .build(); - } - - public CommandSpec createReloadCommand() { - return CommandSpec.builder() - .description(Text.of("Reloads all resources and configuration-files")) - .permission("bluemap.reload") - .executor((source, args) -> { - source.sendMessage(Text.of(TextColors.GOLD, "Reloading BlueMap...")); - - plugin.getAsyncExecutor().submit(() -> { - try { - bluemap.reload(); - - if (bluemap.isLoaded()) { - source.sendMessage(Text.of(TextColors.GREEN, "BlueMap reloaded!")); - } else { - source.sendMessage(Text.of(TextColors.RED, "Could not load BlueMap! See the console for details!")); - } - - } catch (Exception ex) { - Logger.global.logError("Failed to reload BlueMap!", ex); - - source.sendMessage(Text.of(TextColors.RED, "There was an error reloading BlueMap! See the console for details!")); - } - }); - - return CommandResult.success(); - }) - .build(); - } - - public CommandSpec createPauseRenderCommand() { - return CommandSpec.builder() - .description(Text.of("Pauses all rendering")) - .permission("bluemap.pause") - .executor((source, args) -> { - if (bluemap.getRenderManager().isRunning()) { - bluemap.getRenderManager().stop(); - source.sendMessage(Text.of(TextColors.GREEN, "BlueMap rendering paused!")); - return CommandResult.success(); - } else { - source.sendMessage(Text.of(TextColors.RED, "BlueMap rendering are already paused!")); - return CommandResult.empty(); - } - }) - .build(); - } - - public CommandSpec createResumeRenderCommand() { - return CommandSpec.builder() - .description(Text.of("Resumes all paused rendering")) - .permission("bluemap.resume") - .executor((source, args) -> { - if (!bluemap.getRenderManager().isRunning()) { - bluemap.getRenderManager().start(); - source.sendMessage(Text.of(TextColors.GREEN, "BlueMap renders resumed!")); - return CommandResult.success(); - } else { - source.sendMessage(Text.of(TextColors.RED, "BlueMap renders are already running!")); - return CommandResult.empty(); - } - }) - .build(); - } - - public CommandSpec createRenderCommand() { - return CommandSpec.builder() - .description(Text.of("Renders the whole world")) - .permission("bluemap.rendertask.create.world") - .childArgumentParseExceptionFallback(false) - .child(createPrioritizeTaskCommand(), "prioritize") - .child(createRemoveTaskCommand(), "remove") - .arguments(GenericArguments.optional(GenericArguments.world(Text.of("world")))) - .executor((source, args) -> { - WorldProperties spongeWorld = args.getOne("world").orElse(null); - - if (spongeWorld == null && source instanceof Locatable) { - Location loc = ((Locatable) source).getLocation(); - spongeWorld = loc.getExtent().getProperties(); - } - - if (spongeWorld == null){ - source.sendMessage(Text.of(TextColors.RED, "You have to define a world to render!")); - return CommandResult.empty(); - } - - World world = bluemap.getWorld(spongeWorld.getUniqueId()); - if (world == null) { - source.sendMessage(Text.of(TextColors.RED, "This world is not loaded with BlueMap! Maybe it is not configured?")); - } - - world.invalidateChunkCache(); - - Sponge.getScheduler().createTaskBuilder() - .async() - .execute(() -> createWorldRenderTask(source, world)) - .submit(plugin); - - return CommandResult.success(); - }) - .build(); - } - - public CommandSpec createPrioritizeTaskCommand() { - return CommandSpec.builder() - .description(Text.of("Prioritizes the render-task with the given uuid")) - .permission("bluemap.rendertask.prioritize") - .arguments(GenericArguments.uuid(Text.of("task-uuid"))) - .executor((source, args) -> { - Optional uuid = args.getOne("task-uuid"); - if (!uuid.isPresent()) { - source.sendMessage(Text.of("You need to specify a task-uuid")); - return CommandResult.empty(); - } - - for (RenderTask task : bluemap.getRenderManager().getRenderTasks()) { - if (task.getUuid().equals(uuid.get())) { - bluemap.getRenderManager().prioritizeRenderTask(task); - break; - } - } - - source.sendMessages(createStatusMessage()); - return CommandResult.success(); - }) - .build(); - } - - public CommandSpec createRemoveTaskCommand() { - return CommandSpec.builder() - .description(Text.of("Removes the render-task with the given uuid")) - .permission("bluemap.rendertask.remove") - .arguments(GenericArguments.uuid(Text.of("task-uuid"))) - .executor((source, args) -> { - Optional uuid = args.getOne("task-uuid"); - if (!uuid.isPresent()) { - source.sendMessage(Text.of("You need to specify a task-uuid")); - return CommandResult.empty(); - } - - for (RenderTask task : bluemap.getRenderManager().getRenderTasks()) { - if (task.getUuid().equals(uuid.get())) { - bluemap.getRenderManager().removeRenderTask(task); - break; - } - } - - source.sendMessages(createStatusMessage()); - return CommandResult.success(); - }) - .build(); - } - - private List createStatusMessage(){ - List lines = new ArrayList<>(); - - RenderManager renderer = bluemap.getRenderManager(); - - lines.add(Text.EMPTY); - lines.add(Text.of(TextColors.BLUE, "Tile-Updates:")); - - if (renderer.isRunning()) { - lines.add(Text.of(TextColors.WHITE, " Render-Threads are ", Text.of(TextActions.runCommand("/bluemap pause"), TextActions.showText(Text.of("click to pause rendering")), TextColors.GREEN, "running"), TextColors.GRAY, "!")); - } else { - lines.add(Text.of(TextColors.WHITE, " Render-Threads are ", Text.of(TextActions.runCommand("/bluemap resume"), TextActions.showText(Text.of("click to resume rendering")), TextColors.RED, "paused"), TextColors.GRAY, "!")); - } - - lines.add(Text.of(TextColors.WHITE, " Scheduled tile-updates: ", Text.of(TextActions.showText(Text.of("tiles waiting for a free render-thread")), TextColors.GOLD, renderer.getQueueSize()), Text.of(TextActions.showText(Text.of("tiles waiting for world-save")), TextColors.GRAY, " + " + bluemap.getUpdateHandler().getUpdateBufferCount()))); - - RenderTask[] tasks = renderer.getRenderTasks(); - if (tasks.length > 0) { - RenderTask task = tasks[0]; - - long time = task.getActiveTime(); - String durationString = DurationFormatUtils.formatDurationWords(time, true, true); - double pct = (double)task.getRenderedTileCount() / (double)(task.getRenderedTileCount() + task.getRemainingTileCount()); - - long ert = (long)((time / pct) * (1d - pct)); - String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true); - - double tps = task.getRenderedTileCount() / (time / 1000.0); - - lines.add(Text.of(TextColors.BLUE, "Current task:")); - lines.add(Text.of(" ", createCancelTaskText(task), TextColors.WHITE, " Task ", TextColors.GOLD, task.getName(), TextColors.WHITE, " for map ", TextActions.showText(Text.of(TextColors.WHITE, "World: ", TextColors.GOLD, task.getMapType().getWorld().getName())), TextColors.GOLD, task.getMapType().getName())); - lines.add(Text.of(TextColors.WHITE, " rendered ", TextColors.GOLD, task.getRenderedTileCount(), TextColors.WHITE, " tiles ", TextColors.GRAY, "(" + (Math.round(pct * 1000)/10.0) + "% | " + GenericMath.round(tps, 1) + "t/s)", TextColors.WHITE, " in ", TextColors.GOLD, durationString)); - lines.add(Text.of(TextColors.WHITE, " with ", TextColors.GOLD, task.getRemainingTileCount(), TextColors.WHITE, " tiles to go. ETA: ", TextColors.GOLD, ertDurationString)); - } - - if (tasks.length > 1) { - lines.add(Text.of(TextColors.BLUE, "Waiting tasks:")); - for (int i = 1; i < tasks.length; i++) { - RenderTask task = tasks[i]; - lines.add(Text.of(" ", createCancelTaskText(task), createPrioritizeTaskText(task), TextColors.WHITE, " Task ", TextColors.GOLD, task.getName(), TextColors.WHITE, " for map ", Text.of(TextActions.showText(Text.of(TextColors.WHITE, "World: ", TextColors.GOLD, task.getMapType().getWorld().getName())), TextColors.GOLD, task.getMapType().getName()), TextColors.GRAY, " (" + task.getRemainingTileCount() + " tiles)")); - } - } - - return lines; - } - - private Text createCancelTaskText(RenderTask task) { - return Text.of(TextActions.runCommand("/bluemap render remove " + task.getUuid()), TextActions.showText(Text.of("click to remove this render-task")), TextColors.RED, "[X]"); - } - - private Text createPrioritizeTaskText(RenderTask task) { - return Text.of(TextActions.runCommand("/bluemap render prioritize " + task.getUuid()), TextActions.showText(Text.of("click to prioritize this render-task")), TextColors.GREEN, "[^]"); - } - - private void createWorldRenderTask(CommandSource source, World world) { - source.sendMessage(Text.of(TextColors.GOLD, "Collecting chunks to render...")); - Collection chunks = world.getChunkList(); - source.sendMessage(Text.of(TextColors.GREEN, chunks.size() + " chunks found!")); - - for (MapType map : bluemap.getMapTypes()) { - if (!map.getWorld().getUUID().equals(world.getUUID())) continue; - - source.sendMessage(Text.of(TextColors.GOLD, "Collecting tiles for map '" + map.getId() + "'")); - - HiresModelManager hmm = map.getTileRenderer().getHiresModelManager(); - Collection tiles = hmm.getTilesForChunks(chunks); - - RenderTask task = new RenderTask("world-render", map); - task.addTiles(tiles); - task.optimizeQueue(); - bluemap.getRenderManager().addRenderTask(task); - - source.sendMessage(Text.of(TextColors.GREEN, tiles.size() + " tiles found! Task created.")); - } - - source.sendMessage(Text.of(TextColors.GREEN, "All render tasks created! Use /bluemap to view the progress!")); - } - -} diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommandSource.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommandSource.java new file mode 100644 index 00000000..8f9b80f6 --- /dev/null +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommandSource.java @@ -0,0 +1,46 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.sponge; + +import org.spongepowered.api.text.serializer.TextSerializers; + +import de.bluecolored.bluemap.common.plugin.serverinterface.CommandSource; +import de.bluecolored.bluemap.common.plugin.text.Text; + +public class SpongeCommandSource implements CommandSource { + + private org.spongepowered.api.command.CommandSource delegate; + + public SpongeCommandSource(org.spongepowered.api.command.CommandSource delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(Text text) { + org.spongepowered.api.text.Text spongeText = TextSerializers.JSON.deserializeUnchecked(text.toJSONString()); + delegate.sendMessage(spongeText); + } + +} diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java new file mode 100644 index 00000000..b58b17d3 --- /dev/null +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java @@ -0,0 +1,170 @@ +package de.bluecolored.bluemap.sponge; + +import java.util.Optional; +import java.util.UUID; + +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.args.GenericArguments; +import org.spongepowered.api.command.spec.CommandSpec; +import org.spongepowered.api.text.Text; +import org.spongepowered.api.text.format.TextColors; +import org.spongepowered.api.world.Locatable; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.storage.WorldProperties; + +import de.bluecolored.bluemap.common.plugin.Commands; + +public class SpongeCommands { + + private Commands commands; + + public SpongeCommands(Commands commands) { + this.commands = commands; + } + + public CommandSpec createRootCommand() { + return CommandSpec.builder() + .description(Text.of("Displays BlueMaps render status")) + .permission("bluemap.status") + .childArgumentParseExceptionFallback(false) + .child(createReloadCommand(), "reload") + .child(createPauseRenderCommand(), "pause") + .child(createResumeRenderCommand(), "resume") + .child(createRenderCommand(), "render") + .child(createDebugCommand(), "debug") + .executor((source, args) -> { + commands.executeRootCommand(new SpongeCommandSource(source)); + return CommandResult.success(); + }) + .build(); + } + + public CommandSpec createReloadCommand() { + return CommandSpec.builder() + .description(Text.of("Reloads all resources and configuration-files")) + .permission("bluemap.reload") + .executor((source, args) -> { + commands.executeReloadCommand(new SpongeCommandSource(source)); + return CommandResult.success(); + }) + .build(); + } + + public CommandSpec createPauseRenderCommand() { + return CommandSpec.builder() + .description(Text.of("Pauses all rendering")) + .permission("bluemap.pause") + .executor((source, args) -> { + if (commands.executePauseCommand(new SpongeCommandSource(source))) { + return CommandResult.success(); + } else { + return CommandResult.empty(); + } + }) + .build(); + } + + public CommandSpec createResumeRenderCommand() { + return CommandSpec.builder() + .description(Text.of("Resumes all paused rendering")) + .permission("bluemap.resume") + .executor((source, args) -> { + if (commands.executeResumeCommand(new SpongeCommandSource(source))) { + return CommandResult.success(); + } else { + return CommandResult.empty(); + } + }) + .build(); + } + + public CommandSpec createRenderCommand() { + return CommandSpec.builder() + .description(Text.of("Renders the whole world")) + .permission("bluemap.rendertask.create.world") + .childArgumentParseExceptionFallback(false) + .child(createPrioritizeTaskCommand(), "prioritize") + .child(createRemoveTaskCommand(), "remove") + .arguments(GenericArguments.optional(GenericArguments.world(Text.of("world")))) + .executor((source, args) -> { + WorldProperties spongeWorld = args.getOne("world").orElse(null); + + if (spongeWorld == null && source instanceof Locatable) { + Location loc = ((Locatable) source).getLocation(); + spongeWorld = loc.getExtent().getProperties(); + } + + if (spongeWorld == null){ + source.sendMessage(Text.of(TextColors.RED, "You have to define a world to render!")); + return CommandResult.empty(); + } + + if (commands.executeRenderWorldCommand(new SpongeCommandSource(source), spongeWorld.getUniqueId())) { + return CommandResult.success(); + } else { + return CommandResult.empty(); + } + }) + .build(); + } + + public CommandSpec createPrioritizeTaskCommand() { + return CommandSpec.builder() + .description(Text.of("Prioritizes the render-task with the given uuid")) + .permission("bluemap.rendertask.prioritize") + .arguments(GenericArguments.uuid(Text.of("task-uuid"))) + .executor((source, args) -> { + Optional uuid = args.getOne("task-uuid"); + if (!uuid.isPresent()) { + source.sendMessage(Text.of(TextColors.RED, "You need to specify a task-uuid")); + return CommandResult.empty(); + } + + commands.executePrioritizeRenderTaskCommand(new SpongeCommandSource(source), uuid.get()); + return CommandResult.success(); + }) + .build(); + } + + public CommandSpec createRemoveTaskCommand() { + return CommandSpec.builder() + .description(Text.of("Removes the render-task with the given uuid")) + .permission("bluemap.rendertask.remove") + .arguments(GenericArguments.uuid(Text.of("task-uuid"))) + .executor((source, args) -> { + Optional uuid = args.getOne("task-uuid"); + if (!uuid.isPresent()) { + source.sendMessage(Text.of(TextColors.RED, "You need to specify a task-uuid")); + return CommandResult.empty(); + } + + commands.executeRemoveRenderTaskCommand(new SpongeCommandSource(source), uuid.get()); + return CommandResult.success(); + }) + .build(); + } + + public CommandSpec createDebugCommand() { + return CommandSpec.builder() + .permission("bluemap.debug") + .description(Text.of("Prints some debug info")) + .extendedDescription(Text.of("Prints some information about how bluemap sees the blocks at and below your position")) + .executor((source, args) -> { + if (source instanceof Locatable) { + Location loc = ((Locatable) source).getLocation(); + UUID worldUuid = loc.getExtent().getUniqueId(); + + if (commands.executeDebugCommand(new SpongeCommandSource(source), worldUuid, loc.getBlockPosition())) { + return CommandResult.success(); + } else { + return CommandResult.empty(); + } + } + + source.sendMessage(Text.of(TextColors.RED, "You can only execute this command as a player!")); + return CommandResult.empty(); + }) + .build(); + } + +} diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java index c7e88a9e..8c070220 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java @@ -85,7 +85,7 @@ public void onServerStart(GameStartingServerEvent evt) { Sponge.getServer().saveWorldProperties(properties); } - Sponge.getCommandManager().register(this, new Commands(this).createRootCommand(), "bluemap"); + Sponge.getCommandManager().register(this, new SpongeCommands(bluemap.getCommands()).createRootCommand(), "bluemap"); asyncExecutor.execute(() -> { try { @@ -146,12 +146,4 @@ public File getConfigFolder() { return configurationDir.toFile(); } - public SpongeExecutorService getAsyncExecutor() { - return asyncExecutor; - } - - public Plugin getBlueMap() { - return bluemap; - } - }