package com.boydti.fawe.command; import static com.google.common.base.Preconditions.checkNotNull; import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; import com.boydti.fawe.jnbt.anvil.MCAClipboard; import com.boydti.fawe.jnbt.anvil.MCAFile; import com.boydti.fawe.jnbt.anvil.MCAFilter; import com.boydti.fawe.jnbt.anvil.MCAFilterCounter; import com.boydti.fawe.jnbt.anvil.MCAQueue; import com.boydti.fawe.jnbt.anvil.filters.DebugFixP2Roads; import com.boydti.fawe.jnbt.anvil.filters.DeleteBiomeFilterSimple; import com.boydti.fawe.jnbt.anvil.filters.DeleteOldFilter; import com.boydti.fawe.jnbt.anvil.filters.DeleteUnclaimedFilter; import com.boydti.fawe.jnbt.anvil.filters.DeleteUninhabitedFilter; import com.boydti.fawe.jnbt.anvil.filters.PlotTrimFilter; import com.boydti.fawe.jnbt.anvil.filters.RemapFilter; import com.boydti.fawe.jnbt.anvil.filters.RemoveLayerFilter; import com.boydti.fawe.jnbt.anvil.filters.SetPatternFilter; import com.boydti.fawe.jnbt.anvil.filters.TrimAirFilter; import com.boydti.fawe.jnbt.anvil.history.IAnvilHistory; import com.boydti.fawe.jnbt.anvil.history.NullAnvilHistory; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal4; import com.boydti.fawe.object.changeset.AnvilHistory; import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.SetQueue; import org.enginehub.piston.annotation.Command; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import java.io.IOException; import java.io.RandomAccessFile; import java.util.function.Consumer; @Command(aliases = {"/anvil"}, desc = "Manipulate billions of blocks: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Anvil-API)") public class AnvilCommands { private final WorldEdit worldEdit; /** * Create a new instance. * * @param worldEdit reference to WorldEdit */ public AnvilCommands(WorldEdit worldEdit) { checkNotNull(worldEdit); this.worldEdit = worldEdit; } /** * Run safely on an unloaded world (no selection) * * @param player * @param folder * @param filter * @param * @param * @return */ @Deprecated public static > T runWithWorld(Player player, String folder, T filter, boolean force) { return runWithWorld(player, folder, filter, force, false); } @Deprecated public static > T runWithWorld(Player player, String folder, T filter, boolean force, boolean unsafe) { boolean copy = false; if (FaweAPI.getWorld(folder) != null) { if (!force) { BBC.WORLD_IS_LOADED.send(player); return null; } copy = true; } FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(folder, true, false); MCAQueue queue = new MCAQueue(defaultQueue); if (copy && !unsafe) { return queue.filterCopy(filter, RegionWrapper.GLOBAL()); } else { return queue.filterWorld(filter); } } /** * Run safely on an existing world within a selection * * @param player * @param editSession * @param selection * @param filter * @param * @param * @return */ @Deprecated public static > T runWithSelection(Player player, EditSession editSession, Region selection, T filter) { if (!(selection instanceof CuboidRegion)) { BBC.NO_REGION.send(player); return null; } CuboidRegion cuboid = (CuboidRegion) selection; RegionWrapper wrappedRegion = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint()); String worldName = editSession.getWorld().getName(); FaweQueue tmp = SetQueue.IMP.getNewQueue(worldName, true, false); MCAQueue queue = new MCAQueue(tmp); FawePlayer fp = FawePlayer.wrap(player); fp.checkAllowedRegion(selection); recordHistory(fp, editSession.getWorld(), iAnvilHistory -> { queue.filterCopy(filter, wrappedRegion, iAnvilHistory); }); return filter; } public static void recordHistory(FawePlayer fp, World world, Consumer run) { LocalSession session = fp.getSession(); if (session == null || session.hasFastMode()) { run.accept(new NullAnvilHistory()); } else { AnvilHistory history = new AnvilHistory(world.getName(), fp.getUUID()); run.accept(history); session.remember(fp.getPlayer(), world, history, fp.getLimit()); } } @Command( aliases = {"replaceall", "rea", "repall"}, usage = " [from-block] ", desc = "Replace all blocks in the selection with another", help = "Replace all blocks in the selection with another\n" + "The -d flag disabled wildcard data matching\n", flags = "df" ) @CommandPermissions("worldedit.anvil.replaceall") public void replaceAll(Player player, String folder, @Optional String from, String to, @Switch('d') boolean useData) throws WorldEditException { // final FaweBlockMatcher matchFrom; // if (from == null) { // matchFrom = FaweBlockMatcher.NOT_AIR; // } else { // if (from.contains(":")) { // useData = true; //override d flag, if they specified data they want it // } // matchFrom = FaweBlockMatcher.fromBlocks(worldEdit.getBlocks(player, from, true), useData); // } // final FaweBlockMatcher matchTo = FaweBlockMatcher.setBlocks(worldEdit.getBlocks(player, to, true)); // ReplaceSimpleFilter filter = new ReplaceSimpleFilter(matchFrom, matchTo); // ReplaceSimpleFilter result = runWithWorld(player, folder, filter, true); // if (result != null) player.print(BBC.VISITOR_BLOCK.format(result.getTotal())); } @Command( aliases = {"remapall"}, usage = "", help = "Remap the world between MCPE/PC values", desc = "Remap the world between MCPE/PC values" ) @CommandPermissions("worldedit.anvil.remapall") public void remapall(Player player, String folder) throws WorldEditException { ClipboardRemapper mapper; ClipboardRemapper.RemapPlatform from; ClipboardRemapper.RemapPlatform to; from = ClipboardRemapper.RemapPlatform.PE; to = ClipboardRemapper.RemapPlatform.PC; RemapFilter filter = new RemapFilter(from, to); RemapFilter result = runWithWorld(player, folder, filter, true); if (result != null) player.print(BBC.VISITOR_BLOCK.format(result.getTotal())); } @Command( aliases = {"deleteallunvisited", "delunvisited" }, usage = " [file-age=60000]", desc = "Delete all chunks which haven't been occupied", help = "Delete all chunks which haven't been occupied for `age-ticks` (20t = 1s) and \n" + "Have not been accessed since `file-duration` (ms) after creation and\n" + "Have not been used in the past `chunk-inactivity` (ms)" + "The auto-save interval is the recommended value for `file-duration` and `chunk-inactivity`" ) @CommandPermissions("worldedit.anvil.deleteallunvisited") public void deleteAllUnvisited(Player player, String folder, int inhabitedTicks, @Optional("60000") int fileDurationMillis) throws WorldEditException { DeleteUninhabitedFilter filter = new DeleteUninhabitedFilter(fileDurationMillis, inhabitedTicks, fileDurationMillis); DeleteUninhabitedFilter result = runWithWorld(player, folder, filter, true); if (result != null) player.print(BBC.VISITOR_BLOCK.format(result.getTotal())); } @Command( aliases = {"deleteallunclaimed", "delallunclaimed" }, usage = " [file-age=60000]", desc = "(Supports: WG, P2, GP) Delete all chunks which haven't been occupied AND claimed", help = "(Supports: WG, P2, GP) Delete all chunks which aren't claimed AND haven't been occupied for `age-ticks` (20t = 1s) and \n" + "Have not been accessed since `file-duration` (ms) after creation and\n" + "Have not been used in the past `chunk-inactivity` (ms)" + "The auto-save interval is the recommended value for `file-duration` and `chunk-inactivity`", min = 1, max = 3 ) @CommandPermissions("worldedit.anvil.deleteallunclaimed") public void deleteAllUnclaimed(Player player, int inhabitedTicks, @Optional("60000") int fileDurationMillis, @Switch('d') boolean debug) throws WorldEditException { String folder = player.getWorld().getName(); DeleteUnclaimedFilter filter = new DeleteUnclaimedFilter(player.getWorld(), fileDurationMillis, inhabitedTicks, fileDurationMillis); if (debug) filter.enableDebug(); DeleteUnclaimedFilter result = runWithWorld(player, folder, filter, true); if (result != null) player.print(BBC.VISITOR_BLOCK.format(result.getTotal())); } @Command( name = "deleteunclaimed", usage = " [file-age=60000]", desc = "(Supports: WG, P2, GP) Delete all chunks which haven't been occupied AND claimed", help = "(Supports: WG, P2, GP) Delete all chunks which aren't claimed AND haven't been occupied for `age-ticks` (20t = 1s) and \n" + "Have not been accessed since `file-duration` (ms) after creation and\n" + "Have not been used in the past `chunk-inactivity` (ms)" + "The auto-save interval is the recommended value for `file-duration` and `chunk-inactivity`", min = 1, max = 3 ) @CommandPermissions("worldedit.anvil.deleteunclaimed") public void deleteUnclaimed(Player player, EditSession editSession, @Selection Region selection, int inhabitedTicks, @Optional("60000") int fileDurationMillis, @Switch('d') boolean debug) throws WorldEditException { DeleteUnclaimedFilter filter = new DeleteUnclaimedFilter(player.getWorld(), fileDurationMillis, inhabitedTicks, fileDurationMillis); if (debug) filter.enableDebug(); DeleteUnclaimedFilter result = runWithSelection(player, editSession, selection, filter); if (result != null) player.print(BBC.VISITOR_BLOCK.format(result.getTotal())); } @Command( aliases = {"deletealloldregions", "deloldreg" }, usage = "