Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-07 20:10:06 +01:00
Pagination changes and cleanup.
Refactored PaginationBox to be abstract. Implementations can generate individual components as needed now. Add lots of Component usage to schematic list, help listings, etc. Fix a few schematic and file resolution issues.
Dieser Commit ist enthalten in:
Ursprung
62353a46db
Commit
b3053f19ce
@ -38,7 +38,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||||
import com.sk89q.worldedit.world.gamemode.GameModes;
|
import com.sk89q.worldedit.world.gamemode.GameModes;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
||||||
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
@ -72,7 +72,7 @@ public class BukkitServerInterface implements MultiUserPlatform {
|
|||||||
if (plugin.getBukkitImplAdapter() != null) {
|
if (plugin.getBukkitImplAdapter() != null) {
|
||||||
return plugin.getBukkitImplAdapter().getDataVersion();
|
return plugin.getBukkitImplAdapter().getDataVersion();
|
||||||
}
|
}
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -303,6 +303,17 @@ public final class WorldEdit {
|
|||||||
if (exts.size() != 1) {
|
if (exts.size() != 1) {
|
||||||
exts = exts.subList(0, 1);
|
exts = exts.subList(0, 1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
int dot = filename.lastIndexOf('.');
|
||||||
|
if (dot < 0 || dot == filename.length() - 1) {
|
||||||
|
String currentExt = filename.substring(dot + 1);
|
||||||
|
if (exts.contains(currentExt) && checkFilename(filename)) {
|
||||||
|
File f = new File(dir, filename);
|
||||||
|
if (f.exists()) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
File result = null;
|
File result = null;
|
||||||
for (Iterator<String> iter = exts.iterator(); iter.hasNext() && (result == null || (!isSave && !result.exists()));) {
|
for (Iterator<String> iter = exts.iterator(); iter.hasNext() && (result == null || (!isSave && !result.exists()));) {
|
||||||
@ -317,7 +328,7 @@ public final class WorldEdit {
|
|||||||
private File getSafeFileWithExtension(File dir, String filename, String extension) {
|
private File getSafeFileWithExtension(File dir, String filename, String extension) {
|
||||||
if (extension != null) {
|
if (extension != null) {
|
||||||
int dot = filename.lastIndexOf('.');
|
int dot = filename.lastIndexOf('.');
|
||||||
if (dot < 0 || !filename.substring(dot).equalsIgnoreCase(extension)) {
|
if (dot < 0 || dot == filename.length() - 1 || !filename.substring(dot + 1).equalsIgnoreCase(extension)) {
|
||||||
filename += "." + extension;
|
filename += "." + extension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ import com.sk89q.worldedit.regions.Region;
|
|||||||
import com.sk89q.worldedit.regions.Regions;
|
import com.sk89q.worldedit.regions.Regions;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
import com.sk89q.worldedit.world.biome.BiomeData;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
@ -56,7 +55,7 @@ import org.enginehub.piston.annotation.param.Arg;
|
|||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -83,10 +82,11 @@ public class BiomeCommands {
|
|||||||
int page) throws WorldEditException {
|
int page) throws WorldEditException {
|
||||||
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
|
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
|
||||||
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
|
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
|
||||||
List<BiomeData> biomes = BiomeType.REGISTRY.values().stream().map(biomeRegistry::getData).collect(Collectors.toList());
|
|
||||||
|
|
||||||
PaginationBox paginationBox = new PaginationBox("Available Biomes", "/biomelist %page%");
|
PaginationBox paginationBox = PaginationBox.fromStrings("Available Biomes", "/biomelist %page%",
|
||||||
paginationBox.setComponents(biomes.stream().map(biome -> TextComponent.of(biome.getName())).collect(Collectors.toList()));
|
BiomeType.REGISTRY.values().stream()
|
||||||
|
.map(biomeRegistry::getData).filter(Objects::nonNull)
|
||||||
|
.map(BiomeData::getName).collect(Collectors.toList()));
|
||||||
player.print(paginationBox.create(page));
|
player.print(paginationBox.create(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ public class BiomeCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/setbiome",
|
name = "/setbiome",
|
||||||
desc = "Sets the biome of the player's current block or region.",
|
desc = "Sets the biome of your current block or region.",
|
||||||
descFooter = "By default, uses all the blocks in your selection"
|
descFooter = "By default, uses all the blocks in your selection"
|
||||||
)
|
)
|
||||||
@Logging(REGION)
|
@Logging(REGION)
|
||||||
|
@ -34,7 +34,6 @@ import com.sk89q.worldedit.math.BlockVector2;
|
|||||||
import com.sk89q.worldedit.math.MathUtils;
|
import com.sk89q.worldedit.math.MathUtils;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
||||||
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
|
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
|
||||||
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
|
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
|
||||||
import org.enginehub.piston.annotation.Command;
|
import org.enginehub.piston.annotation.Command;
|
||||||
@ -62,10 +61,10 @@ public class ChunkCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "chunkinfo",
|
name = "chunkinfo",
|
||||||
desc = "Get information about the chunk that you are inside"
|
desc = "Get information about the chunk you're inside"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.chunkinfo")
|
@CommandPermissions("worldedit.chunkinfo")
|
||||||
public void chunkInfo(Player player) throws WorldEditException {
|
public void chunkInfo(Player player) {
|
||||||
Location pos = player.getBlockIn();
|
Location pos = player.getBlockIn();
|
||||||
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
|
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
|
||||||
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
|
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
|
||||||
@ -90,8 +89,8 @@ public class ChunkCommands {
|
|||||||
@Arg(desc = "Page number.", def = "1") int page) throws WorldEditException {
|
@Arg(desc = "Page number.", def = "1") int page) throws WorldEditException {
|
||||||
Set<BlockVector2> chunks = session.getSelection(player.getWorld()).getChunks();
|
Set<BlockVector2> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||||
|
|
||||||
PaginationBox paginationBox = new PaginationBox("Selected Chunks", "/listchunks %page%");
|
PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks %page%",
|
||||||
paginationBox.setComponents(chunks.stream().map(chunk -> TextComponent.of(chunk.toString())).collect(Collectors.toList()));
|
chunks.stream().map(BlockVector2::toString).collect(Collectors.toList()));
|
||||||
player.print(paginationBox.create(page));
|
player.print(paginationBox.create(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.command;
|
package com.sk89q.worldedit.command;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
@ -39,6 +37,8 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
|||||||
import com.sk89q.worldedit.function.operation.Operations;
|
import com.sk89q.worldedit.function.operation.Operations;
|
||||||
import com.sk89q.worldedit.math.transform.Transform;
|
import com.sk89q.worldedit.math.transform.Transform;
|
||||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||||
|
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||||
|
import com.sk89q.worldedit.util.formatting.component.SchematicPaginationBox;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
import com.sk89q.worldedit.util.io.Closer;
|
import com.sk89q.worldedit.util.io.Closer;
|
||||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||||
@ -60,7 +60,6 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -70,10 +69,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||||
public class SchematicCommands {
|
public class SchematicCommands {
|
||||||
|
|
||||||
/**
|
|
||||||
* 9 schematics per page fits in the MC chat window.
|
|
||||||
*/
|
|
||||||
private static final int SCHEMATICS_PER_PAGE = 9;
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SchematicCommands.class);
|
private static final Logger log = LoggerFactory.getLogger(SchematicCommands.class);
|
||||||
private final WorldEdit worldEdit;
|
private final WorldEdit worldEdit;
|
||||||
|
|
||||||
@ -100,7 +95,9 @@ public class SchematicCommands {
|
|||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
|
||||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||||
File f = worldEdit.getSafeOpenFile(player, dir, filename, BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(), ClipboardFormats.getFileExtensionArray());
|
File f = worldEdit.getSafeOpenFile(player, dir, filename,
|
||||||
|
BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(),
|
||||||
|
ClipboardFormats.getFileExtensionArray());
|
||||||
|
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
player.printError("Schematic " + filename + " does not exist!");
|
player.printError("Schematic " + filename + " does not exist!");
|
||||||
@ -128,7 +125,7 @@ public class SchematicCommands {
|
|||||||
player.print(filename + " loaded. Paste it with //paste");
|
player.print(filename + " loaded. Paste it with //paste");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
|
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
|
||||||
log.warn("Failed to load a saved clipboard", e);
|
log.warn("Failed to load schematic: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +274,7 @@ public class SchematicCommands {
|
|||||||
@Switch(name = 'd', desc = "Sort by date, oldest first")
|
@Switch(name = 'd', desc = "Sort by date, oldest first")
|
||||||
boolean oldFirst,
|
boolean oldFirst,
|
||||||
@Switch(name = 'n', desc = "Sort by date, newest first")
|
@Switch(name = 'n', desc = "Sort by date, newest first")
|
||||||
boolean newFirst) {
|
boolean newFirst) throws WorldEditException {
|
||||||
if (oldFirst && newFirst) {
|
if (oldFirst && newFirst) {
|
||||||
throw new StopExecutionException(TextComponent.of("Cannot sort by oldest and newest."));
|
throw new StopExecutionException(TextComponent.of("Cannot sort by oldest and newest."));
|
||||||
}
|
}
|
||||||
@ -292,16 +289,6 @@ public class SchematicCommands {
|
|||||||
File[] files = new File[fileList.size()];
|
File[] files = new File[fileList.size()];
|
||||||
fileList.toArray(files);
|
fileList.toArray(files);
|
||||||
|
|
||||||
int pageCount = files.length / SCHEMATICS_PER_PAGE + 1;
|
|
||||||
if (page < 1) {
|
|
||||||
actor.printError("Page must be at least 1");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (page > pageCount) {
|
|
||||||
actor.printError("Page must be less than " + (pageCount + 1));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int sortType = oldFirst ? -1 : newFirst ? 1 : 0;
|
final int sortType = oldFirst ? -1 : newFirst ? 1 : 0;
|
||||||
// cleanup file list
|
// cleanup file list
|
||||||
Arrays.sort(files, (f1, f2) -> {
|
Arrays.sort(files, (f1, f2) -> {
|
||||||
@ -321,20 +308,9 @@ public class SchematicCommands {
|
|||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
|
||||||
List<String> schematics = listFiles(worldEdit.getConfiguration().saveDir, files);
|
String pageCommand = actor.isPlayer() ? "/schem list -p %page%" + (oldFirst ? " -d" : newFirst ? " -n" : "") : null;
|
||||||
int offset = (page - 1) * SCHEMATICS_PER_PAGE;
|
PaginationBox paginationBox = new SchematicPaginationBox(worldEdit.getConfiguration().saveDir, files, pageCommand);
|
||||||
|
actor.print(paginationBox.create(page));
|
||||||
actor.print("Available schematics (Filename: Format) [" + page + "/" + pageCount + "]:");
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size());
|
|
||||||
for (int i = offset; i < limit; ) {
|
|
||||||
build.append(schematics.get(i));
|
|
||||||
if (++i != limit) {
|
|
||||||
build.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actor.print(build.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<File> allFiles(File root) {
|
private List<File> allFiles(File root) {
|
||||||
@ -353,22 +329,4 @@ public class SchematicCommands {
|
|||||||
return fileList;
|
return fileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> listFiles(String prefix, File[] files) {
|
|
||||||
if (prefix == null) prefix = "";
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
for (File file : files) {
|
|
||||||
StringBuilder build = new StringBuilder();
|
|
||||||
|
|
||||||
build.append("\u00a72");
|
|
||||||
//ClipboardFormat format = ClipboardFormats.findByFile(file);
|
|
||||||
Multimap<String, ClipboardFormat> exts = ClipboardFormats.getFileExtensionMap();
|
|
||||||
ClipboardFormat format = exts.get(Files.getFileExtension(file.getName()))
|
|
||||||
.stream().findFirst().orElse(null);
|
|
||||||
boolean inRoot = file.getParentFile().getName().equals(prefix);
|
|
||||||
build.append(inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1])
|
|
||||||
.append(": ").append(format == null ? "Unknown" : format.getName() + "*");
|
|
||||||
result.add(build.toString());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ public class SelectionCommands {
|
|||||||
}
|
}
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
default:
|
default:
|
||||||
CommandListBox box = new CommandListBox("Selection modes");
|
CommandListBox box = new CommandListBox("Selection modes", null);
|
||||||
TextComponentProducer contents = box.getContents();
|
TextComponentProducer contents = box.getContents();
|
||||||
contents.append(SubtleFormat.wrap("Select one of the modes below:")).newline();
|
contents.append(SubtleFormat.wrap("Select one of the modes below:")).newline();
|
||||||
|
|
||||||
@ -636,7 +636,7 @@ public class SelectionCommands {
|
|||||||
box.appendCommand("cyl", "Select a cylinder", "//sel cyl");
|
box.appendCommand("cyl", "Select a cylinder", "//sel cyl");
|
||||||
box.appendCommand("convex", "Select a convex polyhedral", "//sel convex");
|
box.appendCommand("convex", "Select a convex polyhedral", "//sel convex");
|
||||||
|
|
||||||
player.print(box.create());
|
player.print(box.create(1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,10 @@ import com.sk89q.worldedit.math.BlockVector3;
|
|||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.CylinderRegion;
|
import com.sk89q.worldedit.regions.CylinderRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.formatting.component.InvalidComponentException;
|
||||||
|
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import org.enginehub.piston.annotation.Command;
|
import org.enginehub.piston.annotation.Command;
|
||||||
@ -58,8 +62,11 @@ import org.enginehub.piston.annotation.CommandContainer;
|
|||||||
import org.enginehub.piston.annotation.param.Arg;
|
import org.enginehub.piston.annotation.param.Arg;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
||||||
@ -474,6 +481,12 @@ public class UtilityCommands {
|
|||||||
return killed;
|
return killed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the formatter with the system locale. in the future, if we can get a local from a player, we can use that
|
||||||
|
private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault());
|
||||||
|
static {
|
||||||
|
formatter.applyPattern("#,##0.#####"); // pattern is locale-insensitive. this can translate to "1.234,56789"
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/calculate",
|
name = "/calculate",
|
||||||
aliases = { "/calc", "/eval", "/evaluate", "/solve" },
|
aliases = { "/calc", "/eval", "/evaluate", "/solve" },
|
||||||
@ -485,8 +498,14 @@ public class UtilityCommands {
|
|||||||
String input) {
|
String input) {
|
||||||
try {
|
try {
|
||||||
Expression expression = Expression.compile(input);
|
Expression expression = Expression.compile(input);
|
||||||
actor.print("= " + expression.evaluate(
|
double result = expression.evaluate(
|
||||||
new double[] {}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout()));
|
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
|
||||||
|
String formatted = formatter.format(result);
|
||||||
|
actor.print(SubtleFormat.wrap(input + " = ")
|
||||||
|
.append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE)));
|
||||||
|
//actor.print(SubtleFormat.wrap(input).append(Component.newline())
|
||||||
|
// .append(SubtleFormat.wrap("= "))
|
||||||
|
// .append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE)));
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
actor.printError(String.format(
|
actor.printError(String.format(
|
||||||
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
|
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
|
||||||
|
@ -22,13 +22,10 @@ package com.sk89q.worldedit.command.util;
|
|||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.util.formatting.component.CodeFormat;
|
|
||||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.component.InvalidComponentException;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
|
||||||
import org.enginehub.piston.Command;
|
import org.enginehub.piston.Command;
|
||||||
import org.enginehub.piston.CommandManager;
|
import org.enginehub.piston.CommandManager;
|
||||||
|
|
||||||
@ -46,7 +43,7 @@ import static java.util.stream.Collectors.toList;
|
|||||||
/**
|
/**
|
||||||
* Implementation of the //help command.
|
* Implementation of the //help command.
|
||||||
*/
|
*/
|
||||||
// Stored in a separate class to prevent import conflicts.
|
// Stored in a separate class to prevent import conflicts, and because it's aliased via /we help.
|
||||||
public class PrintCommandHelp {
|
public class PrintCommandHelp {
|
||||||
|
|
||||||
private static Command detectCommand(CommandManager manager, String command) {
|
private static Command detectCommand(CommandManager manager, String command) {
|
||||||
@ -69,17 +66,11 @@ public class PrintCommandHelp {
|
|||||||
return mapping.orElse(null);
|
return mapping.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void help(List<String> commandPath, int page, WorldEdit we, Actor actor) {
|
public static void help(List<String> commandPath, int page, WorldEdit we, Actor actor) throws InvalidComponentException {
|
||||||
if (page < 1) {
|
|
||||||
actor.printError("Page must be >= 1.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CommandManager manager = we.getPlatformManager().getPlatformCommandManager().getCommandManager();
|
CommandManager manager = we.getPlatformManager().getPlatformCommandManager().getCommandManager();
|
||||||
|
|
||||||
final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
|
|
||||||
|
|
||||||
if (commandPath.isEmpty()) {
|
if (commandPath.isEmpty()) {
|
||||||
printAllCommands(page, perPage, manager.getAllCommands(), actor, ImmutableList.of());
|
printCommands(page, manager.getAllCommands(), actor, ImmutableList.of());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +89,11 @@ public class PrintCommandHelp {
|
|||||||
|
|
||||||
if (subCommands.isEmpty()) {
|
if (subCommands.isEmpty()) {
|
||||||
actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
|
actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
|
||||||
Joiner.on(" ").join(visited), subCommand));
|
Joiner.on(" ").join(visited.stream().map(Command::getName).iterator()), subCommand));
|
||||||
|
// full help for single command
|
||||||
|
CommandUsageBox box = new CommandUsageBox(visited, visited.stream()
|
||||||
|
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||||
|
actor.print(box.create());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +102,11 @@ public class PrintCommandHelp {
|
|||||||
visited.add(currentCommand);
|
visited.add(currentCommand);
|
||||||
} else {
|
} else {
|
||||||
actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
|
actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
|
||||||
subCommand, Joiner.on(" ").join(visited)));
|
subCommand, Joiner.on(" ").join(visited.stream().map(Command::getName).iterator())));
|
||||||
|
// list subcommands for currentCommand
|
||||||
|
CommandUsageBox box = new CommandUsageBox(visited, visited.stream()
|
||||||
|
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||||
|
actor.print(box.create());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,46 +119,35 @@ public class PrintCommandHelp {
|
|||||||
.map(Command::getName).collect(Collectors.joining(" ")));
|
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||||
actor.print(box.create());
|
actor.print(box.create());
|
||||||
} else {
|
} else {
|
||||||
printAllCommands(page, perPage, subCommands.values().stream(), actor, visited);
|
printCommands(page, subCommands.values().stream(), actor, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printAllCommands(int page, int perPage, Stream<Command> commandStream, Actor actor,
|
private static void printCommands(int page, Stream<Command> commandStream, Actor actor,
|
||||||
List<Command> commandList) {
|
List<Command> commandList) throws InvalidComponentException {
|
||||||
// Get a list of aliases
|
// Get a list of aliases
|
||||||
List<Command> commands = commandStream
|
List<Command> commands = commandStream
|
||||||
.sorted(byCleanName())
|
.sorted(byCleanName())
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
|
|
||||||
// Calculate pagination
|
String used = commandList.isEmpty() ? null
|
||||||
int offset = perPage * (page - 1);
|
: Joiner.on(" ").join(commandList.stream().map(Command::getName).iterator());
|
||||||
int pageTotal = (int) Math.ceil(commands.size() / (double) perPage);
|
CommandListBox box = new CommandListBox(
|
||||||
|
(used == null ? "Help" : "Subcommands: " + used),
|
||||||
|
"//help %page%" + (used == null ? "" : " " + used));
|
||||||
|
if (!actor.isPlayer()) {
|
||||||
|
box.formatForConsole();
|
||||||
|
}
|
||||||
|
|
||||||
// Box
|
for (Command mapping : commands) {
|
||||||
CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page, pageTotal));
|
|
||||||
TextComponent.Builder tip = box.getContents().getBuilder().color(TextColor.GRAY);
|
|
||||||
|
|
||||||
if (offset >= commands.size()) {
|
|
||||||
tip.color(TextColor.RED)
|
|
||||||
.append(TextComponent.of(String.format("There is no page %d (total number of pages is %d).\n", page, pageTotal)));
|
|
||||||
} else {
|
|
||||||
List<Command> list = commands.subList(offset, Math.min(offset + perPage, commands.size()));
|
|
||||||
|
|
||||||
tip.append(TextComponent.of("Type "));
|
|
||||||
tip.append(CodeFormat.wrap("//help [<page>] <command...>"));
|
|
||||||
tip.append(TextComponent.of(" for more information.\n"));
|
|
||||||
|
|
||||||
// Add each command
|
|
||||||
for (Command mapping : list) {
|
|
||||||
String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName();
|
String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName();
|
||||||
String command = Stream.concat(commandList.stream(), Stream.of(mapping))
|
String command = Stream.concat(commandList.stream(), Stream.of(mapping))
|
||||||
.map(Command::getName)
|
.map(Command::getName)
|
||||||
.collect(Collectors.joining(" ", "/", ""));
|
.collect(Collectors.joining(" ", "/", ""));
|
||||||
box.appendCommand(alias, mapping.getDescription(), command);
|
box.appendCommand(alias, mapping.getDescription(), command);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actor.print(box.create());
|
actor.print(box.create(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrintCommandHelp() {
|
private PrintCommandHelp() {
|
||||||
|
@ -24,7 +24,6 @@ import com.sk89q.worldedit.session.SessionOwner;
|
|||||||
import com.sk89q.worldedit.util.Identifiable;
|
import com.sk89q.worldedit.util.Identifiable;
|
||||||
import com.sk89q.worldedit.util.auth.Subject;
|
import com.sk89q.worldedit.util.auth.Subject;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
|||||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||||
import com.sk89q.worldedit.util.logging.LogFormat;
|
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||||
@ -142,7 +143,6 @@ public final class PlatformCommandManager {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class);
|
private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class);
|
||||||
private static final java.util.logging.Logger COMMAND_LOG =
|
private static final java.util.logging.Logger COMMAND_LOG =
|
||||||
java.util.logging.Logger.getLogger("com.sk89q.worldedit.CommandLog");
|
java.util.logging.Logger.getLogger("com.sk89q.worldedit.CommandLog");
|
||||||
private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$");
|
|
||||||
|
|
||||||
private final WorldEdit worldEdit;
|
private final WorldEdit worldEdit;
|
||||||
private final PlatformManager platformManager;
|
private final PlatformManager platformManager;
|
||||||
@ -507,7 +507,7 @@ public final class PlatformCommandManager {
|
|||||||
.append(e.getRichMessage())
|
.append(e.getRichMessage())
|
||||||
.build());
|
.build());
|
||||||
ImmutableList<Command> cmd = e.getCommands();
|
ImmutableList<Command> cmd = e.getCommands();
|
||||||
if (cmd.size() > 0) {
|
if (!cmd.isEmpty()) {
|
||||||
actor.print(TextComponent.builder("Usage: ")
|
actor.print(TextComponent.builder("Usage: ")
|
||||||
.color(TextColor.RED)
|
.color(TextColor.RED)
|
||||||
.append(TextComponent.of("/", ColorConfig.getMainText()))
|
.append(TextComponent.of("/", ColorConfig.getMainText()))
|
||||||
@ -515,15 +515,14 @@ public final class PlatformCommandManager {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
} catch (CommandExecutionException e) {
|
} catch (CommandExecutionException e) {
|
||||||
Throwable t = e.getCause();
|
handleUnknownException(actor, e.getCause());
|
||||||
actor.printError("Please report this error: [See console]");
|
|
||||||
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
|
||||||
log.error("An unexpected error while handling a WorldEdit command", t);
|
|
||||||
} catch (CommandException e) {
|
} catch (CommandException e) {
|
||||||
actor.print(TextComponent.builder("")
|
actor.print(TextComponent.builder("")
|
||||||
.color(TextColor.RED)
|
.color(TextColor.RED)
|
||||||
.append(e.getRichMessage())
|
.append(e.getRichMessage())
|
||||||
.build());
|
.build());
|
||||||
|
} catch (Throwable t) {
|
||||||
|
handleUnknownException(actor, t);
|
||||||
} finally {
|
} finally {
|
||||||
Optional<EditSession> editSessionOpt =
|
Optional<EditSession> editSessionOpt =
|
||||||
context.snapshotMemory().injectedValue(Key.of(EditSession.class));
|
context.snapshotMemory().injectedValue(Key.of(EditSession.class));
|
||||||
@ -554,6 +553,12 @@ public final class PlatformCommandManager {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleUnknownException(Actor actor, Throwable t) {
|
||||||
|
actor.printError("Please report this error: [See console]");
|
||||||
|
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
||||||
|
log.error("An unexpected error while handling a WorldEdit command", t);
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
||||||
try {
|
try {
|
||||||
|
@ -102,10 +102,11 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
return readVersion1(schematicTag);
|
return readVersion1(schematicTag);
|
||||||
} else if (version == 2) {
|
} else if (version == 2) {
|
||||||
int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
|
int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
|
||||||
if (dataVersion > WorldEdit.getInstance().getPlatformManager()
|
int liveDataVersion = WorldEdit.getInstance().getPlatformManager()
|
||||||
.queryCapability(Capability.WORLD_EDITING).getDataVersion()) {
|
.queryCapability(Capability.WORLD_EDITING).getDataVersion();
|
||||||
// maybe should just warn? simple schematics may be compatible still.
|
if (dataVersion > liveDataVersion) {
|
||||||
throw new IOException("Schematic was made in a newer Minecraft version. Data may be incompatible.");
|
log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.",
|
||||||
|
dataVersion, liveDataVersion);
|
||||||
}
|
}
|
||||||
BlockArrayClipboard clip = readVersion1(schematicTag);
|
BlockArrayClipboard clip = readVersion1(schematicTag);
|
||||||
return readVersion2(clip, schematicTag);
|
return readVersion2(clip, schematicTag);
|
||||||
|
@ -19,47 +19,75 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.util.formatting.component;
|
package com.sk89q.worldedit.util.formatting.component;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
|
|
||||||
public class CommandListBox extends MessageBox {
|
import java.util.List;
|
||||||
|
|
||||||
private boolean first = true;
|
public class CommandListBox extends PaginationBox {
|
||||||
|
|
||||||
|
private List<CommandEntry> commands = Lists.newArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new box.
|
* Create a new box.
|
||||||
*
|
*
|
||||||
* @param title the title
|
* @param title the title
|
||||||
*/
|
*/
|
||||||
public CommandListBox(String title) {
|
public CommandListBox(String title, String pageCommand) {
|
||||||
super(title, new TextComponentProducer());
|
super(title, pageCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandListBox appendCommand(String alias, Component description) {
|
@Override
|
||||||
return appendCommand(alias, description, null);
|
public Component getComponent(int number) {
|
||||||
|
return commands.get(number).createComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandListBox appendCommand(String alias, String description, String insertion) {
|
@Override
|
||||||
return appendCommand(alias, TextComponent.of(description), insertion);
|
public int getComponentsSize() {
|
||||||
|
return commands.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandListBox appendCommand(String alias, Component description, String insertion) {
|
public void appendCommand(String alias, Component description) {
|
||||||
if (!first) {
|
appendCommand(alias, description, null);
|
||||||
getContents().newline();
|
|
||||||
}
|
}
|
||||||
TextComponent commandName = TextComponent.of(alias, TextColor.GOLD);
|
|
||||||
if (insertion != null) {
|
public void appendCommand(String alias, String description, String insertion) {
|
||||||
commandName = commandName
|
appendCommand(alias, TextComponent.of(description), insertion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendCommand(String alias, Component description, String insertion) {
|
||||||
|
commands.add(new CommandEntry(alias, description, insertion));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CommandEntry {
|
||||||
|
private final String alias;
|
||||||
|
private final Component description;
|
||||||
|
private final String insertion;
|
||||||
|
|
||||||
|
CommandEntry(String alias, Component description, String insertion) {
|
||||||
|
this.alias = alias;
|
||||||
|
this.description = description;
|
||||||
|
this.insertion = insertion;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component createComponent() {
|
||||||
|
TextComponentProducer line = new TextComponentProducer();
|
||||||
|
line.append(SubtleFormat.wrap("? ")
|
||||||
|
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "//help " + insertion))
|
||||||
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Additional Help"))));
|
||||||
|
TextComponent command = TextComponent.of(alias, TextColor.GOLD);
|
||||||
|
if (insertion == null) {
|
||||||
|
line.append(command);
|
||||||
|
} else {
|
||||||
|
line.append(command
|
||||||
.clickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, insertion))
|
.clickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, insertion))
|
||||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to select")));
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to select"))));
|
||||||
|
}
|
||||||
|
return line.append(TextComponent.of(": ")).append(description).create();
|
||||||
}
|
}
|
||||||
getContents().append(commandName.append(TextComponent.of(": ")));
|
|
||||||
getContents().append(description);
|
|
||||||
first = false;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class CommandUsageBox extends TextComponentProducer {
|
|||||||
* @param commands the commands to describe
|
* @param commands the commands to describe
|
||||||
* @param commandString the commands that were used, such as "/we" or "/brush sphere"
|
* @param commandString the commands that were used, such as "/we" or "/brush sphere"
|
||||||
*/
|
*/
|
||||||
public CommandUsageBox(List<Command> commands, String commandString) {
|
public CommandUsageBox(List<Command> commands, String commandString) throws InvalidComponentException {
|
||||||
this(commands, commandString, null);
|
this(commands, commandString, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ public class CommandUsageBox extends TextComponentProducer {
|
|||||||
* @param commandString the commands that were used, such as "/we" or "/brush sphere"
|
* @param commandString the commands that were used, such as "/we" or "/brush sphere"
|
||||||
* @param parameters list of parameters to use
|
* @param parameters list of parameters to use
|
||||||
*/
|
*/
|
||||||
public CommandUsageBox(List<Command> commands, String commandString, @Nullable CommandParameters parameters) {
|
public CommandUsageBox(List<Command> commands, String commandString, @Nullable CommandParameters parameters) throws InvalidComponentException {
|
||||||
checkNotNull(commands);
|
checkNotNull(commands);
|
||||||
checkNotNull(commandString);
|
checkNotNull(commandString);
|
||||||
Map<String, Command> subCommands = getSubCommands(Iterables.getLast(commands));
|
Map<String, Command> subCommands = getSubCommands(Iterables.getLast(commands));
|
||||||
@ -66,8 +66,9 @@ public class CommandUsageBox extends TextComponentProducer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachSubcommandUsage(Map<String, Command> dispatcher, String commandString, @Nullable CommandParameters parameters) {
|
private void attachSubcommandUsage(Map<String, Command> dispatcher, String commandString, @Nullable CommandParameters parameters) throws InvalidComponentException {
|
||||||
CommandListBox box = new CommandListBox("Subcommands");
|
CommandListBox box = new CommandListBox(commandString.isEmpty() ? "Help" : "Subcommands:" + commandString,
|
||||||
|
"//help %page%" + (commandString.isEmpty() ? "" : " " + commandString));
|
||||||
String prefix = !commandString.isEmpty() ? commandString + " " : "";
|
String prefix = !commandString.isEmpty() ? commandString + " " : "";
|
||||||
|
|
||||||
List<Command> list = dispatcher.values().stream()
|
List<Command> list = dispatcher.values().stream()
|
||||||
@ -80,7 +81,7 @@ public class CommandUsageBox extends TextComponentProducer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
append(box.create());
|
append(box.create(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachCommandUsage(List<Command> commands, String commandString) {
|
private void attachCommandUsage(List<Command> commands, String commandString) {
|
||||||
|
@ -21,9 +21,12 @@ package com.sk89q.worldedit.util.formatting.component;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.format.TextDecoration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes for a box with a border above and below.
|
* Makes for a box with a border above and below.
|
||||||
@ -40,28 +43,38 @@ public class MessageBox extends TextComponentProducer {
|
|||||||
public MessageBox(String title, TextComponentProducer contents) {
|
public MessageBox(String title, TextComponentProducer contents) {
|
||||||
checkNotNull(title);
|
checkNotNull(title);
|
||||||
|
|
||||||
int leftOver = GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - title.length() - 2;
|
append(centerAndBorder(TextComponent.of(title))).newline();
|
||||||
int leftSide = (int) Math.floor(leftOver * 1.0/3);
|
|
||||||
int rightSide = (int) Math.floor(leftOver * 2.0/3);
|
|
||||||
if (leftSide > 0) {
|
|
||||||
append(TextComponent.of(createBorder(leftSide), TextColor.YELLOW));
|
|
||||||
}
|
|
||||||
append(Component.space());
|
|
||||||
append(title);
|
|
||||||
append(Component.space());
|
|
||||||
if (rightSide > 0) {
|
|
||||||
append(TextComponent.of(createBorder(rightSide), TextColor.YELLOW));
|
|
||||||
}
|
|
||||||
newline();
|
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createBorder(int count) {
|
protected Component centerAndBorder(TextComponent text) {
|
||||||
StringBuilder builder = new StringBuilder();
|
TextComponentProducer line = new TextComponentProducer();
|
||||||
for (int i = 0; i < count; i++) {
|
int leftOver = GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - getLength(text);
|
||||||
builder.append("-");
|
int side = (int) Math.floor(leftOver / 2.0);
|
||||||
|
if (side > 0) {
|
||||||
|
if (side > 1) {
|
||||||
|
line.append(createBorder(side - 1));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
line.append(Component.space());
|
||||||
|
}
|
||||||
|
line.append(text);
|
||||||
|
if (side > 0) {
|
||||||
|
line.append(Component.space());
|
||||||
|
if (side > 1) {
|
||||||
|
line.append(createBorder(side - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getLength(TextComponent text) {
|
||||||
|
return text.content().length() + text.children().stream().filter(c -> c instanceof TextComponent)
|
||||||
|
.mapToInt(c -> getLength((TextComponent) c)).sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextComponent createBorder(int count) {
|
||||||
|
return TextComponent.of(Strings.repeat("-", count),
|
||||||
|
TextColor.YELLOW, Sets.newHashSet(TextDecoration.STRIKETHROUGH));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,14 +25,14 @@ import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
|||||||
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PaginationBox extends MessageBox {
|
public abstract class PaginationBox extends MessageBox {
|
||||||
|
|
||||||
public static final int IDEAL_ROWS_FOR_PLAYER = 8;
|
private static final int IDEAL_ROWS_FOR_PLAYER = 8;
|
||||||
|
|
||||||
private String pageCommand;
|
private String pageCommand;
|
||||||
private List<TextComponent> components;
|
|
||||||
private int componentsPerPage = IDEAL_ROWS_FOR_PLAYER;
|
private int componentsPerPage = IDEAL_ROWS_FOR_PLAYER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,30 +40,30 @@ public class PaginationBox extends MessageBox {
|
|||||||
*
|
*
|
||||||
* @param title The title
|
* @param title The title
|
||||||
*/
|
*/
|
||||||
public PaginationBox(String title) {
|
protected PaginationBox(String title) {
|
||||||
this(title, null);
|
this(title, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public abstract Component getComponent(int number);
|
||||||
* Sets the components to create pages for.
|
|
||||||
*
|
public abstract int getComponentsSize();
|
||||||
* @param components The components
|
|
||||||
*/
|
|
||||||
public void setComponents(List<TextComponent> components) {
|
|
||||||
this.components = components;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setComponentsPerPage(int componentsPerPage) {
|
public void setComponentsPerPage(int componentsPerPage) {
|
||||||
this.componentsPerPage = componentsPerPage;
|
this.componentsPerPage = componentsPerPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void formatForConsole() {
|
||||||
|
this.pageCommand = null;
|
||||||
|
this.componentsPerPage = 20;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Paginated component
|
* Creates a Paginated component
|
||||||
*
|
*
|
||||||
* @param title The title
|
* @param title The title
|
||||||
* @param pageCommand The command to run to switch page, with %page% representing page number
|
* @param pageCommand The command to run to switch page, with %page% representing page number
|
||||||
*/
|
*/
|
||||||
public PaginationBox(String title, String pageCommand) {
|
protected PaginationBox(String title, @Nullable String pageCommand) {
|
||||||
super(title, new TextComponentProducer());
|
super(title, new TextComponentProducer());
|
||||||
|
|
||||||
if (pageCommand != null && !pageCommand.contains("%page%")) {
|
if (pageCommand != null && !pageCommand.contains("%page%")) {
|
||||||
@ -72,48 +72,76 @@ public class PaginationBox extends MessageBox {
|
|||||||
this.pageCommand = pageCommand;
|
this.pageCommand = pageCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent create(int page) throws InvalidComponentException {
|
public Component create(int page) throws InvalidComponentException {
|
||||||
if (components == null) {
|
if (page == 1 && getComponentsSize() == 0) {
|
||||||
throw new IllegalStateException("You must provide components before creating.");
|
|
||||||
}
|
|
||||||
if (page == 1 && components.isEmpty()) {
|
|
||||||
return getContents().reset().append("There's nothing to see here").create();
|
return getContents().reset().append("There's nothing to see here").create();
|
||||||
}
|
}
|
||||||
int pageCount = (int) Math.ceil(components.size() / (double) componentsPerPage);
|
int pageCount = (int) Math.ceil(getComponentsSize() / (double) componentsPerPage);
|
||||||
if (page < 1 || page > pageCount) {
|
if (page < 1 || page > pageCount) {
|
||||||
throw new InvalidComponentException("Invalid page number.");
|
throw new InvalidComponentException("Invalid page number.");
|
||||||
}
|
}
|
||||||
getContents().reset();
|
final int lastComp = Math.min(page * componentsPerPage, getComponentsSize());
|
||||||
for (int i = (page - 1) * componentsPerPage; i < Math.min(page * componentsPerPage, components.size()); i++) {
|
for (int i = (page - 1) * componentsPerPage; i < lastComp; i++) {
|
||||||
getContents().append(components.get(i)).newline();
|
getContents().append(getComponent(i));
|
||||||
|
if (i + 1 != lastComp) {
|
||||||
|
getContents().newline();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (pageCount == 1) {
|
||||||
|
return super.create();
|
||||||
|
}
|
||||||
|
getContents().newline();
|
||||||
TextComponent pageNumberComponent = TextComponent.of("Page ", TextColor.YELLOW)
|
TextComponent pageNumberComponent = TextComponent.of("Page ", TextColor.YELLOW)
|
||||||
.append(TextComponent.of(String.valueOf(page), TextColor.GOLD))
|
.append(TextComponent.of(String.valueOf(page), TextColor.GOLD))
|
||||||
.append(TextComponent.of(" of "))
|
.append(TextComponent.of(" of "))
|
||||||
.append(TextComponent.of(String.valueOf(pageCount), TextColor.GOLD));
|
.append(TextComponent.of(String.valueOf(pageCount), TextColor.GOLD));
|
||||||
|
|
||||||
if (pageCommand != null) {
|
if (pageCommand != null) {
|
||||||
|
TextComponentProducer navProducer = new TextComponentProducer();
|
||||||
if (page > 1) {
|
if (page > 1) {
|
||||||
TextComponent prevComponent = TextComponent.of("<<< ", TextColor.GOLD)
|
TextComponent prevComponent = TextComponent.of("<<< ", TextColor.GOLD)
|
||||||
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page - 1))))
|
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page - 1))))
|
||||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate")));
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate")));
|
||||||
getContents().append(prevComponent);
|
navProducer.append(prevComponent);
|
||||||
}
|
}
|
||||||
getContents().append(pageNumberComponent);
|
navProducer.append(pageNumberComponent);
|
||||||
if (page < pageCount) {
|
if (page < pageCount) {
|
||||||
TextComponent nextComponent = TextComponent.of(" >>>", TextColor.GOLD)
|
TextComponent nextComponent = TextComponent.of(" >>>", TextColor.GOLD)
|
||||||
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page + 1))))
|
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page + 1))))
|
||||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate")));
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate")));
|
||||||
getContents().append(nextComponent);
|
navProducer.append(nextComponent);
|
||||||
}
|
}
|
||||||
|
getContents().append(centerAndBorder(navProducer.create()));
|
||||||
} else {
|
} else {
|
||||||
getContents().append(pageNumberComponent);
|
getContents().append(centerAndBorder(pageNumberComponent));
|
||||||
}
|
}
|
||||||
return TextComponent.of("").append(Component.newline()).append(super.create());
|
return super.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TextComponent create() {
|
public TextComponent create() {
|
||||||
throw new IllegalStateException("Pagination components must be created with a page");
|
throw new IllegalStateException("Pagination components must be created with a page");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PaginationBox fromStrings(String header, @Nullable String pageCommand, List<String> lines) {
|
||||||
|
return new ListPaginationBox(header, pageCommand, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ListPaginationBox extends PaginationBox {
|
||||||
|
private final List<String> lines;
|
||||||
|
|
||||||
|
ListPaginationBox(String header, String pageCommand, List<String> lines) {
|
||||||
|
super(header, pageCommand);
|
||||||
|
this.lines = lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getComponent(int number) {
|
||||||
|
return TextComponent.of(lines.get(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getComponentsSize() {
|
||||||
|
return lines.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.sk89q.worldedit.util.formatting.component;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
||||||
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
public class SchematicPaginationBox extends PaginationBox {
|
||||||
|
private final String prefix;
|
||||||
|
private final File[] files;
|
||||||
|
|
||||||
|
public SchematicPaginationBox(String rootDir, File[] files, String pageCommand) {
|
||||||
|
super("Available schematics", pageCommand);
|
||||||
|
this.prefix = rootDir == null ? "" : rootDir;
|
||||||
|
this.files = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getComponent(int number) {
|
||||||
|
checkArgument(number < files.length - 1 && number >= 0);
|
||||||
|
File file = files[number];
|
||||||
|
Multimap<String, ClipboardFormat> exts = ClipboardFormats.getFileExtensionMap();
|
||||||
|
String format = exts.get(Files.getFileExtension(file.getName()))
|
||||||
|
.stream().findFirst().map(ClipboardFormat::getName).orElse("Unknown");
|
||||||
|
boolean inRoot = file.getParentFile().getName().equals(prefix);
|
||||||
|
|
||||||
|
String path = inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1];
|
||||||
|
|
||||||
|
return TextComponent.builder()
|
||||||
|
.content("")
|
||||||
|
.append(TextComponent.of("[L]")
|
||||||
|
.color(TextColor.GOLD)
|
||||||
|
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + path))
|
||||||
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to load"))))
|
||||||
|
.append(Component.space())
|
||||||
|
.append(TextComponent.of(path)
|
||||||
|
.color(TextColor.DARK_GREEN)
|
||||||
|
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of(format))))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getComponentsSize() {
|
||||||
|
return files.length;
|
||||||
|
}
|
||||||
|
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren