mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-02-23 07:51:43 +01:00
Move commands to common and start implementing spigot plugin
This commit is contained in:
parent
b6cc6c5ea7
commit
3daab62714
@ -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('§'));
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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() {
|
||||
|
@ -0,0 +1,10 @@
|
||||
accept-download: false
|
||||
metrics: true
|
||||
renderThreadCount: -2
|
||||
data: "bluemap"
|
||||
webroot: "bluemap/web"
|
||||
webserver {
|
||||
enabled: true
|
||||
port: 8100
|
||||
maxConnectionCount: 100
|
||||
}
|
171
BlueMapBukkit/src/main/resources/bluemap-bukkit.conf
Normal file
171
BlueMapBukkit/src/main/resources/bluemap-bukkit.conf
Normal file
@ -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: <data>/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 "<webroot>/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
|
||||
}
|
||||
|
||||
]
|
@ -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:
|
@ -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:
|
||||
*
|
||||
* <ul>
|
||||
* <li>/bluemap</li>
|
||||
* <li>/bluemap reload</li>
|
||||
* <li>/bluemap pause</li>
|
||||
* <li>/bluemap resume</li>
|
||||
* <li>/bluemap render [world]</li>
|
||||
* <li>/bluemap render prioritize [task-uuid]</li>
|
||||
* <li>/bluemap render remove [task-uuid]</li>
|
||||
* <li>/bluemap debug</li>
|
||||
* </ul>
|
||||
*/
|
||||
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<Text> createStatusMessage(){
|
||||
List<Text> 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<Vector2i> 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<Vector2i> 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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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<Text> textLines) {
|
||||
for (Text text : textLines) {
|
||||
sendMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -14,25 +14,29 @@ public class Text {
|
||||
private String clickCommand;
|
||||
private List<Text> 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;
|
||||
}
|
||||
|
@ -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<org.spongepowered.api.world.World> 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.<WorldProperties>getOne("world").orElse(null);
|
||||
|
||||
if (spongeWorld == null && source instanceof Locatable) {
|
||||
Location<org.spongepowered.api.world.World> 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> uuid = args.<UUID>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> uuid = args.<UUID>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<Text> createStatusMessage(){
|
||||
List<Text> 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<Vector2i> 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<Vector2i> 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!"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
@ -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.<WorldProperties>getOne("world").orElse(null);
|
||||
|
||||
if (spongeWorld == null && source instanceof Locatable) {
|
||||
Location<org.spongepowered.api.world.World> 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> uuid = args.<UUID>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> uuid = args.<UUID>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<org.spongepowered.api.world.World> 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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user