2019-11-23 04:31:48 +00:00
|
|
|
package com.sk89q.worldedit.command;
|
|
|
|
|
2021-07-01 20:16:25 +00:00
|
|
|
import com.fastasyncworldedit.core.Fawe;
|
|
|
|
import com.fastasyncworldedit.core.FaweAPI;
|
|
|
|
import com.fastasyncworldedit.core.configuration.Caption;
|
|
|
|
import com.fastasyncworldedit.core.configuration.Settings;
|
|
|
|
import com.fastasyncworldedit.core.database.DBHandler;
|
|
|
|
import com.fastasyncworldedit.core.database.RollbackDatabase;
|
2021-07-23 15:48:51 +00:00
|
|
|
import com.fastasyncworldedit.core.history.RollbackOptimizedHistory;
|
|
|
|
import com.fastasyncworldedit.core.history.changeset.SimpleChangeSetSummary;
|
2021-07-24 15:34:05 +00:00
|
|
|
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
2021-07-01 20:16:25 +00:00
|
|
|
import com.fastasyncworldedit.core.util.MainUtil;
|
|
|
|
import com.fastasyncworldedit.core.util.StringMan;
|
2020-01-03 21:05:25 +00:00
|
|
|
import com.google.common.base.Function;
|
2019-11-23 04:31:48 +00:00
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
import com.sk89q.worldedit.LocalSession;
|
|
|
|
import com.sk89q.worldedit.WorldEditException;
|
|
|
|
import com.sk89q.worldedit.command.argument.Arguments;
|
|
|
|
import com.sk89q.worldedit.command.util.CommandPermissions;
|
|
|
|
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
2021-07-24 15:34:05 +00:00
|
|
|
import com.sk89q.worldedit.command.util.annotation.AllowedRegion;
|
2019-11-23 04:31:48 +00:00
|
|
|
import com.sk89q.worldedit.command.util.annotation.Confirm;
|
2021-07-24 15:34:05 +00:00
|
|
|
import com.sk89q.worldedit.command.util.annotation.Time;
|
2019-11-23 04:31:48 +00:00
|
|
|
import com.sk89q.worldedit.entity.Player;
|
|
|
|
import com.sk89q.worldedit.extension.platform.Actor;
|
2020-01-06 08:36:16 +00:00
|
|
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
2019-11-23 04:31:48 +00:00
|
|
|
import com.sk89q.worldedit.math.BlockVector2;
|
|
|
|
import com.sk89q.worldedit.math.BlockVector3;
|
|
|
|
import com.sk89q.worldedit.regions.Region;
|
|
|
|
import com.sk89q.worldedit.util.Countable;
|
|
|
|
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;
|
2020-01-06 08:36:16 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.component.TextComponentProducer;
|
2020-01-03 21:05:25 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
2019-11-23 04:31:48 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
|
|
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
|
|
|
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
|
|
|
|
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
|
|
|
import com.sk89q.worldedit.world.World;
|
|
|
|
import com.sk89q.worldedit.world.block.BlockState;
|
2020-07-14 02:50:59 +00:00
|
|
|
import org.enginehub.piston.annotation.Command;
|
|
|
|
import org.enginehub.piston.annotation.CommandContainer;
|
|
|
|
import org.enginehub.piston.annotation.param.Arg;
|
|
|
|
import org.enginehub.piston.annotation.param.ArgFlag;
|
|
|
|
import org.enginehub.piston.annotation.param.Switch;
|
|
|
|
import org.jetbrains.annotations.Range;
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
import javax.annotation.Nullable;
|
2019-11-23 04:31:48 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.lang.ref.Reference;
|
|
|
|
import java.lang.ref.SoftReference;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Objects;
|
|
|
|
import java.util.UUID;
|
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
import java.util.function.Supplier;
|
2020-07-14 02:50:59 +00:00
|
|
|
|
|
|
|
import static com.sk89q.worldedit.internal.command.CommandUtil.checkCommandArgument;
|
2019-11-23 04:31:48 +00:00
|
|
|
|
|
|
|
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
|
|
|
public class HistorySubCommands {
|
|
|
|
|
|
|
|
private final HistoryCommands parent;
|
|
|
|
|
|
|
|
public HistorySubCommands(HistoryCommands parent) {
|
|
|
|
this.parent = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "restore",
|
|
|
|
aliases = {"rerun"},
|
|
|
|
desc = "Rerun edits"
|
|
|
|
+ " - The time uses s, m, h, d, y.\n"
|
|
|
|
+ " - Import from disk: /history import"
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
2021-07-23 15:48:51 +00:00
|
|
|
@CommandPermissions("worldedit.history.restore")
|
2019-11-23 04:31:48 +00:00
|
|
|
@Confirm
|
2021-07-24 15:34:05 +00:00
|
|
|
public synchronized void rerun(
|
|
|
|
Player player, World world, RollbackDatabase database,
|
|
|
|
@AllowedRegion Region[] allowedRegions,
|
|
|
|
@ArgFlag(name = 'u', desc = "String user", def = "me")
|
|
|
|
UUID other,
|
|
|
|
@ArgFlag(name = 'r', def = "0", desc = "radius")
|
|
|
|
@Range(from = 0, to = Integer.MAX_VALUE)
|
|
|
|
int radius,
|
|
|
|
@ArgFlag(name = 't', desc = "Time e.g. 20s", def = "0")
|
|
|
|
@Time
|
|
|
|
long timeDiff
|
|
|
|
) throws WorldEditException {
|
2019-11-23 04:31:48 +00:00
|
|
|
rollback(player, world, database, allowedRegions, other, radius, timeDiff, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "rollback",
|
|
|
|
desc = "Undo a specific edit. "
|
|
|
|
+ " - The time uses s, m, h, d, y."
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
2021-07-23 15:48:51 +00:00
|
|
|
@CommandPermissions("worldedit.history.rollback")
|
2019-11-23 04:31:48 +00:00
|
|
|
@Confirm
|
2021-07-24 15:34:05 +00:00
|
|
|
public synchronized void rollback(
|
|
|
|
Player player, World world, RollbackDatabase database,
|
|
|
|
@AllowedRegion Region[] allowedRegions,
|
|
|
|
@ArgFlag(name = 'u', desc = "String user", def = "")
|
|
|
|
UUID other,
|
|
|
|
@ArgFlag(name = 'r', def = "0", desc = "radius")
|
|
|
|
@Range(from = 0, to = Integer.MAX_VALUE)
|
|
|
|
int radius,
|
|
|
|
@ArgFlag(name = 't', desc = "Time e.g. 20s", def = "0")
|
|
|
|
@Time
|
|
|
|
long timeDiff,
|
|
|
|
@Switch(name = 'f', desc = "Restore instead of rollback")
|
|
|
|
boolean restore
|
|
|
|
) throws WorldEditException {
|
2019-11-23 04:31:48 +00:00
|
|
|
if (!Settings.IMP.HISTORY.USE_DATABASE) {
|
2020-10-05 17:41:41 +00:00
|
|
|
player.print(Caption.of("fawe.error.setting.disable", "history.use-database (Import with /history import )"));
|
2019-11-23 04:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
checkCommandArgument(radius > 0, "Radius must be >= 0");
|
|
|
|
checkCommandArgument(timeDiff > 0, "Time must be >= 0");
|
|
|
|
|
2020-10-05 17:41:41 +00:00
|
|
|
if (other == null) {
|
|
|
|
other = player.getUniqueId();
|
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
if (!other.equals(player.getUniqueId())) {
|
|
|
|
player.checkPermission("worldedit.history.undo.other");
|
|
|
|
}
|
2020-10-05 17:41:41 +00:00
|
|
|
if (other == Identifiable.EVERYONE) {
|
|
|
|
other = null;
|
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
Location origin = player.getLocation();
|
|
|
|
BlockVector3 bot = origin.toBlockPoint().subtract(radius, radius, radius);
|
|
|
|
BlockVector3 top = origin.toBlockPoint().add(radius, radius, radius);
|
2021-08-17 21:13:51 +00:00
|
|
|
bot = bot.clampY(world.getMinY(), world.getMaxY());
|
|
|
|
top = top.clampY(world.getMinY(), world.getMaxY());
|
2019-11-23 04:31:48 +00:00
|
|
|
// TODO mask the regions bot / top to the bottom and top coord in the allowedRegions
|
|
|
|
// TODO: then mask the edit to the bot / top
|
2020-10-05 17:41:41 +00:00
|
|
|
// if (allowedRegions.length != 1 || !allowedRegions[0].isGlobal()) {
|
|
|
|
// finalQueue = new MaskedIQueueExtent(SetQueue.IMP.getNewQueue(fp.getWorld(), true, false), allowedRegions);
|
|
|
|
// } else {
|
|
|
|
// finalQueue = SetQueue.IMP.getNewQueue(fp.getWorld(), true, false);
|
|
|
|
// }
|
2019-11-23 04:31:48 +00:00
|
|
|
int count = 0;
|
|
|
|
UUID finalOther = other;
|
|
|
|
long minTime = System.currentTimeMillis() - timeDiff;
|
|
|
|
for (Supplier<RollbackOptimizedHistory> supplier : database.getEdits(other, minTime, bot, top, !restore, restore)) {
|
|
|
|
count++;
|
|
|
|
RollbackOptimizedHistory edit = supplier.get();
|
2021-08-08 18:35:57 +00:00
|
|
|
if (restore) {
|
|
|
|
edit.redo(player, allowedRegions);
|
|
|
|
} else {
|
|
|
|
edit.undo(player, allowedRegions);
|
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
String path = edit.getWorld().getName() + "/" + finalOther + "-" + edit.getIndex();
|
2019-12-16 09:01:41 +00:00
|
|
|
player.print(Caption.of("fawe.worldedit.rollback.rollback.element", path));
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
2020-10-05 17:41:41 +00:00
|
|
|
player.print(Caption.of("fawe.worldedit.tool.tool.inspect.info.footer", count));
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "import",
|
|
|
|
desc = "Import history into the database"
|
|
|
|
+ " - The time uses s, m, h, d, y.\n"
|
|
|
|
+ " - Import from disk: /history import"
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("fawe.rollback.import")
|
|
|
|
@Confirm
|
|
|
|
public synchronized void importdb(Actor actor) throws WorldEditException {
|
|
|
|
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY);
|
|
|
|
if (folder.exists()) {
|
|
|
|
for (File worldFolder : Objects.requireNonNull(folder.listFiles())) {
|
|
|
|
if (worldFolder != null && worldFolder.isDirectory()) {
|
|
|
|
String worldName = worldFolder.getName();
|
|
|
|
World world = FaweAPI.getWorld(worldName);
|
|
|
|
if (world != null) {
|
|
|
|
for (File userFolder : worldFolder.listFiles()) {
|
|
|
|
if (!userFolder.isDirectory()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
String userUUID = userFolder.getName();
|
|
|
|
try {
|
|
|
|
UUID uuid = UUID.fromString(userUUID);
|
|
|
|
for (File historyFile : userFolder.listFiles()) {
|
|
|
|
String name = historyFile.getName();
|
|
|
|
if (!name.endsWith(".bd")) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
RollbackOptimizedHistory rollback = new RollbackOptimizedHistory(
|
|
|
|
world, uuid,
|
|
|
|
Integer.parseInt(
|
2021-07-24 15:34:05 +00:00
|
|
|
name.substring(0, name.length() - 3))
|
|
|
|
);
|
2020-01-06 08:36:16 +00:00
|
|
|
SimpleChangeSetSummary summary = rollback
|
2019-11-23 04:31:48 +00:00
|
|
|
.summarize(RegionWrapper.GLOBAL(), false);
|
|
|
|
if (summary != null) {
|
|
|
|
rollback.setDimensions(
|
2021-08-17 21:13:51 +00:00
|
|
|
BlockVector3.at(summary.minX, world.getMinY(), summary.minZ),
|
2019-11-23 04:31:48 +00:00
|
|
|
BlockVector3
|
2021-08-17 21:13:51 +00:00
|
|
|
.at(summary.maxX, world.getMaxY(), summary.maxZ)
|
2021-07-24 15:34:05 +00:00
|
|
|
);
|
2019-11-23 04:31:48 +00:00
|
|
|
rollback.setTime(historyFile.lastModified());
|
2020-02-18 23:06:19 +00:00
|
|
|
RollbackDatabase db = DBHandler.IMP
|
2019-11-23 04:31:48 +00:00
|
|
|
.getDatabase(world);
|
|
|
|
db.logEdit(rollback);
|
2020-03-05 21:07:20 +00:00
|
|
|
actor.print(TextComponent.of("Logging: " + historyFile));
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-05 21:07:20 +00:00
|
|
|
actor.print(TextComponent.of("Done import!"));
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "info",
|
|
|
|
aliases = {"summary", "summarize"},
|
|
|
|
desc = "Summarize an edit"
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
2020-01-06 08:36:16 +00:00
|
|
|
@CommandPermissions("worldedit.history.info")
|
2021-07-24 15:34:05 +00:00
|
|
|
public synchronized void summary(
|
|
|
|
Player player, RollbackDatabase database, Arguments arguments,
|
|
|
|
@Arg(desc = "Player uuid/name")
|
|
|
|
UUID other,
|
|
|
|
@Arg(desc = "edit index")
|
|
|
|
Integer index
|
|
|
|
) throws WorldEditException, ExecutionException, InterruptedException {
|
2019-11-23 04:31:48 +00:00
|
|
|
RollbackOptimizedHistory edit = database.getEdit(other, index).get();
|
|
|
|
if (edit == null) {
|
2021-04-05 17:54:49 +00:00
|
|
|
player.print(Caption.of("fawe.worldedit.schematic.schematic.none"));
|
2019-11-23 04:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Location origin = player.getLocation();
|
|
|
|
|
|
|
|
String name = Fawe.imp().getName(edit.getUUID());
|
|
|
|
String cmd = edit.getCommand();
|
|
|
|
BlockVector3 pos1 = edit.getMinimumPoint();
|
|
|
|
BlockVector3 pos2 = edit.getMaximumPoint();
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
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()));
|
2019-11-23 04:31:48 +00:00
|
|
|
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();
|
|
|
|
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();
|
2020-01-06 08:36:16 +00:00
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
TranslatableComponent header = Caption.of(
|
|
|
|
"fawe.worldedit.history.find.element",
|
|
|
|
name,
|
|
|
|
timeStr,
|
|
|
|
distance,
|
|
|
|
direction.name(),
|
|
|
|
cmd
|
|
|
|
);
|
2020-01-06 08:36:16 +00:00
|
|
|
|
|
|
|
String sizeStr = StringMan.humanReadableByteCountBin(edit.getSizeOnDisk());
|
|
|
|
String extra = "";
|
2020-10-05 17:41:41 +00:00
|
|
|
if (biomes) {
|
|
|
|
extra += "biomes, ";
|
|
|
|
}
|
|
|
|
if (createdEnts) {
|
|
|
|
extra += "+entity, ";
|
|
|
|
}
|
|
|
|
if (removedEnts) {
|
|
|
|
extra += "-entity, ";
|
|
|
|
}
|
|
|
|
if (createdTiles) {
|
|
|
|
extra += "+tile, ";
|
|
|
|
}
|
|
|
|
if (removedTiles) {
|
|
|
|
extra += "-tile, ";
|
|
|
|
}
|
2020-01-06 08:36:16 +00:00
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
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));
|
2020-01-06 08:36:16 +00:00
|
|
|
TextComponentProducer content = new TextComponentProducer().append(header).newline().append(body).newline().append(distr);
|
|
|
|
player.print(content.create());
|
|
|
|
}
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
private PaginationBox list(
|
|
|
|
RollbackDatabase database,
|
|
|
|
String pageCommand,
|
|
|
|
List<Supplier<? extends ChangeSet>> histories,
|
|
|
|
BlockVector3 origin
|
|
|
|
) {
|
|
|
|
return PaginationBox.fromStrings("Edits:", pageCommand, histories, new Function<>() {
|
|
|
|
@Nonnull
|
|
|
|
@Override
|
|
|
|
public Component apply(@Nullable Supplier<? extends ChangeSet> 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 {
|
|
|
|
// TODO
|
|
|
|
return TextComponent.empty();
|
|
|
|
}
|
|
|
|
}
|
2020-01-06 08:36:16 +00:00
|
|
|
}
|
2021-07-24 15:34:05 +00:00
|
|
|
);
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "find",
|
|
|
|
aliases = {"inspect", "search", "near"},
|
|
|
|
desc = "Find nearby edits"
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.history.find")
|
2021-07-24 15:34:05 +00:00
|
|
|
public synchronized void find(
|
|
|
|
Player player, World world, RollbackDatabase database, Arguments arguments,
|
|
|
|
@ArgFlag(name = 'u', def = "", desc = "String user")
|
|
|
|
UUID other,
|
|
|
|
@ArgFlag(name = 'r', def = "0", desc = "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 = "")
|
|
|
|
Integer page
|
|
|
|
) throws WorldEditException {
|
2019-11-23 04:31:48 +00:00
|
|
|
if (!Settings.IMP.HISTORY.USE_DATABASE) {
|
2020-10-05 17:41:41 +00:00
|
|
|
player.print(Caption.of("fawe.error.setting.disable", "history.use-database (Import with //history import )"));
|
2019-11-23 04:31:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-10-05 17:41:41 +00:00
|
|
|
if (other == null && radius == 0 && timeDiff == 0) {
|
2021-04-05 17:54:49 +00:00
|
|
|
throw new InsufficientArgumentsException(Caption.of("fawe.error.invalid-user"));
|
2020-10-05 17:41:41 +00:00
|
|
|
}
|
2021-04-05 17:54:49 +00:00
|
|
|
checkCommandArgument(radius > 0, Caption.of("fawe.error.radius-too-small"));
|
|
|
|
checkCommandArgument(timeDiff > 0, Caption.of("fawe.error.time-too-less"));
|
2019-11-23 04:31:48 +00:00
|
|
|
|
|
|
|
Location origin = player.getLocation();
|
2019-12-25 02:34:20 +00:00
|
|
|
String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim();
|
2020-01-06 08:36:16 +00:00
|
|
|
Reference<List<Supplier<? extends ChangeSet>>> cached = player.getMeta(pageCommand);
|
|
|
|
List<Supplier<? extends ChangeSet>> history = cached == null ? null : cached.get();
|
2019-11-23 04:31:48 +00:00
|
|
|
|
2020-01-06 08:36:16 +00:00
|
|
|
if (page == null || history == null) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (other == null) {
|
|
|
|
other = player.getUniqueId();
|
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
if (!other.equals(player.getUniqueId())) {
|
|
|
|
player.checkPermission("worldedit.history.undo.other");
|
|
|
|
}
|
2020-10-05 17:41:41 +00:00
|
|
|
if (other == Identifiable.EVERYONE) {
|
|
|
|
other = null;
|
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
|
|
|
|
BlockVector3 bot = origin.toBlockPoint().subtract(radius, radius, radius);
|
|
|
|
BlockVector3 top = origin.toBlockPoint().add(radius, radius, radius);
|
2021-08-17 21:13:51 +00:00
|
|
|
bot = bot.clampY(world.getMinY(), world.getMaxY());
|
|
|
|
top = top.clampY(world.getMinY(), world.getMaxY());
|
2019-11-23 04:31:48 +00:00
|
|
|
|
|
|
|
long minTime = System.currentTimeMillis() - timeDiff;
|
|
|
|
Iterable<Supplier<RollbackOptimizedHistory>> edits = database.getEdits(other, minTime, bot, top, false, false);
|
2020-01-06 08:36:16 +00:00
|
|
|
history = Lists.newArrayList(edits);
|
|
|
|
player.setMeta(pageCommand, new SoftReference<>(history));
|
|
|
|
page = 1;
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-07 00:30:11 +00:00
|
|
|
PaginationBox box = list(database, pageCommand, history, origin.toBlockPoint());
|
|
|
|
player.print(box.create(page));
|
2020-01-06 08:36:16 +00:00
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
|
2020-01-06 08:36:16 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "distr",
|
|
|
|
aliases = {"distribution"},
|
|
|
|
desc = "View block distribution for an edit"
|
2020-01-06 08:36:16 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.history.distr")
|
2021-07-24 15:34:05 +00:00
|
|
|
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 {
|
2020-01-06 08:36:16 +00:00
|
|
|
String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim();
|
|
|
|
Reference<PaginationBox> cached = player.getMeta(pageCommand);
|
|
|
|
PaginationBox pages = cached == null ? null : cached.get();
|
|
|
|
if (page == null || pages == null) {
|
|
|
|
RollbackOptimizedHistory edit = database.getEdit(other, index).get();
|
2021-07-16 18:07:02 +00:00
|
|
|
SimpleChangeSetSummary summary = edit.summarize(RegionWrapper.GLOBAL(), false);
|
2020-01-06 08:36:16 +00:00
|
|
|
if (summary != null) {
|
|
|
|
List<Countable<BlockState>> distr = summary.getBlockDistributionWithData();
|
2021-07-24 15:34:05 +00:00
|
|
|
SelectionCommands.BlockDistributionResult distrPages = new SelectionCommands.BlockDistributionResult(
|
|
|
|
distr,
|
|
|
|
true,
|
|
|
|
pageCommand
|
|
|
|
);
|
2020-01-06 08:36:16 +00:00
|
|
|
pages = new PaginationBox.MergedPaginationBox("Block Distribution", pageCommand, pages, distrPages);
|
|
|
|
player.setMeta(pageCommand, new SoftReference<>(pages));
|
|
|
|
}
|
|
|
|
page = 1;
|
|
|
|
}
|
2021-07-16 18:07:02 +00:00
|
|
|
if (pages == null) {
|
|
|
|
player.print(Caption.of("fawe.worldedit.history.distr.summary_null"));
|
|
|
|
} else {
|
|
|
|
player.print(pages.create(page));
|
|
|
|
}
|
2020-01-06 08:36:16 +00:00
|
|
|
}
|
2019-11-23 04:31:48 +00:00
|
|
|
|
2020-01-06 08:36:16 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "list",
|
|
|
|
desc = "List your history"
|
2020-01-06 08:36:16 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.history.list")
|
2021-07-24 15:34:05 +00:00
|
|
|
public void list(
|
|
|
|
Player player, LocalSession session, RollbackDatabase database, Arguments arguments,
|
|
|
|
@Arg(desc = "Player uuid/name")
|
|
|
|
UUID other,
|
|
|
|
@ArgFlag(name = 'p', desc = "Page to view.", def = "")
|
|
|
|
Integer page
|
|
|
|
) {
|
2020-01-06 08:36:16 +00:00
|
|
|
int index = session.getHistoryIndex();
|
2021-07-24 15:34:05 +00:00
|
|
|
List<Supplier<? extends ChangeSet>> history = Lists.transform(
|
|
|
|
session.getHistory(),
|
|
|
|
(Function<ChangeSet, Supplier<ChangeSet>>) input -> () -> input
|
|
|
|
);
|
2020-01-07 00:30:11 +00:00
|
|
|
Location origin = player.getLocation();
|
|
|
|
String pageCommand = "/" + arguments.get().replaceAll("-p [0-9]+", "").trim();
|
|
|
|
Reference<PaginationBox> cached = player.getMeta(pageCommand);
|
|
|
|
PaginationBox pages = cached == null ? null : cached.get();
|
|
|
|
if (page == null || pages == null) {
|
|
|
|
pages = list(database, pageCommand, history, origin.toBlockPoint());
|
|
|
|
page = 1;
|
|
|
|
}
|
|
|
|
player.print(pages.create(page));
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "clear",
|
|
|
|
desc = "Clear your history"
|
2019-11-23 04:31:48 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.history.clear")
|
|
|
|
public void clearHistory(Actor actor, LocalSession session) {
|
|
|
|
parent.clearHistory(actor, session);
|
|
|
|
}
|
2021-07-24 15:34:05 +00:00
|
|
|
|
2019-11-23 04:31:48 +00:00
|
|
|
}
|