diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java index 1809d829..6af4ebb1 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java @@ -35,6 +35,11 @@ public class BukkitPlayer extends FawePlayer { return this.parent.hasPermission(perm); } + @Override + public boolean isSneaking() { + return parent.isSneaking(); + } + @Override public void setPermission(final String perm, final boolean flag) { /* diff --git a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java index 1cef0caf..ec27ecf4 100644 --- a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -423,6 +423,11 @@ public abstract class FawePlayer extends Metadatable { */ public abstract UUID getUUID(); + + public boolean isSneaking() { + return false; + } + /** * Check the player's permission * diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/LazyClipboardHolder.java b/core/src/main/java/com/boydti/fawe/object/clipboard/LazyClipboardHolder.java index 06f87f04..b454ee53 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/LazyClipboardHolder.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/LazyClipboardHolder.java @@ -57,6 +57,11 @@ public class LazyClipboardHolder extends URIClipboardHolder { return clipboard; } + @Override + public URI getURI(Clipboard clipboard) { + return (this.clipboard == clipboard) ? getUri() : null; + } + @Override public synchronized void close() { if (clipboard instanceof BlockArrayClipboard) { diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/MultiClipboardHolder.java b/core/src/main/java/com/boydti/fawe/object/clipboard/MultiClipboardHolder.java index 68c8a0d0..6fa41da6 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/MultiClipboardHolder.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/MultiClipboardHolder.java @@ -61,6 +61,18 @@ public class MultiClipboardHolder extends URIClipboardHolder { } } + @Override + public URI getURI(Clipboard clipboard) { + for (ClipboardHolder holder : getHolders()) { + if (holder instanceof URIClipboardHolder) { + URIClipboardHolder uriHolder = (URIClipboardHolder) holder; + URI uri = uriHolder.getURI(clipboard); + if (uri != null) return uri; + } + } + return null; + } + public void add(URIClipboardHolder holder) { add((ClipboardHolder) holder); } diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/URIClipboardHolder.java b/core/src/main/java/com/boydti/fawe/object/clipboard/URIClipboardHolder.java index 108ce264..cff98a70 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/URIClipboardHolder.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/URIClipboardHolder.java @@ -36,4 +36,8 @@ public class URIClipboardHolder extends ClipboardHolder { public Set getURIs() { return Collections.singleton(uri); } + + public URI getURI(Clipboard clipboard) { + return getClipboard() == clipboard ? getUri() : null; + } } diff --git a/core/src/main/java/com/boydti/fawe/object/schematic/visualizer/SchemVis.java b/core/src/main/java/com/boydti/fawe/object/schematic/visualizer/SchemVis.java index 060de8ce..af431614 100644 --- a/core/src/main/java/com/boydti/fawe/object/schematic/visualizer/SchemVis.java +++ b/core/src/main/java/com/boydti/fawe/object/schematic/visualizer/SchemVis.java @@ -20,6 +20,7 @@ import com.sk89q.worldedit.*; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.event.platform.InputType; import com.sk89q.worldedit.event.platform.PlayerInputEvent; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; @@ -52,6 +53,7 @@ public class SchemVis extends ImmutableVirtualWorld { private final FawePlayer player; private final Location origin; private final BlockVector2D chunkOffset; + private BlockVector2D lastPosition; public SchemVis(FawePlayer player) { this.files = new Long2ObjectOpenHashMap<>(); @@ -65,6 +67,27 @@ public class SchemVis extends ImmutableVirtualWorld { this.chunkOffset = new BlockVector2D(pos.x >> 4,pos.z >> 4); } + private Set getFiles(BlockVector2D chunkPosA, BlockVector2D chunkPosB) { + BlockVector2D pos1 = new BlockVector2D(Math.min(chunkPosA.getBlockX(), chunkPosB.getBlockX()), Math.min(chunkPosA.getBlockZ(), chunkPosB.getBlockZ())); + BlockVector2D pos2 = new BlockVector2D(Math.max(chunkPosA.getBlockX(), chunkPosB.getBlockX()), Math.max(chunkPosA.getBlockZ(), chunkPosB.getBlockZ())); + Set contained = new HashSet<>(); + for (Long2ObjectMap.Entry> entry : files.long2ObjectEntrySet()) { + long key = entry.getLongKey(); + int chunkX = MathMan.unpairIntX(key); + if (chunkX < pos1.getBlockX() || chunkX > pos2.getBlockX()) continue; + int chunkZ = MathMan.unpairIntY(key); + if (chunkZ < pos1.getBlockZ() || chunkZ > pos2.getBlockZ()) continue; + contained.add(entry.getValue().getKey()); + + } + return contained; + } + + private File getRealFile(File cached) { + String fileName = cached.getName(); + return new File(cached.getParentFile(), fileName.substring(1, fileName.length() - 7)); + } + @Override public void handlePlayerInput(Player player, PlayerInputEvent event) { int range = 240; @@ -77,69 +100,84 @@ public class SchemVis extends ImmutableVirtualWorld { if (entry != null) { File cachedFile = entry.getKey(); String filename = cachedFile.getName(); - // get non `.cached` file - File file = new File(cachedFile.getParentFile(), filename.substring(1, filename.length() - 7)); - URI uri = file.toURI(); - ClipboardFormat format = ClipboardFormat.findByFile(file); - if (format != null) { - LocalSession session = this.player.getSession(); + LocalSession session = this.player.getSession(); + synchronized (this) { try { - synchronized (this) { - switch (event.getInputType()) { - case PRIMARY: // set clipboard - format.hold(player, uri, new FileInputStream(file)); - BBC.SCHEMATIC_LOADED.send(player, filename); - session.setVirtualWorld(null); - break; - case SECONDARY: // add/remove clipboard - ClipboardHolder existing = session.getExistingClipboard(); + BlockVector2D tmpLastPosition = lastPosition; + lastPosition = new BlockVector2D(chunkX, chunkZ); - boolean contains = existing instanceof URIClipboardHolder && ((URIClipboardHolder) existing).contains(uri); - if (contains) { - // Remove it - if (existing instanceof MultiClipboardHolder) { - MultiClipboardHolder multi = ((MultiClipboardHolder) existing); - multi.remove(uri); - if (multi.getClipboards().isEmpty()) session.setClipboard(null); - } else { - session.setClipboard(null); - } - BBC.CLIPBOARD_CLEARED.send(player); + boolean sneaking = this.player.isSneaking(); + if (event.getInputType() == InputType.PRIMARY && !sneaking) { + + File file = new File(cachedFile.getParentFile(), filename.substring(1, filename.length() - 7)); + URI uri = file.toURI(); + ClipboardFormat format = ClipboardFormat.findByFile(file); + format.hold(player, uri, new FileInputStream(file)); + BBC.SCHEMATIC_LOADED.send(player, filename); + session.setVirtualWorld(null); + return; + } + Set toSelect; + if (sneaking && tmpLastPosition != null) toSelect = getFiles(tmpLastPosition, lastPosition); + else toSelect = Collections.singleton(cachedFile); + + Map select = new HashMap<>(); + for (File clicked : toSelect) { + ClipboardHolder existing = session.getExistingClipboard(); + + File file = new File(clicked.getParentFile(), filename.substring(1, filename.length() - 7)); + URI uri = file.toURI(); + ClipboardFormat format = ClipboardFormat.findByFile(file); + + boolean contains = existing instanceof URIClipboardHolder && ((URIClipboardHolder) existing).contains(uri); + if (contains) { + if (!sneaking) { + // Remove it + if (existing instanceof MultiClipboardHolder) { + MultiClipboardHolder multi = ((MultiClipboardHolder) existing); + multi.remove(uri); + if (multi.getClipboards().isEmpty()) session.setClipboard(null); } else { - // Add it - ByteSource source = Files.asByteSource(file); - MultiClipboardHolder multi = new MultiClipboardHolder(URI.create(""), worldData, new LazyClipboardHolder(uri, source, format, worldData, null)); - session.addClipboard(multi); - BBC.SCHEMATIC_LOADED.send(player, filename); + session.setClipboard(null); } - - // Resend relevant chunks - FaweQueue packetQueue = SetQueue.IMP.getNewQueue(this.player.getWorld(), true, false); - if (packetQueue.supports(Capability.CHUNK_PACKETS)) { - ArrayDeque toSend = new ArrayDeque<>(); - int OX = chunkOffset.getBlockX(); - int OZ = chunkOffset.getBlockZ(); - ObjectIterator> iter = chunks.long2ObjectEntrySet().fastIterator(); - while (iter.hasNext()) { - Long2ObjectMap.Entry mcaChunkEntry = iter.next(); - long curChunkPos = mcaChunkEntry.getLongKey(); - Map.Entry curFileEntry = files.get(curChunkPos); - if (curFileEntry != null && curFileEntry == entry) { - MCAChunk chunk = mcaChunkEntry.getValue(); - if (contains) { - iter.remove(); - } - else select(chunk); - toSend.add(curChunkPos); - } - } - for (long curChunkPos : toSend) send(packetQueue, MathMan.unpairIntX(curChunkPos), MathMan.unpairIntY(curChunkPos)); - } - - break; + select.put(clicked, false); + BBC.CLIPBOARD_CLEARED.send(player); + } + } else { + // Add it + ByteSource source = Files.asByteSource(file); + MultiClipboardHolder multi = new MultiClipboardHolder(URI.create(""), worldData, new LazyClipboardHolder(uri, source, format, worldData, null)); + session.addClipboard(multi); + select.put(clicked, true); + BBC.SCHEMATIC_LOADED.send(player, file.getName()); } } + // Resend relevant chunks + FaweQueue packetQueue = SetQueue.IMP.getNewQueue(this.player.getWorld(), true, false); + if (packetQueue.supports(Capability.CHUNK_PACKETS)) { + ArrayDeque toSend = new ArrayDeque<>(); + int OX = chunkOffset.getBlockX(); + int OZ = chunkOffset.getBlockZ(); + ObjectIterator> iter = chunks.long2ObjectEntrySet().fastIterator(); + while (iter.hasNext()) { + Long2ObjectMap.Entry mcaChunkEntry = iter.next(); + long curChunkPos = mcaChunkEntry.getLongKey(); + Map.Entry curFileEntry = files.get(curChunkPos); + if (curFileEntry != null) { + Boolean selected = select.get(curFileEntry.getKey()); + if (selected != null) { + if (!selected) { + iter.remove(); + } else { + select(mcaChunkEntry.getValue()); + } + toSend.add(curChunkPos); + } + } + } + for (long curChunkPos : toSend) send(packetQueue, MathMan.unpairIntX(curChunkPos), MathMan.unpairIntY(curChunkPos)); + } } catch (IOException e) { throw new RuntimeException(e); } diff --git a/core/src/main/java/com/boydti/fawe/web/SchemSync.java b/core/src/main/java/com/boydti/fawe/web/SchemSync.java new file mode 100644 index 00000000..eaa1ef6c --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/web/SchemSync.java @@ -0,0 +1,59 @@ +package com.boydti.fawe.web; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.util.MainUtil; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SchemSync implements Runnable { + private final static char PORT = 62522; + + private final File tokensFile; + private Map tokens; + + public SchemSync() { + this.tokensFile = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TOKENS, "TOKENS.TXT"); + } + + private void loadTokens() { + if (tokens == null) { + String tokensDir = Settings.IMP.PATHS.TOKENS; + tokens = new HashMap<>(); + + } + } + + @Override + public void run() { + try { + byte[] header = new byte[32]; + ServerSocket serverSocket = new ServerSocket(PORT); + while (!Thread.interrupted()) { + Socket clientSocket = serverSocket.accept(); + try (InputStream in = clientSocket.getInputStream()) { + int read = in.read(header); + if (read != header.length) continue; + + ByteBuffer buf = ByteBuffer.wrap(header); + UUID uuid = new UUID(buf.getLong(), buf.getLong()); + UUID expectedToken = tokens.get(uuid); + if (expectedToken == null) continue; + + UUID receivedToken = new UUID(buf.getLong(), buf.getLong()); + if (!receivedToken.equals(expectedToken)) continue; + } + } + + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 25d06d1d..fe1ee8c1 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -36,11 +36,13 @@ import com.sk89q.minecraft.util.commands.*; import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.command.tool.brush.*; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.function.mask.BlockMask; @@ -72,17 +74,31 @@ public class BrushCommands extends MethodCommands { super(worldEdit); } - private BrushSettings get(CommandContext context) throws InvalidToolBindException { - BrushSettings bs = new BrushSettings(); - bs.addPermissions(getPermissions()); + private BrushSettings set(LocalSession session, CommandContext context, Brush brush) throws InvalidToolBindException { CommandLocals locals = context.getLocals(); + Actor actor = locals.get(Actor.class); + BrushSettings bs = new BrushSettings(); + + BrushTool tool = session.getBrushTool((Player) actor, false); + if (tool != null) { + BrushSettings currentContext = tool.getContext(); + if (currentContext != null) { + Brush currentBrush = currentContext.getBrush(); + if (currentBrush != null && currentBrush.getClass() == brush.getClass()) { + bs = currentContext; + } + } + } + + bs.addPermissions(getPermissions()); + if (locals != null) { String args = (String) locals.get("arguments"); if (args != null) { bs.addSetting(BrushSettings.SettingType.BRUSH, args.substring(args.indexOf(' ') + 1)); } } - return bs; + return bs.setBrush(brush); } @@ -98,7 +114,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.blendball") public BrushSettings blendBallBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context).setBrush(new BlendBall()).setSize(radius); + return set(session, context, new BlendBall()).setSize(radius); } @Command( @@ -112,7 +128,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.erode") public BrushSettings erodeBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context).setBrush(new ErodeBrush()).setSize(radius); + return set(session, context, new ErodeBrush()).setSize(radius); } @Command( @@ -126,7 +142,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.pull") public BrushSettings pullBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context).setBrush(new RaiseBrush()).setSize(radius); + return set(session, context, new RaiseBrush()).setSize(radius); } @Command( @@ -141,7 +157,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.sphere") public BrushSettings circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context).setBrush(new CircleBrush(player)).setSize(radius).setFill(fill); + return set(session, context, new CircleBrush(player)).setSize(radius).setFill(fill); } @Command( @@ -157,8 +173,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.recursive") public BrushSettings recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new RecurseBrush(depthFirst)) + return set(session, context, + new RecurseBrush(depthFirst)) .setSize(radius) .setFill(fill) .setMask(new IdMask(editSession)); @@ -180,8 +196,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.line") public BrushSettings lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new LineBrush(shell, select, flat)) + return set(session, context, + new LineBrush(shell, select, flat)) .setSize(radius) .setFill(fill); } @@ -193,7 +209,8 @@ public class BrushCommands extends MethodCommands { help = "Click to select some objects,click the same block twice to connect the objects.\n" + "Insufficient brush radius, or clicking the the wrong spot will result in undesired shapes. The shapes must be simple lines or loops.\n" + "Pic1: http://i.imgur.com/CeRYAoV.jpg -> http://i.imgur.com/jtM0jA4.png\n" + - "Pic2: http://i.imgur.com/bUeyc72.png -> http://i.imgur.com/tg6MkcF.png", + "Pic2: http://i.imgur.com/bUeyc72.png -> http://i.imgur.com/tg6MkcF.png" + + "Tutorial: https://www.planetminecraft.com/blog/fawe-tutorial/", min = 0, max = 2 ) @@ -201,8 +218,8 @@ public class BrushCommands extends MethodCommands { public BrushSettings splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); - return get(context) - .setBrush(new SplineBrush(player, session)) + return set(session, context, + new SplineBrush(player, session)) .setSize(radius) .setFill(fill); } @@ -220,7 +237,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.sweep") public BrushSettings sweepBrush(Player player, LocalSession session, EditSession editSession, @Optional("-1") int copies, CommandContext context) throws WorldEditException { player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.s()); - return get(context).setBrush(new SweepBrush(copies)); + return set(session, context, new SweepBrush(copies)); } @Command( @@ -237,8 +254,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.spline") public BrushSettings catenaryBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("1.2") @Range(min=1) double lengthFactor, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new CatenaryBrush(shell, select, lengthFactor)) + return set(session, context, + new CatenaryBrush(shell, select, lengthFactor)) .setSize(radius) .setFill(fill); } @@ -256,8 +273,8 @@ public class BrushCommands extends MethodCommands { public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException { player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new SurfaceSpline(tension, bias, continuity, quality)) + return set(session, context, + new SurfaceSpline(tension, bias, continuity, quality)) .setSize(radius) .setFill(fill); } @@ -275,8 +292,8 @@ public class BrushCommands extends MethodCommands { double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ()); worldEdit.checkMaxBrushRadius(max); Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100, sphericity / 100); - return get(context) - .setBrush(brush) + return set(session, context, + brush) .setSize(max) .setFill(fill); } @@ -318,8 +335,8 @@ public class BrushCommands extends MethodCommands { } } - return get(context) - .setBrush(brush) + return set(session, context, + brush) .setSize(radius) .setFill(fill); } @@ -337,8 +354,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.shatter") public BrushSettings shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new ShatterBrush(count)) + return set(session, context, + new ShatterBrush(count)) .setSize(radius) .setFill(fill) .setMask(new ExistingBlockMask(editSession)); @@ -368,12 +385,21 @@ public class BrushCommands extends MethodCommands { if (randomRotate) { brush.setRandomRotate(true); } - return get(context) - .setBrush(brush) + return set(session, context, + brush) .setSize(radius) .setFill(fill); } +// @Command( +// aliases = {"image", "img"} +// // TODO directional image coloring +// ) +// @CommandPermissions("worldedit.brush.stencil") +// public BrushSettings imageBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException { +// +// } + @Command( aliases = {"surface", "surf"}, usage = " [radius=5]", @@ -388,7 +414,7 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.surface") public BrushSettings surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context).setBrush(new SurfaceSphereBrush()).setFill(fill).setSize(radius); + return set(session, context, new SurfaceSphereBrush()).setFill(fill).setSize(radius); } @Command( @@ -412,8 +438,8 @@ public class BrushCommands extends MethodCommands { } else { brush = new ScatterBrush((int) points, (int) distance); } - return get(context) - .setBrush(brush) + return set(session, context, + brush) .setSize(radius) .setFill(fill); } @@ -446,8 +472,8 @@ public class BrushCommands extends MethodCommands { return null; } - return get(context) - .setBrush(new PopulateSchem(mask, holders, (int) density, rotate)) + return set(session, context, + new PopulateSchem(mask, holders, (int) density, rotate)) .setSize(radius); } catch (IOException e) { throw new RuntimeException(e); @@ -488,8 +514,8 @@ public class BrushCommands extends MethodCommands { blocks.add(worldEdit.getBlockFactory().parseFromInput(arg, parserContext)); } } - return get(context) - .setBrush(new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()]))) + return set(session, context, + new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()]))) .setSize(radius); } @@ -507,8 +533,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.splatter") public BrushSettings splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new SplatterBrush((int) points, (int) recursion, solid)) + return set(session, context, + new SplatterBrush((int) points, (int) recursion, solid)) .setSize(radius) .setFill(fill); } @@ -528,8 +554,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.scattercommand") public BrushSettings scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3))) + return set(session, context, + new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3))) .setSize(radius); } @@ -549,12 +575,12 @@ public class BrushCommands extends MethodCommands { @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(height); - BrushSettings settings = get(context); + BrushSettings settings; if (hollow) { - settings.setBrush(new HollowCylinderBrush(height)); + settings = set(session, context, new HollowCylinderBrush(height)); } else { - settings.setBrush(new CylinderBrush(height)); + settings = set(session, context, new CylinderBrush(height)); } settings.setSize(radius) .setFill(fill); @@ -582,7 +608,7 @@ public class BrushCommands extends MethodCommands { worldEdit.checkMaxBrushRadius(size.getBlockX()); worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockZ()); - return get(context).setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin)); + return set(session, context, new ClipboardBrush(holder, ignoreAir, usingOrigin)); } @Command( @@ -607,8 +633,8 @@ public class BrushCommands extends MethodCommands { FaweLimit limit = Settings.IMP.getLimit(fp); iterations = Math.min(limit.MAX_ITERATIONS, iterations); - return get(context) - .setBrush(new SmoothBrush(iterations, naturalBlocksOnly)) + return set(session, context, + new SmoothBrush(iterations, naturalBlocksOnly)) .setSize(radius); } @@ -624,8 +650,8 @@ public class BrushCommands extends MethodCommands { worldEdit.checkMaxBrushRadius(radius); Pattern fill = (new BaseBlock(0)); - return get(context) - .setBrush(new SphereBrush()) + return set(session, context, + new SphereBrush()) .setSize(radius) .setFill(fill) .setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE))); @@ -647,8 +673,8 @@ public class BrushCommands extends MethodCommands { public BrushSettings gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - return get(context) - .setBrush(new GravityBrush(fromMaxY)) + return set(session, context, + new GravityBrush(fromMaxY)) .setSize(radius); } @@ -758,8 +784,8 @@ public class BrushCommands extends MethodCommands { if (randomRotate) { brush.setRandomRotate(true); } - return get(context) - .setBrush(brush) + return set(session, context, + brush) .setSize(radius); } @@ -782,8 +808,8 @@ public class BrushCommands extends MethodCommands { worldEdit.checkMaxBrushRadius(radius); player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius)); - return get(context) - .setBrush(new CopyPastaBrush(player, session, randomRotate, autoRotate)) + return set(session, context, + new CopyPastaBrush(player, session, randomRotate, autoRotate)) .setSize(radius); } @@ -802,8 +828,8 @@ public class BrushCommands extends MethodCommands { @CommandPermissions("worldedit.brush.command") public BrushSettings command(Player player, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException { String cmd = args.getJoinedStrings(1); - return get(context) - .setBrush(new CommandBrush(cmd, radius)) + return set(session, context, + new CommandBrush(cmd, radius)) .setSize(radius); } @@ -846,8 +872,8 @@ public class BrushCommands extends MethodCommands { CreatureButcher flags = new CreatureButcher(player); flags.fromCommand(args); - return get(context) - .setBrush(new ButcherBrush(flags)) + return set(session, context, + new ButcherBrush(flags)) .setSize(radius); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 8cfcd4b9..74650a8c 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -297,18 +297,24 @@ public class ClipboardCommands extends MethodCommands { URI uri = uriHolder.getUri(); File file = new File(uri.getPath()); if (file.exists() && file.isFile()) { - files.add(file); + files.add(file.getAbsoluteFile()); } else if (!uri.getPath().isEmpty()) { invalid.add(uri); } } } + + final LocalConfiguration config = this.worldEdit.getConfiguration(); + final File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir).getAbsoluteFile(); + url = MainUtil.upload(null, null, "zip", new RunnableVal() { @Override public void run(OutputStream out) { try (ZipOutputStream zos = new ZipOutputStream(out)) { for (File file : files) { - ZipEntry ze = new ZipEntry(file.getName()); + String fileName = file.getName(); + if (MainUtil.isInSubDirectory(working, file)) fileName = working.toURI().relativize(file.toURI()).getPath(); + ZipEntry ze = new ZipEntry(fileName); zos.putNextEntry(ze); Files.copy(file.toPath(), zos); zos.closeEntry(); diff --git a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index da47ed73..1e782321 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -399,7 +399,7 @@ public class SchematicCommands extends MethodCommands { } @Command(aliases = {"delete", "d"}, usage = "", desc = "Delete a saved schematic", help = "Delete a schematic from the schematic list", min = 1, max = 1) - @CommandPermissions({"worldedit.schematic.delete", "worldedit.schematic.other"}) + @CommandPermissions({"worldedit.schematic.delete", "worldedit.schematic.delete.other"}) public void delete(final Player player, final LocalSession session, final CommandContext args) throws WorldEditException { final LocalConfiguration config = this.worldEdit.getConfiguration(); final File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -490,7 +490,7 @@ public class SchematicCommands extends MethodCommands { help = "List all schematics in the schematics directory\n" + " -f restricts by format\n" ) - @CommandPermissions("worldedit.heightmap.list") + @CommandPermissions("worldedit.schematic.show") public void show(Player player, CommandContext args, @Switch('f') String formatName) { FawePlayer fp = FawePlayer.wrap(player); if (args.argsLength() == 0) { @@ -560,9 +560,11 @@ public class SchematicCommands extends MethodCommands { String unload = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "unload"); String delete = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "delete"); String list = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "list"); + String showCmd = schemCmd + " " + Commands.getAlias(SchematicCommands.class, "show"); URIClipboardHolder multi = as(URIClipboardHolder.class, fp.getSession().getExistingClipboard()); + final boolean hasShow = actor.hasPermission("worldedit.schematic.show"); UtilityCommands.list(dir, actor, args, page, -1, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS, new RunnableVal3() { @Override public void run(Message msg, URI uri, String relFilePath) { @@ -596,6 +598,7 @@ public class SchematicCommands extends MethodCommands { } else { msg.text("&7[&a+&7]").command(loadMulti + " " + relFilePath).tooltip("(WIP) Append this to your clipboard"); } + if (hasShow) msg.text("&7[&3O&7]").cmdTip(showCmd + " " + args.getJoinedStrings(0) + " " + relFilePath); if (!isDir) msg.text("&7[&cX&7]").suggestTip("/" + delete + " " + relFilePath); msg.text(color + relFilePath); if (isDir) {