Rollback optimizations / features
This commit is contained in:
parent
63ad22a021
commit
d38db03600
@ -23,7 +23,7 @@ public class BukkitCommand implements CommandExecutor {
|
||||
BBC.NO_PERM.send(plr, this.cmd.getPerm());
|
||||
return true;
|
||||
}
|
||||
this.cmd.execute(plr, args);
|
||||
this.cmd.executeSafe(plr, args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,11 @@ import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Rollback extends FaweCommand {
|
||||
@ -44,25 +46,33 @@ public class Rollback extends FaweCommand {
|
||||
}
|
||||
player.deleteMeta("rollback");
|
||||
final FaweLocation origin = player.getLocation();
|
||||
rollback(player, Arrays.copyOfRange(args, 1, args.length), new RunnableVal<List<DiskStorageHistory>>() {
|
||||
rollback(player, !player.hasPermission("fawe.rollback.deep"), Arrays.copyOfRange(args, 1, args.length), new RunnableVal<List<DiskStorageHistory>>() {
|
||||
@Override
|
||||
public void run(List<DiskStorageHistory> edits) {
|
||||
long total = 0;
|
||||
player.sendMessage("&d=== Edits ===");
|
||||
player.sendMessage("&d=| Username | Bounds | Distance | Changes | Age |=");
|
||||
for (DiskStorageHistory edit : edits) {
|
||||
int[] headerAndFooter = edit.readHeaderAndFooter(new RegionWrapper(origin.x, origin.x, origin.z, origin.z));
|
||||
RegionWrapper region = new RegionWrapper(headerAndFooter[0], headerAndFooter[2], headerAndFooter[1], headerAndFooter[3]);
|
||||
int dx = region.distanceX(origin.x);
|
||||
int dz = region.distanceZ(origin.z);
|
||||
DiskStorageHistory.DiskStorageSummary summary = edit.summarize(new RegionWrapper(origin.x, origin.x, origin.z, origin.z), !player.hasPermission("fawe.rollback.deep"));
|
||||
RegionWrapper region = new RegionWrapper(summary.minX, summary.maxX, summary.minZ, summary.maxZ);
|
||||
int distance = region.distance(origin.x, origin.z);
|
||||
String name = Fawe.imp().getName(edit.getUUID());
|
||||
long seconds = (System.currentTimeMillis() - edit.getBDFile().lastModified()) / 1000;
|
||||
total += edit.getBDFile().length();
|
||||
player.sendMessage(name + " : " + dx + "," + dz + " : " + MainUtil.secToTime(seconds));
|
||||
int size = summary.getSize();
|
||||
Map<Integer, Double> percents = summary.getPercents();
|
||||
StringBuilder percentString = new StringBuilder();
|
||||
String prefix = "";
|
||||
for (Map.Entry<Integer, Double> entry : percents.entrySet()) {
|
||||
percentString.append(prefix).append(entry.getValue()).append("% ").append(ItemType.toName(entry.getKey()));
|
||||
prefix = ", ";
|
||||
}
|
||||
player.sendMessage("&c" + name + " | " + region + " | " + distance + "m | " + size + " | " + MainUtil.secToTime(seconds));
|
||||
player.sendMessage("&8 - &7(" + percentString + ")");
|
||||
}
|
||||
player.sendMessage("&d=============");
|
||||
player.sendMessage("&d==================================================");
|
||||
player.sendMessage("&dSize: " + (((double) (total / 1024)) / 1000) + "MB");
|
||||
player.sendMessage("&dTo rollback: /frb undo");
|
||||
player.sendMessage("&d=============");
|
||||
player.sendMessage("&d==================================================");
|
||||
player.setMeta("rollback", edits);
|
||||
}
|
||||
});
|
||||
@ -70,6 +80,10 @@ public class Rollback extends FaweCommand {
|
||||
}
|
||||
case "undo":
|
||||
case "revert": {
|
||||
if (!player.hasPermission("fawe.rollback.perform")) {
|
||||
BBC.NO_PERM.send(player, "fawe.rollback.perform");
|
||||
return false;
|
||||
}
|
||||
final List<DiskStorageHistory> edits = (List<DiskStorageHistory>) player.getMeta("rollback");
|
||||
player.deleteMeta("rollback");
|
||||
if (edits == null) {
|
||||
@ -97,7 +111,7 @@ public class Rollback extends FaweCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void rollback(final FawePlayer player, final String[] args, final RunnableVal<List<DiskStorageHistory>> result) {
|
||||
public void rollback(final FawePlayer player, final boolean shallow, final String[] args, final RunnableVal<List<DiskStorageHistory>> result) {
|
||||
TaskManager.IMP.async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -148,9 +162,13 @@ public class Rollback extends FaweCommand {
|
||||
}
|
||||
}
|
||||
FaweLocation origin = player.getLocation();
|
||||
List<DiskStorageHistory> edits = MainUtil.getBDFiles(origin, user, radius, time);
|
||||
List<DiskStorageHistory> edits = MainUtil.getBDFiles(origin, user, radius, time, shallow);
|
||||
if (edits == null) {
|
||||
player.sendMessage("&cToo broad, try refining your search!");
|
||||
return;
|
||||
}
|
||||
if (edits.size() == 0) {
|
||||
player.sendMessage("No edits found!");
|
||||
player.sendMessage("&cNo edits found!");
|
||||
return;
|
||||
}
|
||||
result.run(edits);
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
|
||||
public abstract class FaweCommand<T> {
|
||||
public final String perm;
|
||||
|
||||
@ -11,5 +13,21 @@ public abstract class FaweCommand<T> {
|
||||
return this.perm;
|
||||
}
|
||||
|
||||
public boolean executeSafe(final FawePlayer<T> player, final String... args) {
|
||||
if (player == null) {
|
||||
execute(player, args);
|
||||
return true;
|
||||
} else {
|
||||
if (player.getMeta("fawe_action") != null) {
|
||||
BBC.WORLDEDIT_COMMAND_LIMIT.send(player);
|
||||
return false;
|
||||
}
|
||||
player.setMeta("fawe_action", true);
|
||||
boolean result = execute(player, args);
|
||||
player.deleteMeta("fawe_action");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean execute(final FawePlayer<T> player, final String... args);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@ -355,19 +356,21 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
return osENTT;
|
||||
}
|
||||
|
||||
int fx;
|
||||
int fz;
|
||||
|
||||
public int[] readHeaderAndFooter(RegionWrapper requiredRegion) {
|
||||
if (fx == 0 && fz == 0 && bdFile.exists()) {
|
||||
private DiskStorageSummary summary;
|
||||
|
||||
public DiskStorageSummary summarize(RegionWrapper requiredRegion, boolean shallow) {
|
||||
if (summary != null) {
|
||||
return summary;
|
||||
}
|
||||
if (bdFile.exists()) {
|
||||
if ((ox != 0 || oz != 0) && !requiredRegion.isIn(ox, oz)) {
|
||||
return new int[] {ox, oz, ox, oz};
|
||||
return summary = new DiskStorageSummary(ox, oz);
|
||||
}
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(bdFile);
|
||||
try (FileInputStream fis = new FileInputStream(bdFile)) {
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
final InputStream gis;
|
||||
final LZ4InputStream gis;
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
gis = new LZ4InputStream(new LZ4InputStream(fis));
|
||||
} else {
|
||||
@ -375,37 +378,31 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
summary = new DiskStorageSummary(ox, oz);
|
||||
if (!requiredRegion.isIn(ox, oz)) {
|
||||
fis.close();
|
||||
gis.close();
|
||||
return new int[] {ox, oz, ox, oz};
|
||||
return summary;
|
||||
}
|
||||
byte[] even = new byte[9];
|
||||
byte[] odd = new byte[9];
|
||||
byte[] result = null;
|
||||
byte[] buffer = new byte[9];
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if ((i++ & 1) == 0) {
|
||||
if (gis.read(even) == -1) {
|
||||
result = odd;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (gis.read(odd) == -1) {
|
||||
result = even;
|
||||
break;
|
||||
}
|
||||
while (!shallow || gis.hasBytesAvailableInDecompressedBuffer(9)) {
|
||||
if (gis.read(buffer) == -1) {
|
||||
fis.close();
|
||||
gis.close();
|
||||
return summary;
|
||||
}
|
||||
int x = ((byte) buffer[0] & 0xFF) + ((byte) buffer[1] << 8) + ox;
|
||||
int z = ((byte) buffer[2] & 0xFF) + ((byte) buffer[3] << 8) + oz;
|
||||
int combined1 = buffer[7];
|
||||
int combined2 = buffer[8];
|
||||
summary.add(x, z, ((combined2 << 4) + (combined1 >> 4)));
|
||||
}
|
||||
fx = ((byte) result[0] & 0xFF) + ((byte) result[1] << 8) + ox;
|
||||
fz = ((byte) result[2] & 0xFF) + ((byte) result[3] << 8) + oz;
|
||||
fis.close();
|
||||
gis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new int[] {ox, oz, fx, fz};
|
||||
return summary;
|
||||
}
|
||||
|
||||
public IntegerPair readHeader() {
|
||||
@ -555,4 +552,72 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
flush();
|
||||
return size.get();
|
||||
}
|
||||
|
||||
public static class DiskStorageSummary {
|
||||
|
||||
private final int z;
|
||||
private final int x;
|
||||
public int[] blocks;
|
||||
|
||||
public int minX;
|
||||
public int minZ;
|
||||
|
||||
public int maxX;
|
||||
public int maxZ;
|
||||
|
||||
public DiskStorageSummary(int x, int z) {
|
||||
blocks = new int[256];
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
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 HashMap<Integer, Integer> getBlocks() {
|
||||
HashMap<Integer, Integer> map = new HashMap<>();
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
if (blocks[i] != 0) {
|
||||
map.put(i, blocks[i]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map<Integer, Double> getPercents() {
|
||||
HashMap<Integer, Integer> map = getBlocks();
|
||||
int count = getSize();
|
||||
HashMap<Integer, Double> newMap = new HashMap<Integer, Double>();
|
||||
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
|
||||
int 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 i = 0; i < blocks.length; i++) {
|
||||
count += blocks[i];
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public class MainUtil {
|
||||
return time;
|
||||
}
|
||||
|
||||
public static List<DiskStorageHistory> getBDFiles(FaweLocation origin, UUID user, int radius, long timediff) {
|
||||
public static List<DiskStorageHistory> getBDFiles(FaweLocation origin, UUID user, int radius, long timediff, boolean shallow) {
|
||||
File history = new File(Fawe.imp().getDirectory(), "history" + File.separator + origin.world);
|
||||
if (!history.exists()) {
|
||||
return new ArrayList<>();
|
||||
@ -168,6 +168,9 @@ public class MainUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (files.size() > 512) {
|
||||
return null;
|
||||
}
|
||||
World world = origin.getWorld();
|
||||
Collections.sort(files, new Comparator<File>() {
|
||||
@Override
|
||||
@ -180,11 +183,12 @@ public class MainUtil {
|
||||
for (File file : files) {
|
||||
UUID uuid = UUID.fromString(file.getParentFile().getName());
|
||||
DiskStorageHistory dsh = new DiskStorageHistory(world, uuid, Integer.parseInt(file.getName().split("\\.")[0]));
|
||||
int[] headerAndFooter = dsh.readHeaderAndFooter(new RegionWrapper(origin.x - 512, origin.x + 512, origin.z - 512, origin.z + 512));
|
||||
RegionWrapper region = new RegionWrapper(headerAndFooter[0], headerAndFooter[2], headerAndFooter[1], headerAndFooter[3]);
|
||||
DiskStorageHistory.DiskStorageSummary summary = dsh.summarize(new RegionWrapper(origin.x - 512, origin.x + 512, origin.z - 512, origin.z + 512), shallow);
|
||||
RegionWrapper region = new RegionWrapper(summary.minX, summary.maxX, summary.minZ, summary.maxZ);
|
||||
if (region.distance(origin.x, origin.z) <= radius) {
|
||||
result.add(dsh);
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -75,6 +75,10 @@ public class LZ4InputStream extends InputStream {
|
||||
return n - numBytesRemainingToSkip;
|
||||
}
|
||||
|
||||
public boolean hasBytesAvailableInDecompressedBuffer(int bytes) {
|
||||
return decompressedBufferPosition + bytes <= decompressedBufferLength;
|
||||
}
|
||||
|
||||
private boolean ensureBytesAvailableInDecompressedBuffer() throws IOException {
|
||||
while (decompressedBufferPosition >= decompressedBufferLength) {
|
||||
if (!fillBuffer()) {
|
||||
|
@ -30,7 +30,7 @@ public class SpongeCommand implements CommandCallable {
|
||||
BBC.NO_PERM.send(plr, this.cmd.getPerm());
|
||||
return CommandResult.success();
|
||||
}
|
||||
this.cmd.execute(plr, args.split(" "));
|
||||
this.cmd.executeSafe(plr, args.split(" "));
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user