Command and world-name improvements

This commit is contained in:
Blue (Lukas Rieger) 2020-05-10 17:29:16 +02:00
parent acaff30b76
commit 0535a29f8e
10 changed files with 131 additions and 10 deletions

View File

@ -150,6 +150,14 @@ public class BukkitPlugin extends JavaPlugin implements ServerInterface {
}
}
@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();

View File

@ -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

View File

@ -189,7 +189,7 @@ public class Plugin {
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);

View File

@ -26,6 +26,7 @@ package de.bluecolored.bluemap.common.plugin.commands;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -35,6 +36,8 @@ 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 {
Collection<String> possibleValues = getPossibleValues();
@ -42,6 +45,10 @@ public abstract class AbstractSuggestionProvider<S> implements SuggestionProvide
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);
}

View File

@ -95,7 +95,7 @@ public class Commands<S> {
.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())
@ -135,7 +135,7 @@ public class Commands<S> {
)
)
.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 <world|map>
.then(argument("x", DoubleArgumentType.doubleArg())
@ -152,7 +152,7 @@ public class Commands<S> {
LiteralCommandNode<S> prioRenderCommand =
literal("prioritize")
.requires(requirements("bluemap.render"))
.then(argument("uuid", StringArgumentType.word())
.then(argument("uuid", StringArgumentType.string())
.executes(this::prioritizeRenderTaskCommand)
)
.build();
@ -160,11 +160,23 @@ public class Commands<S> {
LiteralCommandNode<S> cancelRenderCommand =
literal("cancel")
.requires(requirements("bluemap.render"))
.then(argument("uuid", StringArgumentType.word())
.then(argument("uuid", StringArgumentType.string())
.executes(this::cancelRenderTaskCommand)
)
.build();
LiteralCommandNode<S> worldsCommand =
literal("worlds")
.requires(requirements("bluemap.status"))
.executes(this::worldsCommand)
.build();
LiteralCommandNode<S> mapsCommand =
literal("maps")
.requires(requirements("bluemap.status"))
.executes(this::mapsCommand)
.build();
// command tree
dispatcher.getRoot().addChild(baseCommand);
baseCommand.addChild(reloadCommand);
@ -174,6 +186,8 @@ public class Commands<S> {
baseCommand.addChild(renderCommand);
renderCommand.addChild(prioRenderCommand);
renderCommand.addChild(cancelRenderCommand);
baseCommand.addChild(worldsCommand);
baseCommand.addChild(mapsCommand);
}
private Predicate<S> requirements(String permission){
@ -454,4 +468,27 @@ public class Commands<S> {
source.sendMessage(Text.of(TextColor.RED, "There is no render-task with this UUID: " + uuidString));
return 0;
}
public int worldsCommand(CommandContext<S> 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<S> 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;
}
}

View File

@ -50,6 +50,17 @@ public interface ServerInterface {
*/
UUID getUUIDForWorld(File worldFolder) throws IOException;
/**
* Returns the name of the world with that UUID, the name is used in commands and should therefore be unique.<br>
* A return-value of <code>null</code> makes bluemap load the world-name from the level.dat and dimension-folder.
*
* @param worldUUID the uuid of the world
* @return the worlds name
*/
default String getWorldName(UUID worldUUID) {
return null;
}
/**
* Returns the Folder containing the configurations for the plugin
*/

View File

@ -377,11 +377,18 @@ public class MCAWorld implements World {
private Path getMCAFilePath(Vector2i region) {
return getRegionFolder().resolve(MCAUtil.createNameFromRegionLocation(region.getX(), region.getY()));
}
public static MCAWorld load(Path worldFolder, UUID uuid, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper) throws IOException {
return load(worldFolder, uuid, blockIdMapper, blockPropertiesMapper, biomeIdMapper, null);
}
public static MCAWorld load(Path worldFolder, UUID uuid, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper, String name) throws IOException {
try {
boolean subDimension = false;
File levelFile = new File(worldFolder.toFile(), "level.dat");
if (!levelFile.exists()) {
subDimension = true;
levelFile = new File(worldFolder.toFile().getParentFile(), "level.dat");
if (!levelFile.exists()) {
throw new FileNotFoundException("Could not find a level.dat file for this world!");
@ -391,7 +398,11 @@ public class MCAWorld implements World {
CompoundTag level = (CompoundTag) NBTUtil.readTag(levelFile);
CompoundTag levelData = level.getCompoundTag("Data");
String name = levelData.getString("LevelName");
if (name == null) {
name = levelData.getString("LevelName");
if (subDimension) name += "/" + worldFolder.toFile().getName();
}
int worldHeight = 255;
int seaLevel = 63;
Vector3i spawnPoint = new Vector3i(

View File

@ -24,15 +24,28 @@
*/
package de.bluecolored.bluemap.forge;
import java.io.IOException;
import java.util.Optional;
import com.flowpowered.math.vector.Vector3d;
import de.bluecolored.bluemap.common.plugin.Plugin;
import de.bluecolored.bluemap.common.plugin.serverinterface.CommandSource;
import de.bluecolored.bluemap.common.plugin.text.Text;
import de.bluecolored.bluemap.core.world.World;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.server.ServerWorld;
public class ForgeCommandSource implements CommandSource {
private ForgeMod mod;
private Plugin plugin;
private net.minecraft.command.CommandSource delegate;
public ForgeCommandSource(net.minecraft.command.CommandSource delegate) {
public ForgeCommandSource(ForgeMod mod, Plugin plugin, net.minecraft.command.CommandSource delegate) {
this.mod = mod;
this.plugin = plugin;
this.delegate = delegate;
}
@ -46,4 +59,26 @@ public class ForgeCommandSource implements CommandSource {
return delegate.hasPermissionLevel(1);
}
@Override
public Optional<Vector3d> getPosition() {
Vec3d pos = delegate.getPos();
if (pos != null) {
return Optional.of(new Vector3d(pos.x, pos.y, pos.z));
}
return Optional.empty();
}
@Override
public Optional<World> getWorld() {
try {
ServerWorld world = delegate.getWorld();
if (world != null) {
return Optional.ofNullable(plugin.getWorld(mod.getUUIDForWorld(world)));
}
} catch (IOException ignore) {}
return Optional.empty();
}
}

View File

@ -88,7 +88,7 @@ public class ForgeMod implements ServerInterface {
}
//register commands
this.commands = new Commands<>(bluemap, event.getCommandDispatcher(), ForgeCommandSource::new);
this.commands = new Commands<>(bluemap, event.getCommandDispatcher(), forgeSource -> new ForgeCommandSource(this, bluemap, forgeSource));
new Thread(() -> {
try {

View File

@ -27,6 +27,7 @@ package de.bluecolored.bluemap.sponge;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;
import javax.inject.Inject;
@ -39,6 +40,7 @@ import org.spongepowered.api.event.game.GameReloadEvent;
import org.spongepowered.api.event.game.state.GameStartingServerEvent;
import org.spongepowered.api.event.game.state.GameStoppingEvent;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.storage.WorldProperties;
import de.bluecolored.bluemap.common.plugin.Plugin;
@ -145,6 +147,14 @@ public class SpongePlugin implements ServerInterface {
throw new IOException("Failed to read level_sponge.dat", t);
}
}
@Override
public String getWorldName(UUID worldUUID) {
Optional<World> world = Sponge.getServer().getWorld(worldUUID);
if (world.isPresent()) return world.get().getName();
return null;
}
@Override
public File getConfigFolder() {