package com.forgeessentials.playerlogger.command; import java.util.HashMap; import java.util.Map; import java.util.Timer; import java.util.UUID; import net.minecraft.command.ICommandSender; import net.minecraftforge.permission.PermissionLevel; import com.forgeessentials.api.permissions.Zone; import com.forgeessentials.commons.selections.Selection; import com.forgeessentials.core.FEConfig; import com.forgeessentials.core.commands.ParserCommandBase; import com.forgeessentials.core.misc.TranslatedCommandException; import com.forgeessentials.playerlogger.ModulePlayerLogger; import com.forgeessentials.util.CommandParserArgs; import com.forgeessentials.util.output.ChatOutputHandler; import com.forgeessentials.util.selections.SelectionHandler; public class CommandRollback extends ParserCommandBase { public static final String PERM = ModulePlayerLogger.PERM_COMMAND + ".rollback"; public static final String PERM_ALL = PERM + Zone.ALL_PERMS; public static final String PERM_PREVIEW = PERM + ".preview"; private static final String[] subCommands = { "help", "start", "cancel", "confirm", "play", "+", "-" }; private Map<UUID, RollbackInfo> rollbacks = new HashMap<>(); private Timer playbackTimer = new Timer(); @Override public String getCommandName() { return "rollback"; } @Override public String[] getDefaultAliases() { return new String[] { "rb" }; } @Override public String getCommandUsage(ICommandSender sender) { return "/zone: Displays command help"; } @Override public String getPermissionNode() { return PERM; } @Override public PermissionLevel getPermissionLevel() { return PermissionLevel.OP; } @Override public boolean canConsoleUseCommand() { return false; } @Override public void parse(CommandParserArgs args) { if (args.isEmpty()) { startRollback(args); return; } args.tabComplete(subCommands); String arg = args.remove().toLowerCase(); switch (arg) { case "help": help(args.sender); break; case "start": startRollback(args); break; case "cancel": cancelRollback(args); break; case "confirm": confirmRollback(args); break; case "+": stepRollback(args, true); break; case "-": stepRollback(args, false); break; case "play": playRollback(args); break; case "stop": stopRollback(args); break; default: throw new TranslatedCommandException("Unknown subcommand"); } } private void startRollback(CommandParserArgs args) { args.checkPermission(PERM_PREVIEW); if (args.isTabCompletion) return; if (rollbacks.containsKey(args.senderPlayer.getPersistentID())) cancelRollback(args); Selection area = SelectionHandler.selectionProvider.getSelection(args.senderPlayer); if (area == null) throw new TranslatedCommandException("No selection available. Please select a region first."); RollbackInfo rb = new RollbackInfo(args.senderPlayer, area); rollbacks.put(args.senderPlayer.getPersistentID(), rb); rb.stepBackward(); rb.previewChanges(); ChatOutputHandler.chatConfirmation(args.sender, "Showing changes since " + FEConfig.FORMAT_DATE_TIME_SECONDS.format(rb.getTime())); } private void stepRollback(CommandParserArgs args, boolean backward) { args.checkPermission(PERM_PREVIEW); if (args.isTabCompletion) return; RollbackInfo rb = rollbacks.get(args.senderPlayer.getPersistentID()); if (rb == null) throw new TranslatedCommandException("No rollback in progress. Start with /rollback first."); if (backward) rb.stepBackward(); else rb.stepForward(); rb.previewChanges(); ChatOutputHandler.chatConfirmation(args.sender, "Showing changes since " + FEConfig.FORMAT_DATE_TIME_SECONDS.format(rb.getTime())); } private void confirmRollback(CommandParserArgs args) { args.checkPermission(PERM); if (args.isTabCompletion) return; RollbackInfo rb = rollbacks.remove(args.senderPlayer.getPersistentID()); if (rb == null) throw new TranslatedCommandException("No rollback in progress. Start with /rollback first."); rb.confirm(); ChatOutputHandler.chatConfirmation(args.sender, "Successfully restored changes"); } private void cancelRollback(CommandParserArgs args) { RollbackInfo rb = rollbacks.remove(args.senderPlayer.getPersistentID()); if (rb == null) throw new TranslatedCommandException("No rollback in progress."); rb.cancel(); ChatOutputHandler.chatConfirmation(args.sender, "Cancelled active rollback"); } private void playRollback(CommandParserArgs args) { args.checkPermission(PERM_PREVIEW); int speed = 1; if (!args.isEmpty()) speed = parseInt(args.sender, args.remove()); if (speed < 0) speed = 1; if (args.isTabCompletion) return; RollbackInfo rb = rollbacks.get(args.senderPlayer.getPersistentID()); if (rb == null) throw new TranslatedCommandException("No rollback in progress. Start with /rollback first."); if (rb.task != null) { rb.task.cancel(); rb.task = null; ChatOutputHandler.chatConfirmation(args.sender, "Stopped playback"); } else { rb.task = new RollbackInfo.PlaybackTask(rb, 1); playbackTimer.schedule(rb.task, 1000, 1000 / speed); ChatOutputHandler.chatConfirmation(args.sender, "Started playback"); } } private void stopRollback(CommandParserArgs args) { args.checkPermission(PERM_PREVIEW); int speed = 1; if (!args.isEmpty()) speed = parseInt(args.sender, args.remove()); if (speed < 0) speed = 1; if (args.isTabCompletion) return; RollbackInfo rb = rollbacks.get(args.senderPlayer.getPersistentID()); if (rb == null) throw new TranslatedCommandException("No rollback in progress. Start with /rollback first."); if (rb.task == null) throw new TranslatedCommandException("No playback running"); rb.task.cancel(); rb.task = null; ChatOutputHandler.chatConfirmation(args.sender, "Stopped playback"); } private static void help(ICommandSender sender) { ChatOutputHandler.chatConfirmation(sender, "/rollback [minutes]: Start rollback"); ChatOutputHandler.chatConfirmation(sender, "/rollback + [min] [sec]: Go back in time"); ChatOutputHandler.chatConfirmation(sender, "/rollback - [min] [sec]: Go forward in time"); ChatOutputHandler.chatConfirmation(sender, "/rollback confirm: Confirm changes"); ChatOutputHandler.chatConfirmation(sender, "/rollback cancel: Cancel rollback"); } }