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 Method methodToNative;
public static Method methodFromNative;
private static boolean setupAdapter = false;
public BukkitQueue_0(final com.sk89q.worldedit.world.World world) {
super(world);
@ -137,6 +138,9 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static void setupAdapter(BukkitImplAdapter adapter) {
try {
if (setupAdapter == (setupAdapter = true)) {
return;
}
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
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.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;
@ -20,8 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class FullClipboardPattern extends AbstractPattern {
private final Extent extent;
private final Clipboard clipboard;
private final BaseBlock block;
private final MutableBlockVector mutable = new MutableBlockVector();
/**
@ -33,16 +32,19 @@ public class FullClipboardPattern extends AbstractPattern {
checkNotNull(clipboard);
this.clipboard = clipboard;
this.extent = extent;
Vector origin = clipboard.getOrigin();
block = clipboard.getBlock(origin);
}
@Override
public BaseBlock apply(Vector to) {
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
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));
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;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
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.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
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.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
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.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -133,4 +143,77 @@ public class Schematic {
editSession.flushQueue();
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.ScrollTarget;
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.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.CommandContext;
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.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -103,10 +97,6 @@ import java.io.InputStream;
import java.net.URL;
import java.nio.channels.Channels;
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;
@ -237,71 +227,11 @@ public class BrushCommands {
}
String filename = args.getString(1);
try {
WorldData worldData = player.getWorld().getWorldData();
if (filename.startsWith("http")) {
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;
}
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));
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, true);
if (clipboards == null) {
return;
}
tool.setScrollAction(new ScrollClipboard(tool, session, clipboards));
break;
} catch (IOException 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.object.FaweLimit;
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.WorldCutClipboard;
import com.boydti.fawe.object.exception.FaweException;
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.MaskTraverser;
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.WorldEdit;
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.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
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.mask.Mask;
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.Operations;
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.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
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.parametric.Optional;
import java.io.IOException;
@ -373,7 +367,6 @@ public class ClipboardCommands {
place(player, session, editSession, ignoreAirBlocks, atOrigin, selectPasted);
return;
}
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
@ -420,63 +413,13 @@ public class ClipboardCommands {
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.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 to = atOrigin ? origin : session.getPlacementPosition(player);
// 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) {
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());
}
Schematic schem = new Schematic(clipboard);
schem.paste(editSession, to, !ignoreAirBlocks);
Region region = clipboard.getRegion().clone();
if (selectPasted) {
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
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.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.StringMan;
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.ParserContext;
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.pattern.BlockPattern;
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.registry.BiomeRegistry;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -97,25 +117,13 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
}
switch (input.toLowerCase().charAt(0)) {
case '#': {
switch (input) {
String[] split2 = input.split(":");
String rest = split2.length > 1 ? input.substring(split2[0].length() + 1) : "";
switch (split2[0].toLowerCase()) {
case "#*":
case "#existing": {
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 "#copy": {
LocalSession session = context.requireSession();
@ -131,141 +139,163 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
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": {
return new IdPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
}
case "#data": {
return new DataPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
}
case "#biome": {
World world = context.getWorld();
BiomeRegistry biomeRegistry = world.getWorldData().getBiomeRegistry();
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
BaseBiome biome = Biomes.findBiomeByName(knownBiomes, rest, biomeRegistry);
return new BiomePattern(Request.request().getEditSession(), biome);
}
case "#~":
case "#r":
case "#relative":
case "#rel": {
return new RelativePattern(catchSuggestion(input, rest, context));
}
case "#!x":
case "#nx":
case "#nox": {
return new NoXPattern(catchSuggestion(input, rest, context));
}
case "#!y":
case "#ny":
case "#noy": {
return new NoYPattern(catchSuggestion(input, rest, context));
}
case "#!z":
case "#nz":
case "#noz": {
return new NoZPattern(catchSuggestion(input, rest, context));
}
case "#mask": {
List<String> split3 = suggestRemaining(rest, "#mask", "<mask>", "<pattern-if>", "<pattern-else>");
Pattern primary = catchSuggestion(input, split3.get(1), context);
Pattern secondary = catchSuggestion(input, split3.get(2), context);
PatternExtent extent = new PatternExtent(primary);
Request request = Request.request();
request.setExtent(extent);
request.setSession(context.getSession());
request.setWorld(context.getWorld());
context.setExtent(extent);
MaskFactory factory = worldEdit.getMaskFactory();
Mask mask = factory.parseFromInput(split3.get(0), context);
if (mask == null | primary == null || secondary == null) {
throw new SuggestInputParseException(null, "#mask:<mask>:<pattern-if>:<pattern-else>");
}
return new MaskedPattern(mask, extent, secondary);
}
case "#offset":
case "#fullcopy": {
LocalSession session = context.requireSession();
if (session != null) {
try {
List<String> split3 = suggestRemaining(rest, "#offset", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Expression.compile(split3.get(0)).evaluate();
int y = (int) Expression.compile(split3.get(1)).evaluate();
int z = (int) Expression.compile(split3.get(2)).evaluate();
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new OffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#offset:<dx>:<dy>:<dz>:<pattern>");
}
case "#surfacespread": {
try {
List<String> split3 = suggestRemaining(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SurfaceRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#surfacespread:<dx>:<dy>:<dz>:<pattern>");
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");
}
case "#solidspread": {
try {
List<String> split3 = suggestRemaining(rest, "#solidspread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SolidRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#solidspread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#randomoffset":
case "#spread": {
try {
List<String> split3 = suggestRemaining(rest, "#spread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new RandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#spread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#l":
case "#linear": {
ArrayList<Pattern> patterns = new ArrayList<>();
for (String token : StringMan.split(rest, ',')) {
patterns.add(catchSuggestion(input, token, context));
}
if (patterns.isEmpty()) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(input);
}
return new LinearBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
}
case "#l3d":
case "#linear3d": {
ArrayList<Pattern> patterns = new ArrayList<>();
for (String token : StringMan.split(rest, ',')) {
patterns.add(catchSuggestion(input, token, context));
}
if (patterns.isEmpty()) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(input);
}
return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
}
default:
throw new SuggestInputParseException(input, DELEGATE_PATTERNS);
}
case "#id": {
return new IdPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
}
case "#data": {
return new DataPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context));
}
case "#biome": {
World world = context.requireWorld();
BiomeRegistry biomeRegistry = world.getWorldData().getBiomeRegistry();
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
BaseBiome biome = Biomes.findBiomeByName(knownBiomes, rest, biomeRegistry);
return new BiomePattern(Request.request().getEditSession(), biome);
}
case "#~":
case "#r":
case "#relative":
case "#rel": {
return new RelativePattern(catchSuggestion(input, rest, context));
}
case "#!x":
case "#nx":
case "#nox": {
return new NoXPattern(catchSuggestion(input, rest, context));
}
case "#!y":
case "#ny":
case "#noy": {
return new NoYPattern(catchSuggestion(input, rest, context));
}
case "#!z":
case "#nz":
case "#noz": {
return new NoZPattern(catchSuggestion(input, rest, context));
}
case "#mask": {
List<String> split3 = suggestRemaining(rest, "#mask", "<mask>", "<pattern-if>", "<pattern-else>");
Pattern primary = catchSuggestion(input, split3.get(1), context);
Pattern secondary = catchSuggestion(input, split3.get(2), context);
PatternExtent extent = new PatternExtent(primary);
Request request = Request.request();
request.setExtent(extent);
request.setSession(context.getSession());
request.setWorld(context.getWorld());
context.setExtent(extent);
MaskFactory factory = worldEdit.getMaskFactory();
Mask mask = factory.parseFromInput(split3.get(0), context);
if (mask == null | primary == null || secondary == null) {
throw new SuggestInputParseException(null, "#mask:<mask>:<pattern-if>:<pattern-else>");
}
return new MaskedPattern(mask, extent, secondary);
}
case "#offset":
try {
List<String> split3 = suggestRemaining(rest, "#offset", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Expression.compile(split3.get(0)).evaluate();
int y = (int) Expression.compile(split3.get(1)).evaluate();
int z = (int) Expression.compile(split3.get(2)).evaluate();
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new OffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#offset:<dx>:<dy>:<dz>:<pattern>");
}
case "#surfacespread": {
try {
List<String> split3 = suggestRemaining(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SurfaceRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#surfacespread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#solidspread": {
try {
List<String> split3 = suggestRemaining(rest, "#solidspread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SolidRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#solidspread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#randomoffset":
case "#spread": {
try {
List<String> split3 = suggestRemaining(rest, "#spread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new RandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#spread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#l":
case "#linear": {
ArrayList<Pattern> patterns = new ArrayList<>();
for (String token : StringMan.split(rest, ',')) {
patterns.add(catchSuggestion(input, token, context));
}
if (patterns.isEmpty()) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(input);
}
return new LinearBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
}
case "#l3d":
case "#linear3d": {
ArrayList<Pattern> patterns = new ArrayList<>();
for (String token : StringMan.split(rest, ',')) {
patterns.add(catchSuggestion(input, token, context));
}
if (patterns.isEmpty()) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(input);
}
return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
}
default:
throw new SuggestInputParseException(input, MainUtil.joinArrayGeneric(SIMPLE_PATTERNS, DELEGATE_PATTERNS));
}
throw new SuggestInputParseException(input, MainUtil.joinArrayGeneric(SIMPLE_PATTERNS, DELEGATE_PATTERNS));
}
case '=': {
try {

View File

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

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer;
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.FaweClipboard;
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.ResettableFileInputStream;
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.util.MainUtil;
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.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.LocalConfiguration;
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.Clipboard;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
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) {
try {
try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) {