From 195c4a76472a7cfe09accdf813b53a3265a654e8 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 6 Jan 2020 08:36:16 +0000 Subject: [PATCH] wip history changes --- .../src/main/java/SimpleChangeSetSummary.java | 59 +++++ .../main/java/com/boydti/fawe/FaweAPI.java | 2 +- .../ExtentBatchProcessorHolder.java | 6 +- .../processors/LimitExtent.java | 4 - .../queue/ParallelQueueExtent.java | 5 +- .../boydti/fawe/logging/LoggingChangeSet.java | 6 +- .../rollback/RollbackOptimizedHistory.java | 7 +- .../com/boydti/fawe/object/HistoryExtent.java | 10 +- .../com/boydti/fawe/object/NullChangeSet.java | 4 +- .../fawe/object/brush/InspectBrush.java | 8 + .../changeset/AbstractDelegateChangeSet.java | 9 +- .../object/changeset/BlockBagChangeSet.java | 3 +- .../fawe/object/changeset/CFIChangeSet.java | 2 +- .../object/changeset/DiskStorageHistory.java | 91 +------- .../object/changeset/FaweStreamChangeSet.java | 2 +- .../fawe/object/collection/YieldIterable.java | 2 + .../boydti/fawe/util/EditSessionBuilder.java | 10 +- .../java/com/boydti/fawe/util/StringMan.java | 11 + .../java/com/sk89q/worldedit/EditSession.java | 16 +- .../com/sk89q/worldedit/LocalSession.java | 53 +++-- .../worldedit/command/HistorySubCommands.java | 221 ++++++++++-------- .../worldedit/command/SelectionCommands.java | 39 ++-- .../extent/AbstractDelegateExtent.java | 5 +- .../com/sk89q/worldedit/extent/Extent.java | 5 +- .../worldedit/extent/PassthroughExtent.java | 5 +- .../transform/BlockTransformExtent.java | 23 +- .../function/operation/ChangeSetExecutor.java | 7 +- .../history/changeset/ChangeSet.java | 43 +++- .../history/changeset/ChangeSetSummary.java | 37 +++ .../util/concurrency/LazyReference.java | 1 - .../formatting/component/PaginationBox.java | 30 +++ .../src/main/resources/lang/strings.json | 3 +- 32 files changed, 442 insertions(+), 287 deletions(-) create mode 100644 worldedit-core/src/main/java/SimpleChangeSetSummary.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSetSummary.java diff --git a/worldedit-core/src/main/java/SimpleChangeSetSummary.java b/worldedit-core/src/main/java/SimpleChangeSetSummary.java new file mode 100644 index 000000000..a60476355 --- /dev/null +++ b/worldedit-core/src/main/java/SimpleChangeSetSummary.java @@ -0,0 +1,59 @@ +import com.sk89q.worldedit.history.changeset.ChangeSetSummary; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; + +import java.util.HashMap; +import java.util.Map; + +public class SimpleChangeSetSummary implements ChangeSetSummary { + public int[] blocks; + + public int minX; + public int minZ; + + public int maxX; + public int maxZ; + + public SimpleChangeSetSummary(int x, int z) { + blocks = new int[BlockTypesCache.states.length]; + minX = x; + maxX = x; + minZ = z; + maxZ = z; + } + + public void add(int x, int z, int id) { + blocks[id]++; + if (x < minX) { + minX = x; + } else if (x > maxX) { + maxX = x; + } + if (z < minZ) { + minZ = z; + } else if (z > maxZ) { + maxZ = z; + } + } + + @Override + public Map getBlocks() { + HashMap map = new HashMap<>(); + for (int i = 0; i < blocks.length; i++) { + if (blocks[i] != 0) { + BlockState state = BlockTypesCache.states[i]; + map.put(state, blocks[i]); + } + } + return map; + } + + @Override + public int getSize() { + int count = 0; + for (int block : blocks) { + count += block; + } + return count; + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java b/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java index 0855f47ae..71222399c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -343,7 +343,7 @@ public class FaweAPI { for (File file : files) { UUID uuid = UUID.fromString(file.getParentFile().getName()); DiskStorageHistory dsh = new DiskStorageHistory(world, uuid, Integer.parseInt(file.getName().split("\\.")[0])); - DiskStorageHistory.DiskStorageSummary summary = dsh.summarize(boundsPlus, shallow); + SimpleChangeSetSummary summary = dsh.summarize(boundsPlus, shallow); RegionWrapper region = new RegionWrapper(summary.minX, summary.maxX, summary.minZ, summary.maxZ); boolean encompassed = false; boolean isIn = false; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ExtentBatchProcessorHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ExtentBatchProcessorHolder.java index 014ecc884..870035c2c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ExtentBatchProcessorHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ExtentBatchProcessorHolder.java @@ -1,7 +1,7 @@ package com.boydti.fawe.beta.implementation.processors; import com.boydti.fawe.beta.IBatchProcessor; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.worldedit.extent.Extent; public abstract class ExtentBatchProcessorHolder extends BatchProcessorHolder implements Extent { @@ -12,13 +12,13 @@ public abstract class ExtentBatchProcessorHolder extends BatchProcessorHolder im } @Override - public Extent enableHistory(FaweChangeSet changeSet) { + public Extent enableHistory(AbstractChangeSet changeSet) { return this.addProcessor(changeSet); } @Override public Extent disableHistory() { - this.remove(FaweChangeSet.class); + this.remove(AbstractChangeSet.class); return this; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/LimitExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/LimitExtent.java index 8e17bc57f..44ff0c59a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/LimitExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/LimitExtent.java @@ -2,10 +2,8 @@ package com.boydti.fawe.beta.implementation.processors; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.Filter; -import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.beta.implementation.filter.block.ExtentFilterBlock; import com.boydti.fawe.object.FaweLimit; -import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.exception.FaweException; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.MaxChangedBlocksException; @@ -14,11 +12,9 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.PassthroughExtent; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.function.generator.GenBase; import com.sk89q.worldedit.function.generator.Resource; import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java index 3ede7890b..07c022d0d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java @@ -9,13 +9,12 @@ import com.boydti.fawe.beta.implementation.filter.CountFilter; import com.boydti.fawe.beta.implementation.filter.DistrFilter; import com.boydti.fawe.beta.implementation.processors.BatchProcessorHolder; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.clipboard.WorldCopyClipboard; import com.boydti.fawe.object.extent.NullExtent; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.PassthroughExtent; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; @@ -79,7 +78,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap } @Override - public Extent enableHistory(FaweChangeSet changeSet) { + public Extent enableHistory(AbstractChangeSet changeSet) { return super.enableHistory(changeSet); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/logging/LoggingChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/logging/LoggingChangeSet.java index 0dcd94ded..bbd71dae8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/logging/LoggingChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/logging/LoggingChangeSet.java @@ -1,7 +1,7 @@ package com.boydti.fawe.logging; import com.boydti.fawe.object.changeset.AbstractDelegateChangeSet; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.worldedit.entity.Player; //import org.primesoft.blockshub.IBlocksHubApi; //import org.primesoft.blockshub.api.IPlayer; @@ -11,7 +11,7 @@ public class LoggingChangeSet extends AbstractDelegateChangeSet { private static boolean initialized = false; - public static FaweChangeSet wrap(Player player, FaweChangeSet parent) { + public static AbstractChangeSet wrap(Player player, AbstractChangeSet parent) { if (!initialized) { initialized = true; // api = (IBlocksHubApi) Fawe.imp().getBlocksHubApi(); @@ -30,7 +30,7 @@ public class LoggingChangeSet extends AbstractDelegateChangeSet { // private final MutableBlockData oldBlock; // private final MutableBlockData newBlock; - private LoggingChangeSet(Player player, FaweChangeSet parent) { + private LoggingChangeSet(Player player, AbstractChangeSet parent) { super(parent); // String world = player.getLocation().world; // try { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/logging/rollback/RollbackOptimizedHistory.java b/worldedit-core/src/main/java/com/boydti/fawe/logging/rollback/RollbackOptimizedHistory.java index 8eba876ef..463a60d1f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/logging/rollback/RollbackOptimizedHistory.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/logging/rollback/RollbackOptimizedHistory.java @@ -1,10 +1,8 @@ package com.boydti.fawe.logging.rollback; -import com.boydti.fawe.Fawe; import com.boydti.fawe.database.DBHandler; import com.boydti.fawe.database.RollbackDatabase; import com.boydti.fawe.object.changeset.DiskStorageHistory; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.World; @@ -55,6 +53,7 @@ public class RollbackOptimizedHistory extends DiskStorageHistory { this.blockSize = (int) size; this.command = command; this.closed = true; + System.out.println("Size " + size); } public long getTime() { @@ -62,8 +61,8 @@ public class RollbackOptimizedHistory extends DiskStorageHistory { } @Override - protected DiskStorageSummary summarizeShallow() { - DiskStorageSummary summary = super.summarizeShallow(); + protected SimpleChangeSetSummary summarizeShallow() { + SimpleChangeSetSummary summary = super.summarizeShallow(); summary.minX = this.minX; summary.minZ = this.minZ; summary.maxX = this.maxX; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index 48dbde699..e6ae99514 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -2,7 +2,7 @@ package com.boydti.fawe.object; import static com.google.common.base.Preconditions.checkNotNull; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -25,7 +25,7 @@ import javax.annotation.Nullable; */ public class HistoryExtent extends AbstractDelegateExtent { - private FaweChangeSet changeSet; + private AbstractChangeSet changeSet; /** * Create a new instance. @@ -33,18 +33,18 @@ public class HistoryExtent extends AbstractDelegateExtent { * @param extent the extent * @param changeSet the change set */ - public HistoryExtent(Extent extent, FaweChangeSet changeSet) { + public HistoryExtent(Extent extent, AbstractChangeSet changeSet) { super(extent); checkNotNull(changeSet); this.changeSet = changeSet; } - public FaweChangeSet getChangeSet() { + public AbstractChangeSet getChangeSet() { return changeSet; } @Override - public void setChangeSet(FaweChangeSet fcs) { + public void setChangeSet(AbstractChangeSet fcs) { this.changeSet = fcs; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java index 08316f554..1a8d166ec 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/NullChangeSet.java @@ -1,6 +1,6 @@ package com.boydti.fawe.object; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; @@ -9,7 +9,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import java.util.ArrayList; import java.util.Iterator; -public class NullChangeSet extends FaweChangeSet { +public class NullChangeSet extends AbstractChangeSet { public NullChangeSet(World world) { super(world); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java index 31d101335..a31a3c543 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java @@ -63,10 +63,12 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool { public boolean perform(final Player player, LocalSession session, boolean rightClick) { if (!session.isToolControlEnabled() || !player.hasPermission("worldedit.tool.inspect")) { player.print(Caption.of("", "worldedit.tool.inspect")); + System.out.println("No tool control"); return false; } if (!Settings.IMP.HISTORY.USE_DATABASE) { player.print(Caption.of("fawe.error.setting.disable", ("history.use-database (Import with /history import )"))); + System.out.println("No db"); return false; } try { @@ -76,14 +78,17 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool { final int z = target.getBlockZ(); World world = player.getWorld(); RollbackDatabase db = DBHandler.IMP.getDatabase(world); + System.out.println("World " + world.getName()); int count = 0; for (Supplier supplier : db.getEdits(target, false)) { + System.out.println("History " + db); count++; RollbackOptimizedHistory edit = supplier.get(); Iterator iter = edit.getFullBlockIterator(null, 0, false); while (iter.hasNext()) { MutableFullBlockChange change = iter.next(); if (change.x != x || change.y != y || change.z != z) { + System.out.println("Not pos " + change.x + "," + change.y + "," + change.z + " | " + x + "," + y + "," + z); continue; } int from = change.from; @@ -107,7 +112,10 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool { } player.print(Caption.of("fawe.worldedit.tool.tool.inspect.info.footer" , count)); } catch (IOException e) { + System.out.println("IOE"); throw new RuntimeException(e); + } catch (Throwable e) { + System.out.println("E throw"); } return true; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java index dbbfe64c2..c59c1d5c9 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java @@ -16,13 +16,12 @@ import com.sk89q.worldedit.world.block.BaseBlock; import java.io.IOException; import java.util.Iterator; -import java.util.UUID; import java.util.concurrent.Future; -public class AbstractDelegateChangeSet extends FaweChangeSet { - public final FaweChangeSet parent; +public class AbstractDelegateChangeSet extends AbstractChangeSet { + public final AbstractChangeSet parent; - public AbstractDelegateChangeSet(FaweChangeSet parent) { + public AbstractDelegateChangeSet(AbstractChangeSet parent) { super(parent.getWorld()); this.parent = parent; this.waitingCombined = parent.waitingCombined; @@ -44,7 +43,7 @@ public class AbstractDelegateChangeSet extends FaweChangeSet { parent.close(); } - public final FaweChangeSet getParent() { + public final AbstractChangeSet getParent() { return parent; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/BlockBagChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/BlockBagChangeSet.java index ab156bb0b..f92ad4fb9 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/BlockBagChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/BlockBagChangeSet.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.changeset; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; @@ -24,7 +23,7 @@ public class BlockBagChangeSet extends AbstractDelegateChangeSet { private int[] missingBlocks = new int[BlockTypes.size()]; private BlockBag blockBag; - public BlockBagChangeSet(FaweChangeSet parent, BlockBag blockBag, boolean mine) { + public BlockBagChangeSet(AbstractChangeSet parent, BlockBag blockBag, boolean mine) { super(parent); this.blockBag = blockBag; this.mine = mine; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java index cc71a6930..be8cecfcc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java @@ -14,7 +14,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.UUID; -public class CFIChangeSet extends FaweChangeSet { +public class CFIChangeSet extends AbstractChangeSet { private final File file; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java index 08fba0991..40330a4af 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java @@ -7,30 +7,20 @@ import com.boydti.fawe.database.RollbackDatabase; import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.IntegerPair; -import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.change.MutableFullBlockChange; import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.UUID; /** @@ -405,15 +395,15 @@ public class DiskStorageHistory extends FaweStreamChangeSet { return new NBTInputStream(MainUtil.getCompressedIS(new FileInputStream(nbtfFile))); } - protected DiskStorageSummary summarizeShallow() { - return new DiskStorageSummary(getOriginX(), getOriginZ()); + protected SimpleChangeSetSummary summarizeShallow() { + return new SimpleChangeSetSummary(getOriginX(), getOriginZ()); } - public DiskStorageSummary summarize(Region region, boolean shallow) { + public SimpleChangeSetSummary summarize(Region region, boolean shallow) { if (bdFile.exists()) { int ox = getOriginX(); int oz = getOriginZ(); - DiskStorageSummary summary = summarizeShallow(); + SimpleChangeSetSummary summary = summarizeShallow(); if (region != null && !region.contains(ox, oz)) { return summary; } @@ -459,79 +449,6 @@ public class DiskStorageHistory extends FaweStreamChangeSet { return new IntegerPair(ox, oz); } - public static class DiskStorageSummary { - - public int[] blocks; - - public int minX; - public int minZ; - - public int maxX; - public int maxZ; - - public DiskStorageSummary(int x, int z) { - blocks = new int[BlockTypesCache.states.length]; - minX = x; - maxX = x; - minZ = z; - maxZ = z; - } - - public void add(int x, int z, int id) { - blocks[id]++; - if (x < minX) { - minX = x; - } else if (x > maxX) { - maxX = x; - } - if (z < minZ) { - minZ = z; - } else if (z > maxZ) { - maxZ = z; - } - } - - public Map getBlocks() { - HashMap map = new HashMap<>(); - for (int i = 0; i < blocks.length; i++) { - if (blocks[i] != 0) { - BlockState state = BlockTypesCache.states[i]; - map.put(state, blocks[i]); - } - } - return map; - } - - public List> getBlockDistributionWithData() { - ArrayList> list = new ArrayList<>(); - for (Map.Entry entry : getBlocks().entrySet()) { - list.add(new Countable<>(entry.getKey(), entry.getValue())); - } - return list; - } - - public Map getPercents() { - Map map = getBlocks(); - int count = getSize(); - Map newMap = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { - BlockState id = entry.getKey(); - int changes = entry.getValue(); - double percent = (changes * 1000L / count) / 10d; - newMap.put(id, percent); - } - return newMap; - } - - public int getSize() { - int count = 0; - for (int block : blocks) { - count += block; - } - return count; - } - } - @Override public boolean isRecordingChanges() { // TODO Auto-generated method stub diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java index c6ccbc9ce..406e7c364 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java @@ -27,7 +27,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; -public abstract class FaweStreamChangeSet extends FaweChangeSet { +public abstract class FaweStreamChangeSet extends AbstractChangeSet { public static final int HEADER_SIZE = 9; private int mode; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/YieldIterable.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/YieldIterable.java index 4525da464..83025877e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/YieldIterable.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/YieldIterable.java @@ -40,11 +40,13 @@ public class YieldIterable implements Iterable, Consumer, Closeable { buffer = queue.poll(50, TimeUnit.MILLISECONDS); if (buffer == END_MARKER) { interrupted = true; + buffer = null; return false; } } } catch (InterruptedException e) { interrupted = true; + buffer = null; } return buffer != null; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index b439793a7..c2ba56de5 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -21,7 +21,7 @@ import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.changeset.BlockBagChangeSet; import com.boydti.fawe.object.changeset.DiskStorageHistory; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.extent.FaweRegionExtent; import com.boydti.fawe.object.extent.MultiRegionExtent; @@ -49,7 +49,7 @@ public class EditSessionBuilder { private String worldName; private Player player; private FaweLimit limit; - private FaweChangeSet changeSet; + private AbstractChangeSet changeSet; private Region[] allowedRegions; private Boolean autoQueue; private Boolean fastmode; @@ -116,7 +116,7 @@ public class EditSessionBuilder { return setDirty(); } - public EditSessionBuilder changeSet(@Nullable FaweChangeSet changeSet) { + public EditSessionBuilder changeSet(@Nullable AbstractChangeSet changeSet) { this.changeSet = changeSet; return setDirty(); } @@ -265,7 +265,7 @@ public class EditSessionBuilder { return extent; } - private FaweChangeSet changeTask; + private AbstractChangeSet changeTask; private int maxY; private Extent bypassHistory; private Extent bypassAll; @@ -493,7 +493,7 @@ public class EditSessionBuilder { return player; } - public FaweChangeSet getChangeTask() { + public AbstractChangeSet getChangeTask() { return changeTask; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/StringMan.java b/worldedit-core/src/main/java/com/boydti/fawe/util/StringMan.java index cf34d9b85..47a33911e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/StringMan.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/StringMan.java @@ -58,6 +58,17 @@ public class StringMan { return -1; } + public static String humanReadableByteCountBin(long bytes) { + long b = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); + return b < 1024L ? bytes + " B" + : b <= 0xfffccccccccccccL >> 40 ? String.format("%.1f KiB", bytes / 0x1p10) + : b <= 0xfffccccccccccccL >> 30 ? String.format("%.1f MiB", bytes / 0x1p20) + : b <= 0xfffccccccccccccL >> 20 ? String.format("%.1f GiB", bytes / 0x1p30) + : b <= 0xfffccccccccccccL >> 10 ? String.format("%.1f TiB", bytes / 0x1p40) + : b <= 0xfffccccccccccccL ? String.format("%.1f PiB", (bytes >> 10) / 0x1p40) + : String.format("%.1f EiB", (bytes >> 20) / 0x1p40); + } + public static String prettyFormat(double d) { if (d == Double.MIN_VALUE || d == Double.NEGATIVE_INFINITY) return "-∞"; if (d == Double.MAX_VALUE || d == Double.POSITIVE_INFINITY) return "∞"; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index ec3aec1e4..a42f03181 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -32,7 +32,7 @@ import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.changeset.BlockBagChangeSet; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.collection.LocalBlockVectorSet; import com.boydti.fawe.object.extent.FaweRegionExtent; import com.boydti.fawe.object.extent.ProcessedWEExtent; @@ -198,7 +198,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { private final FaweLimit originalLimit; private final FaweLimit limit; private final Player player; - private FaweChangeSet changeSet; + private AbstractChangeSet changeSet; private boolean history; private final MutableBlockVector3 mutablebv = new MutableBlockVector3(); @@ -212,11 +212,11 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { private final int maxY; @Deprecated - public EditSession(@NotNull World world, @Nullable Player player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { + public EditSession(@NotNull World world, @Nullable Player player, @Nullable FaweLimit limit, @Nullable AbstractChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { this(null, world, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, bus, event); } - public EditSession(@Nullable String worldName, @Nullable World world, @Nullable Player player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable Region[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { + public EditSession(@Nullable String worldName, @Nullable World world, @Nullable Player player, @Nullable FaweLimit limit, @Nullable AbstractChangeSet changeSet, @Nullable Region[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) { this(new EditSessionBuilder(world, worldName).player(player).limit(limit).changeSet(changeSet).allowedRegions(allowedRegions).autoQueue(autoQueue).fastmode(fastmode).checkMemory(checkMemory).combineStages(combineStages).blockBag(blockBag).eventBus(bus).event(event)); } @@ -393,7 +393,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * Used internally to set the ChangeSet during completion to record custom changes which aren't normally recorded * @param set */ - public void setRawChangeSet(@Nullable FaweChangeSet set) { + public void setRawChangeSet(@Nullable AbstractChangeSet set) { changeSet = set; changes++; } @@ -999,10 +999,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { // Enqueue it if (getChangeSet() != null) { if (Settings.IMP.HISTORY.COMBINE_STAGES) { - ((FaweChangeSet) getChangeSet()).closeAsync(); + ((AbstractChangeSet) getChangeSet()).closeAsync(); } else { try { - ((FaweChangeSet) getChangeSet()).close(); + ((AbstractChangeSet) getChangeSet()).close(); } catch (IOException e) { throw new RuntimeException(e); } @@ -2794,7 +2794,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { public boolean regenerate(Region region, BiomeType biome, Long seed) { //TODO Optimize - avoid Vector2D creation (make mutable) - final FaweChangeSet fcs = (FaweChangeSet) this.getChangeSet(); + final AbstractChangeSet fcs = (AbstractChangeSet) this.getChangeSet(); this.setChangeSet(null); final FaweRegionExtent fe = this.getRegionExtent(); final boolean cuboid = region instanceof CuboidRegion; 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 6eec0cc87..f137ad23e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -28,7 +28,6 @@ import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.changeset.DiskStorageHistory; -import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.clipboard.MultiClipboardHolder; import com.boydti.fawe.object.collection.SparseBitSet; import com.boydti.fawe.object.extent.ResettableExtent; @@ -39,6 +38,8 @@ import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.TextureHolder; import com.boydti.fawe.util.TextureUtil; import com.boydti.fawe.wrappers.WorldWrapper; +import com.google.common.base.Function; +import com.google.common.collect.Lists; import com.sk89q.jchronic.Chronic; import com.sk89q.jchronic.Options; import com.sk89q.jchronic.utils.Span; @@ -153,7 +154,7 @@ public class LocalSession implements TextureHolder { private transient VirtualWorld virtual; private transient BlockVector3 cuiTemporaryBlock; - private transient List> lastDistribution; + private transient List lastDistribution; private transient World worldOverride; private transient boolean tickingWatchdog = false; @@ -331,6 +332,10 @@ public class LocalSession implements TextureHolder { return (historyNegativeIndex == null ? historyNegativeIndex = 0 : historyNegativeIndex); } + public List getHistory() { + return Lists.transform(history, this::getChangeSet); + } + public boolean save() { saveHistoryNegativeIndex(uuid, currentWorld); if (defaultSelector == RegionSelectorType.CUBOID) { @@ -395,9 +400,9 @@ public class LocalSession implements TextureHolder { remember(editSession, true, limit); } - private FaweChangeSet getChangeSet(Object o) { - if (o instanceof FaweChangeSet) { - FaweChangeSet cs = (FaweChangeSet) o; + private ChangeSet getChangeSet(Object o) { + if (o instanceof ChangeSet) { + ChangeSet cs = (ChangeSet) o; try { cs.close(); } catch (IOException e) { @@ -427,16 +432,16 @@ public class LocalSession implements TextureHolder { return; } loadSessionHistoryFromDisk(player.getUniqueId(), world); - if (changeSet instanceof FaweChangeSet) { + if (changeSet instanceof ChangeSet) { ListIterator iter = history.listIterator(); int i = 0; int cutoffIndex = history.size() - getHistoryNegativeIndex(); while (iter.hasNext()) { Object item = iter.next(); if (++i > cutoffIndex) { - FaweChangeSet oldChangeSet; - if (item instanceof FaweChangeSet) { - oldChangeSet = (FaweChangeSet) item; + ChangeSet oldChangeSet; + if (item instanceof ChangeSet) { + oldChangeSet = (ChangeSet) item; } else { oldChangeSet = getChangeSet(item); } @@ -454,7 +459,7 @@ public class LocalSession implements TextureHolder { if (limit != null) { int limitMb = limit.MAX_HISTORY; while (((!Settings.IMP.HISTORY.USE_DISK && history.size() > MAX_HISTORY_SIZE) || (historySize >> 20) > limitMb) && history.size() > 1) { - FaweChangeSet item = (FaweChangeSet) history.remove(0); + ChangeSet item = (ChangeSet) history.remove(0); item.delete(); long size = MainUtil.getSize(item); historySize -= size; @@ -478,7 +483,7 @@ public class LocalSession implements TextureHolder { } */ - FaweChangeSet changeSet = (FaweChangeSet) editSession.getChangeSet(); + ChangeSet changeSet = editSession.getChangeSet(); if (changeSet.isEmpty()) { return; } @@ -495,9 +500,9 @@ public class LocalSession implements TextureHolder { while (iter.hasNext()) { Object item = iter.next(); if (++i > cutoffIndex) { - FaweChangeSet oldChangeSet; - if (item instanceof FaweChangeSet) { - oldChangeSet = (FaweChangeSet) item; + ChangeSet oldChangeSet; + if (item instanceof ChangeSet) { + oldChangeSet = (ChangeSet) item; } else { oldChangeSet = getChangeSet(item); } @@ -518,7 +523,7 @@ public class LocalSession implements TextureHolder { history.add(0, changeSet); } while (((!Settings.IMP.HISTORY.USE_DISK && history.size() > MAX_HISTORY_SIZE) || (historySize >> 20) > limitMb) && history.size() > 1) { - FaweChangeSet item = (FaweChangeSet) history.remove(0); + ChangeSet item = (ChangeSet) history.remove(0); item.delete(); long size = MainUtil.getSize(item); historySize -= size; @@ -534,10 +539,11 @@ public class LocalSession implements TextureHolder { */ public EditSession undo(@Nullable BlockBag newBlockBag, Actor actor) { checkNotNull(actor); - loadSessionHistoryFromDisk(actor.getUniqueId(), ((Player) actor).getWorldForEditing()); + World world = ((Player) actor).getWorldForEditing(); + loadSessionHistoryFromDisk(actor.getUniqueId(), world); if (getHistoryNegativeIndex() < history.size()) { - FaweChangeSet changeSet = getChangeSet(history.get(getHistoryIndex())); - try (EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld()) + ChangeSet changeSet = getChangeSet(history.get(getHistoryIndex())); + try (EditSession newEditSession = new EditSessionBuilder(world) .allowedRegionsEverywhere() .checkMemory(false) .changeSetNull() @@ -570,12 +576,13 @@ public class LocalSession implements TextureHolder { */ public EditSession redo(@Nullable BlockBag newBlockBag, Actor actor) { checkNotNull(actor); - loadSessionHistoryFromDisk(actor.getUniqueId(), ((Player)actor).getWorldForEditing()); + World world = ((Player) actor).getWorldForEditing(); + loadSessionHistoryFromDisk(actor.getUniqueId(), world); if (getHistoryNegativeIndex() > 0) { setDirty(); historyNegativeIndex--; - FaweChangeSet changeSet = getChangeSet(history.get(getHistoryIndex())); - try (EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld()) + ChangeSet changeSet = getChangeSet(history.get(getHistoryIndex())); + try (EditSession newEditSession = new EditSessionBuilder(world) .allowedRegionsEverywhere() .checkMemory(false) .changeSetNull() @@ -1590,14 +1597,14 @@ public class LocalSession implements TextureHolder { * * @return block distribution or {@code null} */ - public List> getLastDistribution() { + public List getLastDistribution() { return lastDistribution == null ? null : Collections.unmodifiableList(lastDistribution); } /** * Store a block distribution in this session. */ - public void setLastDistribution(List> dist) { + public void setLastDistribution(List dist) { lastDistribution = dist; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java index 200b1d3ca..504a2a5f1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistorySubCommands.java @@ -10,8 +10,8 @@ import com.boydti.fawe.database.DBHandler; import com.boydti.fawe.database.RollbackDatabase; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.StringMan; import com.google.common.base.Function; import com.google.common.collect.Lists; import com.sk89q.worldedit.LocalSession; @@ -22,6 +22,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.internal.annotation.AllowedRegion; import com.sk89q.worldedit.internal.annotation.Time; import com.sk89q.worldedit.math.BlockVector2; @@ -32,6 +33,7 @@ import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.component.TextComponentProducer; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -46,7 +48,6 @@ import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.LongAdder; import java.util.function.Supplier; import javax.annotation.Nullable; import org.enginehub.piston.annotation.Command; @@ -168,7 +169,7 @@ public class HistorySubCommands { world, uuid, Integer.parseInt( name.substring(0, name.length() - 3))); - DiskStorageHistory.DiskStorageSummary summary = rollback + SimpleChangeSetSummary summary = rollback .summarize(RegionWrapper.GLOBAL(), false); if (summary != null) { rollback.setDimensions( @@ -194,15 +195,14 @@ public class HistorySubCommands { } @Command( - name = "summary", - aliases = {"info", "summarize"}, + name = "info", + aliases = {"summary", "summarize"}, desc = "Summarize an edit" ) - @CommandPermissions("worldedit.history.find") + @CommandPermissions("worldedit.history.info") public synchronized void summary(Player player, RollbackDatabase database, Arguments arguments, @Arg(desc = "Player uuid/name") UUID other, - @Arg(desc = "edit index") Integer index, - @ArgFlag(name = 'p', desc = "Page to view.", def = "-1") int page) throws WorldEditException, ExecutionException, InterruptedException { + @Arg(desc = "edit index") Integer index) throws WorldEditException, ExecutionException, InterruptedException { RollbackOptimizedHistory edit = database.getEdit(other, index).get(); if (edit == null) { player.print(TranslatableComponent.of("fawe.worldedit.schematic.schematic.none")); @@ -226,47 +226,75 @@ public class HistorySubCommands { String timeStr = MainUtil.secToTime(seconds); int size = edit.size(); - - String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim(); - List> list = null; - Reference>> cached = player.getMeta(pageCommand); - if (cached != null) { - list = cached.get(); - } - if (list == null) { - DiskStorageHistory.DiskStorageSummary summary = edit.summarize(null, false); - if (summary != null) { - list = summary.getBlockDistributionWithData(); - player.setMeta(pageCommand, new SoftReference<>(list)); - } - } boolean biomes = edit.getBioFile().exists(); boolean createdEnts = edit.getEnttFile().exists(); boolean removedEnts = edit.getEntfFile().exists(); boolean createdTiles = edit.getNbttFile().exists(); boolean removedTiles = edit.getNbtfFile().exists(); - System.out.println("TODO FIXME move to translations"); - if (page == -1) { - player.print("name: " + name - + ", cmd: " + edit.getCommand() - + ", dist: " + distance + "m " + direction.name() - + ", time: " + timeStr + " ago" - + ", size: " + size + " blocks" - + ", biomes: " + biomes - + ", +entity: " + createdEnts - + ", -entity: " + removedEnts - + ", +tile: " + createdTiles - + ", -tile: " + removedTiles - + ", disk: " + (edit.getSizeOnDisk() / 1000) + "mb" - + ", min " + edit.getMinimumPoint() - + ", max " + edit.getMaximumPoint() - ); - } - page = 1; - if (list != null) { - SelectionCommands.BlockDistributionResult pages = new SelectionCommands.BlockDistributionResult((List) list, true, pageCommand); - player.print(pages.create(page)); - } + + TranslatableComponent header = Caption.of("fawe.worldedit.history.find.element", name, timeStr, distance, direction.name(), cmd); + + String sizeStr = StringMan.humanReadableByteCountBin(edit.getSizeOnDisk()); + String extra = ""; + if (biomes) extra += "biomes, "; + if (createdEnts) extra += "+entity, "; + if (removedEnts) extra += "-entity, "; + if (createdTiles) extra += "+tile, "; + if (removedTiles) extra += "-tile, "; + + TranslatableComponent body = Caption.of("fawe.worldedit.history.find.element.more", size, edit.getMinimumPoint(), edit.getMaximumPoint(), extra.trim(), sizeStr); + Component distr = TextComponent.of("/history distr").clickEvent(ClickEvent.suggestCommand("//history distr " + other + " " + index)); + TextComponentProducer content = new TextComponentProducer().append(header).newline().append(body).newline().append(distr); + player.print(content.create()); + } + + private void list(RollbackDatabase database, String pageCommand, List histories, BlockVector3 origin) { + return PaginationBox.fromStrings("Edits:", pageCommand, histories, new Function, Component>() { + @NotNull + @Override + public Component apply(@Nullable Supplier input) { + ChangeSet edit = input.get(); + + if (edit instanceof RollbackOptimizedHistory) { + RollbackOptimizedHistory rollback = (RollbackOptimizedHistory) edit; + + UUID uuid = rollback.getUUID(); + int index = rollback.getIndex(); + String name = Fawe.imp().getName(rollback.getUUID()); + + String cmd = rollback.getCommand(); + BlockVector3 pos1 = rollback.getMinimumPoint(); + BlockVector3 pos2 = rollback.getMaximumPoint(); + + double distanceX = Math.min(Math.abs(pos1.getX() - origin.getX()), Math.abs(pos2.getX() - origin.getX())); + double distanceZ = Math.min(Math.abs(pos1.getZ() - origin.getZ()), Math.abs(pos2.getZ() - origin.getZ())); + int distance = (int) Math.sqrt(distanceX * distanceX + distanceZ * distanceZ); + + BlockVector2 dirVec = BlockVector2.at(rollback.getOriginX() - origin.getX(), rollback.getOriginZ() - origin.getZ()); + Direction direction = Direction.findClosest(dirVec.toVector3(), Direction.Flag.ALL); + + long seconds = (System.currentTimeMillis() - rollback.getBDFile().lastModified()) / 1000; + String timeStr = MainUtil.secToTime(seconds); + + int size = edit.size(); + + TranslatableComponent elem = Caption.of("fawe.worldedit.history.find.element", name, timeStr, distance, direction.name(), cmd); + + String infoCmd = "//history summary " + uuid + " " + index; + TranslatableComponent hover = Caption.of("fawe.worldedit.history.find.hover", size); + elem = elem.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, hover)); + elem = elem.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, infoCmd)); + return elem; + } else { + + } + + + + System.out.println(" - return elem"); + return elem; + } + }); } @Command( @@ -276,28 +304,26 @@ public class HistorySubCommands { ) @CommandPermissions("worldedit.history.find") public synchronized void find(Player player, World world, RollbackDatabase database, Arguments arguments, - @ArgFlag(name = 'u', desc = "String user") UUID other, + @ArgFlag(name = 'u', def="", desc = "String user") UUID other, @ArgFlag(name = 'r', def = "0", desc = "radius") - @Range(from = 0, to = Integer.MAX_VALUE) int radius, + @Range(from = 0, to = Integer.MAX_VALUE) Integer radius, @ArgFlag(name = 't', desc = "Time e.g. 20s", def = "0") - @Time long timeDiff, - @ArgFlag(name = 'p', desc = "Page to view.", def = "1") int page) throws WorldEditException { + @Time Long timeDiff, + @ArgFlag(name = 'p', desc = "Page to view.", def = "") Integer page) throws WorldEditException { if (!Settings.IMP.HISTORY.USE_DATABASE) { player.print(Caption.of("fawe.error.setting.disable" , "history.use-database (Import with //history import )")); return; } + if (other == null && radius == 0 && timeDiff == 0) throw new InsufficientArgumentsException("User must be provided"); checkCommandArgument(radius > 0, "Radius must be >= 0"); checkCommandArgument(timeDiff > 0, "Time must be >= 0"); Location origin = player.getLocation(); String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim(); + Reference>> cached = player.getMeta(pageCommand); + List> history = cached == null ? null : cached.get(); - List> list = null; - Reference>> cached = player.getMeta(pageCommand); - if (cached != null) { - list = cached.get(); - } - if (list == null) { + if (page == null || history == null) { if (other == null) other = player.getUniqueId(); if (!other.equals(player.getUniqueId())) { player.checkPermission("worldedit.history.undo.other"); @@ -309,56 +335,59 @@ public class HistorySubCommands { bot = bot.clampY(0, world.getMaxY()); top = top.clampY(0, world.getMaxY()); - LongAdder total = new LongAdder(); - long minTime = System.currentTimeMillis() - timeDiff; Iterable> edits = database.getEdits(other, minTime, bot, top, false, false); - list = Lists.newArrayList(edits); - player.setMeta(pageCommand, new SoftReference<>(list)); + history = Lists.newArrayList(edits); + player.setMeta(pageCommand, new SoftReference<>(history)); + page = 1; } - PaginationBox pages = PaginationBox.fromStrings("Edits:", pageCommand, list, new Function, Component>() { - @NotNull - @Override - public Component apply(@Nullable Supplier input) { - RollbackOptimizedHistory edit = input.get(); - UUID uuid = edit.getUUID(); - int index = edit.getIndex(); - if (!edit.isEmpty()) { - database.delete(uuid, index); - return TextComponent.empty(); - } - String name = Fawe.imp().getName(edit.getUUID()); - String cmd = edit.getCommand(); - BlockVector3 pos1 = edit.getMinimumPoint(); - BlockVector3 pos2 = edit.getMaximumPoint(); - - double distanceX = Math.min(Math.abs(pos1.getX() - origin.getX()), Math.abs(pos2.getX() - origin.getX())); - double distanceZ = Math.min(Math.abs(pos1.getZ() - origin.getZ()), Math.abs(pos2.getZ() - origin.getZ())); - int distance = (int) Math.sqrt(distanceX * distanceX + distanceZ * distanceZ); - - BlockVector2 dirVec = BlockVector2.at(edit.getOriginX() - origin.getX(), edit.getOriginZ() - origin.getZ()); - Direction direction = Direction.findClosest(dirVec.toVector3(), Direction.Flag.ALL); - - long seconds = (System.currentTimeMillis() - edit.getBDFile().lastModified()) / 1000; - String timeStr = MainUtil.secToTime(seconds); - - int size = edit.size(); - - TranslatableComponent elem = Caption.of("fawe.worldedit.history.find.element", name, timeStr, distance, direction.name(), cmd); - - String infoCmd = "//history summary " + uuid + " " + index; - TranslatableComponent hover = Caption.of("fawe.worldedit.history.find.hover", size); - elem = elem.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, hover)); - elem = elem.clickEvent(ClickEvent.of(ClickEvent.Action.RUN_COMMAND, infoCmd)); - - return elem; - } - }); player.print(pages.create(page)); } + @Command( + name = "distr", + aliases = {"distribution"}, + desc = "View block distribution for an edit" + ) + @CommandPermissions("worldedit.history.distr") + public void distr(Player player, LocalSession session, RollbackDatabase database, Arguments arguments, + @Arg(desc = "Player uuid/name") UUID other, + @Arg(desc = "edit index") Integer index, + @ArgFlag(name = 'p', desc = "Page to view.", def = "") Integer page) throws ExecutionException, InterruptedException { + String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim(); + Reference cached = player.getMeta(pageCommand); + PaginationBox pages = cached == null ? null : cached.get(); + if (page == null || pages == null) { + RollbackOptimizedHistory edit = database.getEdit(other, index).get(); + SimpleChangeSetSummary summary = edit.summarize(null, false); + if (summary != null) { + List> distr = summary.getBlockDistributionWithData(); + SelectionCommands.BlockDistributionResult distrPages = new SelectionCommands.BlockDistributionResult((List) distr, true, pageCommand); + pages = new PaginationBox.MergedPaginationBox("Block Distribution", pageCommand, pages, distrPages); + player.setMeta(pageCommand, new SoftReference<>(pages)); + } + page = 1; + } + player.print(pages.create(page)); + } + + @Command( + name = "list", + desc = "List your history" + ) + @CommandPermissions("worldedit.history.list") + public void list(Actor actor, LocalSession session, + @Arg(desc = "Player uuid/name") UUID other, + @ArgFlag(name = 'p', desc = "Page to view.", def = "") Integer page) { + int index = session.getHistoryIndex(); + List history = session.getHistory(); + + // index + + } + @Command( name = "clear", desc = "Clear your history" diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 1f01bdd19..4ea7d2762 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -25,6 +25,10 @@ import com.google.common.base.Strings; import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.block.BlockDistributionCounter; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.function.visitor.RegionVisitor; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.boydti.fawe.object.clipboard.URIClipboardHolder; import com.boydti.fawe.object.mask.IdMask; @@ -530,25 +534,34 @@ public class SelectionCommands { boolean clipboardDistr, @Switch(name = 'd', desc = "Separate blocks by state") boolean separateStates, - @ArgFlag(name = 'p', desc = "Gets page from a previous distribution.", def = "1") + @ArgFlag(name = 'p', desc = "Gets page from a previous distribution.", def = "") Integer page) throws WorldEditException { List distribution; Region region; - if (clipboardDistr) { - // TODO multi clipboard distribution - Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing - region = clipboard.getRegion(); - new ExtentTraverser(editSession).setNext(new AbstractDelegateExtent(clipboard)); + if (page == null) { + Extent extent; + if (clipboardDistr) { + Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing + extent = clipboard; + region = clipboard.getRegion(); + } else { + extent = editSession; + region = session.getSelection(world); + } + if (separateStates) + distribution = (List) extent.getBlockDistributionWithData(region); + else + distribution = (List) extent.getBlockDistribution(region); + session.setLastDistribution(distribution); + page = 1; } else { - region = session.getSelection(world); + distribution = (List) session.getLastDistribution(); + if (distribution == null) { + actor.printError(TranslatableComponent.of("worldedit.distr.no-previous")); + return; + } } - if (separateStates) - distribution = (List) editSession.getBlockDistributionWithData(region); - else - distribution = (List) editSession.getBlockDistribution(region); - - if (distribution.isEmpty()) { // *Should* always be false actor.printError(TranslatableComponent.of("worldedit.distr.no-blocks")); return; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index ab359cd02..8a7ce511c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -24,11 +24,10 @@ import static org.slf4j.LoggerFactory.getLogger; import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.object.HistoryExtent; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.extent.LightingExtent; import com.boydti.fawe.util.ExtentTraverser; -import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; @@ -116,7 +115,7 @@ public class AbstractDelegateExtent implements Extent, LightingExtent { /* History */ - public void setChangeSet(FaweChangeSet changeSet) { + public void setChangeSet(AbstractChangeSet changeSet) { if (extent instanceof HistoryExtent) { HistoryExtent history = ((HistoryExtent) extent); if (changeSet == null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 5b7dc6b59..f46d220af 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -25,7 +25,7 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.implementation.filter.block.ExtentFilterBlock; import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.IBatchProcessor; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.clipboard.WorldCopyClipboard; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.extent.NullExtent; @@ -34,7 +34,6 @@ import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.RegionMaskingFilter; import com.sk89q.worldedit.function.block.BlockReplace; @@ -659,7 +658,7 @@ public interface Extent extends InputExtent, OutputExtent { return processor.construct(this); } - default Extent enableHistory(FaweChangeSet changeSet) { + default Extent enableHistory(AbstractChangeSet changeSet) { return addProcessor(changeSet); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java index 337c1f509..fe3c19cde 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java @@ -2,11 +2,10 @@ package com.sk89q.worldedit.extent; import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.IBatchProcessor; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.generator.GenBase; import com.sk89q.worldedit.function.generator.Resource; @@ -221,7 +220,7 @@ public class PassthroughExtent extends AbstractDelegateExtent { return super.addProcessor(processor); } - public Extent enableHistory(FaweChangeSet changeSet) { + public Extent enableHistory(AbstractChangeSet changeSet) { return super.enableHistory(changeSet); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index 01b4a014d..720072153 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -105,16 +105,27 @@ public class BlockTransformExtent extends ResettableExtent { private static long combine(Direction... directions) { - return Arrays.stream(directions).mapToLong(dir -> (1L << dir.ordinal())) - .reduce(0, (a, b) -> a | b); + long mask = 0; + for (Direction dir : directions) { + mask = mask | (1L << dir.ordinal()); + } + return mask; } private static long[] adapt(Direction... dirs) { - return Arrays.stream(dirs).mapToLong(dir -> 1L << dir.ordinal()).toArray(); + long[] arr = new long[dirs.length]; + for (int i = 0; i < arr.length; i++) { + arr[i] = 1L << dirs[i].ordinal(); + } + return arr; } private static long[] adapt(Long... dirs) { - return Arrays.stream(dirs).mapToLong(dir -> dir).toArray(); + long[] arr = new long[dirs.length]; + for (int i = 0; i < arr.length; i++) { + arr[i] = dirs[i]; + } + return arr; } private static long[] getDirections(AbstractProperty property) { @@ -228,7 +239,9 @@ public class BlockTransformExtent extends ResettableExtent { } private static long notIndex(long mask, int... indexes) { - mask |= Arrays.stream(indexes).mapToLong(index -> (1L << (index + values().length))).reduce(0, (a, b) -> a | b); + for (int index : indexes) { + mask = mask | (1L << (index + values().length)); + } return mask; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java index 49eab2402..1559d4bba 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java @@ -21,14 +21,13 @@ package com.sk89q.worldedit.function.operation; import static com.google.common.base.Preconditions.checkNotNull; -import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.UndoContext; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.changeset.ChangeSet; import java.util.Iterator; -import java.util.List; /** * Performs an undo or redo from a given {@link ChangeSet}. @@ -71,8 +70,8 @@ public class ChangeSetExecutor implements Operation { this.type = type; this.context = context; - if (changeSet instanceof FaweChangeSet) { - iterator = ((FaweChangeSet) changeSet).getIterator(blockBag, inventory, type == Type.REDO); + if (changeSet instanceof AbstractChangeSet) { + iterator = ((AbstractChangeSet) changeSet).getIterator(blockBag, inventory, type == Type.REDO); } else if (type == Type.UNDO) { iterator = changeSet.backwardIterator(); } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java index 003a007b6..b988f6118 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSet.java @@ -19,15 +19,22 @@ package com.sk89q.worldedit.history.changeset; +import com.google.common.collect.Maps; import com.sk89q.worldedit.history.change.Change; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.block.BlockState; +import java.io.Closeable; +import java.io.IOException; +import java.util.Collections; import java.util.Iterator; +import java.util.Map; /** * Tracks a set of undoable operations and allows their undo and redo. The * entirety of a change set should be undone and redone at once. */ -public interface ChangeSet { +public interface ChangeSet extends Closeable { /** * Add the given change to the history. @@ -77,4 +84,38 @@ public interface ChangeSet { */ int size(); + /** + * Close the changeset + */ + @Override + default void close() throws IOException { + + } + + /** + * Delete the changeset (e.g. files on disk, or in a database) + */ + default void delete() {} + + ChangeSetSummary summarize(Region region, boolean shallow) { + return new ChangeSetSummary() { + @Override + public Map getBlocks() { + return Collections.emptyMap(); + } + + @Override + public int getSize() { + return size(); + } + }; + } + + /** + * Get if the changeset is empty (i.e. size == 0) + * @return is empty + */ + default boolean isEmpty() { + return size() == 0; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSetSummary.java b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSetSummary.java new file mode 100644 index 000000000..78e4a8b8a --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/history/changeset/ChangeSetSummary.java @@ -0,0 +1,37 @@ +package com.sk89q.worldedit.history.changeset; + +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public interface ChangeSetSummary { + Map getBlocks(); + + int getSize(); + + default List> getBlockDistributionWithData() { + ArrayList> list = new ArrayList<>(); + for (Map.Entry entry : getBlocks().entrySet()) { + list.add(new Countable<>(entry.getKey(), entry.getValue())); + } + return list; + } + + default Map getPercents() { + Map map = getBlocks(); + int count = getSize(); + Map newMap = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + BlockState id = entry.getKey(); + int changes = entry.getValue(); + double percent = (changes * 1000L / count) / 10d; + newMap.put(id, percent); + } + return newMap; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java index 720ca0161..9ec2c569f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/LazyReference.java @@ -71,5 +71,4 @@ public class LazyReference { refInfo.lock.unlock(); } } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java index 944c253e6..8c444b16f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java @@ -196,4 +196,34 @@ public abstract class PaginationBox extends MessageBox { return lines.size(); } } + + public static class MergedPaginationBox extends PaginationBox { + private final PaginationBox[] values; + + public MergedPaginationBox(String header, String pageCommand, PaginationBox... values) { + super(header, pageCommand); + this.values = values; + } + + @Override + public Component getComponent(int number) { + for (PaginationBox box : values) { + int size = box.getComponentsSize(); + if (size > number) { + return box.getComponent(number); + } + number -= size; + } + return null; + } + + @Override + public int getComponentsSize() { + int size = 0; + for (PaginationBox box : values) { + size += box.getComponentsSize(); + } + return size; + } + } } diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 1f5c2135a..df73dcf2c 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -4,7 +4,8 @@ "fawe.info": "&7{0}", "fawe.debug": "&3{0}", - "fawe.worldedit.history.find.element": "&8 - &2{0}: {1} &7ago &3{2}m &6{3} &c/{4}", + "fawe.worldedit.history.find.element": "&2{0} {1} &7ago &3{2}m &6{3} &c/{4}", + "fawe.worldedit.history.find.element.more": " - Changes: {0}\n - Bounds: {1} -> {2}\n - Extra: {3}\n - Size on Disk: {4}", "fawe.worldedit.history.find.hover": "{0} blocks changed, click for more info", "fawe.info.lighting.propagate.selection": "Lighting has been propagated in {0} chunks. (Note: To remove light use //removelight)",