Multi clipboard pattern

This commit is contained in:
Jesse Boyd 2017-03-13 02:44:29 +11:00
parent b56f6664d5
commit b20120a1f2
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
10 changed files with 446 additions and 291 deletions

View File

@ -39,6 +39,7 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static BukkitImplAdapter adapter; public static BukkitImplAdapter adapter;
public static Method methodToNative; public static Method methodToNative;
public static Method methodFromNative; public static Method methodFromNative;
private static boolean setupAdapter = false;
public BukkitQueue_0(final com.sk89q.worldedit.world.World world) { public BukkitQueue_0(final com.sk89q.worldedit.world.World world) {
super(world); super(world);
@ -137,6 +138,9 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static void setupAdapter(BukkitImplAdapter adapter) { public static void setupAdapter(BukkitImplAdapter adapter) {
try { try {
if (setupAdapter == (setupAdapter = true)) {
return;
}
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter"); Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
fieldAdapter.setAccessible(true); fieldAdapter.setAccessible(true);

View File

@ -0,0 +1,12 @@
package com.boydti.fawe.object.clipboard;
import com.google.common.io.ByteSource;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.world.registry.WorldData;
import java.util.UUID;
public class RandomClipboardHolder extends LazyClipboardHolder {
public RandomClipboardHolder(ByteSource source, ClipboardFormat format, WorldData worldData, UUID uuid) {
super(source, format, worldData, uuid);
}
}

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.object.pattern;
import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -20,8 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class FullClipboardPattern extends AbstractPattern { public class FullClipboardPattern extends AbstractPattern {
private final Extent extent; private final Extent extent;
private final Clipboard clipboard; private final Clipboard clipboard;
private final BaseBlock block;
private final MutableBlockVector mutable = new MutableBlockVector(); private final MutableBlockVector mutable = new MutableBlockVector();
/** /**
@ -33,16 +32,19 @@ public class FullClipboardPattern extends AbstractPattern {
checkNotNull(clipboard); checkNotNull(clipboard);
this.clipboard = clipboard; this.clipboard = clipboard;
this.extent = extent; this.extent = extent;
Vector origin = clipboard.getOrigin();
block = clipboard.getBlock(origin);
} }
@Override @Override
public BaseBlock apply(Vector to) { public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
Region region = clipboard.getRegion(); Region region = clipboard.getRegion();
ForwardExtentCopy copy = new ForwardExtentCopy(clipboard, clipboard.getRegion(), clipboard.getOrigin(), extent, to); ForwardExtentCopy copy = new ForwardExtentCopy(clipboard, clipboard.getRegion(), clipboard.getOrigin(), extent, setPosition);
copy.setSourceMask(new ExistingBlockMask(clipboard)); copy.setSourceMask(new ExistingBlockMask(clipboard));
Operations.completeBlindly(copy); Operations.completeBlindly(copy);
return block; return true;
}
@Override
public BaseBlock apply(Vector position) {
throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!");
} }
} }

View File

@ -0,0 +1,54 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.schematic.Schematic;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
import static com.google.common.base.Preconditions.checkNotNull;
public class RandomFullClipboardPattern extends AbstractPattern {
private final Extent extent;
private final ClipboardHolder[] clipboards;
private final MutableBlockVector mutable = new MutableBlockVector();
private boolean randomRotate;
private WorldData worldData;
public RandomFullClipboardPattern(Extent extent, WorldData worldData, ClipboardHolder[] clipboards, boolean randomRotate) {
checkNotNull(clipboards);
this.clipboards = clipboards;
this.extent = extent;
this.randomRotate = randomRotate;
this.worldData = worldData;
}
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
ClipboardHolder holder = clipboards[PseudoRandom.random.random(clipboards.length)];
if (randomRotate) {
holder.setTransform(new AffineTransform().rotateY(PseudoRandom.random.random(4) * 90));
}
Clipboard clipboard = holder.getClipboard();
Schematic schematic = new Schematic(clipboard);
if (holder.getTransform().isIdentity()) {
schematic.paste(extent, setPosition, false);
} else {
schematic.paste(extent, worldData, setPosition, false, holder.getTransform());
}
return true;
}
@Override
public BaseBlock apply(Vector position) {
throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!");
}
}

View File

@ -1,24 +1,34 @@
package com.boydti.fawe.object.schematic; package com.boydti.fawe.object.schematic;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MaskTraverser; import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -133,4 +143,77 @@ public class Schematic {
editSession.flushQueue(); editSession.flushQueue();
return editSession; return editSession;
} }
public void paste(Extent extent, WorldData worldData, Vector to, boolean pasteAir, Transform transform) {
Region region = clipboard.getRegion();
BlockTransformExtent source = new BlockTransformExtent(clipboard, transform, worldData.getBlockRegistry());
ForwardExtentCopy copy = new ForwardExtentCopy(source, clipboard.getRegion(), clipboard.getOrigin(), extent, to);
copy.setTransform(transform);
if (!pasteAir) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}
Operations.completeBlindly(copy);
}
public void paste(Extent extent, Vector to, boolean pasteAir) {
Region region = clipboard.getRegion().clone();
final int maxY = extent.getMaximumPoint().getBlockY();
final Vector bot = clipboard.getMinimumPoint();
final Vector origin = clipboard.getOrigin();
// Optimize for BlockArrayClipboard
if (clipboard instanceof BlockArrayClipboard && region instanceof CuboidRegion) {
// To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min)
final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ();
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
@Override
public void run(Vector mutable, BaseBlock block) {
mutable.mutX(mutable.getX() + relx);
mutable.mutY(mutable.getY() + rely);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
try {
extent.setBlock(mutable, block);
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
}
}, pasteAir);
} else {
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
final int relx = to.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() - origin.getBlockZ();
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
@Override
public boolean apply(Vector mutable) throws WorldEditException {
BaseBlock block = clipboard.getBlock(mutable);
if (block == EditSession.nullBlock && !pasteAir) {
return false;
}
mutable.mutX(mutable.getX() + relx);
mutable.mutY(mutable.getY() + rely);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
return extent.setBlock(mutable, block);
}
return false;
}
}, (HasFaweQueue) (extent instanceof HasFaweQueue ? extent : null));
Operations.completeBlindly(visitor);
}
// Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin)
final int entityOffsetX = to.getBlockX() - origin.getBlockX();
final int entityOffsetY = to.getBlockY() - origin.getBlockY();
final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ();
// entities
for (Entity entity : clipboard.getEntities()) {
Location pos = entity.getLocation();
Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX, pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(), pos.getPitch());
extent.createEntity(newPos, entity.getState());
}
}
} }

View File

@ -50,12 +50,8 @@ import com.boydti.fawe.object.brush.scroll.ScrollRange;
import com.boydti.fawe.object.brush.scroll.ScrollSize; import com.boydti.fawe.object.brush.scroll.ScrollSize;
import com.boydti.fawe.object.brush.scroll.ScrollTarget; import com.boydti.fawe.object.brush.scroll.ScrollTarget;
import com.boydti.fawe.object.brush.visualization.VisualMode; import com.boydti.fawe.object.brush.visualization.VisualMode;
import com.boydti.fawe.object.clipboard.LazyClipboardHolder;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -93,9 +89,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.File; import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
@ -103,10 +97,6 @@ import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -237,71 +227,11 @@ public class BrushCommands {
} }
String filename = args.getString(1); String filename = args.getString(1);
try { try {
WorldData worldData = player.getWorld().getWorldData(); ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, true);
if (filename.startsWith("http")) { if (clipboards == null) {
URL url = new URL(filename);
URL webInterface = new URL(Settings.IMP.WEB.ASSETS);
if (!url.getHost().equalsIgnoreCase(webInterface.getHost())) {
BBC.WEB_UNAUTHORIZED.send(player, url);
return; return;
} }
List<LazyClipboardHolder> clipboards = new ArrayList<>();
try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) {
try (InputStream in = Channels.newInputStream(rbc)) {
try (ZipInputStream zip = new ZipInputStream(in)) {
ZipEntry entry;
byte[] buffer = new byte[8192];
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().endsWith(".schematic")) {
FastByteArrayOutputStream out = new FastByteArrayOutputStream();
int len = 0;
while ((len = zip.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
byte[] array = out.toByteArray();
ByteSource source = ByteSource.wrap(array);
LazyClipboardHolder clipboard = new LazyClipboardHolder(source, ClipboardFormat.SCHEMATIC, worldData, null);
clipboards.add(clipboard);
}
}
}
}
}
tool.setScrollAction(new ScrollClipboard(tool, session, clipboards.toArray(new LazyClipboardHolder[clipboards.size()])));
} else {
if (filename.contains("../") && !player.hasPermission("worldedit.schematic.load.other")) {
BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return;
}
File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = new File(working, (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? (player.getUniqueId().toString() + File.separator) : "") + filename);
if (!dir.exists()) {
if ((!filename.contains("/") && !filename.contains("\\")) || player.hasPermission("worldedit.schematic.load.other")) {
dir = new File(this.worldEdit.getWorkingDirectoryFile(config.saveDir), filename);
}
}
if (!dir.exists() || !dir.isDirectory()) {
BBC.SCHEMATIC_NOT_FOUND.send(player, filename);
return;
}
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".schematic");
}
});
if (files.length < 1) {
BBC.SCHEMATIC_NOT_FOUND.send(player, filename);
return;
}
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
for (int i = 0; i < files.length; i++) {
File file = files[i];
ByteSource source = Files.asByteSource(file);
clipboards[i] = new LazyClipboardHolder(source, ClipboardFormat.SCHEMATIC, worldData, null);
}
tool.setScrollAction(new ScrollClipboard(tool, session, clipboards)); tool.setScrollAction(new ScrollClipboard(tool, session, clipboards));
}
break; break;
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -24,11 +24,11 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.object.clipboard.WorldCutClipboard; import com.boydti.fawe.object.clipboard.WorldCutClipboard;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.io.FastByteArrayOutputStream; import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.schematic.Schematic;
import com.boydti.fawe.util.ImgurUtility; import com.boydti.fawe.util.ImgurUtility;
import com.boydti.fawe.util.MaskTraverser; import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
@ -40,14 +40,11 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.Masks;
@ -55,17 +52,14 @@ import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import java.io.IOException; import java.io.IOException;
@ -373,7 +367,6 @@ public class ClipboardCommands {
place(player, session, editSession, ignoreAirBlocks, atOrigin, selectPasted); place(player, session, editSession, ignoreAirBlocks, atOrigin, selectPasted);
return; return;
} }
Clipboard clipboard = holder.getClipboard(); Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion(); Region region = clipboard.getRegion();
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player); Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
@ -420,63 +413,13 @@ public class ClipboardCommands {
@Switch('s') boolean selectPasted) throws WorldEditException { @Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard(); final Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion().clone();
final int maxY = editSession.getMaxY();
final Vector bot = clipboard.getMinimumPoint();
final Vector origin = clipboard.getOrigin(); final Vector origin = clipboard.getOrigin();
final Vector to = atOrigin ? origin : session.getPlacementPosition(player); final Vector to = atOrigin ? origin : session.getPlacementPosition(player);
// Optimize for BlockArrayClipboard
if (clipboard instanceof BlockArrayClipboard && region instanceof CuboidRegion) { Schematic schem = new Schematic(clipboard);
// To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min) schem.paste(editSession, to, !ignoreAirBlocks);
final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY(); Region region = clipboard.getRegion().clone();
final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ();
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
@Override
public void run(Vector mutable, BaseBlock block) {
mutable.mutX(mutable.getX() + relx);
mutable.mutY(mutable.getY() + rely);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
editSession.setBlockFast(mutable, block);
}
}
}, !ignoreAirBlocks);
} else {
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
final int relx = to.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() - origin.getBlockZ();
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
@Override
public boolean apply(Vector mutable) throws WorldEditException {
BaseBlock block = clipboard.getBlock(mutable);
if (block == EditSession.nullBlock && ignoreAirBlocks) {
return false;
}
mutable.mutX(mutable.getX() + relx);
mutable.mutY(mutable.getY() + rely);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
return editSession.setBlockFast(mutable, block);
}
return false;
}
}, editSession);
Operations.completeBlindly(visitor);
}
// Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin)
final int entityOffsetX = to.getBlockX() - origin.getBlockX();
final int entityOffsetY = to.getBlockY() - origin.getBlockY();
final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ();
// entities
for (Entity entity : clipboard.getEntities()) {
Location pos = entity.getLocation();
Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX, pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(), pos.getPitch());
editSession.createEntity(newPos, entity.getState());
}
if (selectPasted) { if (selectPasted) {
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint())); Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max); RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);

View File

@ -2,7 +2,25 @@ package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.command.FaweParser; import com.boydti.fawe.command.FaweParser;
import com.boydti.fawe.command.SuggestInputParseException; import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.object.pattern.*; import com.boydti.fawe.object.pattern.BiomePattern;
import com.boydti.fawe.object.pattern.DataPattern;
import com.boydti.fawe.object.pattern.ExistingPattern;
import com.boydti.fawe.object.pattern.ExpressionPattern;
import com.boydti.fawe.object.pattern.FullClipboardPattern;
import com.boydti.fawe.object.pattern.IdPattern;
import com.boydti.fawe.object.pattern.Linear3DBlockPattern;
import com.boydti.fawe.object.pattern.LinearBlockPattern;
import com.boydti.fawe.object.pattern.MaskedPattern;
import com.boydti.fawe.object.pattern.NoXPattern;
import com.boydti.fawe.object.pattern.NoYPattern;
import com.boydti.fawe.object.pattern.NoZPattern;
import com.boydti.fawe.object.pattern.OffsetPattern;
import com.boydti.fawe.object.pattern.PatternExtent;
import com.boydti.fawe.object.pattern.RandomFullClipboardPattern;
import com.boydti.fawe.object.pattern.RandomOffsetPattern;
import com.boydti.fawe.object.pattern.RelativePattern;
import com.boydti.fawe.object.pattern.SolidRandomOffsetPattern;
import com.boydti.fawe.object.pattern.SurfaceRandomOffsetPattern;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
@ -14,6 +32,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.ClipboardPattern; import com.sk89q.worldedit.function.pattern.ClipboardPattern;
@ -29,6 +48,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.Biomes; import com.sk89q.worldedit.world.biome.Biomes;
import com.sk89q.worldedit.world.registry.BiomeRegistry; import com.sk89q.worldedit.world.registry.BiomeRegistry;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -97,25 +117,13 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
} }
switch (input.toLowerCase().charAt(0)) { switch (input.toLowerCase().charAt(0)) {
case '#': { case '#': {
switch (input) { String[] split2 = input.split(":");
String rest = split2.length > 1 ? input.substring(split2[0].length() + 1) : "";
switch (split2[0].toLowerCase()) {
case "#*": case "#*":
case "#existing": { case "#existing": {
return new ExistingPattern(Request.request().getEditSession()); return new ExistingPattern(Request.request().getEditSession());
} }
case "#fullcopy": {
LocalSession session = context.requireSession();
if (session != null) {
try {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
return new FullClipboardPattern(Request.request().getEditSession(), clipboard);
} catch (EmptyClipboardException e) {
throw new InputParseException("To use #fullcopy, please first copy something to your clipboard");
}
} else {
throw new InputParseException("No session is available, so no clipboard is available");
}
}
case "#clipboard": case "#clipboard":
case "#copy": { case "#copy": {
LocalSession session = context.requireSession(); LocalSession session = context.requireSession();
@ -131,11 +139,35 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
throw new InputParseException("No session is available, so no clipboard is available"); throw new InputParseException("No session is available, so no clipboard is available");
} }
} }
case "#fullcopy": {
LocalSession session = context.requireSession();
if (session != null) {
try {
if (split2.length > 1) {
String location = split2[1];
try {
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(context.getActor(), context.requireWorld().getWorldData(), location, true);
if (clipboards == null) {
System.out.println("NULL!");
throw new InputParseException("#fullcopy:<source>");
}
boolean random = split2.length == 3 && split2[2].equalsIgnoreCase("true");
return new RandomFullClipboardPattern(Request.request().getEditSession(), context.requireWorld().getWorldData(), clipboards, random);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
return new FullClipboardPattern(Request.request().getEditSession(), clipboard);
} catch (EmptyClipboardException e) {
throw new InputParseException("To use #fullcopy, please first copy something to your clipboard");
}
} else {
throw new InputParseException("No session is available, so no clipboard is available");
}
} }
String[] split2 = input.split(":");
if (split2.length > 1 || input.endsWith(":")) {
String rest = input.substring(split2[0].length() + 1);
switch (split2[0].toLowerCase()) {
case "#id": { case "#id": {
return new IdPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context)); return new IdPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
} }
@ -143,7 +175,7 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
return new DataPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context)); return new DataPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
} }
case "#biome": { case "#biome": {
World world = context.getWorld(); World world = context.requireWorld();
BiomeRegistry biomeRegistry = world.getWorldData().getBiomeRegistry(); BiomeRegistry biomeRegistry = world.getWorldData().getBiomeRegistry();
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes(); List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
BaseBiome biome = Biomes.findBiomeByName(knownBiomes, rest, biomeRegistry); BaseBiome biome = Biomes.findBiomeByName(knownBiomes, rest, biomeRegistry);
@ -262,11 +294,9 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()])); return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
} }
default: default:
throw new SuggestInputParseException(input, DELEGATE_PATTERNS);
}
}
throw new SuggestInputParseException(input, MainUtil.joinArrayGeneric(SIMPLE_PATTERNS, DELEGATE_PATTERNS)); throw new SuggestInputParseException(input, MainUtil.joinArrayGeneric(SIMPLE_PATTERNS, DELEGATE_PATTERNS));
} }
}
case '=': { case '=': {
try { try {
Expression exp = Expression.compile(input.substring(1), "x", "y", "z"); Expression exp = Expression.compile(input.substring(1), "x", "y", "z");

View File

@ -246,7 +246,6 @@ public final class CommandManager {
.registerMethods(new ToolCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit))
.registerMethods(new BrushCommands(worldEdit)) .registerMethods(new BrushCommands(worldEdit))
.parent().graph().getDispatcher(); .parent().graph().getDispatcher();
if (platform != null) { if (platform != null) {
platform.registerCommands(dispatcher); platform.registerCommands(dispatcher);
} }

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.extent.clipboard.io; package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.FaweOutputStream;
@ -27,6 +28,8 @@ import com.boydti.fawe.object.clipboard.AbstractClipboardFormat;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.clipboard.FaweClipboard; import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.boydti.fawe.object.clipboard.IClipboardFormat; import com.boydti.fawe.object.clipboard.IClipboardFormat;
import com.boydti.fawe.object.clipboard.LazyClipboardHolder;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.PGZIPOutputStream; import com.boydti.fawe.object.io.PGZIPOutputStream;
import com.boydti.fawe.object.io.ResettableFileInputStream; import com.boydti.fawe.object.io.ResettableFileInputStream;
import com.boydti.fawe.object.schematic.FaweFormat; import com.boydti.fawe.object.schematic.FaweFormat;
@ -35,29 +38,43 @@ import com.boydti.fawe.object.schematic.Schematic;
import com.boydti.fawe.object.schematic.StructureFormat; import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -297,6 +314,87 @@ public enum ClipboardFormat {
}); });
} }
public ClipboardHolder[] loadAllFromInput(Actor player, WorldData worldData, String input, boolean message) throws IOException {
checkNotNull(player);
checkNotNull(input);
WorldEdit worldEdit = WorldEdit.getInstance();
LocalConfiguration config = worldEdit.getConfiguration();
if (input.startsWith("http")) {
URL url = new URL(input);
URL webInterface = new URL(Settings.IMP.WEB.ASSETS);
if (!url.getHost().equalsIgnoreCase(webInterface.getHost())) {
if (message) BBC.WEB_UNAUTHORIZED.send(player, url);
return null;
}
ClipboardHolder[] clipboards = loadAllFromUrl(url, worldData);
return clipboards;
} else {
if (input.contains("../") && !player.hasPermission("worldedit.schematic.load.other")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return null;
}
File working = worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = new File(working, (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? (player.getUniqueId().toString() + File.separator) : "") + input);
if (!dir.exists()) {
if ((!input.contains("/") && !input.contains("\\")) || player.hasPermission("worldedit.schematic.load.other")) {
dir = new File(worldEdit.getWorkingDirectoryFile(config.saveDir), input);
}
}
if (!dir.exists() || !dir.isDirectory()) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
ClipboardHolder[] clipboards = loadAllFromDirectory(dir, worldData);
if (clipboards.length < 1) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
return clipboards;
}
}
public ClipboardHolder[] loadAllFromDirectory(File dir, WorldData worldData) {
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".schematic");
}
});
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
for (int i = 0; i < files.length; i++) {
File file = files[i];
ByteSource source = Files.asByteSource(file);
clipboards[i] = new LazyClipboardHolder(source, this, worldData, null);
}
return clipboards;
}
public ClipboardHolder[] loadAllFromUrl(URL url, WorldData worldData) throws IOException {
List<LazyClipboardHolder> clipboards = new ArrayList<>();
try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) {
try (InputStream in = Channels.newInputStream(rbc)) {
try (ZipInputStream zip = new ZipInputStream(in)) {
ZipEntry entry;
byte[] buffer = new byte[8192];
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().endsWith(".schematic")) {
FastByteArrayOutputStream out = new FastByteArrayOutputStream();
int len = 0;
while ((len = zip.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
byte[] array = out.toByteArray();
ByteSource source = ByteSource.wrap(array);
LazyClipboardHolder clipboard = new LazyClipboardHolder(source, this, worldData, null);
clipboards.add(clipboard);
}
}
}
}
}
return clipboards.toArray(new LazyClipboardHolder[clipboards.size()]);
}
private void write(OutputStream value, Clipboard clipboard) { private void write(OutputStream value, Clipboard clipboard) {
try { try {
try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) { try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) {