From c3b0fda0171d9a5509f7c4585309d65ac92fc6ca Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Fri, 9 Nov 2018 21:05:08 +0100 Subject: [PATCH] Improve worldeditor row ordering --- .../de/diddiz/LogBlock/CommandsHandler.java | 12 +++- .../java/de/diddiz/LogBlock/WorldEditor.java | 66 +++++++++++++++++-- .../LogBlock/WorldEditorEditFactory.java | 4 +- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index 0986f2c..734edd2 100755 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -671,11 +671,11 @@ public class CommandsHandler implements CommandExecutor { sender.sendMessage(ChatColor.RED + "Cannot rollback summarized changes"); return; } + params.needDate = true; params.needCoords = true; params.needType = true; params.needData = true; params.needChestAccess = true; - params.order = Order.DESC; params.sum = SummarizationMode.NONE; conn = logblock.getConnection(); if (conn == null) { @@ -695,6 +695,10 @@ public class CommandsHandler implements CommandExecutor { while (rs.next()) { editFactory.processRow(rs); } + if (params.order == Order.DESC) { + editor.reverseRowOrder(); + } + editor.sortRows(Order.DESC); final int changes = editor.getSize(); if (changes > 10000) { editor.setSender(sender); @@ -757,11 +761,11 @@ public class CommandsHandler implements CommandExecutor { sender.sendMessage(ChatColor.RED + "Cannot redo summarized changes"); return; } + params.needDate = true; params.needCoords = true; params.needType = true; params.needData = true; params.needChestAccess = true; - params.order = Order.ASC; params.sum = SummarizationMode.NONE; conn = logblock.getConnection(); if (conn == null) { @@ -781,6 +785,10 @@ public class CommandsHandler implements CommandExecutor { while (rs.next()) { editFactory.processRow(rs); } + if (params.order == Order.ASC) { + editor.reverseRowOrder(); + } + editor.sortRows(Order.ASC); final int changes = editor.getSize(); if (!params.silent) { sender.sendMessage(ChatColor.GREEN.toString() + changes + " " + (params.bct == BlockChangeType.ENTITIES ? "entities" : "blocks") + " found."); diff --git a/src/main/java/de/diddiz/LogBlock/WorldEditor.java b/src/main/java/de/diddiz/LogBlock/WorldEditor.java index c4f621b..b54b401 100644 --- a/src/main/java/de/diddiz/LogBlock/WorldEditor.java +++ b/src/main/java/de/diddiz/LogBlock/WorldEditor.java @@ -25,6 +25,7 @@ import org.bukkit.entity.ItemFrame; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import de.diddiz.LogBlock.QueryParams.Order; import de.diddiz.LogBlock.blockstate.BlockStateCodecs; import de.diddiz.util.BukkitUtils; import de.diddiz.util.Utils; @@ -36,11 +37,11 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; -import java.util.Queue; import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import static de.diddiz.LogBlock.config.Config.dontRollback; @@ -49,7 +50,7 @@ import static de.diddiz.util.BukkitUtils.*; public class WorldEditor implements Runnable { private final LogBlock logblock; - private final Queue edits = new LinkedBlockingQueue(); + private final ArrayList edits = new ArrayList<>(); private final World world; /** @@ -62,6 +63,7 @@ public class WorldEditor implements Runnable { public LookupCacheElement[] errors; private boolean forceReplace; private HashMap uuidReplacements = new HashMap<>(); + private boolean started = false; public WorldEditor(LogBlock logblock, World world) { this(logblock, world, false); @@ -94,19 +96,43 @@ public class WorldEditor implements Runnable { this.sender = sender; } - public void queueBlockEdit(int x, int y, int z, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess item) { - edits.add(new BlockEdit(0, new Location(world, x, y, z), null, replaced, replaceData, replacedState, type, typeData, typeState, item)); + public void queueBlockEdit(long time, int x, int y, int z, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess item) { + if (started) { + throw new IllegalStateException("Already started"); + } + edits.add(new BlockEdit(time, new Location(world, x, y, z), null, replaced, replaceData, replacedState, type, typeData, typeState, item)); } public void queueEntityEdit(ResultSet rs, QueryParams p, boolean rollback) throws SQLException { + if (started) { + throw new IllegalStateException("Already started"); + } edits.add(new EntityEdit(rs, p, rollback)); } + public void reverseRowOrder() { + if (started) { + throw new IllegalStateException("Already started"); + } + Collections.reverse(edits); + } + + public void sortRows(QueryParams.Order order) { + if (started) { + throw new IllegalStateException("Already started"); + } + edits.sort(new EditComparator(order)); + } + public long getElapsedTime() { return elapsedTime; } synchronized public void start() throws Exception { + if (started) { + throw new IllegalStateException("Already started"); + } + started = true; final long start = System.currentTimeMillis(); taskID = logblock.getServer().getScheduler().scheduleSyncRepeatingTask(logblock, this, 0, 1); if (taskID == -1) { @@ -127,7 +153,7 @@ public class WorldEditor implements Runnable { float size = edits.size(); while (!edits.isEmpty() && counter < 100) { try { - switch (edits.poll().perform()) { + switch (edits.remove(edits.size() - 1).perform()) { case SUCCESS: successes++; break; @@ -181,6 +207,8 @@ public class WorldEditor implements Runnable { public interface Edit { PerformResult perform() throws WorldEditorException; + + public long getTime(); } public class EntityEdit extends EntityChange implements Edit { @@ -191,6 +219,11 @@ public class WorldEditor implements Runnable { this.rollback = rollback; } + @Override + public long getTime() { + return date; + } + @Override public PerformResult perform() throws WorldEditorException { if (changeType == (rollback ? EntityChangeType.KILL : EntityChangeType.CREATE)) { @@ -292,7 +325,12 @@ public class WorldEditor implements Runnable { public class BlockEdit extends BlockChange implements Edit { public BlockEdit(long time, Location loc, Actor actor, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess ca) { - super(time, loc, actor, replaced, replaceData,replacedState , type, typeData, typeState, ca); + super(time, loc, actor, replaced, replaceData, replacedState, type, typeData, typeState, ca); + } + + @Override + public long getTime() { + return date; } public PerformResult perform() throws WorldEditorException { @@ -400,6 +438,20 @@ public class WorldEditor implements Runnable { } } + public static class EditComparator implements Comparator { + private final int mult; + public EditComparator(QueryParams.Order order) { + mult = order == Order.DESC ? 1 : -1; + } + + @Override + public int compare(Edit edit1, Edit edit2) { + long time1 = edit1.getTime(); + long time2 = edit2.getTime(); + return time1 > time2 ? mult : time1 < time2 ? -mult : 0; + } + } + @SuppressWarnings("serial") public static class WorldEditorException extends Exception implements LookupCacheElement { private final Location loc; diff --git a/src/main/java/de/diddiz/LogBlock/WorldEditorEditFactory.java b/src/main/java/de/diddiz/LogBlock/WorldEditorEditFactory.java index e23dc6b..80728cc 100644 --- a/src/main/java/de/diddiz/LogBlock/WorldEditorEditFactory.java +++ b/src/main/java/de/diddiz/LogBlock/WorldEditorEditFactory.java @@ -30,9 +30,9 @@ public class WorldEditorEditFactory { chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove") == rollback, rs.getInt("itemtype")); } if (rollback) { - editor.queueBlockEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), chestaccess); + editor.queueBlockEdit(rs.getTimestamp("date").getTime(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), chestaccess); } else { - editor.queueBlockEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), chestaccess); + editor.queueBlockEdit(rs.getTimestamp("date").getTime(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), chestaccess); } } }