From 6996a970270e85e9650b5536ba813de8fcf18fbe Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Thu, 11 Apr 2019 21:32:32 +1000 Subject: [PATCH] various minor CFI works without PlotSquared tab completion biome tweaks WIP on anvil document disallowed-blocks in legacy config --- .../com/boydti/fawe/bukkit/FaweBukkit.java | 13 +- .../bukkit/listener/ATabCompleteListener.java | 2 +- .../listener/AsyncTabCompleteListener.java | 3 +- .../main/resources/defaults/config-legacy.yml | 3 + .../com/boydti/fawe/command/CFICommands.java | 158 ++++++++---------- .../com/boydti/fawe/command/PlotLoader.java | 96 +++++++++++ .../com/boydti/fawe/jnbt/anvil/MCAChunk.java | 77 ++++----- .../com/boydti/fawe/jnbt/anvil/MCAQueue.java | 2 +- .../fawe/jnbt/anvil/WritableMCAChunk.java | 3 +- .../com/boydti/fawe/object/FaweChunk.java | 4 + .../fawe/object/changeset/FaweChangeSet.java | 5 +- .../fawe/object/extent/TransformExtent.java | 2 - .../java/com/boydti/fawe/util/StringMan.java | 54 ++++++ .../extension/platform/CommandManager.java | 63 +++---- .../function/mask/BlockMaskBuilder.java | 5 +- .../parametric/AParametricCallable.java | 29 ++-- .../worldedit/world/block/BlockState.java | 8 +- .../worldedit/world/block/BlockTypes.java | 3 +- 18 files changed, 327 insertions(+), 203 deletions(-) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 0a2444c3f..68d21ade2 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -3,10 +3,12 @@ package com.boydti.fawe.bukkit; import com.boydti.fawe.Fawe; import com.boydti.fawe.IFawe; import com.boydti.fawe.bukkit.chat.BukkitChatManager; +import com.boydti.fawe.bukkit.listener.AsyncTabCompleteListener; import com.boydti.fawe.bukkit.listener.BrushListener; import com.boydti.fawe.bukkit.listener.BukkitImageListener; import com.boydti.fawe.bukkit.listener.CFIPacketListener; import com.boydti.fawe.bukkit.listener.RenderListener; +import com.boydti.fawe.bukkit.listener.SyncTabCompleteListener; import com.boydti.fawe.bukkit.regions.ASkyBlockHook; import com.boydti.fawe.bukkit.regions.FactionsFeature; import com.boydti.fawe.bukkit.regions.FactionsOneFeature; @@ -40,6 +42,7 @@ import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.cui.CUI; import com.boydti.fawe.util.image.ImageViewer; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; import org.bukkit.command.ConsoleCommandSender; @@ -127,13 +130,13 @@ public class FaweBukkit implements IFawe, Listener { new ChunkListener_9(); } - /*try { + try { Class.forName("com.destroystokyo.paper.event.server.AsyncTabCompleteEvent"); - new AsyncTabCompleteListener(WorldEditPlugin.getInstance()); - } catch (Throwable ignore) - { + Bukkit.getPluginManager().registerEvents(new AsyncTabCompleteListener(WorldEditPlugin.getInstance()), plugin); + } catch (Throwable ignore) { + ignore.printStackTrace(); Bukkit.getPluginManager().registerEvents(new SyncTabCompleteListener(WorldEditPlugin.getInstance()), plugin); - }*/ + } }); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/ATabCompleteListener.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/ATabCompleteListener.java index 04a66c2c2..53c0a9b70 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/ATabCompleteListener.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/ATabCompleteListener.java @@ -32,7 +32,7 @@ public class ATabCompleteListener implements Listener { CommandSuggestionEvent event = new CommandSuggestionEvent(worldEdit.wrapCommandSender(sender), buffer.substring(index, buffer.length())); worldEdit.getWorldEdit().getEventBus().post(event); List suggestions = event.getSuggestions(); - if (suggestions != null) { + if (suggestions != null && !suggestions.isEmpty()) { return suggestions; } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/AsyncTabCompleteListener.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/AsyncTabCompleteListener.java index 2334edefb..33253f629 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/AsyncTabCompleteListener.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/AsyncTabCompleteListener.java @@ -14,14 +14,13 @@ import java.util.List; public class AsyncTabCompleteListener extends ATabCompleteListener { public AsyncTabCompleteListener(WorldEditPlugin worldEdit) { super(worldEdit); - Bukkit.getPluginManager().registerEvents(this, worldEdit); } @EventHandler public void onTabComplete(AsyncTabCompleteEvent event) { if (event.isCommand()) { List result = this.onTab(event.getBuffer(), event.getSender()); - if (result != null) { + if (result != null && !result.isEmpty()) { event.setCompletions(result); event.setHandled(true); } diff --git a/worldedit-bukkit/src/main/resources/defaults/config-legacy.yml b/worldedit-bukkit/src/main/resources/defaults/config-legacy.yml index 624b7dc7d..681dd21c9 100644 --- a/worldedit-bukkit/src/main/resources/defaults/config-legacy.yml +++ b/worldedit-bukkit/src/main/resources/defaults/config-legacy.yml @@ -18,6 +18,7 @@ limits: max-blocks-changed: + # Ignored, use FAWE config limits default: -1 maximum: -1 max-polygonal-points: @@ -29,6 +30,8 @@ limits: butcher-radius: default: -1 maximum: -1 + # Use either block ids, names, or regex + # Regex supports properties as well (see FAWE mask documentation) disallowed-blocks: [] use-inventory: diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java index 67247737a..404fef5da 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java @@ -1,43 +1,40 @@ package com.boydti.fawe.command; import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; +import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Commands; import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.clipboard.MultiClipboardHolder; import com.boydti.fawe.object.pattern.PatternExtent; -import com.boydti.fawe.util.*; +import com.boydti.fawe.util.CleanTextureUtil; +import com.boydti.fawe.util.FilteredTextureUtil; +import com.boydti.fawe.util.ImgurUtility; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.SetQueue; +import com.boydti.fawe.util.StringMan; +import com.boydti.fawe.util.TaskManager; +import com.boydti.fawe.util.TextureUtil; import com.boydti.fawe.util.chat.Message; import com.boydti.fawe.util.image.ImageUtil; -import com.github.intellectualsites.plotsquared.plot.PlotSquared; -import com.github.intellectualsites.plotsquared.plot.commands.Auto; -import com.github.intellectualsites.plotsquared.plot.config.Captions; -import com.github.intellectualsites.plotsquared.plot.config.Settings; -import com.github.intellectualsites.plotsquared.plot.database.DBFunc; -import com.github.intellectualsites.plotsquared.plot.object.Plot; -import com.github.intellectualsites.plotsquared.plot.object.PlotArea; -import com.github.intellectualsites.plotsquared.plot.object.PlotId; -import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; -import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager; -import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; -import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; -import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.worldedit.*; -import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.EmptyClipboardException; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.MethodCommands; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.BlockPattern; @@ -47,6 +44,7 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; @@ -56,6 +54,8 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; + +import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.io.ByteArrayOutputStream; @@ -68,8 +68,11 @@ import java.text.SimpleDateFormat; import java.util.ArrayDeque; import java.util.Date; import java.util.HashSet; +import java.util.List; import java.util.Set; -import javax.imageio.ImageIO; +import java.util.function.Consumer; +import java.util.function.Function; + import static com.boydti.fawe.util.image.ImageUtil.load; @Command(aliases = {"/cfi"}, desc = "Create a world from images: [More Info](https://git.io/v5iDy)") @@ -87,8 +90,11 @@ public class CFICommands extends MethodCommands { this.dispathcer= dispatcher; } - private File getFolder(String worldName) { - return new File(PlotSquared.imp().getWorldContainer(), worldName + File.separator + "region"); + public static File getFolder(String worldName) { + Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); + List worlds = platform.getWorlds(); + FaweQueue queue = SetQueue.IMP.getNewQueue(worlds.get(0), true, false); + return new File(queue.getSaveFolder().getParentFile().getParentFile(), worldName + File.separator + "region"); } @Command( @@ -174,23 +180,6 @@ public class CFICommands extends MethodCommands { fp.sendMessage(BBC.getPrefix() + "Cancelled!"); } - @Deprecated - public static void autoClaimFromDatabase(PlotPlayer player, PlotArea area, PlotId start, com.github.intellectualsites.plotsquared.plot.object.RunnableVal whenDone) { - final Plot plot = area.getNextFreePlot(player, start); - if (plot == null) { - whenDone.run(null); - return; - } - whenDone.value = plot; - plot.owner = player.getUUID(); - DBFunc.createPlotSafe(plot, whenDone, new Runnable() { - @Override - public void run() { - autoClaimFromDatabase(player, area, plot.getId(), whenDone); - } - }); - } - @Command( aliases = {"done", "create"}, usage = "", @@ -199,59 +188,54 @@ public class CFICommands extends MethodCommands { @CommandPermissions("worldedit.anvil.cfi") public void done(FawePlayer fp) throws ParameterException, IOException { CFISettings settings = assertSettings(fp); + HeightMapMCAGenerator generator = settings.getGenerator(); - PlotAreaManager manager = PlotSquared.get().getPlotAreaManager(); - if (manager instanceof SinglePlotAreaManager) { - SinglePlotAreaManager sManager = (SinglePlotAreaManager) manager; - SinglePlotArea area = sManager.getArea(); - PlotPlayer player = PlotPlayer.wrap(fp.parent); - - fp.sendMessage(BBC.getPrefix() + "Claiming world"); - Plot plot = TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Plot o) { - int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(area.worldname); - int diff = player.getAllowedPlots() - currentPlots; - if (diff < 1) { - Captions.CANT_CLAIM_MORE_PLOTS_NUM.send(player, -diff); - return; + Function function = new Function() { + @Override + public Boolean apply(File folder) { + if (folder != null) { + try { + generator.setFolder(folder); + fp.sendMessage(BBC.getPrefix() + "Generating " + folder); + generator.generate(); + generator.setPacketViewer(null); + generator.setImageViewer(null); + settings.remove(); + fp.sendMessage(BBC.getPrefix() + "Done!"); + return true; + } catch (IOException e) { + throw new RuntimeException(e); } + } else { + fp.sendMessage("Unable to generate world... (see console)?"); + } + return false; + } + }; - if (area.getMeta("lastPlot") == null) { - area.setMeta("lastPlot", new PlotId(0, 0)); - } - PlotId lastId = (PlotId) area.getMeta("lastPlot"); - while (true) { - lastId = Auto.getNextPlotId(lastId, 1); - if (area.canClaim(player, lastId, lastId)) { - break; + try { + new PlotLoader().load(fp, settings, function); + } catch (Throwable ignore) { + ignore.printStackTrace(); + function.apply(generator.getFolder().getParentFile()); + } + + File folder = generator.getFolder(); + if (folder != null) { + World world = FaweAPI.getWorld(folder.getName()); + if (world != null) { + if (fp.getWorld() != world) { + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + Location spawn = new Location(world, world.getSpawnPosition().toVector3()); + fp.getPlayer().setPosition(spawn); } - } - area.setMeta("lastPlot", lastId); - this.value = area.getPlot(lastId); - this.value.setOwner(player.getUUID()); + }); } - }); - if (plot == null) return; - - File folder = getFolder(plot.getWorldName()); - HeightMapMCAGenerator generator = settings.getGenerator(); - generator.setFolder(folder); - - fp.sendMessage(BBC.getPrefix() + "Generating"); - generator.generate(); - generator.setPacketViewer(null); - generator.setImageViewer(null); - settings.remove(); - fp.sendMessage(BBC.getPrefix() + "Done!"); - TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Object value) { - plot.teleportPlayer(player); - } - }); - } else { - fp.sendMessage(BBC.getPrefix() + "Must have the `worlds` component enabled in the PlotSquared config.yml"); + } else { + fp.sendMessage("Unable to import world (" + folder.getName() + ") please do so manually"); + } } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java b/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java new file mode 100644 index 000000000..8c4402947 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java @@ -0,0 +1,96 @@ +package com.boydti.fawe.command; + +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.util.TaskManager; +import com.github.intellectualsites.plotsquared.plot.PlotSquared; +import com.github.intellectualsites.plotsquared.plot.commands.Auto; +import com.github.intellectualsites.plotsquared.plot.config.Captions; +import com.github.intellectualsites.plotsquared.plot.config.Settings; +import com.github.intellectualsites.plotsquared.plot.database.DBFunc; +import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotArea; +import com.github.intellectualsites.plotsquared.plot.object.PlotId; +import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; +import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager; +import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; +import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; +import com.sk89q.worldedit.function.pattern.FawePattern; +import com.sk89q.worldedit.util.Location; + +import java.io.File; +import java.io.IOException; +import java.util.function.Consumer; +import java.util.function.Function; + +public class PlotLoader { + @Deprecated + public static void autoClaimFromDatabase(PlotPlayer player, PlotArea area, PlotId start, com.github.intellectualsites.plotsquared.plot.object.RunnableVal whenDone) { + final Plot plot = area.getNextFreePlot(player, start); + if (plot == null) { + whenDone.run(null); + return; + } + whenDone.value = plot; + plot.owner = player.getUUID(); + DBFunc.createPlotSafe(plot, whenDone, new Runnable() { + @Override + public void run() { + autoClaimFromDatabase(player, area, plot.getId(), whenDone); + } + }); + } + + public void load(FawePlayer fp, CFICommands.CFISettings settings, Function createTask) throws IOException { + PlotAreaManager manager = PlotSquared.get().getPlotAreaManager(); + if (manager instanceof SinglePlotAreaManager) { + SinglePlotAreaManager sManager = (SinglePlotAreaManager) manager; + SinglePlotArea area = sManager.getArea(); + PlotPlayer player = PlotPlayer.wrap(fp.parent); + + fp.sendMessage(BBC.getPrefix() + "Claiming world"); + Plot plot = TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Plot o) { + int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(area.worldname); + int diff = player.getAllowedPlots() - currentPlots; + if (diff < 1) { + Captions.CANT_CLAIM_MORE_PLOTS_NUM.send(player, -diff); + return; + } + + if (area.getMeta("lastPlot") == null) { + area.setMeta("lastPlot", new PlotId(0, 0)); + } + PlotId lastId = (PlotId) area.getMeta("lastPlot"); + while (true) { + lastId = Auto.getNextPlotId(lastId, 1); + if (area.canClaim(player, lastId, lastId)) { + break; + } + } + area.setMeta("lastPlot", lastId); + this.value = area.getPlot(lastId); + this.value.setOwner(player.getUUID()); + } + }); + if (plot != null) { + + File folder = CFICommands.getFolder(plot.getWorldName()); + Boolean result = createTask.apply(folder); + if (result == Boolean.TRUE) { + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + plot.teleportPlayer(player); + } + }); + } + return; + } + } + createTask.apply(null); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java index 9f279365e..97e46bbb2 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java @@ -12,6 +12,7 @@ import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.jnbt.*; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; import java.io.DataOutput; import java.io.DataOutputStream; @@ -21,17 +22,6 @@ import java.util.function.BiConsumer; public class MCAChunk extends FaweChunk { -// ids: byte[16][4096] -// data: byte[16][2048] -// skylight: byte[16][2048] -// blocklight: byte[16][2048] -// entities: Map -// tiles: List -// biomes: byte[256] -// compressedSize: int -// modified: boolean -// deleted: boolean - public int[][] ids; public byte[][] skyLight; public byte[][] blockLight; @@ -88,6 +78,9 @@ public class MCAChunk extends FaweChunk { } public void write(NBTOutputStream nbtOut) throws IOException { + + + nbtOut.writeNamedTagName("", NBTConstants.TYPE_COMPOUND); nbtOut.writeLazyCompoundTag("Level", out -> { out.writeNamedTag("V", (byte) 1); @@ -224,7 +217,6 @@ public class MCAChunk extends FaweChunk { int startIndexShift = startIndex >> 1; int endIndexShift = endIndex >> 1; int otherStartIndexShift = otherStartIndex >> 1; - int otherEndIndexShift = otherEndIndex >> 1; if ((startIndex & 1) != 0) { startIndexShift++; otherStartIndexShift++; @@ -233,7 +225,6 @@ public class MCAChunk extends FaweChunk { } if ((endIndex & 1) != 1) { endIndexShift--; - otherEndIndexShift--; setNibble(endIndex, thisSkyLight, getNibble(otherEndIndex, otherSkyLight)); setNibble(endIndex, thisBlockLight, getNibble(otherEndIndex, otherBlockLight)); } @@ -365,7 +356,7 @@ public class MCAChunk extends FaweChunk { } if (!other.entities.isEmpty()) { for (Map.Entry entry : other.entities.entrySet()) { - // TODO + // TODO FIXME } } } @@ -601,27 +592,27 @@ public class MCAChunk extends FaweChunk { @Override public int getBlockCombinedId(int x, int y, int z) { - // TODO FIXME - return 0; -// int layer = y >> 4; -// byte[] idLayer = ids[layer]; -// if (idLayer == null) { -// return 0; -// } -// int j = FaweCache.CACHE_J[y][z & 15][x & 15]; -// int id = idLayer[j] & 0xFF; -// if (FaweCache.hasData(id)) { -// byte[] dataLayer = data[layer]; -// if (dataLayer != null) { -// return (id << 4) + getNibble(j, dataLayer); -// } -// } -// return id << 4; + int layer = y >> 4; + int[] idLayer = ids[layer]; + if (idLayer == null) { + return 0; + } + int j = FaweCache.CACHE_J[y][z & 15][x & 15]; + return idLayer[j]; } @Override public BiomeType[] getBiomeArray() { - return null; + BiomeType[] arr = new BiomeType[256]; + for (int i = 0; i < arr.length; i++) { + arr[i] = BiomeTypes.get(biomes[i]); + } + return arr; + } + + @Override + public BiomeType getBiomeType(int x, int z) { + return BiomeTypes.get(biomes[(x & 15) + ((z & 15) << 4)]); } @Override @@ -730,20 +721,16 @@ public class MCAChunk extends FaweChunk { @Override public void setBlock(int x, int y, int z, int combinedId) { - // TODO FIXME -// setModified(); -// int layer = y >> 4; -// byte[] idsLayer = ids[layer]; -// if (idsLayer == null) { -// idsLayer = this.ids[layer] = new byte[4096]; -// this.data[layer] = new byte[2048]; -// this.skyLight[layer] = new byte[2048]; -// this.blockLight[layer] = new byte[2048]; -// } -// int j = FaweCache.CACHE_J[y][z & 15][x & 15]; -// idsLayer[j] = (byte) id; -// byte[] dataLayer = this.data[layer]; -// setNibble(j, dataLayer, data); + setModified(); + int layer = y >> 4; + int[] idsLayer = ids[layer]; + if (idsLayer == null) { + idsLayer = this.ids[layer] = new int[4096]; + this.skyLight[layer] = new byte[2048]; + this.blockLight[layer] = new byte[2048]; + } + int j = FaweCache.CACHE_J[y][z & 15][x & 15]; + idsLayer[j] = combinedId; } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java index b54dac7cf..a05b93f36 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java @@ -88,7 +88,7 @@ public class MCAQueue extends NMSMappedFaweQueue { // cleanup } catch (Throwable e) { Arrays.fill(blockToPalette, Integer.MAX_VALUE); - System.out.println("======================== exception e"); + e.printStackTrace(); throw e; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java index a1e87a3e0..6361ea4f2 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweChunk.java @@ -169,6 +169,10 @@ public abstract class FaweChunk implements Callable { public abstract BiomeType[] getBiomeArray(); + public BiomeType getBiomeType(int x, int z) { + return getBiomeArray()[(x & 15) + ((z & 15) << 4)]; + } + public void forEachQueuedBlock(FaweChunkVisitor onEach) { for (int y = 0; y < HEIGHT; y++) { for (int z = 0; z < 16; z++) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java index bd9edd915..3f5e2747a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java @@ -266,9 +266,8 @@ public abstract class FaweChangeSet implements ChangeSet { int bx = cx << 4; int bz = cz << 4; synchronized (FaweChangeSet.this) { - // Biome changes - if (previous.getBiomeArray() != null) { - BiomeType[] previousBiomes = previous.getBiomeArray(); + BiomeType[] previousBiomes = previous.getBiomeArray(); + if (previousBiomes != null) { BiomeType[] nextBiomes = next.getBiomeArray(); int index = 0; for (int z = 0; z < 16; z++) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TransformExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TransformExtent.java index 8ba661862..0fae70cb3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TransformExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TransformExtent.java @@ -107,14 +107,12 @@ public class TransformExtent extends BlockTransformExtent { @Override public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException { - System.out.println("Set block transform"); return super.setBlock(getPos(x, y, z), transformInverse(block)); } @Override public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException { - System.out.println("Set block transform2"); return super.setBlock(getPos(location), transformInverse(block)); } 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 1622629f9..f621d01cd 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 @@ -1,5 +1,7 @@ package com.boydti.fawe.util; +import com.sk89q.util.StringUtil; + import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; @@ -12,6 +14,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.IntConsumer; import java.util.function.IntFunction; +import java.util.function.Predicate; public class StringMan { public static String replaceFromMap(final String string, final Map replacements) { @@ -323,6 +326,57 @@ public class StringMan { return true; } + public static Comparator blockStateComparator(String input) { + return new Comparator() { + @Override + public int compare(String o1, String o2) { + return blockStateStringDistance(input, o1) - blockStateStringDistance(input, o2); + } + }; + } + + public static boolean blockStateMatches(String input, String item) { + return blockStateStringDistance(input, item) != Integer.MAX_VALUE; + } + + public static int blockStateStringDistance(String input, String item) { + int distance = 0; + boolean sequentail = false; + int j = 0; + for (int i = 0; i < input.length(); i++) { + char ai = input.charAt(i); + outer: + while (true) { + if (j >= item.length()) return Integer.MAX_VALUE; + + char bj = item.charAt(j++); + if (sequentail) { + switch (bj) { + case ':': + case '_': + sequentail = false; + if (bj == ai) break outer; + continue; + } + continue; + } + if (bj != ai) { + distance++; + switch (bj) { + case ':': + case '_': + continue; + default: + sequentail = true; + continue; + } + } + break; + } + } + return distance; + } + public static int getLevenshteinDistance(String s, String t) { int n = s.length(); int m = t.length(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 3da51e2ae..3479ec3a4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -286,6 +286,7 @@ public final class CommandManager { .group("/anvil") .describeAs("Anvil command") .registerMethods(new AnvilCommands(worldEdit)).parent() + .registerMethods(new CFICommand(worldEdit, builder)) .registerMethods(new BiomeCommands(worldEdit)) .registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit)) @@ -318,6 +319,7 @@ public final class CommandManager { .group("superpickaxe", "pickaxe", "sp").describeAs("Super-pickaxe commands") .registerMethods(new SuperPickaxeCommands(worldEdit)) .parent().graph().getDispatcher(); + if (platform != null) { platform.registerCommands(dispatcher); } @@ -336,49 +338,34 @@ public final class CommandManager { this.platform = platform; // Delay command registration to allow time for other plugins to hook into FAWE - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - synchronized (CommandManager.this) { - try { - Class.forName("com.github.intellectualsites.plotsquared.plot.PlotSquared"); - CFICommand cfi = new CFICommand(worldEdit, builder); - registerCommands(cfi); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + try { + new CommandScriptLoader().load(); + } catch (Throwable e) { + e.printStackTrace(); + } - try { - new CommandScriptLoader().load(); - } catch (Throwable e) { - e.printStackTrace(); - } + LocalConfiguration config = platform.getConfiguration(); + boolean logging = config.logCommands; + String path = config.logFile; - LocalConfiguration config = platform.getConfiguration(); - boolean logging = config.logCommands; - String path = config.logFile; + // Register log + if (!logging || path.isEmpty()) { + dynamicHandler.setHandler(null); + commandLog.setLevel(Level.OFF); + } else { + File file = new File(config.getWorkingDirectory(), path); + commandLog.setLevel(Level.ALL); - // Register log - if (!logging || path.isEmpty()) { - dynamicHandler.setHandler(null); - commandLog.setLevel(Level.OFF); - } else { - File file = new File(config.getWorkingDirectory(), path); - commandLog.setLevel(Level.ALL); + log.info("Logging WorldEdit commands to " + file.getAbsolutePath()); - log.info("Logging WorldEdit commands to " + file.getAbsolutePath()); - - try { - dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true)); - } catch (IOException e) { - log.warn("Could not use command log file " + path + ": " + e.getMessage()); - } - } - - setupDispatcher(); - } + try { + dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true)); + } catch (IOException e) { + log.warn("Could not use command log file " + path + ": " + e.getMessage()); } - }); + } + + setupDispatcher(); } public void unregister() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java index fe2844bbc..5036a87c4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java @@ -229,7 +229,10 @@ public class BlockMaskBuilder { throw new SuggestInputParseException(input + " does not have: " + property, input, () -> { Set keys = new HashSet<>(); finalTypes.forEach(t -> t.getProperties().stream().forEach(p -> keys.add(p.getKey()))); - return keys.stream().map(p -> p.getId()).filter(p -> p.startsWith(property)).collect(Collectors.toList()); + return keys.stream().map(p -> p.getId()) + .filter(p -> StringMan.blockStateMatches(property, p)) + .sorted(StringMan.blockStateComparator(property)) + .collect(Collectors.toList()); }); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AParametricCallable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AParametricCallable.java index 64964d07c..91abf5dff 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AParametricCallable.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AParametricCallable.java @@ -228,20 +228,23 @@ public abstract class AParametricCallable implements CommandCallable { for (;maxConsumedI < parameters.length; maxConsumedI++) { parameter = parameters[maxConsumedI]; if (parameter.getBinding().getBehavior(parameter) != BindingBehavior.PROVIDES) { - // Parse the user input into a method argument - ArgumentStack usedArguments = getScopedContext(parameter, scoped); + if (mayConsumeArguments(maxConsumedI, scoped)) { + // Parse the user input into a method argument + ArgumentStack usedArguments = getScopedContext(parameter, scoped); - usedArguments.mark(); - try { - parameter.getBinding().bind(parameter, usedArguments, false); - minConsumedI = maxConsumedI + 1; - } catch (Throwable e) { - while (e.getCause() != null && !(e instanceof ParameterException || e instanceof InvocationTargetException)) e = e.getCause(); - consumed = usedArguments.reset(); - // Not optional? Then we can't execute this command - if (!parameter.isOptional()) { - if (!(e instanceof MissingParameterException)) minConsumedI = maxConsumedI; - throw e; + usedArguments.mark(); + try { + parameter.getBinding().bind(parameter, usedArguments, false); + minConsumedI = maxConsumedI + 1; + } catch (Throwable e) { + while (e.getCause() != null && !(e instanceof ParameterException || e instanceof InvocationTargetException)) + e = e.getCause(); + consumed = usedArguments.reset(); + // Not optional? Then we can't execute this command + if (!parameter.isOptional()) { + if (!(e instanceof MissingParameterException)) minConsumedI = maxConsumedI; + throw e; + } } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index e9e8ac6c7..9a72f35a5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.world.block; import com.boydti.fawe.command.SuggestInputParseException; import com.boydti.fawe.object.string.MutableCharSequence; +import com.boydti.fawe.util.StringMan; import com.google.common.base.Function; import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; @@ -38,6 +39,7 @@ import com.sk89q.worldedit.world.registry.BlockMaterial; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -121,8 +123,9 @@ public class BlockState implements BlockStateHolder, FawePattern { if (type == null) { String input = key.toString(); throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(BlockTypes.values) - .filter(b -> b.getId().contains(input)) + .filter(b -> StringMan.blockStateMatches(input, b.getId())) .map(e1 -> e1.getId()) + .sorted(StringMan.blockStateComparator(input)) .collect(Collectors.toList()) ); } @@ -183,7 +186,8 @@ public class BlockState implements BlockStateHolder, FawePattern { throw new SuggestInputParseException("Invalid property " + charSequence + ":" + input + " for type " + type, input, () -> finalType.getProperties().stream() .map(p -> p.getName()) - .filter(p -> p.startsWith(input)) + .filter(p -> StringMan.blockStateMatches(input, p)) + .sorted(StringMan.blockStateComparator(input)) .collect(Collectors.toList())); } else { throw new SuggestInputParseException("No operator for " + state, "", () -> Arrays.asList("=")); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index 382eda423..a157b2cbe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -912,8 +912,9 @@ public final class BlockTypes { } throw new SuggestInputParseException("Does not match a valid block type: " + inputLower, inputLower, () -> Stream.of(BlockTypes.values) - .filter(b -> b.getId().contains(inputLower)) + .filter(b -> StringMan.blockStateMatches(inputLower, b.getId())) .map(e1 -> e1.getId()) + .sorted(StringMan.blockStateComparator(inputLower)) .collect(Collectors.toList()) ); }