More command improvements

This commit is contained in:
Blue (Lukas Rieger) 2020-05-11 13:23:56 +02:00
parent 0535a29f8e
commit 90473bd83b
3 changed files with 245 additions and 29 deletions

View File

@ -26,8 +26,8 @@
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.SuggestionProvider;
@ -35,8 +35,6 @@
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
public abstract class AbstractSuggestionProvider<S> implements SuggestionProvider<S> {
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[^a-zA-Z0-9_-]");
@Override
public CompletableFuture<Suggestions> getSuggestions(CommandContext<S> context, SuggestionsBuilder builder) throws CommandSyntaxException {
@ -45,12 +43,8 @@ public CompletableFuture<Suggestions> getSuggestions(CommandContext<S> context,
String remaining = builder.getRemaining().toLowerCase();
for (String str : possibleValues) {
if (ESCAPE_PATTERN.matcher(str).find() && str.indexOf('"') == -1) {
str = "\"" + str + "\"";
}
if (str.toLowerCase().startsWith(remaining)) {
builder.suggest(str);
builder.suggest(str = StringArgumentType.escapeIfRequired(str));
}
}

View File

@ -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<S> {
public static final String DEFAULT_MARKER_SET_ID = "markers";
private final Plugin plugin;
private final CommandDispatcher<S> dispatcher;
@ -99,11 +106,7 @@ public void init() {
.then(argument("x", DoubleArgumentType.doubleArg())
.then(argument("y", DoubleArgumentType.doubleArg())
.then(argument("z", DoubleArgumentType.doubleArg())
.executes(this::debugCommand)
)
)
)
)
.executes(this::debugCommand)))))
.build();
LiteralCommandNode<S> pauseCommand =
@ -124,16 +127,12 @@ public void init() {
.executes(this::renderCommand) // /bluemap render
.then(argument("radius", IntegerArgumentType.integer())
.executes(this::renderCommand) // /bluemap render <radius>
)
.executes(this::renderCommand)) // /bluemap render <radius>
.then(argument("x", DoubleArgumentType.doubleArg())
.then(argument("z", DoubleArgumentType.doubleArg())
.then(argument("radius", IntegerArgumentType.integer())
.executes(this::renderCommand) // /bluemap render <x> <z> <radius>
)
)
)
.executes(this::renderCommand)))) // /bluemap render <x> <z> <radius>
.then(argument("world|map", StringArgumentType.string()).suggests(new WorldOrMapSuggestionProvider<>(plugin))
.executes(this::renderCommand) // /bluemap render <world|map>
@ -141,28 +140,21 @@ public void init() {
.then(argument("x", DoubleArgumentType.doubleArg())
.then(argument("z", DoubleArgumentType.doubleArg())
.then(argument("radius", IntegerArgumentType.integer())
.executes(this::renderCommand) // /bluemap render <world|map> <x> <z> <radius>
)
)
)
)
.executes(this::renderCommand))))) // /bluemap render <world|map> <x> <z> <radius>
.build();
LiteralCommandNode<S> prioRenderCommand =
literal("prioritize")
.requires(requirements("bluemap.render"))
.then(argument("uuid", StringArgumentType.string())
.executes(this::prioritizeRenderTaskCommand)
)
.executes(this::prioritizeRenderTaskCommand))
.build();
LiteralCommandNode<S> cancelRenderCommand =
literal("cancel")
.requires(requirements("bluemap.render"))
.then(argument("uuid", StringArgumentType.string())
.executes(this::cancelRenderTaskCommand)
)
.executes(this::cancelRenderTaskCommand))
.build();
LiteralCommandNode<S> worldsCommand =
@ -177,6 +169,34 @@ public void init() {
.executes(this::mapsCommand)
.build();
LiteralCommandNode<S> markerCommand =
literal("marker")
.requires(requirements("bluemap.marker"))
.build();
LiteralCommandNode<S> 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<S> removeMarkerCommand =
literal("remove")
.requires(requirements("bluemap.marker"))
.then(argument("id", StringArgumentType.word()).suggests(MarkerIdSuggestionProvider.getInstance())
.executes(this::removeMarkerCommand))
.build();
// command tree
dispatcher.getRoot().addChild(baseCommand);
baseCommand.addChild(reloadCommand);
@ -188,6 +208,9 @@ public void init() {
renderCommand.addChild(cancelRenderCommand);
baseCommand.addChild(worldsCommand);
baseCommand.addChild(mapsCommand);
baseCommand.addChild(markerCommand);
markerCommand.addChild(createMarkerCommand);
markerCommand.addChild(removeMarkerCommand);
}
private Predicate<S> requirements(String permission){
@ -491,4 +514,112 @@ public int mapsCommand(CommandContext<S> context) {
return 1;
}
public int createMarkerCommand(CommandContext<S> context) {
CommandSource source = commandSourceInterface.apply(context.getSource());
String markerId = context.getArgument("id", String.class);
String markerLabel = context.getArgument("label", String.class)
.replace("<", "&lt;")
.replace(">", "&gt;"); //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<Double> x = getOptionalArgument(context, "x", Double.class);
Optional<Double> y = getOptionalArgument(context, "y", Double.class);
Optional<Double> 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] <x> <y> <z> <label>")));
return 0;
}
}
// get api
BlueMapAPI api = BlueMapAPI.getInstance().orElse(null);
if (api == null) {
source.sendMessage(Text.of(TextColor.RED, "MarkerAPI is not available, try ", TextColor.GRAY, "/bluemap reload"));
return 0;
}
// resolve api-map
Optional<BlueMapMap> apiMap = api.getMap(map.getId());
if (!apiMap.isPresent()) {
source.sendMessage(Text.of(TextColor.RED, "Failed to get map from API, try ", TextColor.GRAY, "/bluemap reload"));
return 0;
}
// add marker
try {
MarkerAPI markerApi = api.getMarkerAPI();
MarkerSet set = markerApi.getMarkerSet(DEFAULT_MARKER_SET_ID).orElse(null);
if (set == null) {
set = markerApi.createMarkerSet(DEFAULT_MARKER_SET_ID);
set.setLabel("Markers");
}
if (set.getMarker(markerId).isPresent()) {
source.sendMessage(Text.of(TextColor.RED, "There already is a marker with this id: ", TextColor.WHITE, markerId));
return 0;
}
POIMarker marker = set.createPOIMarker(markerId, apiMap.get(), position);
marker.setLabel(markerLabel);
markerApi.save();
MarkerIdSuggestionProvider.getInstance().forceUpdate();
} catch (IOException e) {
source.sendMessage(Text.of(TextColor.RED, "There was an error trying to add the marker, please check the console for details!"));
Logger.global.logError("Exception trying to add a marker!", e);
}
source.sendMessage(Text.of(TextColor.GREEN, "Marker added!"));
return 1;
}
public int removeMarkerCommand(CommandContext<S> context) {
CommandSource source = commandSourceInterface.apply(context.getSource());
String markerId = context.getArgument("id", String.class);
BlueMapAPI api = BlueMapAPI.getInstance().orElse(null);
if (api == null) {
source.sendMessage(Text.of(TextColor.RED, "MarkerAPI is not available, try ", TextColor.GRAY, "/bluemap reload"));
return 0;
}
try {
MarkerAPI markerApi = api.getMarkerAPI();
MarkerSet set = markerApi.createMarkerSet("markers");
if (!set.removeMarker(markerId)) {
source.sendMessage(Text.of(TextColor.RED, "There is no marker with this id: ", TextColor.WHITE, markerId));
}
markerApi.save();
MarkerIdSuggestionProvider.getInstance().forceUpdate();
} catch (IOException e) {
source.sendMessage(Text.of(TextColor.RED, "There was an error trying to remove the marker, please check the console for details!"));
Logger.global.logError("Exception trying to remove a marker!", e);
}
source.sendMessage(Text.of(TextColor.GREEN, "Marker removed!"));
return 1;
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.common.plugin.commands;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import de.bluecolored.bluemap.api.BlueMapAPI;
import de.bluecolored.bluemap.api.marker.Marker;
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.core.logger.Logger;
public class MarkerIdSuggestionProvider<S> extends AbstractSuggestionProvider<S> {
private static MarkerIdSuggestionProvider<?> instance;
private MarkerAPI markerApi;
private long lastUpdate = -1;
private MarkerIdSuggestionProvider() {}
@Override
public Collection<String> getPossibleValues() {
Collection<String> values = new HashSet<>();
if (markerApi == null || lastUpdate + 1000 * 60 < System.currentTimeMillis()) { // only (re)load marker-values max every minute
lastUpdate = System.currentTimeMillis();
Optional<BlueMapAPI> api = BlueMapAPI.getInstance();
if (!api.isPresent()) return values;
try {
markerApi = api.get().getMarkerAPI();
} catch (IOException e) {
Logger.global.noFloodError("0FEz5tm345rf", "Failed to load MarkerAPI!", e);
return values;
}
}
MarkerSet set = markerApi.getMarkerSet(Commands.DEFAULT_MARKER_SET_ID).orElse(null);
if (set != null) {
for (Marker marker : set.getMarkers()) {
if (marker instanceof POIMarker) {
values.add(marker.getId());
}
}
}
return values;
}
public void forceUpdate() {
lastUpdate = -1;
}
@SuppressWarnings("unchecked")
public static <S> MarkerIdSuggestionProvider<S> getInstance(){
if (instance == null) {
instance = new MarkerIdSuggestionProvider<>();
}
return (MarkerIdSuggestionProvider<S>) instance;
}
}