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 5a9971c0..3c3637b2 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java @@ -150,6 +150,14 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException { } } + @Override + public String getWorldName(UUID worldUUID) { + World world = getServer().getWorld(worldUUID); + if (world != null) return world.getName(); + + return null; + } + private UUID getUUIDForWorldSync (File worldFolder) throws IOException { for (World world : getServer().getWorlds()) { if (worldFolder.equals(world.getWorldFolder().getCanonicalFile())) return world.getUID(); diff --git a/BlueMapBukkit/src/main/resources/plugin.yml b/BlueMapBukkit/src/main/resources/plugin.yml index 80e030be..88cae5be 100644 --- a/BlueMapBukkit/src/main/resources/plugin.yml +++ b/BlueMapBukkit/src/main/resources/plugin.yml @@ -3,7 +3,6 @@ description: "A 3d-map of your Minecraft worlds view-able in your browser using main: de.bluecolored.bluemap.bukkit.BukkitPlugin version: ${version} author: "Blue (TBlueF / Lukas Rieger)" -authors: [Blue (TBlueF / Lukas Rieger)] website: "https://github.com/BlueMap-Minecraft" commands: permissions: @@ -15,6 +14,7 @@ permissions: bluemap.resume: true bluemap.render: true bluemap.debug: true + bluemap.marker: true default: op bluemap.status: default: op @@ -27,4 +27,6 @@ permissions: bluemap.render: default: op bluemap.debug: + default: op + bluemap.marker: default: op \ No newline at end of file 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 ed63a095..02ffa629 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 @@ -189,7 +189,7 @@ public synchronized void load() throws IOException, ParseResourceException { World world = worlds.get(worldUUID); if (world == null) { try { - world = MCAWorld.load(worldFolder.toPath(), worldUUID, configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig()); + world = MCAWorld.load(worldFolder.toPath(), worldUUID, configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig(), serverInterface.getWorldName(worldUUID)); worlds.put(worldUUID, world); } catch (IOException e) { Logger.global.logError("Failed to load map '" + id + "': Failed to read level.dat", e); diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/AbstractSuggestionProvider.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/AbstractSuggestionProvider.java index f07daa65..f717ecca 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/AbstractSuggestionProvider.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/AbstractSuggestionProvider.java @@ -27,6 +27,7 @@ import java.util.Collection; import java.util.concurrent.CompletableFuture; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.SuggestionProvider; @@ -34,7 +35,7 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; public abstract class AbstractSuggestionProvider implements SuggestionProvider { - + @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { Collection possibleValues = getPossibleValues(); @@ -43,7 +44,7 @@ public CompletableFuture getSuggestions(CommandContext context, String remaining = builder.getRemaining().toLowerCase(); for (String str : possibleValues) { if (str.toLowerCase().startsWith(remaining)) { - builder.suggest(str); + builder.suggest(str = StringArgumentType.escapeIfRequired(str)); } } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java index 7bf1d25b..8fc439a5 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java @@ -45,6 +45,11 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; +import de.bluecolored.bluemap.api.BlueMapAPI; +import de.bluecolored.bluemap.api.BlueMapMap; +import de.bluecolored.bluemap.api.marker.MarkerAPI; +import de.bluecolored.bluemap.api.marker.MarkerSet; +import de.bluecolored.bluemap.api.marker.POIMarker; import de.bluecolored.bluemap.common.MapType; import de.bluecolored.bluemap.common.RenderTask; import de.bluecolored.bluemap.common.plugin.Plugin; @@ -59,6 +64,8 @@ import de.bluecolored.bluemap.core.world.World; public class Commands { + + public static final String DEFAULT_MARKER_SET_ID = "markers"; private final Plugin plugin; private final CommandDispatcher dispatcher; @@ -95,15 +102,11 @@ public void init() { .requires(requirements("bluemap.debug")) .executes(this::debugCommand) - .then(argument("world", StringArgumentType.word()).suggests(new WorldSuggestionProvider<>(plugin)) + .then(argument("world", StringArgumentType.string()).suggests(new WorldSuggestionProvider<>(plugin)) .then(argument("x", DoubleArgumentType.doubleArg()) .then(argument("y", DoubleArgumentType.doubleArg()) .then(argument("z", DoubleArgumentType.doubleArg()) - .executes(this::debugCommand) - ) - ) - ) - ) + .executes(this::debugCommand))))) .build(); LiteralCommandNode pauseCommand = @@ -124,45 +127,74 @@ public void init() { .executes(this::renderCommand) // /bluemap render .then(argument("radius", IntegerArgumentType.integer()) - .executes(this::renderCommand) // /bluemap render - ) + .executes(this::renderCommand)) // /bluemap render .then(argument("x", DoubleArgumentType.doubleArg()) .then(argument("z", DoubleArgumentType.doubleArg()) .then(argument("radius", IntegerArgumentType.integer()) - .executes(this::renderCommand) // /bluemap render - ) - ) - ) + .executes(this::renderCommand)))) // /bluemap render - .then(argument("world|map", StringArgumentType.word()).suggests(new WorldOrMapSuggestionProvider<>(plugin)) + .then(argument("world|map", StringArgumentType.string()).suggests(new WorldOrMapSuggestionProvider<>(plugin)) .executes(this::renderCommand) // /bluemap render .then(argument("x", DoubleArgumentType.doubleArg()) .then(argument("z", DoubleArgumentType.doubleArg()) .then(argument("radius", IntegerArgumentType.integer()) - .executes(this::renderCommand) // /bluemap render - ) - ) - ) - ) - + .executes(this::renderCommand))))) // /bluemap render .build(); LiteralCommandNode prioRenderCommand = literal("prioritize") .requires(requirements("bluemap.render")) - .then(argument("uuid", StringArgumentType.word()) - .executes(this::prioritizeRenderTaskCommand) - ) + .then(argument("uuid", StringArgumentType.string()) + .executes(this::prioritizeRenderTaskCommand)) .build(); LiteralCommandNode cancelRenderCommand = literal("cancel") .requires(requirements("bluemap.render")) - .then(argument("uuid", StringArgumentType.word()) - .executes(this::cancelRenderTaskCommand) - ) + .then(argument("uuid", StringArgumentType.string()) + .executes(this::cancelRenderTaskCommand)) + .build(); + + LiteralCommandNode worldsCommand = + literal("worlds") + .requires(requirements("bluemap.status")) + .executes(this::worldsCommand) + .build(); + + LiteralCommandNode mapsCommand = + literal("maps") + .requires(requirements("bluemap.status")) + .executes(this::mapsCommand) + .build(); + + LiteralCommandNode markerCommand = + literal("marker") + .requires(requirements("bluemap.marker")) + .build(); + + LiteralCommandNode createMarkerCommand = + literal("create") + .requires(requirements("bluemap.marker")) + .then(argument("id", StringArgumentType.word()) + .then(argument("map", StringArgumentType.string()).suggests(new MapSuggestionProvider<>(plugin)) + + .then(argument("label", StringArgumentType.string()) + .executes(this::createMarkerCommand)) + + .then(argument("x", DoubleArgumentType.doubleArg()) + .then(argument("y", DoubleArgumentType.doubleArg()) + .then(argument("z", DoubleArgumentType.doubleArg()) + .then(argument("label", StringArgumentType.string()) + .executes(this::createMarkerCommand))))))) + .build(); + + LiteralCommandNode removeMarkerCommand = + literal("remove") + .requires(requirements("bluemap.marker")) + .then(argument("id", StringArgumentType.word()).suggests(MarkerIdSuggestionProvider.getInstance()) + .executes(this::removeMarkerCommand)) .build(); // command tree @@ -174,6 +206,11 @@ public void init() { baseCommand.addChild(renderCommand); renderCommand.addChild(prioRenderCommand); renderCommand.addChild(cancelRenderCommand); + baseCommand.addChild(worldsCommand); + baseCommand.addChild(mapsCommand); + baseCommand.addChild(markerCommand); + markerCommand.addChild(createMarkerCommand); + markerCommand.addChild(removeMarkerCommand); } private Predicate requirements(String permission){ @@ -454,4 +491,135 @@ public int cancelRenderTaskCommand(CommandContext context) { source.sendMessage(Text.of(TextColor.RED, "There is no render-task with this UUID: " + uuidString)); return 0; } + + public int worldsCommand(CommandContext context) { + CommandSource source = commandSourceInterface.apply(context.getSource()); + + source.sendMessage(Text.of(TextColor.BLUE, "Worlds loaded by BlueMap:")); + for (World world : plugin.getWorlds()) { + source.sendMessage(Text.of(TextColor.GRAY, " - ", TextColor.WHITE, world.getName()).setHoverText(Text.of(TextColor.GRAY, world.getUUID()))); + } + + return 1; + } + + public int mapsCommand(CommandContext context) { + CommandSource source = commandSourceInterface.apply(context.getSource()); + + source.sendMessage(Text.of(TextColor.BLUE, "Maps loaded by BlueMap:")); + for (MapType map : plugin.getMapTypes()) { + source.sendMessage(Text.of(TextColor.GRAY, " - ", TextColor.WHITE, map.getId(), TextColor.GRAY, " (" + map.getName() + ")").setHoverText(Text.of(TextColor.WHITE, "World: ", TextColor.GRAY, map.getWorld().getName()))); + } + + return 1; + } + + public int createMarkerCommand(CommandContext context) { + CommandSource source = commandSourceInterface.apply(context.getSource()); + + String markerId = context.getArgument("id", String.class); + String markerLabel = context.getArgument("label", String.class) + .replace("<", "<") + .replace(">", ">"); //no html via commands + + // parse world/map argument + String mapString = context.getArgument("map", String.class); + MapType map = parseMap(mapString).orElse(null); + + if (map == null) { + source.sendMessage(Text.of(TextColor.RED, "There is no ", helper.mapHelperHover(), " with this name: ", TextColor.WHITE, mapString)); + return 0; + } + + // parse position + Optional x = getOptionalArgument(context, "x", Double.class); + Optional y = getOptionalArgument(context, "y", Double.class); + Optional z = getOptionalArgument(context, "z", Double.class); + + Vector3d position; + + if (x.isPresent() && y.isPresent() && z.isPresent()) { + position = new Vector3d(x.get(), y.get(), z.get()); + } else { + position = source.getPosition().orElse(null); + + if (position == null) { + source.sendMessage(Text.of(TextColor.RED, "Can't detect a position from this command-source, you'll have to define the x,y,z coordinates for the marker!").setHoverText(Text.of(TextColor.GRAY, "/bluemap marker create " + markerId + " " + "[world|map]