diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index bf15a504a..b0c1ebd45 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -52,6 +52,7 @@ import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.snapshot.Snapshot; import javax.annotation.Nullable; +import java.time.ZoneId; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedList; @@ -91,7 +92,7 @@ public class LocalSession { private transient int cuiVersion = -1; private transient boolean fastMode = false; private transient Mask mask; - private transient TimeZone timezone = TimeZone.getDefault(); + private transient ZoneId timezone = ZoneId.systemDefault(); private transient BlockVector3 cuiTemporaryBlock; private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; @@ -169,7 +170,7 @@ public class LocalSession { * * @return the timezone */ - public TimeZone getTimeZone() { + public ZoneId getTimeZone() { return timezone; } @@ -178,7 +179,7 @@ public class LocalSession { * * @param timezone the user's timezone */ - public void setTimezone(TimeZone timezone) { + public void setTimezone(ZoneId timezone) { checkNotNull(timezone); this.timezone = timezone; } @@ -849,9 +850,10 @@ public class LocalSession { public Calendar detectDate(String input) { checkNotNull(input); - Time.setTimeZone(getTimeZone()); + TimeZone tz = TimeZone.getTimeZone(getTimeZone()); + Time.setTimeZone(tz); Options opt = new com.sk89q.jchronic.Options(); - opt.setNow(Calendar.getInstance(getTimeZone())); + opt.setNow(Calendar.getInstance(tz)); Span date = Chronic.parse(input, opt); if (date == null) { return null; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java index 1c4987734..643b064b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java @@ -21,32 +21,34 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException; import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.storage.MissingWorldException; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.File; import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; /** * Snapshot commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SnapshotCommands { - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); - + private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); + private final WorldEdit we; public SnapshotCommands(WorldEdit we) { @@ -54,14 +56,13 @@ public class SnapshotCommands { } @Command( - aliases = { "list" }, - usage = "[num]", - desc = "List snapshots", - min = 0, - max = 1 + name = "list", + desc = "List snapshots" ) @CommandPermissions("worldedit.snapshots.list") - public void list(Player player, CommandContext args) throws WorldEditException { + public void list(Player player, + @Arg(desc = "# of snapshots to list", def = "5") + int num) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -75,7 +76,7 @@ public class SnapshotCommands { if (!snapshots.isEmpty()) { - int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5; + num = Math.min(40, Math.max(5, num)); player.print("Snapshots for world: '" + player.getWorld().getName() + "'"); for (byte i = 0; i < Math.min(num, snapshots.size()); i++) { @@ -104,14 +105,13 @@ public class SnapshotCommands { } @Command( - aliases = { "use" }, - usage = "", - desc = "Choose a snapshot to use", - min = 1, - max = 1 + name = "use", + desc = "Choose a snapshot to use" ) @CommandPermissions("worldedit.snapshots.restore") - public void use(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void use(Player player, LocalSession session, + @Arg(desc = "Snapeshot to use") + String name) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -120,8 +120,6 @@ public class SnapshotCommands { return; } - String name = args.getString(0); - // Want the latest snapshot? if (name.equalsIgnoreCase("latest")) { try { @@ -147,14 +145,13 @@ public class SnapshotCommands { } @Command( - aliases = { "sel" }, - usage = "", - desc = "Choose the snapshot based on the list id", - min = 1, - max = 1 + name = "sel", + desc = "Choose the snapshot based on the list id" ) @CommandPermissions("worldedit.snapshots.restore") - public void sel(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void sel(Player player, LocalSession session, + @Arg(desc = "The list ID to select") + int index) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { @@ -162,14 +159,6 @@ public class SnapshotCommands { return; } - int index = -1; - try { - index = Integer.parseInt(args.getString(0)); - } catch (NumberFormatException e) { - player.printError("Invalid index, " + args.getString(0) + " is not a valid integer."); - return; - } - if (index < 1) { player.printError("Invalid index, must be equal or higher then 1."); return; @@ -194,14 +183,13 @@ public class SnapshotCommands { } @Command( - aliases = { "before" }, - usage = "", - desc = "Choose the nearest snapshot before a date", - min = 1, - max = -1 + name = "before", + desc = "Choose the nearest snapshot before a date" ) @CommandPermissions("worldedit.snapshots.restore") - public void before(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void before(Player player, LocalSession session, + @Arg(desc = "The soonest date that may be used") + ZonedDateTime date) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -210,37 +198,29 @@ public class SnapshotCommands { return; } - Calendar date = session.detectDate(args.getJoinedStrings(0)); + try { + Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName()); - if (date == null) { - player.printError("Could not detect the date inputted."); - } else { - try { - Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName()); - - if (snapshot == null) { - dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot before " - + dateFormat.format(date.getTime()) + "."); - } else { - session.setSnapshot(snapshot); - player.print("Snapshot set to: " + snapshot.getName()); - } - } catch (MissingWorldException ex) { - player.printError("No snapshots were found for this world."); + if (snapshot == null) { + player.printError("Couldn't find a snapshot before " + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); + } else { + session.setSnapshot(snapshot); + player.print("Snapshot set to: " + snapshot.getName()); } + } catch (MissingWorldException ex) { + player.printError("No snapshots were found for this world."); } } @Command( - aliases = { "after" }, - usage = "", - desc = "Choose the nearest snapshot after a date", - min = 1, - max = -1 + name = "after", + desc = "Choose the nearest snapshot after a date" ) @CommandPermissions("worldedit.snapshots.restore") - public void after(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void after(Player player, LocalSession session, + @Arg(desc = "The soonest date that may be used") + ZonedDateTime date) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -249,24 +229,17 @@ public class SnapshotCommands { return; } - Calendar date = session.detectDate(args.getJoinedStrings(0)); - - if (date == null) { - player.printError("Could not detect the date inputted."); - } else { - try { - Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); - if (snapshot == null) { - dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot after " - + dateFormat.format(date.getTime()) + "."); - } else { - session.setSnapshot(snapshot); - player.print("Snapshot set to: " + snapshot.getName()); - } - } catch (MissingWorldException ex) { - player.printError("No snapshots were found for this world."); + try { + Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); + if (snapshot == null) { + player.printError("Couldn't find a snapshot after " + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); + } else { + session.setSnapshot(snapshot); + player.print("Snapshot set to: " + snapshot.getName()); } + } catch (MissingWorldException ex) { + player.printError("No snapshots were found for this world."); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index b8d6c7f3f..14a90e2fe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -19,14 +19,13 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.regions.Region; @@ -36,12 +35,16 @@ import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.snapshot.SnapshotRestore; import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.MissingWorldException; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.File; import java.io.IOException; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SnapshotUtilCommands { private final WorldEdit we; @@ -51,15 +54,15 @@ public class SnapshotUtilCommands { } @Command( - aliases = { "restore", "/restore" }, - usage = "[snapshot]", - desc = "Restore the selection from a snapshot", - min = 0, - max = 1 + name = "restore", + aliases = { "/restore" }, + desc = "Restore the selection from a snapshot" ) @Logging(REGION) @CommandPermissions("worldedit.snapshots.restore") - public void restore(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { + public void restore(Player player, LocalSession session, EditSession editSession, + @Arg(name = "snapshot", desc = "The snapshot to restore", def = "") + String snapshotName) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -71,9 +74,9 @@ public class SnapshotUtilCommands { Region region = session.getSelection(player.getWorld()); Snapshot snapshot; - if (args.argsLength() > 0) { + if (snapshotName != null) { try { - snapshot = config.snapshotRepo.getSnapshot(args.getString(0)); + snapshot = config.snapshotRepo.getSnapshot(snapshotName); } catch (InvalidSnapshotException e) { player.printError("That snapshot does not exist or is not available."); return; @@ -110,7 +113,7 @@ public class SnapshotUtilCommands { } } - ChunkStore chunkStore = null; + ChunkStore chunkStore; // Load chunk store try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 787859323..5378d5819 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -40,16 +40,17 @@ import com.sk89q.worldedit.util.report.SystemInfoReport; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.TimeZone; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.util.Locale; public class WorldEditCommands { - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); - + private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); + private final WorldEdit we; - + public WorldEditCommands(WorldEdit we) { this.we = we; } @@ -138,11 +139,13 @@ public class WorldEditCommands { max = 1 ) public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { - TimeZone tz = TimeZone.getTimeZone(args.getString(0)); + ZoneId tz = ZoneId.of(args.getString(0)); session.setTimezone(tz); - player.print("Timezone set for this session to: " + tz.getDisplayName()); + player.print("Timezone set for this session to: " + tz.getDisplayName( + TextStyle.FULL, Locale.ENGLISH + )); player.print("The current time in that timezone is: " - + dateFormat.format(Calendar.getInstance(tz).getTime())); + + dateFormat.format(ZonedDateTime.now(tz))); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java new file mode 100644 index 000000000..5d96c28ab --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java @@ -0,0 +1,40 @@ +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.LocalSession; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Calendar; + +public class ZonedDateTimeConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(ZonedDateTime.class), new ZonedDateTimeConverter()); + } + + private ZonedDateTimeConverter() { + } + + @Override + public String describeAcceptableArguments() { + return "any date"; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + LocalSession session = context.injectedValue(Key.of(LocalSession.class)) + .orElseThrow(() -> new IllegalStateException("Need a local session")); + Calendar date = session.detectDate(argument); + if (date == null) { + return FailedConversion.from(new IllegalArgumentException("Not a date: " + argument)); + } + return SuccessfulConversion.fromSingle(date.toInstant().atZone(ZoneOffset.UTC)); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 037617ab3..795d8cddb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -50,6 +50,10 @@ import com.sk89q.worldedit.command.ScriptingCommands; import com.sk89q.worldedit.command.ScriptingCommandsRegistration; import com.sk89q.worldedit.command.SelectionCommands; import com.sk89q.worldedit.command.SelectionCommandsRegistration; +import com.sk89q.worldedit.command.SnapshotCommands; +import com.sk89q.worldedit.command.SnapshotCommandsRegistration; +import com.sk89q.worldedit.command.SnapshotUtilCommands; +import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; @@ -58,6 +62,7 @@ import com.sk89q.worldedit.command.argument.ExpandAmountConverter; import com.sk89q.worldedit.command.argument.MaskConverter; import com.sk89q.worldedit.command.argument.PatternConverter; import com.sk89q.worldedit.command.argument.VectorConverter; +import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; @@ -201,6 +206,7 @@ public final class PlatformCommandMananger { VectorConverter.register(commandManager); EnumConverter.register(commandManager); ExpandAmountConverter.register(commandManager); + ZonedDateTimeConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -250,6 +256,24 @@ public final class PlatformCommandMananger { .required() .build()); }); + commandManager.register("snapshot", cmd -> { + cmd.aliases(ImmutableList.of("snapshot", "snap")); + cmd.description("Snapshot commands for saving/loading snapshots"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + register( + manager, + SnapshotCommandsRegistration.builder(), + new SnapshotCommands(worldEdit) + ); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); + }); commandManager.register("brush", cmd -> { cmd.aliases(ImmutableList.of("br")); cmd.description("Brushing commands"); @@ -318,6 +342,11 @@ public final class PlatformCommandMananger { SelectionCommandsRegistration.builder(), new SelectionCommands(worldEdit) ); + register( + commandManager, + SnapshotUtilCommandsRegistration.builder(), + new SnapshotUtilCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* @@ -333,10 +362,6 @@ public final class PlatformCommandMananger { .describeAs("WorldEdit commands") .registerMethods(new WorldEditCommands(worldEdit)) .parent() - .group("snapshot", "snap") - .describeAs("Schematic commands for saving/loading areas") - .registerMethods(new SnapshotCommands(worldEdit)) - .parent() .group("brush", "br") .describeAs("Brushing commands") .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java index 0af2b6e18..e05ba9e60 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java @@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.Calendar; +import java.time.ZonedDateTime; import java.util.zip.ZipFile; /** @@ -46,7 +46,7 @@ public class Snapshot implements Comparable { protected File file; protected String name; - protected Calendar date; + protected ZonedDateTime date; /** * Construct a snapshot restoration operation. @@ -185,7 +185,7 @@ public class Snapshot implements Comparable { * * @return date for the snapshot */ - public Calendar getDate() { + public ZonedDateTime getDate() { return date; } @@ -194,7 +194,7 @@ public class Snapshot implements Comparable { * * @param date the date of the snapshot */ - public void setDate(Calendar date) { + public void setDate(ZonedDateTime date) { this.date = date; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java index 72650a408..1838c2747 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java @@ -23,15 +23,16 @@ package com.sk89q.worldedit.world.snapshot; import com.sk89q.worldedit.world.storage.MissingWorldException; +import javax.annotation.Nullable; import java.io.File; import java.io.FilenameFilter; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; -import javax.annotation.Nullable; - /** * A repository contains zero or more snapshots. */ @@ -115,12 +116,12 @@ public class SnapshotRepository { * @return a snapshot or null */ @Nullable - public Snapshot getSnapshotAfter(Calendar date, String world) throws MissingWorldException { + public Snapshot getSnapshotAfter(ZonedDateTime date, String world) throws MissingWorldException { List snapshots = getSnapshots(true, world); Snapshot last = null; for (Snapshot snapshot : snapshots) { - if (snapshot.getDate() != null && snapshot.getDate().before(date)) { + if (snapshot.getDate() != null && snapshot.getDate().compareTo(date) < 0) { return last; } @@ -137,12 +138,12 @@ public class SnapshotRepository { * @return a snapshot or null */ @Nullable - public Snapshot getSnapshotBefore(Calendar date, String world) throws MissingWorldException { + public Snapshot getSnapshotBefore(ZonedDateTime date, String world) throws MissingWorldException { List snapshots = getSnapshots(false, world); Snapshot last = null; for (Snapshot snapshot : snapshots) { - if (snapshot.getDate().after(date)) { + if (snapshot.getDate().compareTo(date) > 0) { return last; } @@ -161,7 +162,7 @@ public class SnapshotRepository { for (SnapshotDateParser parser : dateParsers) { Calendar date = parser.detectDate(snapshot.getFile()); if (date != null) { - snapshot.setDate(date); + snapshot.setDate(date.toInstant().atZone(ZoneOffset.UTC)); return; } }